Skip to content

Commit fac8e0f

Browse files
jessegrossdavem330
authored andcommitted
tunnels: Don't apply GRO to multiple layers of encapsulation.
When drivers express support for TSO of encapsulated packets, they only mean that they can do it for one layer of encapsulation. Supporting additional levels would mean updating, at a minimum, more IP length fields and they are unaware of this. No encapsulation device expresses support for handling offloaded encapsulated packets, so we won't generate these types of frames in the transmit path. However, GRO doesn't have a check for multiple levels of encapsulation and will attempt to build them. UDP tunnel GRO actually does prevent this situation but it only handles multiple UDP tunnels stacked on top of each other. This generalizes that solution to prevent any kind of tunnel stacking that would cause problems. Fixes: bf5a755 ("net-gre-gro: Add GRE support to the GRO stack") Signed-off-by: Jesse Gross <jesse@kernel.org> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent b8cba75 commit fac8e0f

File tree

6 files changed

+39
-8
lines changed

6 files changed

+39
-8
lines changed

include/linux/netdevice.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2096,8 +2096,8 @@ struct napi_gro_cb {
20962096
/* This is non-zero if the packet may be of the same flow. */
20972097
u8 same_flow:1;
20982098

2099-
/* Used in udp_gro_receive */
2100-
u8 udp_mark:1;
2099+
/* Used in tunnel GRO receive */
2100+
u8 encap_mark:1;
21012101

21022102
/* GRO checksum is valid */
21032103
u8 csum_valid:1;

net/core/dev.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4438,7 +4438,7 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff
44384438
NAPI_GRO_CB(skb)->same_flow = 0;
44394439
NAPI_GRO_CB(skb)->flush = 0;
44404440
NAPI_GRO_CB(skb)->free = 0;
4441-
NAPI_GRO_CB(skb)->udp_mark = 0;
4441+
NAPI_GRO_CB(skb)->encap_mark = 0;
44424442
NAPI_GRO_CB(skb)->gro_remcsum_start = 0;
44434443

44444444
/* Setup for GRO checksum validation */

net/ipv4/af_inet.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1380,6 +1380,19 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head,
13801380
return pp;
13811381
}
13821382

1383+
static struct sk_buff **ipip_gro_receive(struct sk_buff **head,
1384+
struct sk_buff *skb)
1385+
{
1386+
if (NAPI_GRO_CB(skb)->encap_mark) {
1387+
NAPI_GRO_CB(skb)->flush = 1;
1388+
return NULL;
1389+
}
1390+
1391+
NAPI_GRO_CB(skb)->encap_mark = 1;
1392+
1393+
return inet_gro_receive(head, skb);
1394+
}
1395+
13831396
#define SECONDS_PER_DAY 86400
13841397

13851398
/* inet_current_timestamp - Return IP network timestamp
@@ -1682,7 +1695,7 @@ static struct packet_offload ip_packet_offload __read_mostly = {
16821695
static const struct net_offload ipip_offload = {
16831696
.callbacks = {
16841697
.gso_segment = inet_gso_segment,
1685-
.gro_receive = inet_gro_receive,
1698+
.gro_receive = ipip_gro_receive,
16861699
.gro_complete = ipip_gro_complete,
16871700
},
16881701
};

net/ipv4/gre_offload.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,11 @@ static struct sk_buff **gre_gro_receive(struct sk_buff **head,
126126
struct packet_offload *ptype;
127127
__be16 type;
128128

129+
if (NAPI_GRO_CB(skb)->encap_mark)
130+
goto out;
131+
132+
NAPI_GRO_CB(skb)->encap_mark = 1;
133+
129134
off = skb_gro_offset(skb);
130135
hlen = off + sizeof(*greh);
131136
greh = skb_gro_header_fast(skb, off);

net/ipv4/udp_offload.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -311,14 +311,14 @@ struct sk_buff **udp_gro_receive(struct sk_buff **head, struct sk_buff *skb,
311311
unsigned int off = skb_gro_offset(skb);
312312
int flush = 1;
313313

314-
if (NAPI_GRO_CB(skb)->udp_mark ||
314+
if (NAPI_GRO_CB(skb)->encap_mark ||
315315
(skb->ip_summed != CHECKSUM_PARTIAL &&
316316
NAPI_GRO_CB(skb)->csum_cnt == 0 &&
317317
!NAPI_GRO_CB(skb)->csum_valid))
318318
goto out;
319319

320-
/* mark that this skb passed once through the udp gro layer */
321-
NAPI_GRO_CB(skb)->udp_mark = 1;
320+
/* mark that this skb passed once through the tunnel gro layer */
321+
NAPI_GRO_CB(skb)->encap_mark = 1;
322322

323323
rcu_read_lock();
324324
uo_priv = rcu_dereference(udp_offload_base);

net/ipv6/ip6_offload.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,19 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head,
258258
return pp;
259259
}
260260

261+
static struct sk_buff **sit_gro_receive(struct sk_buff **head,
262+
struct sk_buff *skb)
263+
{
264+
if (NAPI_GRO_CB(skb)->encap_mark) {
265+
NAPI_GRO_CB(skb)->flush = 1;
266+
return NULL;
267+
}
268+
269+
NAPI_GRO_CB(skb)->encap_mark = 1;
270+
271+
return ipv6_gro_receive(head, skb);
272+
}
273+
261274
static int ipv6_gro_complete(struct sk_buff *skb, int nhoff)
262275
{
263276
const struct net_offload *ops;
@@ -302,7 +315,7 @@ static struct packet_offload ipv6_packet_offload __read_mostly = {
302315
static const struct net_offload sit_offload = {
303316
.callbacks = {
304317
.gso_segment = ipv6_gso_segment,
305-
.gro_receive = ipv6_gro_receive,
318+
.gro_receive = sit_gro_receive,
306319
.gro_complete = sit_gro_complete,
307320
},
308321
};

0 commit comments

Comments
 (0)