lkml.org 
[lkml]   [2016]   [Mar]   [1]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH 4.4 002/342] gro: Make GRO aware of lightweight tunnels.
Date
4.4-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Jesse Gross <jesse@kernel.org>

[ Upstream commit ce87fc6ce3f9f4488546187e3757cf666d9d4a2a ]

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: 2e15ea39 ("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>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
include/net/dst_metadata.h | 18 ++++++++++++++++++
net/core/dev.c | 7 +++++--
2 files changed, 23 insertions(+), 2 deletions(-)

--- a/include/net/dst_metadata.h
+++ b/include/net/dst_metadata.h
@@ -44,6 +44,24 @@ static inline bool skb_valid_dst(const s
return dst && !(dst->flags & DST_METADATA);
}

+static inline int skb_metadata_dst_cmp(const struct sk_buff *skb_a,
+ const struct sk_buff *skb_b)
+{
+ const struct metadata_dst *a, *b;
+
+ if (!(skb_a->_skb_refdst | skb_b->_skb_refdst))
+ return 0;
+
+ a = (const struct metadata_dst *) skb_dst(skb_a);
+ b = (const struct metadata_dst *) skb_dst(skb_b);
+
+ if (!a != !b || a->u.tun_info.options_len != b->u.tun_info.options_len)
+ return 1;
+
+ return memcmp(&a->u.tun_info, &b->u.tun_info,
+ sizeof(a->u.tun_info) + a->u.tun_info.options_len);
+}
+
struct metadata_dst *metadata_dst_alloc(u8 optslen, gfp_t flags);
struct metadata_dst __percpu *metadata_dst_alloc_percpu(u8 optslen, gfp_t flags);

--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4145,6 +4145,7 @@ static void gro_list_prepare(struct napi

diffs = (unsigned long)p->dev ^ (unsigned long)skb->dev;
diffs |= p->vlan_tci ^ skb->vlan_tci;
+ diffs |= skb_metadata_dst_cmp(p, skb);
if (maclen == ETH_HLEN)
diffs |= compare_ether_header(skb_mac_header(p),
skb_mac_header(skb));
@@ -4342,10 +4343,12 @@ static gro_result_t napi_skb_finish(gro_
break;

case GRO_MERGED_FREE:
- if (NAPI_GRO_CB(skb)->free == NAPI_GRO_FREE_STOLEN_HEAD)
+ if (NAPI_GRO_CB(skb)->free == NAPI_GRO_FREE_STOLEN_HEAD) {
+ skb_dst_drop(skb);
kmem_cache_free(skbuff_head_cache, skb);
- else
+ } else {
__kfree_skb(skb);
+ }
break;

case GRO_HELD:
\
 
 \ /
  Last update: 2016-03-02 03:21    [W:0.944 / U:0.524 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site