Skip to content

Commit ce87fc6

Browse files
jessegrossdavem330
authored andcommitted
gro: Make GRO aware of lightweight tunnels.
GRO is currently not aware of tunnel metadata generated by lightweight tunnels and stored in the dst. This leads to two possible problems: * Incorrectly merging two frames that have different metadata. * Leaking of allocated metadata from merged frames. This avoids those problems by comparing the tunnel information before merging, similar to how we handle other metadata (such as vlan tags), and releasing any state when we are done. Reported-by: John <john.phillips5@hpe.com> Fixes: 2e15ea3 ("ip_gre: Add support to collect tunnel metadata.") Signed-off-by: Jesse Gross <jesse@kernel.org> Acked-by: Eric Dumazet <edumazet@google.com> Acked-by: Thomas Graf <tgraf@suug.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 5f2f3ca commit ce87fc6

File tree

2 files changed

+23
-2
lines changed

2 files changed

+23
-2
lines changed

include/net/dst_metadata.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,24 @@ static inline bool skb_valid_dst(const struct sk_buff *skb)
4444
return dst && !(dst->flags & DST_METADATA);
4545
}
4646

47+
static inline int skb_metadata_dst_cmp(const struct sk_buff *skb_a,
48+
const struct sk_buff *skb_b)
49+
{
50+
const struct metadata_dst *a, *b;
51+
52+
if (!(skb_a->_skb_refdst | skb_b->_skb_refdst))
53+
return 0;
54+
55+
a = (const struct metadata_dst *) skb_dst(skb_a);
56+
b = (const struct metadata_dst *) skb_dst(skb_b);
57+
58+
if (!a != !b || a->u.tun_info.options_len != b->u.tun_info.options_len)
59+
return 1;
60+
61+
return memcmp(&a->u.tun_info, &b->u.tun_info,
62+
sizeof(a->u.tun_info) + a->u.tun_info.options_len);
63+
}
64+
4765
struct metadata_dst *metadata_dst_alloc(u8 optslen, gfp_t flags);
4866
struct metadata_dst __percpu *metadata_dst_alloc_percpu(u8 optslen, gfp_t flags);
4967

net/core/dev.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4351,6 +4351,7 @@ static void gro_list_prepare(struct napi_struct *napi, struct sk_buff *skb)
43514351

43524352
diffs = (unsigned long)p->dev ^ (unsigned long)skb->dev;
43534353
diffs |= p->vlan_tci ^ skb->vlan_tci;
4354+
diffs |= skb_metadata_dst_cmp(p, skb);
43544355
if (maclen == ETH_HLEN)
43554356
diffs |= compare_ether_header(skb_mac_header(p),
43564357
skb_mac_header(skb));
@@ -4548,10 +4549,12 @@ static gro_result_t napi_skb_finish(gro_result_t ret, struct sk_buff *skb)
45484549
break;
45494550

45504551
case GRO_MERGED_FREE:
4551-
if (NAPI_GRO_CB(skb)->free == NAPI_GRO_FREE_STOLEN_HEAD)
4552+
if (NAPI_GRO_CB(skb)->free == NAPI_GRO_FREE_STOLEN_HEAD) {
4553+
skb_dst_drop(skb);
45524554
kmem_cache_free(skbuff_head_cache, skb);
4553-
else
4555+
} else {
45544556
__kfree_skb(skb);
4557+
}
45554558
break;
45564559

45574560
case GRO_HELD:

0 commit comments

Comments
 (0)