Skip to content

Commit eac1b93

Browse files
xli98davem330
authored andcommitted
gro: add ability to control gro max packet size
Eric Dumazet suggested to allow users to modify max GRO packet size. We have seen GRO being disabled by users of appliances (such as wifi access points) because of claimed bufferbloat issues, or some work arounds in sch_cake, to split GRO/GSO packets. Instead of disabling GRO completely, one can chose to limit the maximum packet size of GRO packets, depending on their latency constraints. This patch adds a per device gro_max_size attribute that can be changed with ip link command. ip link set dev eth0 gro_max_size 16000 Suggested-by: Eric Dumazet <[email protected]> Signed-off-by: Coco Li <[email protected]> Signed-off-by: Eric Dumazet <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 007747a commit eac1b93

File tree

6 files changed

+41
-1
lines changed

6 files changed

+41
-1
lines changed

include/linux/netdevice.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1942,6 +1942,8 @@ enum netdev_ml_priv_type {
19421942
* dev->addr_list_lock.
19431943
* @unlink_list: As netif_addr_lock() can be called recursively,
19441944
* keep a list of interfaces to be deleted.
1945+
* @gro_max_size: Maximum size of aggregated packet in generic
1946+
* receive offload (GRO)
19451947
*
19461948
* @dev_addr_shadow: Copy of @dev_addr to catch direct writes.
19471949
* @linkwatch_dev_tracker: refcount tracker used by linkwatch.
@@ -2131,6 +2133,8 @@ struct net_device {
21312133
struct bpf_prog __rcu *xdp_prog;
21322134
unsigned long gro_flush_timeout;
21332135
int napi_defer_hard_irqs;
2136+
#define GRO_MAX_SIZE 65536
2137+
unsigned int gro_max_size;
21342138
rx_handler_func_t __rcu *rx_handler;
21352139
void __rcu *rx_handler_data;
21362140

@@ -4806,6 +4810,13 @@ static inline void netif_set_gso_max_segs(struct net_device *dev,
48064810
WRITE_ONCE(dev->gso_max_segs, segs);
48074811
}
48084812

4813+
static inline void netif_set_gro_max_size(struct net_device *dev,
4814+
unsigned int size)
4815+
{
4816+
/* This pairs with the READ_ONCE() in skb_gro_receive() */
4817+
WRITE_ONCE(dev->gro_max_size, size);
4818+
}
4819+
48094820
static inline void skb_gso_error_unwind(struct sk_buff *skb, __be16 protocol,
48104821
int pulled_hlen, u16 mac_offset,
48114822
int mac_len)

include/uapi/linux/if_link.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,7 @@ enum {
347347
*/
348348
IFLA_PARENT_DEV_NAME,
349349
IFLA_PARENT_DEV_BUS_NAME,
350+
IFLA_GRO_MAX_SIZE,
350351

351352
__IFLA_MAX
352353
};

net/core/dev.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10180,6 +10180,7 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
1018010180

1018110181
dev->gso_max_size = GSO_MAX_SIZE;
1018210182
dev->gso_max_segs = GSO_MAX_SEGS;
10183+
dev->gro_max_size = GRO_MAX_SIZE;
1018310184
dev->upper_level = 1;
1018410185
dev->lower_level = 1;
1018510186
#ifdef CONFIG_LOCKDEP

net/core/gro.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,10 +132,14 @@ int skb_gro_receive(struct sk_buff *p, struct sk_buff *skb)
132132
unsigned int headlen = skb_headlen(skb);
133133
unsigned int len = skb_gro_len(skb);
134134
unsigned int delta_truesize;
135+
unsigned int gro_max_size;
135136
unsigned int new_truesize;
136137
struct sk_buff *lp;
137138

138-
if (unlikely(p->len + len >= 65536 || NAPI_GRO_CB(skb)->flush))
139+
/* pairs with WRITE_ONCE() in netif_set_gro_max_size() */
140+
gro_max_size = READ_ONCE(p->dev->gro_max_size);
141+
142+
if (unlikely(p->len + len >= gro_max_size || NAPI_GRO_CB(skb)->flush))
139143
return -E2BIG;
140144

141145
lp = NAPI_GRO_CB(p)->last;

net/core/rtnetlink.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1026,6 +1026,7 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev,
10261026
+ nla_total_size(4) /* IFLA_NUM_RX_QUEUES */
10271027
+ nla_total_size(4) /* IFLA_GSO_MAX_SEGS */
10281028
+ nla_total_size(4) /* IFLA_GSO_MAX_SIZE */
1029+
+ nla_total_size(4) /* IFLA_GRO_MAX_SIZE */
10291030
+ nla_total_size(1) /* IFLA_OPERSTATE */
10301031
+ nla_total_size(1) /* IFLA_LINKMODE */
10311032
+ nla_total_size(4) /* IFLA_CARRIER_CHANGES */
@@ -1728,6 +1729,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb,
17281729
nla_put_u32(skb, IFLA_NUM_TX_QUEUES, dev->num_tx_queues) ||
17291730
nla_put_u32(skb, IFLA_GSO_MAX_SEGS, dev->gso_max_segs) ||
17301731
nla_put_u32(skb, IFLA_GSO_MAX_SIZE, dev->gso_max_size) ||
1732+
nla_put_u32(skb, IFLA_GRO_MAX_SIZE, dev->gro_max_size) ||
17311733
#ifdef CONFIG_RPS
17321734
nla_put_u32(skb, IFLA_NUM_RX_QUEUES, dev->num_rx_queues) ||
17331735
#endif
@@ -1880,6 +1882,7 @@ static const struct nla_policy ifla_policy[IFLA_MAX+1] = {
18801882
[IFLA_PROTO_DOWN_REASON] = { .type = NLA_NESTED },
18811883
[IFLA_NEW_IFINDEX] = NLA_POLICY_MIN(NLA_S32, 1),
18821884
[IFLA_PARENT_DEV_NAME] = { .type = NLA_NUL_STRING },
1885+
[IFLA_GRO_MAX_SIZE] = { .type = NLA_U32 },
18831886
};
18841887

18851888
static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
@@ -2299,6 +2302,14 @@ static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[],
22992302
}
23002303
}
23012304

2305+
if (tb[IFLA_GRO_MAX_SIZE]) {
2306+
u32 gro_max_size = nla_get_u32(tb[IFLA_GRO_MAX_SIZE]);
2307+
2308+
if (gro_max_size > GRO_MAX_SIZE) {
2309+
NL_SET_ERR_MSG(extack, "too big gro_max_size");
2310+
return -EINVAL;
2311+
}
2312+
}
23022313
return 0;
23032314
}
23042315

@@ -2772,6 +2783,15 @@ static int do_setlink(const struct sk_buff *skb,
27722783
}
27732784
}
27742785

2786+
if (tb[IFLA_GRO_MAX_SIZE]) {
2787+
u32 gro_max_size = nla_get_u32(tb[IFLA_GRO_MAX_SIZE]);
2788+
2789+
if (dev->gro_max_size ^ gro_max_size) {
2790+
netif_set_gro_max_size(dev, gro_max_size);
2791+
status |= DO_SETLINK_MODIFIED;
2792+
}
2793+
}
2794+
27752795
if (tb[IFLA_OPERSTATE])
27762796
set_operstate(dev, nla_get_u8(tb[IFLA_OPERSTATE]));
27772797

@@ -3222,6 +3242,8 @@ struct net_device *rtnl_create_link(struct net *net, const char *ifname,
32223242
netif_set_gso_max_size(dev, nla_get_u32(tb[IFLA_GSO_MAX_SIZE]));
32233243
if (tb[IFLA_GSO_MAX_SEGS])
32243244
netif_set_gso_max_segs(dev, nla_get_u32(tb[IFLA_GSO_MAX_SEGS]));
3245+
if (tb[IFLA_GRO_MAX_SIZE])
3246+
netif_set_gro_max_size(dev, nla_get_u32(tb[IFLA_GRO_MAX_SIZE]));
32253247

32263248
return dev;
32273249
}

tools/include/uapi/linux/if_link.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,7 @@ enum {
347347
*/
348348
IFLA_PARENT_DEV_NAME,
349349
IFLA_PARENT_DEV_BUS_NAME,
350+
IFLA_GRO_MAX_SIZE,
350351

351352
__IFLA_MAX
352353
};

0 commit comments

Comments
 (0)