Skip to content

Commit dd58c63

Browse files
committed
Merge branch 'cls_flower'
Jiri Pirko says: ==================== introduce programable flow dissector and cls_flower Per Davem's request, I prepared this patchset which introduces programmable flow dissector. For current users of flow_keys, there is a wrapper skb_flow_dissect_flow_keys which maintains the previous behaviour. For purposes of cls_flower, couple of new dissection keys were introduced. Note that this dissector can be also eventually used by openvswitch code. Also, as a next step, I plan to get rid of *skb_flow_get_ports(export) and *__skb_get_poff as their functionality can be now implemented by skb_flow_dissect as well. v2->v3: - remove TCA_FLOWER_POLICE attr suggested by Jamal v1->v2: - move __skb_tx_hash rather to dev.c as suggested by Alex ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 212da1f + 77b9900 commit dd58c63

File tree

20 files changed

+1285
-298
lines changed

20 files changed

+1285
-298
lines changed

drivers/net/bonding/bond_main.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@
7676
#include <net/netns/generic.h>
7777
#include <net/pkt_sched.h>
7878
#include <linux/rculist.h>
79-
#include <net/flow_keys.h>
79+
#include <net/flow_dissector.h>
8080
#include <net/switchdev.h>
8181
#include <net/bonding.h>
8282
#include <net/bond_3ad.h>
@@ -3051,32 +3051,32 @@ static bool bond_flow_dissect(struct bonding *bond, struct sk_buff *skb,
30513051
int noff, proto = -1;
30523052

30533053
if (bond->params.xmit_policy > BOND_XMIT_POLICY_LAYER23)
3054-
return skb_flow_dissect(skb, fk);
3054+
return skb_flow_dissect_flow_keys(skb, fk);
30553055

3056-
fk->ports = 0;
3056+
fk->ports.ports = 0;
30573057
noff = skb_network_offset(skb);
30583058
if (skb->protocol == htons(ETH_P_IP)) {
30593059
if (unlikely(!pskb_may_pull(skb, noff + sizeof(*iph))))
30603060
return false;
30613061
iph = ip_hdr(skb);
3062-
fk->src = iph->saddr;
3063-
fk->dst = iph->daddr;
3062+
fk->addrs.src = iph->saddr;
3063+
fk->addrs.dst = iph->daddr;
30643064
noff += iph->ihl << 2;
30653065
if (!ip_is_fragment(iph))
30663066
proto = iph->protocol;
30673067
} else if (skb->protocol == htons(ETH_P_IPV6)) {
30683068
if (unlikely(!pskb_may_pull(skb, noff + sizeof(*iph6))))
30693069
return false;
30703070
iph6 = ipv6_hdr(skb);
3071-
fk->src = (__force __be32)ipv6_addr_hash(&iph6->saddr);
3072-
fk->dst = (__force __be32)ipv6_addr_hash(&iph6->daddr);
3071+
fk->addrs.src = (__force __be32)ipv6_addr_hash(&iph6->saddr);
3072+
fk->addrs.dst = (__force __be32)ipv6_addr_hash(&iph6->daddr);
30733073
noff += sizeof(*iph6);
30743074
proto = iph6->nexthdr;
30753075
} else {
30763076
return false;
30773077
}
30783078
if (bond->params.xmit_policy == BOND_XMIT_POLICY_LAYER34 && proto >= 0)
3079-
fk->ports = skb_flow_get_ports(skb, noff, proto);
3079+
fk->ports.ports = skb_flow_get_ports(skb, noff, proto);
30803080

30813081
return true;
30823082
}
@@ -3102,8 +3102,8 @@ u32 bond_xmit_hash(struct bonding *bond, struct sk_buff *skb)
31023102
bond->params.xmit_policy == BOND_XMIT_POLICY_ENCAP23)
31033103
hash = bond_eth_hash(skb);
31043104
else
3105-
hash = (__force u32)flow.ports;
3106-
hash ^= (__force u32)flow.dst ^ (__force u32)flow.src;
3105+
hash = (__force u32)flow.ports.ports;
3106+
hash ^= (__force u32)flow.addrs.dst ^ (__force u32)flow.addrs.src;
31073107
hash ^= (hash >> 16);
31083108
hash ^= (hash >> 8);
31093109

drivers/net/ethernet/cisco/enic/enic_clsf.c

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#include <linux/in.h>
66
#include <linux/types.h>
77
#include <linux/skbuff.h>
8-
#include <net/flow_keys.h>
8+
#include <net/flow_dissector.h>
99
#include "enic_res.h"
1010
#include "enic_clsf.h"
1111

@@ -22,7 +22,7 @@ int enic_addfltr_5t(struct enic *enic, struct flow_keys *keys, u16 rq)
2222
int res;
2323
struct filter data;
2424

25-
switch (keys->ip_proto) {
25+
switch (keys->basic.ip_proto) {
2626
case IPPROTO_TCP:
2727
data.u.ipv4.protocol = PROTO_TCP;
2828
break;
@@ -33,10 +33,10 @@ int enic_addfltr_5t(struct enic *enic, struct flow_keys *keys, u16 rq)
3333
return -EPROTONOSUPPORT;
3434
};
3535
data.type = FILTER_IPV4_5TUPLE;
36-
data.u.ipv4.src_addr = ntohl(keys->src);
37-
data.u.ipv4.dst_addr = ntohl(keys->dst);
38-
data.u.ipv4.src_port = ntohs(keys->port16[0]);
39-
data.u.ipv4.dst_port = ntohs(keys->port16[1]);
36+
data.u.ipv4.src_addr = ntohl(keys->addrs.src);
37+
data.u.ipv4.dst_addr = ntohl(keys->addrs.dst);
38+
data.u.ipv4.src_port = ntohs(keys->ports.src);
39+
data.u.ipv4.dst_port = ntohs(keys->ports.dst);
4040
data.u.ipv4.flags = FILTER_FIELDS_IPV4_5TUPLE;
4141

4242
spin_lock_bh(&enic->devcmd_lock);
@@ -158,11 +158,11 @@ static struct enic_rfs_fltr_node *htbl_key_search(struct hlist_head *h,
158158
struct enic_rfs_fltr_node *tpos;
159159

160160
hlist_for_each_entry(tpos, h, node)
161-
if (tpos->keys.src == k->src &&
162-
tpos->keys.dst == k->dst &&
163-
tpos->keys.ports == k->ports &&
164-
tpos->keys.ip_proto == k->ip_proto &&
165-
tpos->keys.n_proto == k->n_proto)
161+
if (tpos->keys.addrs.src == k->addrs.src &&
162+
tpos->keys.addrs.dst == k->addrs.dst &&
163+
tpos->keys.ports.ports == k->ports.ports &&
164+
tpos->keys.basic.ip_proto == k->basic.ip_proto &&
165+
tpos->keys.basic.n_proto == k->basic.n_proto)
166166
return tpos;
167167
return NULL;
168168
}
@@ -177,9 +177,10 @@ int enic_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb,
177177
int res, i;
178178

179179
enic = netdev_priv(dev);
180-
res = skb_flow_dissect(skb, &keys);
181-
if (!res || keys.n_proto != htons(ETH_P_IP) ||
182-
(keys.ip_proto != IPPROTO_TCP && keys.ip_proto != IPPROTO_UDP))
180+
res = skb_flow_dissect_flow_keys(skb, &keys);
181+
if (!res || keys.basic.n_proto != htons(ETH_P_IP) ||
182+
(keys.basic.ip_proto != IPPROTO_TCP &&
183+
keys.basic.ip_proto != IPPROTO_UDP))
183184
return -EPROTONOSUPPORT;
184185

185186
tbl_idx = skb_get_hash_raw(skb) & ENIC_RFS_FLW_MASK;

drivers/net/ethernet/cisco/enic/enic_ethtool.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ static int enic_grxclsrule(struct enic *enic, struct ethtool_rxnfc *cmd)
334334
n = htbl_fltr_search(enic, (u16)fsp->location);
335335
if (!n)
336336
return -EINVAL;
337-
switch (n->keys.ip_proto) {
337+
switch (n->keys.basic.ip_proto) {
338338
case IPPROTO_TCP:
339339
fsp->flow_type = TCP_V4_FLOW;
340340
break;
@@ -346,16 +346,16 @@ static int enic_grxclsrule(struct enic *enic, struct ethtool_rxnfc *cmd)
346346
break;
347347
}
348348

349-
fsp->h_u.tcp_ip4_spec.ip4src = n->keys.src;
349+
fsp->h_u.tcp_ip4_spec.ip4src = n->keys.addrs.src;
350350
fsp->m_u.tcp_ip4_spec.ip4src = (__u32)~0;
351351

352-
fsp->h_u.tcp_ip4_spec.ip4dst = n->keys.dst;
352+
fsp->h_u.tcp_ip4_spec.ip4dst = n->keys.addrs.dst;
353353
fsp->m_u.tcp_ip4_spec.ip4dst = (__u32)~0;
354354

355-
fsp->h_u.tcp_ip4_spec.psrc = n->keys.port16[0];
355+
fsp->h_u.tcp_ip4_spec.psrc = n->keys.ports.src;
356356
fsp->m_u.tcp_ip4_spec.psrc = (__u16)~0;
357357

358-
fsp->h_u.tcp_ip4_spec.pdst = n->keys.port16[1];
358+
fsp->h_u.tcp_ip4_spec.pdst = n->keys.ports.dst;
359359
fsp->m_u.tcp_ip4_spec.pdst = (__u16)~0;
360360

361361
fsp->ring_cookie = n->rq_id;

drivers/net/hyperv/netvsc_drv.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -196,12 +196,12 @@ static bool netvsc_set_hash(u32 *hash, struct sk_buff *skb)
196196
struct flow_keys flow;
197197
int data_len;
198198

199-
if (!skb_flow_dissect(skb, &flow) ||
200-
!(flow.n_proto == htons(ETH_P_IP) ||
201-
flow.n_proto == htons(ETH_P_IPV6)))
199+
if (!skb_flow_dissect_flow_keys(skb, &flow) ||
200+
!(flow.basic.n_proto == htons(ETH_P_IP) ||
201+
flow.basic.n_proto == htons(ETH_P_IPV6)))
202202
return false;
203203

204-
if (flow.ip_proto == IPPROTO_TCP)
204+
if (flow.basic.ip_proto == IPPROTO_TCP)
205205
data_len = 12;
206206
else
207207
data_len = 8;

include/linux/netdevice.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2832,6 +2832,9 @@ static inline int netif_set_xps_queue(struct net_device *dev,
28322832
}
28332833
#endif
28342834

2835+
u16 __skb_tx_hash(const struct net_device *dev, struct sk_buff *skb,
2836+
unsigned int num_tx_queues);
2837+
28352838
/*
28362839
* Returns a Tx hash for the given packet when dev->real_num_tx_queues is used
28372840
* as a distribution range limit for the returned value.

include/linux/skbuff.h

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
#include <linux/dma-mapping.h>
3535
#include <linux/netdev_features.h>
3636
#include <linux/sched.h>
37-
#include <net/flow_keys.h>
37+
#include <net/flow_dissector.h>
3838

3939
/* A. Checksumming of received packets by device.
4040
*
@@ -918,7 +918,6 @@ skb_set_hash(struct sk_buff *skb, __u32 hash, enum pkt_hash_types type)
918918
skb->hash = hash;
919919
}
920920

921-
void __skb_get_hash(struct sk_buff *skb);
922921
static inline __u32 skb_get_hash(struct sk_buff *skb)
923922
{
924923
if (!skb->l4_hash && !skb->sw_hash)
@@ -1936,8 +1935,8 @@ static inline void skb_probe_transport_header(struct sk_buff *skb,
19361935

19371936
if (skb_transport_header_was_set(skb))
19381937
return;
1939-
else if (skb_flow_dissect(skb, &keys))
1940-
skb_set_transport_header(skb, keys.thoff);
1938+
else if (skb_flow_dissect_flow_keys(skb, &keys))
1939+
skb_set_transport_header(skb, keys.basic.thoff);
19411940
else
19421941
skb_set_transport_header(skb, offset_hint);
19431942
}
@@ -3300,9 +3299,6 @@ static inline bool skb_rx_queue_recorded(const struct sk_buff *skb)
33003299
return skb->queue_mapping != 0;
33013300
}
33023301

3303-
u16 __skb_tx_hash(const struct net_device *dev, struct sk_buff *skb,
3304-
unsigned int num_tx_queues);
3305-
33063302
static inline struct sec_path *skb_sec_path(struct sk_buff *skb)
33073303
{
33083304
#ifdef CONFIG_XFRM
@@ -3424,10 +3420,6 @@ struct sk_buff *skb_checksum_trimmed(struct sk_buff *skb,
34243420
unsigned int transport_len,
34253421
__sum16(*skb_chkf)(struct sk_buff *skb));
34263422

3427-
u32 skb_get_poff(const struct sk_buff *skb);
3428-
u32 __skb_get_poff(const struct sk_buff *skb, void *data,
3429-
const struct flow_keys *keys, int hlen);
3430-
34313423
/**
34323424
* skb_head_is_locked - Determine if the skb->head is locked down
34333425
* @skb: skb to check

include/net/flow_dissector.h

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
#ifndef _NET_FLOW_DISSECTOR_H
2+
#define _NET_FLOW_DISSECTOR_H
3+
4+
#include <linux/types.h>
5+
#include <linux/skbuff.h>
6+
#include <linux/in6.h>
7+
#include <uapi/linux/if_ether.h>
8+
9+
/**
10+
* struct flow_dissector_key_basic:
11+
* @thoff: Transport header offset
12+
* @n_proto: Network header protocol (eg. IPv4/IPv6)
13+
* @ip_proto: Transport header protocol (eg. TCP/UDP)
14+
*/
15+
struct flow_dissector_key_basic {
16+
u16 thoff;
17+
__be16 n_proto;
18+
u8 ip_proto;
19+
};
20+
21+
/**
22+
* struct flow_dissector_key_addrs:
23+
* @src: source ip address in case of IPv4
24+
* For IPv6 it contains 32bit hash of src address
25+
* @dst: destination ip address in case of IPv4
26+
* For IPv6 it contains 32bit hash of dst address
27+
*/
28+
struct flow_dissector_key_addrs {
29+
/* (src,dst) must be grouped, in the same way than in IP header */
30+
__be32 src;
31+
__be32 dst;
32+
};
33+
34+
/**
35+
* flow_dissector_key_tp_ports:
36+
* @ports: port numbers of Transport header
37+
* src: source port number
38+
* dst: destination port number
39+
*/
40+
struct flow_dissector_key_ports {
41+
union {
42+
__be32 ports;
43+
struct {
44+
__be16 src;
45+
__be16 dst;
46+
};
47+
};
48+
};
49+
50+
/**
51+
* struct flow_dissector_key_ipv6_addrs:
52+
* @src: source ip address
53+
* @dst: destination ip address
54+
*/
55+
struct flow_dissector_key_ipv6_addrs {
56+
/* (src,dst) must be grouped, in the same way than in IP header */
57+
struct in6_addr src;
58+
struct in6_addr dst;
59+
};
60+
61+
/**
62+
* struct flow_dissector_key_eth_addrs:
63+
* @src: source Ethernet address
64+
* @dst: destination Ethernet address
65+
*/
66+
struct flow_dissector_key_eth_addrs {
67+
/* (dst,src) must be grouped, in the same way than in ETH header */
68+
unsigned char dst[ETH_ALEN];
69+
unsigned char src[ETH_ALEN];
70+
};
71+
72+
enum flow_dissector_key_id {
73+
FLOW_DISSECTOR_KEY_BASIC, /* struct flow_dissector_key_basic */
74+
FLOW_DISSECTOR_KEY_IPV4_ADDRS, /* struct flow_dissector_key_addrs */
75+
FLOW_DISSECTOR_KEY_IPV6_HASH_ADDRS, /* struct flow_dissector_key_addrs */
76+
FLOW_DISSECTOR_KEY_PORTS, /* struct flow_dissector_key_ports */
77+
FLOW_DISSECTOR_KEY_IPV6_ADDRS, /* struct flow_dissector_key_ipv6_addrs */
78+
FLOW_DISSECTOR_KEY_ETH_ADDRS, /* struct flow_dissector_key_eth_addrs */
79+
80+
FLOW_DISSECTOR_KEY_MAX,
81+
};
82+
83+
struct flow_dissector_key {
84+
enum flow_dissector_key_id key_id;
85+
size_t offset; /* offset of struct flow_dissector_key_*
86+
in target the struct */
87+
};
88+
89+
struct flow_dissector {
90+
unsigned int used_keys; /* each bit repesents presence of one key id */
91+
unsigned short int offset[FLOW_DISSECTOR_KEY_MAX];
92+
};
93+
94+
void skb_flow_dissector_init(struct flow_dissector *flow_dissector,
95+
const struct flow_dissector_key *key,
96+
unsigned int key_count);
97+
98+
bool __skb_flow_dissect(const struct sk_buff *skb,
99+
struct flow_dissector *flow_dissector,
100+
void *target_container,
101+
void *data, __be16 proto, int nhoff, int hlen);
102+
103+
static inline bool skb_flow_dissect(const struct sk_buff *skb,
104+
struct flow_dissector *flow_dissector,
105+
void *target_container)
106+
{
107+
return __skb_flow_dissect(skb, flow_dissector, target_container,
108+
NULL, 0, 0, 0);
109+
}
110+
111+
struct flow_keys {
112+
struct flow_dissector_key_addrs addrs;
113+
struct flow_dissector_key_ports ports;
114+
struct flow_dissector_key_basic basic;
115+
};
116+
117+
extern struct flow_dissector flow_keys_dissector;
118+
extern struct flow_dissector flow_keys_buf_dissector;
119+
120+
static inline bool skb_flow_dissect_flow_keys(const struct sk_buff *skb,
121+
struct flow_keys *flow)
122+
{
123+
memset(flow, 0, sizeof(*flow));
124+
return __skb_flow_dissect(skb, &flow_keys_dissector, flow,
125+
NULL, 0, 0, 0);
126+
}
127+
128+
static inline bool skb_flow_dissect_flow_keys_buf(struct flow_keys *flow,
129+
void *data, __be16 proto,
130+
int nhoff, int hlen)
131+
{
132+
memset(flow, 0, sizeof(*flow));
133+
return __skb_flow_dissect(NULL, &flow_keys_buf_dissector, flow,
134+
data, proto, nhoff, hlen);
135+
}
136+
137+
__be32 __skb_flow_get_ports(const struct sk_buff *skb, int thoff, u8 ip_proto,
138+
void *data, int hlen_proto);
139+
140+
static inline __be32 skb_flow_get_ports(const struct sk_buff *skb,
141+
int thoff, u8 ip_proto)
142+
{
143+
return __skb_flow_get_ports(skb, thoff, ip_proto, NULL, 0);
144+
}
145+
146+
u32 flow_hash_from_keys(struct flow_keys *keys);
147+
void __skb_get_hash(struct sk_buff *skb);
148+
u32 skb_get_poff(const struct sk_buff *skb);
149+
u32 __skb_get_poff(const struct sk_buff *skb, void *data,
150+
const struct flow_keys *keys, int hlen);
151+
152+
/* struct flow_keys_digest:
153+
*
154+
* This structure is used to hold a digest of the full flow keys. This is a
155+
* larger "hash" of a flow to allow definitively matching specific flows where
156+
* the 32 bit skb->hash is not large enough. The size is limited to 16 bytes so
157+
* that it can by used in CB of skb (see sch_choke for an example).
158+
*/
159+
#define FLOW_KEYS_DIGEST_LEN 16
160+
struct flow_keys_digest {
161+
u8 data[FLOW_KEYS_DIGEST_LEN];
162+
};
163+
164+
void make_flow_keys_digest(struct flow_keys_digest *digest,
165+
const struct flow_keys *flow);
166+
167+
#endif

0 commit comments

Comments
 (0)