* [PATCH net-next 01/11] flow_dissector: Move skb related functions to skbuff.h
2015-09-01 16:24 [PATCH net-next 00/11] flow_dissector: Paramterize dissection and other features Tom Herbert
@ 2015-09-01 16:24 ` Tom Herbert
2015-09-01 16:24 ` [PATCH net-next 02/11] skbuff: Make __skb_set_sw_hash a general function Tom Herbert
` (10 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Tom Herbert @ 2015-09-01 16:24 UTC (permalink / raw)
To: davem, netdev; +Cc: kernel-team
Move the flow dissector functions that are specific to skbuffs into
skbuff.h out of flow_dissector.h. This makes flow_dissector.h have
no dependencies on skbuff.h.
Signed-off-by: Tom Herbert <tom@herbertland.com>
---
include/linux/skbuff.h | 47 +++++++++++++++++++++++++++++++++++++++++
include/net/flow_dissector.h | 50 --------------------------------------------
2 files changed, 47 insertions(+), 50 deletions(-)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 989307f9..8a697c6 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -945,6 +945,53 @@ skb_set_hash(struct sk_buff *skb, __u32 hash, enum pkt_hash_types type)
skb->hash = hash;
}
+void __skb_get_hash(struct sk_buff *skb);
+u32 skb_get_poff(const struct sk_buff *skb);
+u32 __skb_get_poff(const struct sk_buff *skb, void *data,
+ const struct flow_keys *keys, int hlen);
+__be32 __skb_flow_get_ports(const struct sk_buff *skb, int thoff, u8 ip_proto,
+ void *data, int hlen_proto);
+
+static inline __be32 skb_flow_get_ports(const struct sk_buff *skb,
+ int thoff, u8 ip_proto)
+{
+ return __skb_flow_get_ports(skb, thoff, ip_proto, NULL, 0);
+}
+
+void skb_flow_dissector_init(struct flow_dissector *flow_dissector,
+ const struct flow_dissector_key *key,
+ unsigned int key_count);
+
+bool __skb_flow_dissect(const struct sk_buff *skb,
+ struct flow_dissector *flow_dissector,
+ void *target_container,
+ void *data, __be16 proto, int nhoff, int hlen);
+
+static inline bool skb_flow_dissect(const struct sk_buff *skb,
+ struct flow_dissector *flow_dissector,
+ void *target_container)
+{
+ return __skb_flow_dissect(skb, flow_dissector, target_container,
+ NULL, 0, 0, 0);
+}
+
+static inline bool skb_flow_dissect_flow_keys(const struct sk_buff *skb,
+ struct flow_keys *flow)
+{
+ memset(flow, 0, sizeof(*flow));
+ return __skb_flow_dissect(skb, &flow_keys_dissector, flow,
+ NULL, 0, 0, 0);
+}
+
+static inline bool skb_flow_dissect_flow_keys_buf(struct flow_keys *flow,
+ void *data, __be16 proto,
+ int nhoff, int hlen)
+{
+ memset(flow, 0, sizeof(*flow));
+ return __skb_flow_dissect(NULL, &flow_keys_buf_dissector, flow,
+ data, proto, nhoff, hlen);
+}
+
static inline __u32 skb_get_hash(struct sk_buff *skb)
{
if (!skb->l4_hash && !skb->sw_hash)
diff --git a/include/net/flow_dissector.h b/include/net/flow_dissector.h
index 1a8c224..6777a84 100644
--- a/include/net/flow_dissector.h
+++ b/include/net/flow_dissector.h
@@ -2,7 +2,6 @@
#define _NET_FLOW_DISSECTOR_H
#include <linux/types.h>
-#include <linux/skbuff.h>
#include <linux/in6.h>
#include <uapi/linux/if_ether.h>
@@ -134,23 +133,6 @@ struct flow_dissector {
unsigned short int offset[FLOW_DISSECTOR_KEY_MAX];
};
-void skb_flow_dissector_init(struct flow_dissector *flow_dissector,
- const struct flow_dissector_key *key,
- unsigned int key_count);
-
-bool __skb_flow_dissect(const struct sk_buff *skb,
- struct flow_dissector *flow_dissector,
- void *target_container,
- void *data, __be16 proto, int nhoff, int hlen);
-
-static inline bool skb_flow_dissect(const struct sk_buff *skb,
- struct flow_dissector *flow_dissector,
- void *target_container)
-{
- return __skb_flow_dissect(skb, flow_dissector, target_container,
- NULL, 0, 0, 0);
-}
-
struct flow_keys {
struct flow_dissector_key_control control;
#define FLOW_KEYS_HASH_START_FIELD basic
@@ -170,38 +152,6 @@ __be32 flow_get_u32_dst(const struct flow_keys *flow);
extern struct flow_dissector flow_keys_dissector;
extern struct flow_dissector flow_keys_buf_dissector;
-static inline bool skb_flow_dissect_flow_keys(const struct sk_buff *skb,
- struct flow_keys *flow)
-{
- memset(flow, 0, sizeof(*flow));
- return __skb_flow_dissect(skb, &flow_keys_dissector, flow,
- NULL, 0, 0, 0);
-}
-
-static inline bool skb_flow_dissect_flow_keys_buf(struct flow_keys *flow,
- void *data, __be16 proto,
- int nhoff, int hlen)
-{
- memset(flow, 0, sizeof(*flow));
- return __skb_flow_dissect(NULL, &flow_keys_buf_dissector, flow,
- data, proto, nhoff, hlen);
-}
-
-__be32 __skb_flow_get_ports(const struct sk_buff *skb, int thoff, u8 ip_proto,
- void *data, int hlen_proto);
-
-static inline __be32 skb_flow_get_ports(const struct sk_buff *skb,
- int thoff, u8 ip_proto)
-{
- return __skb_flow_get_ports(skb, thoff, ip_proto, NULL, 0);
-}
-
-u32 flow_hash_from_keys(struct flow_keys *keys);
-void __skb_get_hash(struct sk_buff *skb);
-u32 skb_get_poff(const struct sk_buff *skb);
-u32 __skb_get_poff(const struct sk_buff *skb, void *data,
- const struct flow_keys *keys, int hlen);
-
/* struct flow_keys_digest:
*
* This structure is used to hold a digest of the full flow keys. This is a
--
1.8.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH net-next 02/11] skbuff: Make __skb_set_sw_hash a general function
2015-09-01 16:24 [PATCH net-next 00/11] flow_dissector: Paramterize dissection and other features Tom Herbert
2015-09-01 16:24 ` [PATCH net-next 01/11] flow_dissector: Move skb related functions to skbuff.h Tom Herbert
@ 2015-09-01 16:24 ` Tom Herbert
2015-09-01 16:24 ` [PATCH net-next 03/11] flowi: Abstract out functions to get flow hash based on flowi Tom Herbert
` (9 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Tom Herbert @ 2015-09-01 16:24 UTC (permalink / raw)
To: davem, netdev; +Cc: kernel-team
Move __skb_set_sw_hash to skbuff.h and add __skb_set_hash which is
a common method (between __skb_set_sw_hash and skb_set_hash) to set
the hash in an skbuff.
Also, move skb_clear_hash to be closer to __skb_set_hash.
Signed-off-by: Tom Herbert <tom@herbertland.com>
---
include/linux/skbuff.h | 45 ++++++++++++++++++++++++++++----------------
include/net/flow_dissector.h | 5 +++++
net/core/flow_dissector.c | 18 ++++++------------
3 files changed, 40 insertions(+), 28 deletions(-)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 8a697c6..5d2c812 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -937,14 +937,40 @@ enum pkt_hash_types {
PKT_HASH_TYPE_L4, /* Input: src_IP, dst_IP, src_port, dst_port */
};
-static inline void
-skb_set_hash(struct sk_buff *skb, __u32 hash, enum pkt_hash_types type)
+static inline void skb_clear_hash(struct sk_buff *skb)
{
- skb->l4_hash = (type == PKT_HASH_TYPE_L4);
+ skb->hash = 0;
skb->sw_hash = 0;
+ skb->l4_hash = 0;
+}
+
+static inline void skb_clear_hash_if_not_l4(struct sk_buff *skb)
+{
+ if (!skb->l4_hash)
+ skb_clear_hash(skb);
+}
+
+static inline void
+__skb_set_hash(struct sk_buff *skb, __u32 hash, bool is_sw, bool is_l4)
+{
+ skb->l4_hash = is_l4;
+ skb->sw_hash = is_sw;
skb->hash = hash;
}
+static inline void
+skb_set_hash(struct sk_buff *skb, __u32 hash, enum pkt_hash_types type)
+{
+ /* Used by drivers to set hash from HW */
+ __skb_set_hash(skb, hash, false, type == PKT_HASH_TYPE_L4);
+}
+
+static inline void
+__skb_set_sw_hash(struct sk_buff *skb, __u32 hash, bool is_l4)
+{
+ __skb_set_hash(skb, hash, true, is_l4);
+}
+
void __skb_get_hash(struct sk_buff *skb);
u32 skb_get_poff(const struct sk_buff *skb);
u32 __skb_get_poff(const struct sk_buff *skb, void *data,
@@ -1027,19 +1053,6 @@ static inline __u32 skb_get_hash_raw(const struct sk_buff *skb)
return skb->hash;
}
-static inline void skb_clear_hash(struct sk_buff *skb)
-{
- skb->hash = 0;
- skb->sw_hash = 0;
- skb->l4_hash = 0;
-}
-
-static inline void skb_clear_hash_if_not_l4(struct sk_buff *skb)
-{
- if (!skb->l4_hash)
- skb_clear_hash(skb);
-}
-
static inline void skb_copy_hash(struct sk_buff *to, const struct sk_buff *from)
{
to->hash = from->hash;
diff --git a/include/net/flow_dissector.h b/include/net/flow_dissector.h
index 6777a84..af76c49 100644
--- a/include/net/flow_dissector.h
+++ b/include/net/flow_dissector.h
@@ -167,4 +167,9 @@ struct flow_keys_digest {
void make_flow_keys_digest(struct flow_keys_digest *digest,
const struct flow_keys *flow);
+static inline bool flow_keys_have_l4(struct flow_keys *keys)
+{
+ return (keys->ports.ports || keys->tags.flow_label);
+}
+
#endif
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index 11e6540..151b6e4 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -590,15 +590,6 @@ void make_flow_keys_digest(struct flow_keys_digest *digest,
}
EXPORT_SYMBOL(make_flow_keys_digest);
-static inline void __skb_set_sw_hash(struct sk_buff *skb, u32 hash,
- struct flow_keys *keys)
-{
- if (keys->ports.ports)
- skb->l4_hash = 1;
- skb->sw_hash = 1;
- skb->hash = hash;
-}
-
/**
* __skb_get_hash: calculate a flow hash
* @skb: sk_buff to calculate flow hash from
@@ -619,7 +610,8 @@ void __skb_get_hash(struct sk_buff *skb)
if (!hash)
return;
- __skb_set_sw_hash(skb, hash, &keys);
+ __skb_set_sw_hash(skb, hash,
+ flow_keys_have_l4(&keys));
}
EXPORT_SYMBOL(__skb_get_hash);
@@ -648,7 +640,8 @@ __u32 __skb_get_hash_flowi6(struct sk_buff *skb, struct flowi6 *fl6)
keys.tags.flow_label = (__force u32)fl6->flowlabel;
keys.basic.ip_proto = fl6->flowi6_proto;
- __skb_set_sw_hash(skb, flow_hash_from_keys(&keys), &keys);
+ __skb_set_sw_hash(skb, flow_hash_from_keys(&keys),
+ flow_keys_have_l4(&keys));
return skb->hash;
}
@@ -668,7 +661,8 @@ __u32 __skb_get_hash_flowi4(struct sk_buff *skb, struct flowi4 *fl4)
keys.keyid.keyid = fl4->fl4_gre_key;
keys.basic.ip_proto = fl4->flowi4_proto;
- __skb_set_sw_hash(skb, flow_hash_from_keys(&keys), &keys);
+ __skb_set_sw_hash(skb, flow_hash_from_keys(&keys),
+ flow_keys_have_l4(&keys));
return skb->hash;
}
--
1.8.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH net-next 03/11] flowi: Abstract out functions to get flow hash based on flowi
2015-09-01 16:24 [PATCH net-next 00/11] flow_dissector: Paramterize dissection and other features Tom Herbert
2015-09-01 16:24 ` [PATCH net-next 01/11] flow_dissector: Move skb related functions to skbuff.h Tom Herbert
2015-09-01 16:24 ` [PATCH net-next 02/11] skbuff: Make __skb_set_sw_hash a general function Tom Herbert
@ 2015-09-01 16:24 ` Tom Herbert
2015-09-01 16:24 ` [PATCH net-next 04/11] flow_dissector: Jump to exit code in __skb_flow_dissect Tom Herbert
` (8 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Tom Herbert @ 2015-09-01 16:24 UTC (permalink / raw)
To: davem, netdev; +Cc: kernel-team
Create __get_hash_from_flowi6 and __get_hash_from_flowi4 to get the
flow keys and hash based on flowi structures. These are called by
__skb_get_hash_flowi6 and __skb_get_hash_flowi4. Also, created
get_hash_from_flowi6 and get_hash_from_flowi4 which can be called
when just the hash value for a flowi is needed.
Signed-off-by: Tom Herbert <tom@herbertland.com>
---
include/linux/skbuff.h | 16 ++++++++++++----
include/net/flow.h | 19 +++++++++++++++++++
include/net/flow_dissector.h | 2 ++
net/core/flow.c | 36 ++++++++++++++++++++++++++++++++++++
4 files changed, 69 insertions(+), 4 deletions(-)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 5d2c812..bbe41bc 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -1030,8 +1030,12 @@ __u32 __skb_get_hash_flowi6(struct sk_buff *skb, struct flowi6 *fl6);
static inline __u32 skb_get_hash_flowi6(struct sk_buff *skb, struct flowi6 *fl6)
{
- if (!skb->l4_hash && !skb->sw_hash)
- __skb_get_hash_flowi6(skb, fl6);
+ if (!skb->l4_hash && !skb->sw_hash) {
+ struct flow_keys keys;
+
+ __skb_set_sw_hash(skb, __get_hash_from_flowi6(fl6, &keys),
+ flow_keys_have_l4(&keys));
+ }
return skb->hash;
}
@@ -1040,8 +1044,12 @@ __u32 __skb_get_hash_flowi4(struct sk_buff *skb, struct flowi4 *fl);
static inline __u32 skb_get_hash_flowi4(struct sk_buff *skb, struct flowi4 *fl4)
{
- if (!skb->l4_hash && !skb->sw_hash)
- __skb_get_hash_flowi4(skb, fl4);
+ if (!skb->l4_hash && !skb->sw_hash) {
+ struct flow_keys keys;
+
+ __skb_set_sw_hash(skb, __get_hash_from_flowi4(fl4, &keys),
+ flow_keys_have_l4(&keys));
+ }
return skb->hash;
}
diff --git a/include/net/flow.h b/include/net/flow.h
index 9e0297c..dafe97c 100644
--- a/include/net/flow.h
+++ b/include/net/flow.h
@@ -10,6 +10,7 @@
#include <linux/socket.h>
#include <linux/in6.h>
#include <linux/atomic.h>
+#include <net/flow_dissector.h>
/*
* ifindex generation is per-net namespace, and loopback is
@@ -243,4 +244,22 @@ void flow_cache_flush(struct net *net);
void flow_cache_flush_deferred(struct net *net);
extern atomic_t flow_cache_genid;
+__u32 __get_hash_from_flowi6(struct flowi6 *fl6, struct flow_keys *keys);
+
+static inline __u32 get_hash_from_flowi6(struct flowi6 *fl6)
+{
+ struct flow_keys keys;
+
+ return __get_hash_from_flowi6(fl6, &keys);
+}
+
+__u32 __get_hash_from_flowi4(struct flowi4 *fl4, struct flow_keys *keys);
+
+static inline __u32 get_hash_from_flowi4(struct flowi4 *fl4)
+{
+ struct flow_keys keys;
+
+ return __get_hash_from_flowi4(fl4, &keys);
+}
+
#endif
diff --git a/include/net/flow_dissector.h b/include/net/flow_dissector.h
index af76c49..74fe160 100644
--- a/include/net/flow_dissector.h
+++ b/include/net/flow_dissector.h
@@ -172,4 +172,6 @@ static inline bool flow_keys_have_l4(struct flow_keys *keys)
return (keys->ports.ports || keys->tags.flow_label);
}
+u32 flow_hash_from_keys(struct flow_keys *keys);
+
#endif
diff --git a/net/core/flow.c b/net/core/flow.c
index 1033725..61930bb 100644
--- a/net/core/flow.c
+++ b/net/core/flow.c
@@ -22,6 +22,7 @@
#include <linux/cpumask.h>
#include <linux/mutex.h>
#include <net/flow.h>
+#include <net/flow_dissector.h>
#include <linux/atomic.h>
#include <linux/security.h>
#include <net/net_namespace.h>
@@ -509,3 +510,38 @@ void flow_cache_fini(struct net *net)
fc->percpu = NULL;
}
EXPORT_SYMBOL(flow_cache_fini);
+
+__u32 __get_hash_from_flowi6(struct flowi6 *fl6, struct flow_keys *keys)
+{
+ memset(keys, 0, sizeof(*keys));
+
+ memcpy(&keys->addrs.v6addrs.src, &fl6->saddr,
+ sizeof(keys->addrs.v6addrs.src));
+ memcpy(&keys->addrs.v6addrs.dst, &fl6->daddr,
+ sizeof(keys->addrs.v6addrs.dst));
+ keys->control.addr_type = FLOW_DISSECTOR_KEY_IPV6_ADDRS;
+ keys->ports.src = fl6->fl6_sport;
+ keys->ports.dst = fl6->fl6_dport;
+ keys->keyid.keyid = fl6->fl6_gre_key;
+ keys->tags.flow_label = (__force u32)fl6->flowlabel;
+ keys->basic.ip_proto = fl6->flowi6_proto;
+
+ return flow_hash_from_keys(keys);
+}
+EXPORT_SYMBOL(__get_hash_from_flowi6);
+
+__u32 __get_hash_from_flowi4(struct flowi4 *fl4, struct flow_keys *keys)
+{
+ memset(keys, 0, sizeof(*keys));
+
+ keys->addrs.v4addrs.src = fl4->saddr;
+ keys->addrs.v4addrs.dst = fl4->daddr;
+ keys->control.addr_type = FLOW_DISSECTOR_KEY_IPV4_ADDRS;
+ keys->ports.src = fl4->fl4_sport;
+ keys->ports.dst = fl4->fl4_dport;
+ keys->keyid.keyid = fl4->fl4_gre_key;
+ keys->basic.ip_proto = fl4->flowi4_proto;
+
+ return flow_hash_from_keys(keys);
+}
+EXPORT_SYMBOL(__get_hash_from_flowi4);
--
1.8.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH net-next 04/11] flow_dissector: Jump to exit code in __skb_flow_dissect
2015-09-01 16:24 [PATCH net-next 00/11] flow_dissector: Paramterize dissection and other features Tom Herbert
` (2 preceding siblings ...)
2015-09-01 16:24 ` [PATCH net-next 03/11] flowi: Abstract out functions to get flow hash based on flowi Tom Herbert
@ 2015-09-01 16:24 ` Tom Herbert
2015-09-01 16:24 ` [PATCH net-next 05/11] flow_dissector: Add flags argument to skb_flow_dissector functions Tom Herbert
` (7 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Tom Herbert @ 2015-09-01 16:24 UTC (permalink / raw)
To: davem, netdev; +Cc: kernel-team
Instead of returning immediately (on a parsing failure for instance) we
jump to cleanup code. This always sets protocol values in key_control
(even on a failure there is still valid information in the key_tags that
was set before the problem was hit).
Signed-off-by: Tom Herbert <tom@herbertland.com>
---
net/core/flow_dissector.c | 51 +++++++++++++++++++++++------------------------
1 file changed, 25 insertions(+), 26 deletions(-)
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index 151b6e4..22f3d76 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -130,6 +130,7 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
struct flow_dissector_key_tags *key_tags;
struct flow_dissector_key_keyid *key_keyid;
u8 ip_proto = 0;
+ bool ret = false;
if (!data) {
data = skb->data;
@@ -171,7 +172,7 @@ again:
ip:
iph = __skb_header_pointer(skb, nhoff, sizeof(_iph), data, hlen, &_iph);
if (!iph || iph->ihl < 5)
- return false;
+ goto out_bad;
nhoff += iph->ihl * 4;
ip_proto = iph->protocol;
@@ -197,7 +198,7 @@ ip:
ipv6:
iph = __skb_header_pointer(skb, nhoff, sizeof(_iph), data, hlen, &_iph);
if (!iph)
- return false;
+ goto out_bad;
ip_proto = iph->nexthdr;
nhoff += sizeof(struct ipv6hdr);
@@ -234,7 +235,7 @@ ipv6:
vlan = __skb_header_pointer(skb, nhoff, sizeof(_vlan), data, hlen, &_vlan);
if (!vlan)
- return false;
+ goto out_bad;
if (skb_flow_dissector_uses_key(flow_dissector,
FLOW_DISSECTOR_KEY_VLANID)) {
@@ -256,7 +257,7 @@ ipv6:
} *hdr, _hdr;
hdr = __skb_header_pointer(skb, nhoff, sizeof(_hdr), data, hlen, &_hdr);
if (!hdr)
- return false;
+ goto out_bad;
proto = hdr->proto;
nhoff += PPPOE_SES_HLEN;
switch (proto) {
@@ -265,7 +266,7 @@ ipv6:
case htons(PPP_IPV6):
goto ipv6;
default:
- return false;
+ goto out_bad;
}
}
case htons(ETH_P_TIPC): {
@@ -275,9 +276,7 @@ ipv6:
} *hdr, _hdr;
hdr = __skb_header_pointer(skb, nhoff, sizeof(_hdr), data, hlen, &_hdr);
if (!hdr)
- return false;
- key_basic->n_proto = proto;
- key_control->thoff = (u16)nhoff;
+ goto out_bad;
if (skb_flow_dissector_uses_key(flow_dissector,
FLOW_DISSECTOR_KEY_TIPC_ADDRS)) {
@@ -287,7 +286,7 @@ ipv6:
key_addrs->tipcaddrs.srcnode = hdr->srcnode;
key_control->addr_type = FLOW_DISSECTOR_KEY_TIPC_ADDRS;
}
- return true;
+ goto out_good;
}
case htons(ETH_P_MPLS_UC):
@@ -297,7 +296,7 @@ mpls:
hdr = __skb_header_pointer(skb, nhoff, sizeof(_hdr), data,
hlen, &_hdr);
if (!hdr)
- return false;
+ goto out_bad;
if ((ntohl(hdr[0].entry) & MPLS_LS_LABEL_MASK) >>
MPLS_LS_LABEL_SHIFT == MPLS_LABEL_ENTROPY) {
@@ -310,21 +309,17 @@ mpls:
htonl(MPLS_LS_LABEL_MASK);
}
- key_basic->n_proto = proto;
- key_basic->ip_proto = ip_proto;
- key_control->thoff = (u16)nhoff;
-
- return true;
+ goto out_good;
}
- return true;
+ goto out_good;
}
case htons(ETH_P_FCOE):
key_control->thoff = (u16)(nhoff + FCOE_HEADER_LEN);
/* fall through */
default:
- return false;
+ goto out_bad;
}
ip_proto_again:
@@ -337,7 +332,7 @@ ip_proto_again:
hdr = __skb_header_pointer(skb, nhoff, sizeof(_hdr), data, hlen, &_hdr);
if (!hdr)
- return false;
+ goto out_bad;
/*
* Only look inside GRE if version zero and no
* routing
@@ -357,7 +352,7 @@ ip_proto_again:
data, hlen, &_keyid);
if (!keyid)
- return false;
+ goto out_bad;
if (skb_flow_dissector_uses_key(flow_dissector,
FLOW_DISSECTOR_KEY_GRE_KEYID)) {
@@ -378,7 +373,7 @@ ip_proto_again:
sizeof(_eth),
data, hlen, &_eth);
if (!eth)
- return false;
+ goto out_bad;
proto = eth->h_proto;
nhoff += sizeof(*eth);
}
@@ -395,7 +390,7 @@ ip_proto_again:
opthdr = __skb_header_pointer(skb, nhoff, sizeof(_opthdr),
data, hlen, &_opthdr);
if (!opthdr)
- return false;
+ goto out_bad;
ip_proto = opthdr[0];
nhoff += (opthdr[1] + 1) << 3;
@@ -415,10 +410,6 @@ ip_proto_again:
break;
}
- key_basic->n_proto = proto;
- key_basic->ip_proto = ip_proto;
- key_control->thoff = (u16)nhoff;
-
if (skb_flow_dissector_uses_key(flow_dissector,
FLOW_DISSECTOR_KEY_PORTS)) {
key_ports = skb_flow_dissector_target(flow_dissector,
@@ -428,7 +419,15 @@ ip_proto_again:
data, hlen);
}
- return true;
+out_good:
+ ret = true;
+
+out_bad:
+ key_basic->n_proto = proto;
+ key_basic->ip_proto = ip_proto;
+ key_control->thoff = (u16)nhoff;
+
+ return ret;
}
EXPORT_SYMBOL(__skb_flow_dissect);
--
1.8.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH net-next 05/11] flow_dissector: Add flags argument to skb_flow_dissector functions
2015-09-01 16:24 [PATCH net-next 00/11] flow_dissector: Paramterize dissection and other features Tom Herbert
` (3 preceding siblings ...)
2015-09-01 16:24 ` [PATCH net-next 04/11] flow_dissector: Jump to exit code in __skb_flow_dissect Tom Herbert
@ 2015-09-01 16:24 ` Tom Herbert
2015-09-01 16:24 ` [PATCH net-next 06/11] flow_dissector: Add control/reporting of fragmentation Tom Herbert
` (6 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Tom Herbert @ 2015-09-01 16:24 UTC (permalink / raw)
To: davem, netdev; +Cc: kernel-team
The flags argument will allow control of the dissection process (for
instance whether to parse beyond L3).
Signed-off-by: Tom Herbert <tom@herbertland.com>
---
drivers/net/bonding/bond_main.c | 2 +-
drivers/net/ethernet/cisco/enic/enic_clsf.c | 2 +-
drivers/net/hyperv/netvsc_drv.c | 2 +-
include/linux/skbuff.h | 19 +++++++++++--------
net/core/flow_dissector.c | 7 ++++---
net/ethernet/eth.c | 2 +-
net/sched/cls_flow.c | 2 +-
net/sched/cls_flower.c | 2 +-
net/sched/sch_choke.c | 4 ++--
9 files changed, 23 insertions(+), 19 deletions(-)
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 06e2d01..771a449 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -3095,7 +3095,7 @@ static bool bond_flow_dissect(struct bonding *bond, struct sk_buff *skb,
int noff, proto = -1;
if (bond->params.xmit_policy > BOND_XMIT_POLICY_LAYER23)
- return skb_flow_dissect_flow_keys(skb, fk);
+ return skb_flow_dissect_flow_keys(skb, fk, 0);
fk->ports.ports = 0;
noff = skb_network_offset(skb);
diff --git a/drivers/net/ethernet/cisco/enic/enic_clsf.c b/drivers/net/ethernet/cisco/enic/enic_clsf.c
index d106186..3c677ed 100644
--- a/drivers/net/ethernet/cisco/enic/enic_clsf.c
+++ b/drivers/net/ethernet/cisco/enic/enic_clsf.c
@@ -177,7 +177,7 @@ int enic_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb,
int res, i;
enic = netdev_priv(dev);
- res = skb_flow_dissect_flow_keys(skb, &keys);
+ res = skb_flow_dissect_flow_keys(skb, &keys, 0);
if (!res || keys.basic.n_proto != htons(ETH_P_IP) ||
(keys.basic.ip_proto != IPPROTO_TCP &&
keys.basic.ip_proto != IPPROTO_UDP))
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 2990024..409b48e 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -239,7 +239,7 @@ static bool netvsc_set_hash(u32 *hash, struct sk_buff *skb)
struct flow_keys flow;
int data_len;
- if (!skb_flow_dissect_flow_keys(skb, &flow) ||
+ if (!skb_flow_dissect_flow_keys(skb, &flow, 0) ||
!(flow.basic.n_proto == htons(ETH_P_IP) ||
flow.basic.n_proto == htons(ETH_P_IPV6)))
return false;
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index bbe41bc..9e62687 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -991,31 +991,34 @@ void skb_flow_dissector_init(struct flow_dissector *flow_dissector,
bool __skb_flow_dissect(const struct sk_buff *skb,
struct flow_dissector *flow_dissector,
void *target_container,
- void *data, __be16 proto, int nhoff, int hlen);
+ void *data, __be16 proto, int nhoff, int hlen,
+ unsigned int flags);
static inline bool skb_flow_dissect(const struct sk_buff *skb,
struct flow_dissector *flow_dissector,
- void *target_container)
+ void *target_container, unsigned int flags)
{
return __skb_flow_dissect(skb, flow_dissector, target_container,
- NULL, 0, 0, 0);
+ NULL, 0, 0, 0, flags);
}
static inline bool skb_flow_dissect_flow_keys(const struct sk_buff *skb,
- struct flow_keys *flow)
+ struct flow_keys *flow,
+ unsigned int flags)
{
memset(flow, 0, sizeof(*flow));
return __skb_flow_dissect(skb, &flow_keys_dissector, flow,
- NULL, 0, 0, 0);
+ NULL, 0, 0, 0, flags);
}
static inline bool skb_flow_dissect_flow_keys_buf(struct flow_keys *flow,
void *data, __be16 proto,
- int nhoff, int hlen)
+ int nhoff, int hlen,
+ unsigned int flags)
{
memset(flow, 0, sizeof(*flow));
return __skb_flow_dissect(NULL, &flow_keys_buf_dissector, flow,
- data, proto, nhoff, hlen);
+ data, proto, nhoff, hlen, flags);
}
static inline __u32 skb_get_hash(struct sk_buff *skb)
@@ -2046,7 +2049,7 @@ static inline void skb_probe_transport_header(struct sk_buff *skb,
if (skb_transport_header_was_set(skb))
return;
- else if (skb_flow_dissect_flow_keys(skb, &keys))
+ else if (skb_flow_dissect_flow_keys(skb, &keys, 0))
skb_set_transport_header(skb, keys.control.thoff);
else
skb_set_transport_header(skb, offset_hint);
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index 22f3d76..c3d9807 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -121,7 +121,8 @@ EXPORT_SYMBOL(__skb_flow_get_ports);
bool __skb_flow_dissect(const struct sk_buff *skb,
struct flow_dissector *flow_dissector,
void *target_container,
- void *data, __be16 proto, int nhoff, int hlen)
+ void *data, __be16 proto, int nhoff, int hlen,
+ unsigned int flags)
{
struct flow_dissector_key_control *key_control;
struct flow_dissector_key_basic *key_basic;
@@ -556,7 +557,7 @@ EXPORT_SYMBOL(flow_hash_from_keys);
static inline u32 ___skb_get_hash(const struct sk_buff *skb,
struct flow_keys *keys, u32 keyval)
{
- if (!skb_flow_dissect_flow_keys(skb, keys))
+ if (!skb_flow_dissect_flow_keys(skb, keys, 0))
return 0;
return __flow_hash_from_keys(keys, keyval);
@@ -726,7 +727,7 @@ u32 skb_get_poff(const struct sk_buff *skb)
{
struct flow_keys keys;
- if (!skb_flow_dissect_flow_keys(skb, &keys))
+ if (!skb_flow_dissect_flow_keys(skb, &keys, 0))
return 0;
return __skb_get_poff(skb, skb->data, &keys, skb_headlen(skb));
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c
index 217127c..d850fdc 100644
--- a/net/ethernet/eth.c
+++ b/net/ethernet/eth.c
@@ -132,7 +132,7 @@ u32 eth_get_headlen(void *data, unsigned int len)
/* parse any remaining L2/L3 headers, check for L4 */
if (!skb_flow_dissect_flow_keys_buf(&keys, data, eth->h_proto,
- sizeof(*eth), len))
+ sizeof(*eth), len, 0))
return max_t(u32, keys.control.thoff, sizeof(*eth));
/* parse for any L4 headers */
diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c
index bb2a0f5..536838b 100644
--- a/net/sched/cls_flow.c
+++ b/net/sched/cls_flow.c
@@ -301,7 +301,7 @@ static int flow_classify(struct sk_buff *skb, const struct tcf_proto *tp,
keymask = f->keymask;
if (keymask & FLOW_KEYS_NEEDED)
- skb_flow_dissect_flow_keys(skb, &flow_keys);
+ skb_flow_dissect_flow_keys(skb, &flow_keys, 0);
for (n = 0; n < f->nkeys; n++) {
key = ffs(keymask) - 1;
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
index 2f3d03f..5769294 100644
--- a/net/sched/cls_flower.c
+++ b/net/sched/cls_flower.c
@@ -129,7 +129,7 @@ static int fl_classify(struct sk_buff *skb, const struct tcf_proto *tp,
* so do it rather here.
*/
skb_key.basic.n_proto = skb->protocol;
- skb_flow_dissect(skb, &head->dissector, &skb_key);
+ skb_flow_dissect(skb, &head->dissector, &skb_key, 0);
fl_set_masked_key(&skb_mkey, &skb_key, &head->mask);
diff --git a/net/sched/sch_choke.c b/net/sched/sch_choke.c
index 665bde0..02bfd3d 100644
--- a/net/sched/sch_choke.c
+++ b/net/sched/sch_choke.c
@@ -170,13 +170,13 @@ static bool choke_match_flow(struct sk_buff *skb1,
if (!choke_skb_cb(skb1)->keys_valid) {
choke_skb_cb(skb1)->keys_valid = 1;
- skb_flow_dissect_flow_keys(skb1, &temp);
+ skb_flow_dissect_flow_keys(skb1, &temp, 0);
make_flow_keys_digest(&choke_skb_cb(skb1)->keys, &temp);
}
if (!choke_skb_cb(skb2)->keys_valid) {
choke_skb_cb(skb2)->keys_valid = 1;
- skb_flow_dissect_flow_keys(skb2, &temp);
+ skb_flow_dissect_flow_keys(skb2, &temp, 0);
make_flow_keys_digest(&choke_skb_cb(skb2)->keys, &temp);
}
--
1.8.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH net-next 06/11] flow_dissector: Add control/reporting of fragmentation
2015-09-01 16:24 [PATCH net-next 00/11] flow_dissector: Paramterize dissection and other features Tom Herbert
` (4 preceding siblings ...)
2015-09-01 16:24 ` [PATCH net-next 05/11] flow_dissector: Add flags argument to skb_flow_dissector functions Tom Herbert
@ 2015-09-01 16:24 ` Tom Herbert
2015-09-01 16:24 ` [PATCH net-next 07/11] flow_dissector: Support IPv6 fragment header Tom Herbert
` (5 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Tom Herbert @ 2015-09-01 16:24 UTC (permalink / raw)
To: davem, netdev; +Cc: kernel-team
Add an input flag to flow dissector on rather dissection should be
attempted on a first fragment. Also add key_control flags to indicate
that a packet is a fragment or first fragment.
Signed-off-by: Tom Herbert <tom@herbertland.com>
---
include/net/flow_dissector.h | 4 ++++
net/core/flow_dissector.c | 15 +++++++++++++--
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/include/net/flow_dissector.h b/include/net/flow_dissector.h
index 74fe160..3410227 100644
--- a/include/net/flow_dissector.h
+++ b/include/net/flow_dissector.h
@@ -12,6 +12,8 @@
struct flow_dissector_key_control {
u16 thoff;
u16 addr_type;
+ u32 is_fragment:1;
+ u32 first_frag:1;
};
/**
@@ -122,6 +124,8 @@ enum flow_dissector_key_id {
FLOW_DISSECTOR_KEY_MAX,
};
+#define FLOW_DISSECTOR_F_PARSE_1ST_FRAG BIT(0)
+
struct flow_dissector_key {
enum flow_dissector_key_id key_id;
size_t offset; /* offset of struct flow_dissector_key_*
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index c3d9807..7536a46 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -177,8 +177,6 @@ ip:
nhoff += iph->ihl * 4;
ip_proto = iph->protocol;
- if (ip_is_fragment(iph))
- ip_proto = 0;
if (!skb_flow_dissector_uses_key(flow_dissector,
FLOW_DISSECTOR_KEY_IPV4_ADDRS))
@@ -189,6 +187,19 @@ ip:
memcpy(&key_addrs->v4addrs, &iph->saddr,
sizeof(key_addrs->v4addrs));
key_control->addr_type = FLOW_DISSECTOR_KEY_IPV4_ADDRS;
+
+ if (ip_is_fragment(iph)) {
+ key_control->is_fragment = 1;
+
+ if (iph->frag_off & htons(IP_OFFSET)) {
+ goto out_good;
+ } else {
+ key_control->first_frag = 1;
+ if (!(flags & FLOW_DISSECTOR_F_PARSE_1ST_FRAG))
+ goto out_good;
+ }
+ }
+
break;
}
case htons(ETH_P_IPV6): {
--
1.8.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH net-next 07/11] flow_dissector: Support IPv6 fragment header
2015-09-01 16:24 [PATCH net-next 00/11] flow_dissector: Paramterize dissection and other features Tom Herbert
` (5 preceding siblings ...)
2015-09-01 16:24 ` [PATCH net-next 06/11] flow_dissector: Add control/reporting of fragmentation Tom Herbert
@ 2015-09-01 16:24 ` Tom Herbert
2015-09-01 16:24 ` [PATCH net-next 08/11] flow_dissector: Add flag to stop parsing at L3 Tom Herbert
` (4 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Tom Herbert @ 2015-09-01 16:24 UTC (permalink / raw)
To: davem, netdev; +Cc: kernel-team
Parse NEXTHDR_FRAGMENT. When seen account for it in the fragment bits of
key_control. Also, check if first fragment should be parsed.
Signed-off-by: Tom Herbert <tom@herbertland.com>
---
net/core/flow_dissector.c | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index 7536a46..907de2f 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -409,6 +409,31 @@ ip_proto_again:
goto ip_proto_again;
}
+ case NEXTHDR_FRAGMENT: {
+ struct frag_hdr _fh, *fh;
+
+ if (proto != htons(ETH_P_IPV6))
+ break;
+
+ fh = __skb_header_pointer(skb, nhoff, sizeof(_fh),
+ data, hlen, &_fh);
+
+ if (!fh)
+ goto out_bad;
+
+ key_control->is_fragment = 1;
+
+ nhoff += sizeof(_fh);
+
+ if (!(fh->frag_off & htons(IP6_OFFSET))) {
+ key_control->first_frag = 1;
+ if (flags & FLOW_DISSECTOR_F_PARSE_1ST_FRAG) {
+ ip_proto = fh->nexthdr;
+ goto ip_proto_again;
+ }
+ }
+ goto out_good;
+ }
case IPPROTO_IPIP:
proto = htons(ETH_P_IP);
goto ip;
--
1.8.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH net-next 08/11] flow_dissector: Add flag to stop parsing at L3
2015-09-01 16:24 [PATCH net-next 00/11] flow_dissector: Paramterize dissection and other features Tom Herbert
` (6 preceding siblings ...)
2015-09-01 16:24 ` [PATCH net-next 07/11] flow_dissector: Support IPv6 fragment header Tom Herbert
@ 2015-09-01 16:24 ` Tom Herbert
2015-09-01 16:24 ` [PATCH net-next 09/11] flow_dissector: Add flag to stop parsing when an IPv6 flow label is seen Tom Herbert
` (3 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Tom Herbert @ 2015-09-01 16:24 UTC (permalink / raw)
To: davem, netdev; +Cc: kernel-team
Add an input flag to flow dissector on rather dissection should be
stopped when an L3 packet is encountered. This would be useful if a
caller just wanted to get IP addresses of the outermost header (e.g.
to do an L3 hash).
Signed-off-by: Tom Herbert <tom@herbertland.com>
---
include/net/flow_dissector.h | 1 +
net/core/flow_dissector.c | 6 ++++++
2 files changed, 7 insertions(+)
diff --git a/include/net/flow_dissector.h b/include/net/flow_dissector.h
index 3410227..bb81e3b 100644
--- a/include/net/flow_dissector.h
+++ b/include/net/flow_dissector.h
@@ -125,6 +125,7 @@ enum flow_dissector_key_id {
};
#define FLOW_DISSECTOR_F_PARSE_1ST_FRAG BIT(0)
+#define FLOW_DISSECTOR_F_STOP_AT_L3 BIT(1)
struct flow_dissector_key {
enum flow_dissector_key_id key_id;
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index 907de2f..94fd841 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -200,6 +200,9 @@ ip:
}
}
+ if (flags & FLOW_DISSECTOR_F_STOP_AT_L3)
+ goto out_good;
+
break;
}
case htons(ETH_P_IPV6): {
@@ -238,6 +241,9 @@ ipv6:
}
}
+ if (flags & FLOW_DISSECTOR_F_STOP_AT_L3)
+ goto out_good;
+
break;
}
case htons(ETH_P_8021AD):
--
1.8.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH net-next 09/11] flow_dissector: Add flag to stop parsing when an IPv6 flow label is seen
2015-09-01 16:24 [PATCH net-next 00/11] flow_dissector: Paramterize dissection and other features Tom Herbert
` (7 preceding siblings ...)
2015-09-01 16:24 ` [PATCH net-next 08/11] flow_dissector: Add flag to stop parsing at L3 Tom Herbert
@ 2015-09-01 16:24 ` Tom Herbert
2015-09-01 16:24 ` [PATCH net-next 10/11] flow_dissector: Add control/reporting of encapsulation Tom Herbert
` (2 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Tom Herbert @ 2015-09-01 16:24 UTC (permalink / raw)
To: davem, netdev; +Cc: kernel-team
Add an input flag to flow dissector on rather dissection should be
stopped when a flow label is encountered. Presumably, the flow label
is derived from a sufficient hash of an inner transport packet so
further dissection is not needed (that is ports are not included in
the flow hash). Using the flow label instead of ports has the additional
benefit that packet fragments should hash to same value as non-fragments
for a flow (assuming that the same flow label is used).
We set this flag by default in for skb_get_hash.
Signed-off-by: Tom Herbert <tom@herbertland.com>
---
include/net/flow_dissector.h | 1 +
net/core/flow_dissector.c | 5 ++++-
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/include/net/flow_dissector.h b/include/net/flow_dissector.h
index bb81e3b..66dbc34 100644
--- a/include/net/flow_dissector.h
+++ b/include/net/flow_dissector.h
@@ -126,6 +126,7 @@ enum flow_dissector_key_id {
#define FLOW_DISSECTOR_F_PARSE_1ST_FRAG BIT(0)
#define FLOW_DISSECTOR_F_STOP_AT_L3 BIT(1)
+#define FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL BIT(2)
struct flow_dissector_key {
enum flow_dissector_key_id key_id;
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index 94fd841..094e343 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -239,6 +239,8 @@ ipv6:
target_container);
key_tags->flow_label = ntohl(flow_label);
}
+ if (flags & FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL)
+ goto out_good;
}
if (flags & FLOW_DISSECTOR_F_STOP_AT_L3)
@@ -599,7 +601,8 @@ EXPORT_SYMBOL(flow_hash_from_keys);
static inline u32 ___skb_get_hash(const struct sk_buff *skb,
struct flow_keys *keys, u32 keyval)
{
- if (!skb_flow_dissect_flow_keys(skb, keys, 0))
+ if (!skb_flow_dissect_flow_keys(skb, keys,
+ FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL))
return 0;
return __flow_hash_from_keys(keys, keyval);
--
1.8.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH net-next 10/11] flow_dissector: Add control/reporting of encapsulation
2015-09-01 16:24 [PATCH net-next 00/11] flow_dissector: Paramterize dissection and other features Tom Herbert
` (8 preceding siblings ...)
2015-09-01 16:24 ` [PATCH net-next 09/11] flow_dissector: Add flag to stop parsing when an IPv6 flow label is seen Tom Herbert
@ 2015-09-01 16:24 ` Tom Herbert
2015-09-01 16:24 ` [PATCH net-next 11/11] flow_dissector: Ignore flow dissector return value from ___skb_get_hash Tom Herbert
2015-09-01 22:22 ` [PATCH net-next 00/11] flow_dissector: Paramterize dissection and other features David Miller
11 siblings, 0 replies; 13+ messages in thread
From: Tom Herbert @ 2015-09-01 16:24 UTC (permalink / raw)
To: davem, netdev; +Cc: kernel-team
Add an input flag to flow dissector on rather dissection should stop
when encapsulation is detected (IP/IP or GRE). Also, add a key_control
flag that indicates encapsulation was encountered during the
dissection.
Signed-off-by: Tom Herbert <tom@herbertland.com>
---
include/net/flow_dissector.h | 2 ++
net/core/flow_dissector.c | 15 +++++++++++++++
2 files changed, 17 insertions(+)
diff --git a/include/net/flow_dissector.h b/include/net/flow_dissector.h
index 66dbc34..bddd108 100644
--- a/include/net/flow_dissector.h
+++ b/include/net/flow_dissector.h
@@ -14,6 +14,7 @@ struct flow_dissector_key_control {
u16 addr_type;
u32 is_fragment:1;
u32 first_frag:1;
+ u32 encapsulation:1;
};
/**
@@ -127,6 +128,7 @@ enum flow_dissector_key_id {
#define FLOW_DISSECTOR_F_PARSE_1ST_FRAG BIT(0)
#define FLOW_DISSECTOR_F_STOP_AT_L3 BIT(1)
#define FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL BIT(2)
+#define FLOW_DISSECTOR_F_STOP_AT_ENCAP BIT(3)
struct flow_dissector_key {
enum flow_dissector_key_id key_id;
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index 094e343..8d89013 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -397,6 +397,11 @@ ip_proto_again:
proto = eth->h_proto;
nhoff += sizeof(*eth);
}
+
+ key_control->encapsulation = 1;
+ if (flags & FLOW_DISSECTOR_F_STOP_AT_ENCAP)
+ goto out_good;
+
goto again;
}
case NEXTHDR_HOP:
@@ -444,9 +449,19 @@ ip_proto_again:
}
case IPPROTO_IPIP:
proto = htons(ETH_P_IP);
+
+ key_control->encapsulation = 1;
+ if (flags & FLOW_DISSECTOR_F_STOP_AT_ENCAP)
+ goto out_good;
+
goto ip;
case IPPROTO_IPV6:
proto = htons(ETH_P_IPV6);
+
+ key_control->encapsulation = 1;
+ if (flags & FLOW_DISSECTOR_F_STOP_AT_ENCAP)
+ goto out_good;
+
goto ipv6;
case IPPROTO_MPLS:
proto = htons(ETH_P_MPLS_UC);
--
1.8.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH net-next 11/11] flow_dissector: Ignore flow dissector return value from ___skb_get_hash
2015-09-01 16:24 [PATCH net-next 00/11] flow_dissector: Paramterize dissection and other features Tom Herbert
` (9 preceding siblings ...)
2015-09-01 16:24 ` [PATCH net-next 10/11] flow_dissector: Add control/reporting of encapsulation Tom Herbert
@ 2015-09-01 16:24 ` Tom Herbert
2015-09-01 22:22 ` [PATCH net-next 00/11] flow_dissector: Paramterize dissection and other features David Miller
11 siblings, 0 replies; 13+ messages in thread
From: Tom Herbert @ 2015-09-01 16:24 UTC (permalink / raw)
To: davem, netdev; +Cc: kernel-team
In ___skb_get_hash ignore return value from skb_flow_dissect_flow_keys.
A failure in that function likely means that there was a parse error,
so we may as well use whatever fields were found before the error was
hit. This is also good because it means we won't keep trying to derive
the hash on subsequent calls to skb_get_hash for the same packet.
Signed-off-by: Tom Herbert <tom@herbertland.com>
---
net/core/flow_dissector.c | 12 +++---------
1 file changed, 3 insertions(+), 9 deletions(-)
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index 8d89013..b5633394 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -616,9 +616,8 @@ EXPORT_SYMBOL(flow_hash_from_keys);
static inline u32 ___skb_get_hash(const struct sk_buff *skb,
struct flow_keys *keys, u32 keyval)
{
- if (!skb_flow_dissect_flow_keys(skb, keys,
- FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL))
- return 0;
+ skb_flow_dissect_flow_keys(skb, keys,
+ FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL);
return __flow_hash_from_keys(keys, keyval);
}
@@ -662,15 +661,10 @@ EXPORT_SYMBOL(make_flow_keys_digest);
void __skb_get_hash(struct sk_buff *skb)
{
struct flow_keys keys;
- u32 hash;
__flow_hash_secret_init();
- hash = ___skb_get_hash(skb, &keys, hashrnd);
- if (!hash)
- return;
-
- __skb_set_sw_hash(skb, hash,
+ __skb_set_sw_hash(skb, ___skb_get_hash(skb, &keys, hashrnd),
flow_keys_have_l4(&keys));
}
EXPORT_SYMBOL(__skb_get_hash);
--
1.8.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH net-next 00/11] flow_dissector: Paramterize dissection and other features
2015-09-01 16:24 [PATCH net-next 00/11] flow_dissector: Paramterize dissection and other features Tom Herbert
` (10 preceding siblings ...)
2015-09-01 16:24 ` [PATCH net-next 11/11] flow_dissector: Ignore flow dissector return value from ___skb_get_hash Tom Herbert
@ 2015-09-01 22:22 ` David Miller
11 siblings, 0 replies; 13+ messages in thread
From: David Miller @ 2015-09-01 22:22 UTC (permalink / raw)
To: tom; +Cc: netdev, kernel-team
From: Tom Herbert <tom@herbertland.com>
Date: Tue, 1 Sep 2015 09:24:22 -0700
> This patch set adds some new capabilities to flow_dissector:
>
> - Add flags to flow dissector functions to control dissection
> - Flag to stop dissection when L3 header is seen (don't
> dissect L4)
> - Flag to stop dissection when encapsulation is detected
> - Flag to parse first fragment of fragmented packet. This
> may provide L4 ports
> - Added new reporting in key_control
> - Packet is a fragment
> - Packet is a first fragment
> - Packet has encapsulation
>
> Also:
> - Make __skb_set_sw_hash a general function
> - Create functions to get a flow hash based on flowi4 or flowi6
> structures without an reference to an skbuff
> - Ignore flow dissector return value from ___skb_get_hash. Just
> use whatever key fields are found to make a hash
>
> Tested:
...
This looks fine, series applied, thanks Tom.
^ permalink raw reply [flat|nested] 13+ messages in thread