summaryrefslogtreecommitdiffstats
path: root/include/net
diff options
context:
space:
mode:
authorJesse Gross <jesse@kernel.org>2016-01-21 02:59:49 +0100
committerDavid S. Miller <davem@davemloft.net>2016-01-21 03:48:38 +0100
commitce87fc6ce3f9f4488546187e3757cf666d9d4a2a (patch)
tree02d13d67cc1113935a5a3b738a51bb70c8b20cad /include/net
parentsunvnet: Initialize network_header and transport_header in vnet_rx_one() (diff)
downloadlinux-ce87fc6ce3f9f4488546187e3757cf666d9d4a2a.tar.xz
linux-ce87fc6ce3f9f4488546187e3757cf666d9d4a2a.zip
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: 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>
Diffstat (limited to 'include/net')
-rw-r--r--include/net/dst_metadata.h18
1 files changed, 18 insertions, 0 deletions
diff --git a/include/net/dst_metadata.h b/include/net/dst_metadata.h
index 6816f0fa5693..30a56ab2ccfb 100644
--- a/include/net/dst_metadata.h
+++ b/include/net/dst_metadata.h
@@ -44,6 +44,24 @@ static inline bool skb_valid_dst(const struct sk_buff *skb)
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);