* [PATCH net-next 1/6] flow_dissector: Move ETH_P_TEB processing to main switch
2017-08-29 17:19 [PATCH net-next 0/6] flow_dissector: Protocol specific flow dissector offload Tom Herbert
@ 2017-08-29 17:19 ` Tom Herbert
2017-08-29 17:19 ` [PATCH net-next 2/6] udp: Constify skb argument in lookup functions Tom Herbert
` (5 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Tom Herbert @ 2017-08-29 17:19 UTC (permalink / raw)
To: davem; +Cc: netdev, Tom Herbert
Support for processing TEB is currently in GRE flow dissection as a
special case. This can be moved to be a case the main proto switch in
__skb_flow_dissect.
---
net/core/flow_dissector.c | 44 +++++++++++++++++++++++---------------------
1 file changed, 23 insertions(+), 21 deletions(-)
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index e2eaa1ff948d..12302acdb073 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -288,27 +288,8 @@ __skb_flow_dissect_gre(const struct sk_buff *skb,
if (hdr->flags & GRE_SEQ)
offset += sizeof(((struct pptp_gre_header *) 0)->seq);
- if (gre_ver == 0) {
- if (*p_proto == htons(ETH_P_TEB)) {
- const struct ethhdr *eth;
- struct ethhdr _eth;
-
- eth = __skb_header_pointer(skb, *p_nhoff + offset,
- sizeof(_eth),
- data, *p_hlen, &_eth);
- if (!eth)
- return FLOW_DISSECT_RET_OUT_BAD;
- *p_proto = eth->h_proto;
- offset += sizeof(*eth);
-
- /* Cap headers that we access via pointers at the
- * end of the Ethernet header as our maximum alignment
- * at that point is only 2 bytes.
- */
- if (NET_IP_ALIGN)
- *p_hlen = *p_nhoff + offset;
- }
- } else { /* version 1, must be PPTP */
+ /* version 1, must be PPTP */
+ if (gre_ver == 1) {
u8 _ppp_hdr[PPP_HDRLEN];
u8 *ppp_hdr;
@@ -573,6 +554,27 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
break;
}
+ case htons(ETH_P_TEB): {
+ const struct ethhdr *eth;
+ struct ethhdr _eth;
+
+ eth = __skb_header_pointer(skb, nhoff, sizeof(_eth),
+ data, hlen, &_eth);
+ if (!eth)
+ goto out_bad;
+
+ proto = eth->h_proto;
+ nhoff += sizeof(*eth);
+
+ /* Cap headers that we access via pointers at the
+ * end of the Ethernet header as our maximum alignment
+ * at that point is only 2 bytes.
+ */
+ if (NET_IP_ALIGN)
+ hlen = nhoff;
+
+ goto proto_again;
+ }
case htons(ETH_P_8021AD):
case htons(ETH_P_8021Q): {
const struct vlan_hdr *vlan;
--
2.11.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH net-next 2/6] udp: Constify skb argument in lookup functions
2017-08-29 17:19 [PATCH net-next 0/6] flow_dissector: Protocol specific flow dissector offload Tom Herbert
2017-08-29 17:19 ` [PATCH net-next 1/6] flow_dissector: Move ETH_P_TEB processing to main switch Tom Herbert
@ 2017-08-29 17:19 ` Tom Herbert
2017-08-29 17:19 ` [PATCH net-next 3/6] flow_dissector: Add protocol specific flow dissection offload Tom Herbert
` (4 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Tom Herbert @ 2017-08-29 17:19 UTC (permalink / raw)
To: davem; +Cc: netdev, Tom Herbert
For UDP socket lookup functions, and associateed functions that take an
skbuf as argument, declare the skb argument as constant.
One caveat is that reuseport_select_sock can be called from the UDP
lookup functions with an skb argument. This function temporarily
modifies the skbuff data pointer (in bpf_run via a pull/push sequence).
To resolve compiler warning I added a local skbuf declaration that is
not const and assigned to the skb argument with an explicit cast.
---
include/net/ip.h | 2 +-
include/net/sock_reuseport.h | 2 +-
include/net/udp.h | 11 ++++++-----
net/core/sock_reuseport.c | 5 +++--
net/ipv4/udp.c | 11 ++++++-----
net/ipv6/udp.c | 10 +++++-----
6 files changed, 22 insertions(+), 19 deletions(-)
diff --git a/include/net/ip.h b/include/net/ip.h
index 9896f46cbbf1..8c0d84ffc659 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -79,7 +79,7 @@ struct ipcm_cookie {
#define PKTINFO_SKB_CB(skb) ((struct in_pktinfo *)((skb)->cb))
/* return enslaved device index if relevant */
-static inline int inet_sdif(struct sk_buff *skb)
+static inline int inet_sdif(const struct sk_buff *skb)
{
#if IS_ENABLED(CONFIG_NET_L3_MASTER_DEV)
if (skb && ipv4_l3mdev_skb(IPCB(skb)->flags))
diff --git a/include/net/sock_reuseport.h b/include/net/sock_reuseport.h
index aecd30308d50..d25352a848d9 100644
--- a/include/net/sock_reuseport.h
+++ b/include/net/sock_reuseport.h
@@ -20,7 +20,7 @@ extern int reuseport_add_sock(struct sock *sk, struct sock *sk2);
extern void reuseport_detach_sock(struct sock *sk);
extern struct sock *reuseport_select_sock(struct sock *sk,
u32 hash,
- struct sk_buff *skb,
+ const struct sk_buff *skb,
int hdr_len);
extern struct bpf_prog *reuseport_attach_prog(struct sock *sk,
struct bpf_prog *prog);
diff --git a/include/net/udp.h b/include/net/udp.h
index 4e5f23fec35e..f3d1de6f0983 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -167,7 +167,7 @@ static inline void udp_csum_pull_header(struct sk_buff *skb)
UDP_SKB_CB(skb)->cscov -= sizeof(struct udphdr);
}
-typedef struct sock *(*udp_lookup_t)(struct sk_buff *skb, __be16 sport,
+typedef struct sock *(*udp_lookup_t)(const struct sk_buff *skb, __be16 sport,
__be16 dport);
struct sk_buff **udp_gro_receive(struct sk_buff **head, struct sk_buff *skb,
@@ -288,8 +288,9 @@ struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport,
__be32 daddr, __be16 dport, int dif);
struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport,
__be32 daddr, __be16 dport, int dif, int sdif,
- struct udp_table *tbl, struct sk_buff *skb);
-struct sock *udp4_lib_lookup_skb(struct sk_buff *skb,
+ struct udp_table *tbl,
+ const struct sk_buff *skb);
+struct sock *udp4_lib_lookup_skb(const struct sk_buff *skb,
__be16 sport, __be16 dport);
struct sock *udp6_lib_lookup(struct net *net,
const struct in6_addr *saddr, __be16 sport,
@@ -299,8 +300,8 @@ struct sock *__udp6_lib_lookup(struct net *net,
const struct in6_addr *saddr, __be16 sport,
const struct in6_addr *daddr, __be16 dport,
int dif, int sdif, struct udp_table *tbl,
- struct sk_buff *skb);
-struct sock *udp6_lib_lookup_skb(struct sk_buff *skb,
+ const struct sk_buff *skb);
+struct sock *udp6_lib_lookup_skb(const struct sk_buff *skb,
__be16 sport, __be16 dport);
/* UDP uses skb->dev_scratch to cache as much information as possible and avoid
diff --git a/net/core/sock_reuseport.c b/net/core/sock_reuseport.c
index eed1ebf7f29d..a17f13b33189 100644
--- a/net/core/sock_reuseport.c
+++ b/net/core/sock_reuseport.c
@@ -164,9 +164,10 @@ void reuseport_detach_sock(struct sock *sk)
EXPORT_SYMBOL(reuseport_detach_sock);
static struct sock *run_bpf(struct sock_reuseport *reuse, u16 socks,
- struct bpf_prog *prog, struct sk_buff *skb,
+ struct bpf_prog *prog, const struct sk_buff *_skb,
int hdr_len)
{
+ struct sk_buff *skb = (struct sk_buff *)_skb; /* Override const */
struct sk_buff *nskb = NULL;
u32 index;
@@ -205,7 +206,7 @@ static struct sock *run_bpf(struct sock_reuseport *reuse, u16 socks,
*/
struct sock *reuseport_select_sock(struct sock *sk,
u32 hash,
- struct sk_buff *skb,
+ const struct sk_buff *skb,
int hdr_len)
{
struct sock_reuseport *reuse;
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index bf6c406bf5e7..a851026ef28b 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -135,7 +135,8 @@ EXPORT_SYMBOL(udp_memory_allocated);
#define PORTS_PER_CHAIN (MAX_UDP_PORTS / UDP_HTABLE_SIZE_MIN)
/* IPCB reference means this can not be used from early demux */
-static bool udp_lib_exact_dif_match(struct net *net, struct sk_buff *skb)
+static bool udp_lib_exact_dif_match(struct net *net,
+ const struct sk_buff *skb)
{
#if IS_ENABLED(CONFIG_NET_L3_MASTER_DEV)
if (!net->ipv4.sysctl_udp_l3mdev_accept &&
@@ -445,7 +446,7 @@ static struct sock *udp4_lib_lookup2(struct net *net,
__be32 daddr, unsigned int hnum,
int dif, int sdif, bool exact_dif,
struct udp_hslot *hslot2,
- struct sk_buff *skb)
+ const struct sk_buff *skb)
{
struct sock *sk, *result;
int score, badness, matches = 0, reuseport = 0;
@@ -484,7 +485,7 @@ static struct sock *udp4_lib_lookup2(struct net *net,
*/
struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr,
__be16 sport, __be32 daddr, __be16 dport, int dif,
- int sdif, struct udp_table *udptable, struct sk_buff *skb)
+ int sdif, struct udp_table *udptable, const struct sk_buff *skb)
{
struct sock *sk, *result;
unsigned short hnum = ntohs(dport);
@@ -552,7 +553,7 @@ struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr,
}
EXPORT_SYMBOL_GPL(__udp4_lib_lookup);
-static inline struct sock *__udp4_lib_lookup_skb(struct sk_buff *skb,
+static inline struct sock *__udp4_lib_lookup_skb(const struct sk_buff *skb,
__be16 sport, __be16 dport,
struct udp_table *udptable)
{
@@ -563,7 +564,7 @@ static inline struct sock *__udp4_lib_lookup_skb(struct sk_buff *skb,
inet_sdif(skb), udptable, skb);
}
-struct sock *udp4_lib_lookup_skb(struct sk_buff *skb,
+struct sock *udp4_lib_lookup_skb(const struct sk_buff *skb,
__be16 sport, __be16 dport)
{
return __udp4_lib_lookup_skb(skb, sport, dport, &udp_table);
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 976f30391356..e9aa4db3ba53 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -56,7 +56,7 @@
#include <trace/events/skb.h>
#include "udp_impl.h"
-static bool udp6_lib_exact_dif_match(struct net *net, struct sk_buff *skb)
+static bool udp6_lib_exact_dif_match(struct net *net, const struct sk_buff *skb)
{
#if defined(CONFIG_NET_L3_MASTER_DEV)
if (!net->ipv4.sysctl_udp_l3mdev_accept &&
@@ -181,7 +181,7 @@ static struct sock *udp6_lib_lookup2(struct net *net,
const struct in6_addr *saddr, __be16 sport,
const struct in6_addr *daddr, unsigned int hnum,
int dif, int sdif, bool exact_dif,
- struct udp_hslot *hslot2, struct sk_buff *skb)
+ struct udp_hslot *hslot2, const struct sk_buff *skb)
{
struct sock *sk, *result;
int score, badness, matches = 0, reuseport = 0;
@@ -221,7 +221,7 @@ struct sock *__udp6_lib_lookup(struct net *net,
const struct in6_addr *saddr, __be16 sport,
const struct in6_addr *daddr, __be16 dport,
int dif, int sdif, struct udp_table *udptable,
- struct sk_buff *skb)
+ const struct sk_buff *skb)
{
struct sock *sk, *result;
unsigned short hnum = ntohs(dport);
@@ -290,7 +290,7 @@ struct sock *__udp6_lib_lookup(struct net *net,
}
EXPORT_SYMBOL_GPL(__udp6_lib_lookup);
-static struct sock *__udp6_lib_lookup_skb(struct sk_buff *skb,
+static struct sock *__udp6_lib_lookup_skb(const struct sk_buff *skb,
__be16 sport, __be16 dport,
struct udp_table *udptable)
{
@@ -301,7 +301,7 @@ static struct sock *__udp6_lib_lookup_skb(struct sk_buff *skb,
inet6_sdif(skb), udptable, skb);
}
-struct sock *udp6_lib_lookup_skb(struct sk_buff *skb,
+struct sock *udp6_lib_lookup_skb(const struct sk_buff *skb,
__be16 sport, __be16 dport)
{
const struct ipv6hdr *iph = ipv6_hdr(skb);
--
2.11.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH net-next 3/6] flow_dissector: Add protocol specific flow dissection offload
2017-08-29 17:19 [PATCH net-next 0/6] flow_dissector: Protocol specific flow dissector offload Tom Herbert
2017-08-29 17:19 ` [PATCH net-next 1/6] flow_dissector: Move ETH_P_TEB processing to main switch Tom Herbert
2017-08-29 17:19 ` [PATCH net-next 2/6] udp: Constify skb argument in lookup functions Tom Herbert
@ 2017-08-29 17:19 ` Tom Herbert
2017-08-30 13:46 ` kbuild test robot
2017-08-30 14:10 ` kbuild test robot
2017-08-29 17:19 ` [PATCH net-next 4/6] udp: flow dissector offload Tom Herbert
` (3 subsequent siblings)
6 siblings, 2 replies; 10+ messages in thread
From: Tom Herbert @ 2017-08-29 17:19 UTC (permalink / raw)
To: davem; +Cc: netdev, Tom Herbert
Add offload capability for performing protocol specific flow dissection
(either by EtherType or IP protocol).
Specifically:
- Add flow_dissect to offload callbacks
- Move flow_dissect_ret enum to flow_dissector.h, cleanup names and add a
couple of values
- Create GOTO_BY_RESULT macro to use in the main flow dissector switch to
simplify handling of functions that return flow_dissect_ret enum
- In __skb_flow_dissect, add default case for switch(proto) as well as
switch(ip_proto) that looks up and calls protocol specific flow
dissection
---
include/linux/netdevice.h | 7 +++
include/net/flow_dissector.h | 9 +++
net/core/dev.c | 14 +++++
net/core/flow_dissector.c | 132 +++++++++++++++++++++++++++++++------------
net/ipv4/route.c | 4 +-
5 files changed, 128 insertions(+), 38 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index c5475b37a631..90ccb434e127 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2208,6 +2208,12 @@ struct offload_callbacks {
struct sk_buff **(*gro_receive)(struct sk_buff **head,
struct sk_buff *skb);
int (*gro_complete)(struct sk_buff *skb, int nhoff);
+ enum flow_dissect_ret (*flow_dissect)(const struct sk_buff *skb,
+ struct flow_dissector_key_control *key_control,
+ struct flow_dissector *flow_dissector,
+ void *target_container, void *data,
+ __be16 *p_proto, u8 *p_ip_proto, int *p_nhoff,
+ int *p_hlen, unsigned int flags);
};
struct packet_offload {
@@ -3253,6 +3259,7 @@ struct sk_buff *napi_get_frags(struct napi_struct *napi);
gro_result_t napi_gro_frags(struct napi_struct *napi);
struct packet_offload *gro_find_receive_by_type(__be16 type);
struct packet_offload *gro_find_complete_by_type(__be16 type);
+struct packet_offload *flow_dissect_find_by_type(__be16 type);
static inline void napi_free_frags(struct napi_struct *napi)
{
diff --git a/include/net/flow_dissector.h b/include/net/flow_dissector.h
index e2663e900b0a..ad75bbfd1c9c 100644
--- a/include/net/flow_dissector.h
+++ b/include/net/flow_dissector.h
@@ -19,6 +19,14 @@ struct flow_dissector_key_control {
#define FLOW_DIS_FIRST_FRAG BIT(1)
#define FLOW_DIS_ENCAPSULATION BIT(2)
+enum flow_dissect_ret {
+ FLOW_DISSECT_RET_OUT_GOOD,
+ FLOW_DISSECT_RET_OUT_BAD,
+ FLOW_DISSECT_RET_PROTO_AGAIN,
+ FLOW_DISSECT_RET_IPPROTO_AGAIN,
+ FLOW_DISSECT_RET_CONTINUE,
+};
+
/**
* struct flow_dissector_key_basic:
* @thoff: Transport header offset
@@ -205,6 +213,7 @@ enum flow_dissector_key_id {
#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)
+#define FLOW_DISSECTOR_F_STOP_AT_L4 BIT(4)
struct flow_dissector_key {
enum flow_dissector_key_id key_id;
diff --git a/net/core/dev.c b/net/core/dev.c
index 270b54754821..22ea8daa930c 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4860,6 +4860,20 @@ struct packet_offload *gro_find_receive_by_type(__be16 type)
}
EXPORT_SYMBOL(gro_find_receive_by_type);
+struct packet_offload *flow_dissect_find_by_type(__be16 type)
+{
+ struct list_head *offload_head = &offload_base;
+ struct packet_offload *ptype;
+
+ list_for_each_entry_rcu(ptype, offload_head, list) {
+ if (ptype->type != type || !ptype->callbacks.flow_dissect)
+ continue;
+ return ptype;
+ }
+ return NULL;
+}
+EXPORT_SYMBOL(flow_dissect_find_by_type);
+
struct packet_offload *gro_find_complete_by_type(__be16 type)
{
struct list_head *offload_head = &offload_base;
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index 12302acdb073..6a2cf240069a 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -9,6 +9,7 @@
#include <net/ipv6.h>
#include <net/gre.h>
#include <net/pptp.h>
+#include <net/protocol.h>
#include <linux/igmp.h>
#include <linux/icmp.h>
#include <linux/sctp.h>
@@ -115,12 +116,6 @@ __be32 __skb_flow_get_ports(const struct sk_buff *skb, int thoff, u8 ip_proto,
}
EXPORT_SYMBOL(__skb_flow_get_ports);
-enum flow_dissect_ret {
- FLOW_DISSECT_RET_OUT_GOOD,
- FLOW_DISSECT_RET_OUT_BAD,
- FLOW_DISSECT_RET_OUT_PROTO_AGAIN,
-};
-
static enum flow_dissect_ret
__skb_flow_dissect_mpls(const struct sk_buff *skb,
struct flow_dissector *flow_dissector,
@@ -322,7 +317,7 @@ __skb_flow_dissect_gre(const struct sk_buff *skb,
if (flags & FLOW_DISSECTOR_F_STOP_AT_ENCAP)
return FLOW_DISSECT_RET_OUT_GOOD;
- return FLOW_DISSECT_RET_OUT_PROTO_AGAIN;
+ return FLOW_DISSECT_RET_PROTO_AGAIN;
}
static void
@@ -383,6 +378,27 @@ __skb_flow_dissect_ipv6(const struct sk_buff *skb,
key_ip->ttl = iph->hop_limit;
}
+#define GOTO_BY_RESULT(ret) do { \
+ switch (ret) { \
+ case FLOW_DISSECT_RET_OUT_GOOD: \
+ goto out_good; \
+ case FLOW_DISSECT_RET_PROTO_AGAIN: \
+ goto proto_again; \
+ case FLOW_DISSECT_RET_IPPROTO_AGAIN: \
+ goto ip_proto_again; \
+ case FLOW_DISSECT_RET_OUT_BAD: \
+ default: \
+ goto out_bad; \
+ } \
+} while (0)
+
+#define GOTO_OR_CONT_BY_RESULT(ret) do { \
+ enum flow_dissect_ret __ret = (ret); \
+ \
+ if (__ret != FLOW_DISSECT_RET_CONTINUE) \
+ GOTO_BY_RESULT(__ret); \
+} while (0)
+
/**
* __skb_flow_dissect - extract the flow_keys struct and return it
* @skb: sk_buff to extract the flow from, can be NULL if the rest are specified
@@ -659,15 +675,10 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
case htons(ETH_P_MPLS_UC):
case htons(ETH_P_MPLS_MC):
mpls:
- switch (__skb_flow_dissect_mpls(skb, flow_dissector,
- target_container, data,
- nhoff, hlen)) {
- case FLOW_DISSECT_RET_OUT_GOOD:
- goto out_good;
- case FLOW_DISSECT_RET_OUT_BAD:
- default:
- goto out_bad;
- }
+ GOTO_BY_RESULT(__skb_flow_dissect_mpls(skb, flow_dissector,
+ target_container, data,
+ nhoff, hlen));
+
case htons(ETH_P_FCOE):
if ((hlen - nhoff) < FCOE_HEADER_LEN)
goto out_bad;
@@ -677,32 +688,44 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
case htons(ETH_P_ARP):
case htons(ETH_P_RARP):
- switch (__skb_flow_dissect_arp(skb, flow_dissector,
- target_container, data,
- nhoff, hlen)) {
- case FLOW_DISSECT_RET_OUT_GOOD:
- goto out_good;
- case FLOW_DISSECT_RET_OUT_BAD:
- default:
- goto out_bad;
+ GOTO_BY_RESULT(__skb_flow_dissect_arp(skb, flow_dissector,
+ target_container, data,
+ nhoff, hlen));
+
+ default: {
+ struct packet_offload *ptype;
+ enum flow_dissect_ret ret;
+
+ rcu_read_lock();
+
+ ptype = flow_dissect_find_by_type(proto);
+
+ if (ptype) {
+ ret = ptype->callbacks.flow_dissect(skb, key_control,
+ flow_dissector,
+ target_container,
+ data, &proto, &ip_proto, &nhoff,
+ &hlen, flags);
+ rcu_read_unlock();
+
+ GOTO_BY_RESULT(ret);
+ } else {
+ rcu_read_unlock();
}
- default:
+
goto out_bad;
}
+ }
ip_proto_again:
switch (ip_proto) {
case IPPROTO_GRE:
- switch (__skb_flow_dissect_gre(skb, key_control, flow_dissector,
- target_container, data,
- &proto, &nhoff, &hlen, flags)) {
- case FLOW_DISSECT_RET_OUT_GOOD:
- goto out_good;
- case FLOW_DISSECT_RET_OUT_BAD:
- goto out_bad;
- case FLOW_DISSECT_RET_OUT_PROTO_AGAIN:
- goto proto_again;
- }
+ GOTO_BY_RESULT(__skb_flow_dissect_gre(skb, key_control,
+ flow_dissector,
+ target_container, data,
+ &proto, &nhoff, &hlen,
+ flags));
+
case NEXTHDR_HOP:
case NEXTHDR_ROUTING:
case NEXTHDR_DEST: {
@@ -768,9 +791,43 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
__skb_flow_dissect_tcp(skb, flow_dissector, target_container,
data, nhoff, hlen);
break;
- default:
+ default: {
+ const struct net_offload *ops = NULL;
+
+ if (flags & FLOW_DISSECTOR_F_STOP_AT_L4)
+ break;
+
+ rcu_read_lock();
+
+ switch (proto) {
+ case htons(ETH_P_IP):
+ ops = rcu_dereference(inet_offloads[ip_proto]);
+ break;
+ case htons(ETH_P_IPV6):
+ ops = rcu_dereference(inet6_offloads[ip_proto]);
+ break;
+ default:
+ break;
+ }
+
+ if (ops && ops->callbacks.flow_dissect) {
+ enum flow_dissect_ret ret;
+
+ ret = ops->callbacks.flow_dissect(skb, key_control,
+ flow_dissector,
+ target_container,
+ data, &proto, &ip_proto, &nhoff,
+ &hlen, flags);
+ rcu_read_unlock();
+
+ GOTO_OR_CONT_BY_RESULT(ret);
+ } else {
+ rcu_read_unlock();
+ }
+
break;
}
+ }
if (dissector_uses_key(flow_dissector,
FLOW_DISSECTOR_KEY_PORTS)) {
@@ -935,7 +992,8 @@ static inline u32 ___skb_get_hash(const struct sk_buff *skb,
struct flow_keys *keys, u32 keyval)
{
skb_flow_dissect_flow_keys(skb, keys,
- FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL);
+ FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL |
+ FLOW_DISSECTOR_F_STOP_AT_L4);
return __flow_hash_from_keys(keys, keyval);
}
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 94d4cd2d5ea4..85f12b8e0b7f 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1811,7 +1811,9 @@ int fib_multipath_hash(const struct fib_info *fi, const struct flowi4 *fl4,
case 1:
/* skb is currently provided only when forwarding */
if (skb) {
- unsigned int flag = FLOW_DISSECTOR_F_STOP_AT_ENCAP;
+ unsigned int flag = FLOW_DISSECTOR_F_STOP_AT_ENCAP |
+ FLOW_DISSECTOR_F_STOP_AT_L4;
+;
struct flow_keys keys;
/* short-circuit if we already have L4 hash present */
--
2.11.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* Re: [PATCH net-next 3/6] flow_dissector: Add protocol specific flow dissection offload
2017-08-29 17:19 ` [PATCH net-next 3/6] flow_dissector: Add protocol specific flow dissection offload Tom Herbert
@ 2017-08-30 13:46 ` kbuild test robot
2017-08-30 14:10 ` kbuild test robot
1 sibling, 0 replies; 10+ messages in thread
From: kbuild test robot @ 2017-08-30 13:46 UTC (permalink / raw)
To: Tom Herbert; +Cc: kbuild-all, davem, netdev, Tom Herbert
[-- Attachment #1: Type: text/plain, Size: 5484 bytes --]
Hi Tom,
[auto build test WARNING on net-next/master]
url: https://github.com/0day-ci/linux/commits/Tom-Herbert/flow_dissector-Protocol-specific-flow-dissector-offload/20170830-210709
config: x86_64-randconfig-x006-201735 (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64
All warnings (new ones prefixed by >>):
net//ipv4/route.c: In function 'fib_multipath_hash':
>> net//ipv4/route.c:1817:4: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]
struct flow_keys keys;
^~~~~~
vim +1817 net//ipv4/route.c
79a13159 Peter Nørlund 2015-09-30 1791
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1792 /* if skb is set it will be used and fl4 can be NULL */
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1793 int fib_multipath_hash(const struct fib_info *fi, const struct flowi4 *fl4,
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1794 const struct sk_buff *skb)
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1795 {
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1796 struct net *net = fi->fib_net;
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1797 struct flow_keys hash_keys;
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1798 u32 mhash;
79a13159 Peter Nørlund 2015-09-30 1799
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1800 switch (net->ipv4.sysctl_fib_multipath_hash_policy) {
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1801 case 0:
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1802 memset(&hash_keys, 0, sizeof(hash_keys));
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1803 hash_keys.control.addr_type = FLOW_DISSECTOR_KEY_IPV4_ADDRS;
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1804 if (skb) {
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1805 ip_multipath_l3_keys(skb, &hash_keys);
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1806 } else {
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1807 hash_keys.addrs.v4addrs.src = fl4->saddr;
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1808 hash_keys.addrs.v4addrs.dst = fl4->daddr;
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1809 }
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1810 break;
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1811 case 1:
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1812 /* skb is currently provided only when forwarding */
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1813 if (skb) {
19a7c5ba Tom Herbert 2017-08-29 1814 unsigned int flag = FLOW_DISSECTOR_F_STOP_AT_ENCAP |
19a7c5ba Tom Herbert 2017-08-29 1815 FLOW_DISSECTOR_F_STOP_AT_L4;
19a7c5ba Tom Herbert 2017-08-29 1816 ;
bf4e0a3d Nikolay Aleksandrov 2017-03-16 @1817 struct flow_keys keys;
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1818
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1819 /* short-circuit if we already have L4 hash present */
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1820 if (skb->l4_hash)
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1821 return skb_get_hash_raw(skb) >> 1;
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1822 memset(&hash_keys, 0, sizeof(hash_keys));
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1823 skb_flow_dissect_flow_keys(skb, &keys, flag);
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1824 hash_keys.addrs.v4addrs.src = keys.addrs.v4addrs.src;
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1825 hash_keys.addrs.v4addrs.dst = keys.addrs.v4addrs.dst;
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1826 hash_keys.ports.src = keys.ports.src;
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1827 hash_keys.ports.dst = keys.ports.dst;
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1828 hash_keys.basic.ip_proto = keys.basic.ip_proto;
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1829 } else {
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1830 memset(&hash_keys, 0, sizeof(hash_keys));
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1831 hash_keys.control.addr_type = FLOW_DISSECTOR_KEY_IPV4_ADDRS;
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1832 hash_keys.addrs.v4addrs.src = fl4->saddr;
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1833 hash_keys.addrs.v4addrs.dst = fl4->daddr;
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1834 hash_keys.ports.src = fl4->fl4_sport;
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1835 hash_keys.ports.dst = fl4->fl4_dport;
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1836 hash_keys.basic.ip_proto = fl4->flowi4_proto;
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1837 }
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1838 break;
79a13159 Peter Nørlund 2015-09-30 1839 }
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1840 mhash = flow_hash_from_keys(&hash_keys);
79a13159 Peter Nørlund 2015-09-30 1841
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1842 return mhash >> 1;
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1843 }
bf4e0a3d Nikolay Aleksandrov 2017-03-16 1844 EXPORT_SYMBOL_GPL(fib_multipath_hash);
79a13159 Peter Nørlund 2015-09-30 1845 #endif /* CONFIG_IP_ROUTE_MULTIPATH */
79a13159 Peter Nørlund 2015-09-30 1846
:::::: The code at line 1817 was first introduced by commit
:::::: bf4e0a3db97eb882368fd82980b3b1fa0b5b9778 net: ipv4: add support for ECMP hash policy choice
:::::: TO: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
:::::: CC: David S. Miller <davem@davemloft.net>
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 35395 bytes --]
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [PATCH net-next 3/6] flow_dissector: Add protocol specific flow dissection offload
2017-08-29 17:19 ` [PATCH net-next 3/6] flow_dissector: Add protocol specific flow dissection offload Tom Herbert
2017-08-30 13:46 ` kbuild test robot
@ 2017-08-30 14:10 ` kbuild test robot
1 sibling, 0 replies; 10+ messages in thread
From: kbuild test robot @ 2017-08-30 14:10 UTC (permalink / raw)
To: Tom Herbert; +Cc: kbuild-all, davem, netdev, Tom Herbert
[-- Attachment #1: Type: text/plain, Size: 795 bytes --]
Hi Tom,
[auto build test ERROR on net-next/master]
url: https://github.com/0day-ci/linux/commits/Tom-Herbert/flow_dissector-Protocol-specific-flow-dissector-offload/20170830-210709
config: i386-randconfig-a0-201735 (attached as .config)
compiler: gcc-5 (Debian 5.4.1-2) 5.4.1 20160904
reproduce:
# save the attached .config to linux build tree
make ARCH=i386
All errors (new ones prefixed by >>):
net/core/flow_dissector.o: In function `__skb_flow_dissect':
>> flow_dissector.c:(.text+0xcb3): undefined reference to `inet6_offloads'
>> flow_dissector.c:(.text+0xcc0): undefined reference to `inet_offloads'
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 20768 bytes --]
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH net-next 4/6] udp: flow dissector offload
2017-08-29 17:19 [PATCH net-next 0/6] flow_dissector: Protocol specific flow dissector offload Tom Herbert
` (2 preceding siblings ...)
2017-08-29 17:19 ` [PATCH net-next 3/6] flow_dissector: Add protocol specific flow dissection offload Tom Herbert
@ 2017-08-29 17:19 ` Tom Herbert
2017-08-29 17:19 ` [PATCH net-next 5/6] fou: Support flow dissection Tom Herbert
` (2 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Tom Herbert @ 2017-08-29 17:19 UTC (permalink / raw)
To: davem; +Cc: netdev, Tom Herbert
Add support to perform UDP specific flow dissection. This is
primarily intended for dissecting encapsulated packets in UDP
encapsulation.
This patch adds a flow_dissect offload for UDP4 and UDP6. The backend
function performs a socket lookup and calls the flow_dissect function
if a socket is found.
---
include/linux/udp.h | 8 ++++++++
include/net/udp.h | 8 ++++++++
include/net/udp_tunnel.h | 8 ++++++++
net/ipv4/udp_offload.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
net/ipv4/udp_tunnel.c | 1 +
net/ipv6/udp_offload.c | 13 +++++++++++++
6 files changed, 83 insertions(+)
diff --git a/include/linux/udp.h b/include/linux/udp.h
index eaea63bc79bb..2e90b189ef6a 100644
--- a/include/linux/udp.h
+++ b/include/linux/udp.h
@@ -79,6 +79,14 @@ struct udp_sock {
int (*gro_complete)(struct sock *sk,
struct sk_buff *skb,
int nhoff);
+ /* Flow dissector function for a UDP socket */
+ enum flow_dissect_ret (*flow_dissect)(struct sock *sk,
+ const struct sk_buff *skb,
+ struct flow_dissector_key_control *key_control,
+ struct flow_dissector *flow_dissector,
+ void *target_container, void *data,
+ __be16 *p_proto, u8 *p_ip_proto, int *p_nhoff,
+ int *p_hlen, unsigned int flags);
/* udp_recvmsg try to use this before splicing sk_receive_queue */
struct sk_buff_head reader_queue ____cacheline_aligned_in_smp;
diff --git a/include/net/udp.h b/include/net/udp.h
index f3d1de6f0983..499e4faf8b14 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -174,6 +174,14 @@ struct sk_buff **udp_gro_receive(struct sk_buff **head, struct sk_buff *skb,
struct udphdr *uh, udp_lookup_t lookup);
int udp_gro_complete(struct sk_buff *skb, int nhoff, udp_lookup_t lookup);
+enum flow_dissect_ret udp_flow_dissect(const struct sk_buff *skb,
+ udp_lookup_t lookup,
+ struct flow_dissector_key_control *key_control,
+ struct flow_dissector *flow_dissector,
+ void *target_container, void *data,
+ __be16 *p_proto, u8 *p_ip_proto, int *p_nhoff,
+ int *p_hlen, unsigned int flags);
+
static inline struct udphdr *udp_gro_udphdr(struct sk_buff *skb)
{
struct udphdr *uh;
diff --git a/include/net/udp_tunnel.h b/include/net/udp_tunnel.h
index 10cce0dd4450..b7102e0f41a9 100644
--- a/include/net/udp_tunnel.h
+++ b/include/net/udp_tunnel.h
@@ -69,6 +69,13 @@ typedef struct sk_buff **(*udp_tunnel_gro_receive_t)(struct sock *sk,
struct sk_buff *skb);
typedef int (*udp_tunnel_gro_complete_t)(struct sock *sk, struct sk_buff *skb,
int nhoff);
+typedef enum flow_dissect_ret (*udp_tunnel_flow_dissect_t)(struct sock *sk,
+ const struct sk_buff *skb,
+ struct flow_dissector_key_control *key_control,
+ struct flow_dissector *flow_dissector,
+ void *target_container, void *data,
+ __be16 *p_proto, u8 *p_ip_proto, int *p_nhoff,
+ int *p_hlen, unsigned int flags);
struct udp_tunnel_sock_cfg {
void *sk_user_data; /* user data used by encap_rcv call back */
@@ -78,6 +85,7 @@ struct udp_tunnel_sock_cfg {
udp_tunnel_encap_destroy_t encap_destroy;
udp_tunnel_gro_receive_t gro_receive;
udp_tunnel_gro_complete_t gro_complete;
+ udp_tunnel_flow_dissect_t flow_dissect;
};
/* Setup the given (UDP) sock to receive UDP encapsulated packets */
diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c
index 97658bfc1b58..7f0a7ed4a6f7 100644
--- a/net/ipv4/udp_offload.c
+++ b/net/ipv4/udp_offload.c
@@ -328,11 +328,56 @@ static int udp4_gro_complete(struct sk_buff *skb, int nhoff)
return udp_gro_complete(skb, nhoff, udp4_lib_lookup_skb);
}
+enum flow_dissect_ret udp_flow_dissect(const struct sk_buff *skb,
+ udp_lookup_t lookup,
+ struct flow_dissector_key_control *key_control,
+ struct flow_dissector *flow_dissector,
+ void *target_container, void *data,
+ __be16 *p_proto, u8 *p_ip_proto, int *p_nhoff,
+ int *p_hlen, unsigned int flags)
+{
+ enum flow_dissect_ret ret = FLOW_DISSECT_RET_CONTINUE;
+ struct udphdr *uh, _uh;
+ struct sock *sk;
+
+ uh = __skb_header_pointer(skb, *p_nhoff, sizeof(_uh), data,
+ *p_hlen, &_uh);
+ if (!uh)
+ return FLOW_DISSECT_RET_OUT_BAD;
+
+ rcu_read_lock();
+
+ sk = (*lookup)(skb, uh->source, uh->dest);
+
+ if (sk && udp_sk(sk)->flow_dissect)
+ ret = udp_sk(sk)->flow_dissect(sk, skb, key_control,
+ flow_dissector, target_container,
+ data, p_proto, p_ip_proto,
+ p_nhoff, p_hlen, flags);
+ rcu_read_unlock();
+
+ return ret;
+}
+EXPORT_SYMBOL(udp_flow_dissect);
+
+static enum flow_dissect_ret udp4_flow_dissect(const struct sk_buff *skb,
+ struct flow_dissector_key_control *key_control,
+ struct flow_dissector *flow_dissector,
+ void *target_container, void *data,
+ __be16 *p_proto, u8 *p_ip_proto, int *p_nhoff,
+ int *p_hlen, unsigned int flags)
+{
+ return udp_flow_dissect(skb, udp4_lib_lookup_skb, key_control,
+ flow_dissector, target_container, data,
+ p_proto, p_ip_proto, p_nhoff, p_hlen, flags);
+}
+
static const struct net_offload udpv4_offload = {
.callbacks = {
.gso_segment = udp4_tunnel_segment,
.gro_receive = udp4_gro_receive,
.gro_complete = udp4_gro_complete,
+ .flow_dissect = udp4_flow_dissect,
},
};
diff --git a/net/ipv4/udp_tunnel.c b/net/ipv4/udp_tunnel.c
index 6539ff15e9a3..a4eec2a044d2 100644
--- a/net/ipv4/udp_tunnel.c
+++ b/net/ipv4/udp_tunnel.c
@@ -71,6 +71,7 @@ void setup_udp_tunnel_sock(struct net *net, struct socket *sock,
udp_sk(sk)->encap_destroy = cfg->encap_destroy;
udp_sk(sk)->gro_receive = cfg->gro_receive;
udp_sk(sk)->gro_complete = cfg->gro_complete;
+ udp_sk(sk)->flow_dissect = cfg->flow_dissect;
udp_tunnel_encap_enable(sock);
}
diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c
index 455fd4e39333..99ade504eaf7 100644
--- a/net/ipv6/udp_offload.c
+++ b/net/ipv6/udp_offload.c
@@ -73,11 +73,24 @@ static int udp6_gro_complete(struct sk_buff *skb, int nhoff)
return udp_gro_complete(skb, nhoff, udp6_lib_lookup_skb);
}
+static enum flow_dissect_ret udp6_flow_dissect(const struct sk_buff *skb,
+ struct flow_dissector_key_control *key_control,
+ struct flow_dissector *flow_dissector,
+ void *target_container, void *data,
+ __be16 *p_proto, u8 *p_ip_proto, int *p_nhoff,
+ int *p_hlen, unsigned int flags)
+{
+ return udp_flow_dissect(skb, udp6_lib_lookup_skb, key_control,
+ flow_dissector, target_container, data,
+ p_proto, p_ip_proto, p_nhoff, p_hlen, flags);
+}
+
static const struct net_offload udpv6_offload = {
.callbacks = {
.gso_segment = udp6_tunnel_segment,
.gro_receive = udp6_gro_receive,
.gro_complete = udp6_gro_complete,
+ .flow_dissect = udp6_flow_dissect,
},
};
--
2.11.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH net-next 5/6] fou: Support flow dissection
2017-08-29 17:19 [PATCH net-next 0/6] flow_dissector: Protocol specific flow dissector offload Tom Herbert
` (3 preceding siblings ...)
2017-08-29 17:19 ` [PATCH net-next 4/6] udp: flow dissector offload Tom Herbert
@ 2017-08-29 17:19 ` Tom Herbert
2017-08-29 17:19 ` [PATCH net-next 6/6] vxlan: support flow dissect Tom Herbert
2017-08-29 22:34 ` [PATCH net-next 0/6] flow_dissector: Protocol specific flow dissector offload David Miller
6 siblings, 0 replies; 10+ messages in thread
From: Tom Herbert @ 2017-08-29 17:19 UTC (permalink / raw)
To: davem; +Cc: netdev, Tom Herbert
Populate offload flow_dissect callabck appropriately for fou and gue.
---
net/ipv4/fou.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 63 insertions(+)
diff --git a/net/ipv4/fou.c b/net/ipv4/fou.c
index 1540db65241a..a831dd49fb28 100644
--- a/net/ipv4/fou.c
+++ b/net/ipv4/fou.c
@@ -282,6 +282,20 @@ static int fou_gro_complete(struct sock *sk, struct sk_buff *skb,
return err;
}
+static enum flow_dissect_ret fou_flow_dissect(struct sock *sk,
+ const struct sk_buff *skb,
+ struct flow_dissector_key_control *key_control,
+ struct flow_dissector *flow_dissector,
+ void *target_container, void *data,
+ __be16 *p_proto, u8 *p_ip_proto, int *p_nhoff,
+ int *p_hlen, unsigned int flags)
+{
+ *p_ip_proto = fou_from_sock(sk)->protocol;
+ *p_nhoff += sizeof(struct udphdr);
+
+ return FLOW_DISSECT_RET_IPPROTO_AGAIN;
+}
+
static struct guehdr *gue_gro_remcsum(struct sk_buff *skb, unsigned int off,
struct guehdr *guehdr, void *data,
size_t hdrlen, struct gro_remcsum *grc,
@@ -500,6 +514,53 @@ static int gue_gro_complete(struct sock *sk, struct sk_buff *skb, int nhoff)
return err;
}
+static enum flow_dissect_ret gue_flow_dissect(struct sock *sk,
+ const struct sk_buff *skb,
+ struct flow_dissector_key_control *key_control,
+ struct flow_dissector *flow_dissector,
+ void *target_container, void *data,
+ __be16 *p_proto, u8 *p_ip_proto, int *p_nhoff,
+ int *p_hlen, unsigned int flags)
+{
+ struct guehdr *guehdr, _guehdr;
+
+ guehdr = __skb_header_pointer(skb, *p_nhoff + sizeof(struct udphdr),
+ sizeof(_guehdr), data, *p_hlen, &_guehdr);
+ if (!guehdr)
+ return FLOW_DISSECT_RET_OUT_BAD;
+
+ switch (guehdr->version) {
+ case 0:
+ if (unlikely(guehdr->control))
+ return FLOW_DISSECT_RET_CONTINUE;
+
+ *p_ip_proto = guehdr->proto_ctype;
+ *p_nhoff += sizeof(struct udphdr) +
+ sizeof(*guehdr) + (guehdr->hlen << 2);
+
+ break;
+ case 1:
+ switch (((struct iphdr *)guehdr)->version) {
+ case 4:
+ *p_ip_proto = IPPROTO_IPIP;
+ break;
+ case 6:
+ *p_ip_proto = IPPROTO_IPV6;
+ break;
+ default:
+ return FLOW_DISSECT_RET_CONTINUE;
+ }
+
+ *p_nhoff += sizeof(struct udphdr);
+
+ break;
+ default:
+ return FLOW_DISSECT_RET_CONTINUE;
+ }
+
+ return FLOW_DISSECT_RET_IPPROTO_AGAIN;
+}
+
static int fou_add_to_port_list(struct net *net, struct fou *fou)
{
struct fou_net *fn = net_generic(net, fou_net_id);
@@ -570,12 +631,14 @@ static int fou_create(struct net *net, struct fou_cfg *cfg,
tunnel_cfg.encap_rcv = fou_udp_recv;
tunnel_cfg.gro_receive = fou_gro_receive;
tunnel_cfg.gro_complete = fou_gro_complete;
+ tunnel_cfg.flow_dissect = fou_flow_dissect;
fou->protocol = cfg->protocol;
break;
case FOU_ENCAP_GUE:
tunnel_cfg.encap_rcv = gue_udp_recv;
tunnel_cfg.gro_receive = gue_gro_receive;
tunnel_cfg.gro_complete = gue_gro_complete;
+ tunnel_cfg.flow_dissect = gue_flow_dissect;
break;
default:
err = -EINVAL;
--
2.11.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH net-next 6/6] vxlan: support flow dissect
2017-08-29 17:19 [PATCH net-next 0/6] flow_dissector: Protocol specific flow dissector offload Tom Herbert
` (4 preceding siblings ...)
2017-08-29 17:19 ` [PATCH net-next 5/6] fou: Support flow dissection Tom Herbert
@ 2017-08-29 17:19 ` Tom Herbert
2017-08-29 22:34 ` [PATCH net-next 0/6] flow_dissector: Protocol specific flow dissector offload David Miller
6 siblings, 0 replies; 10+ messages in thread
From: Tom Herbert @ 2017-08-29 17:19 UTC (permalink / raw)
To: davem; +Cc: netdev, Tom Herbert
Populate offload flow_dissect callback appropriately for VXLAN and
VXLAN-GPE.
---
drivers/net/vxlan.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 50 insertions(+)
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index ae3a1da703c2..41e50de40af4 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -1336,6 +1336,55 @@ static bool vxlan_ecn_decapsulate(struct vxlan_sock *vs, void *oiph,
return err <= 1;
}
+static enum flow_dissect_ret vxlan_flow_dissect(struct sock *sk,
+ const struct sk_buff *skb,
+ struct flow_dissector_key_control *key_control,
+ struct flow_dissector *flow_dissector,
+ void *target_container, void *data,
+ __be16 *p_proto, u8 *p_ip_proto, int *p_nhoff,
+ int *p_hlen, unsigned int flags)
+{
+ __be16 protocol = htons(ETH_P_TEB);
+ struct vxlanhdr *vhdr, _vhdr;
+ struct vxlan_sock *vs;
+
+ vhdr = __skb_header_pointer(skb, *p_nhoff + sizeof(struct udphdr),
+ sizeof(_vhdr), data, *p_hlen, &_vhdr);
+ if (!vhdr)
+ return FLOW_DISSECT_RET_OUT_BAD;
+
+ vs = rcu_dereference_sk_user_data(sk);
+ if (!vs)
+ return FLOW_DISSECT_RET_OUT_BAD;
+
+ if (vs->flags & VXLAN_F_GPE) {
+ struct vxlanhdr_gpe *gpe = (struct vxlanhdr_gpe *)vhdr;
+
+ /* Need to have Next Protocol set for interfaces in GPE mode. */
+ if (gpe->version != 0 || !gpe->np_applied || gpe->oam_flag)
+ return FLOW_DISSECT_RET_CONTINUE;
+
+ switch (gpe->next_protocol) {
+ case VXLAN_GPE_NP_IPV4:
+ protocol = htons(ETH_P_IP);
+ break;
+ case VXLAN_GPE_NP_IPV6:
+ protocol = htons(ETH_P_IPV6);
+ break;
+ case VXLAN_GPE_NP_ETHERNET:
+ protocol = htons(ETH_P_TEB);
+ break;
+ default:
+ return FLOW_DISSECT_RET_CONTINUE;
+ }
+ }
+
+ *p_nhoff += sizeof(struct udphdr) + sizeof(_vhdr);
+ *p_proto = protocol;
+
+ return FLOW_DISSECT_RET_PROTO_AGAIN;
+}
+
/* Callback from net/ipv4/udp.c to receive packets */
static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
{
@@ -2864,6 +2913,7 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, bool ipv6,
tunnel_cfg.encap_destroy = NULL;
tunnel_cfg.gro_receive = vxlan_gro_receive;
tunnel_cfg.gro_complete = vxlan_gro_complete;
+ tunnel_cfg.flow_dissect = vxlan_flow_dissect;
setup_udp_tunnel_sock(net, sock, &tunnel_cfg);
--
2.11.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* Re: [PATCH net-next 0/6] flow_dissector: Protocol specific flow dissector offload
2017-08-29 17:19 [PATCH net-next 0/6] flow_dissector: Protocol specific flow dissector offload Tom Herbert
` (5 preceding siblings ...)
2017-08-29 17:19 ` [PATCH net-next 6/6] vxlan: support flow dissect Tom Herbert
@ 2017-08-29 22:34 ` David Miller
6 siblings, 0 replies; 10+ messages in thread
From: David Miller @ 2017-08-29 22:34 UTC (permalink / raw)
To: tom; +Cc: netdev
Please add proper signoffs to your patches.
Thanks.
^ permalink raw reply [flat|nested] 10+ messages in thread