Skip to content

Commit 06635a3

Browse files
jpirkodavem330
authored andcommitted
flow_dissect: use programable dissector in skb_flow_dissect and friends
Signed-off-by: Jiri Pirko <jiri@resnulli.us> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent fbff949 commit 06635a3

File tree

12 files changed

+229
-146
lines changed

12 files changed

+229
-146
lines changed

drivers/net/bonding/bond_main.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -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: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -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.port16[0]);
39+
data.u.ipv4.dst_port = ntohs(keys->ports.port16[1]);
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.port16[0];
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.port16[1];
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/skbuff.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1935,8 +1935,8 @@ static inline void skb_probe_transport_header(struct sk_buff *skb,
19351935

19361936
if (skb_transport_header_was_set(skb))
19371937
return;
1938-
else if (skb_flow_dissect(skb, &keys))
1939-
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);
19401940
else
19411941
skb_set_transport_header(skb, offset_hint);
19421942
}

include/net/flow_dissector.h

Lines changed: 34 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -59,42 +59,47 @@ struct flow_dissector {
5959
unsigned short int offset[FLOW_DISSECTOR_KEY_MAX];
6060
};
6161

62-
/* struct flow_keys:
63-
* @src: source ip address in case of IPv4
64-
* For IPv6 it contains 32bit hash of src address
65-
* @dst: destination ip address in case of IPv4
66-
* For IPv6 it contains 32bit hash of dst address
67-
* @ports: port numbers of Transport header
68-
* port16[0]: src port number
69-
* port16[1]: dst port number
70-
* @thoff: Transport header offset
71-
* @n_proto: Network header protocol (eg. IPv4/IPv6)
72-
* @ip_proto: Transport header protocol (eg. TCP/UDP)
73-
* All the members, except thoff, are in network byte order.
74-
*/
75-
struct flow_keys {
76-
/* (src,dst) must be grouped, in the same way than in IP header */
77-
__be32 src;
78-
__be32 dst;
79-
union {
80-
__be32 ports;
81-
__be16 port16[2];
82-
};
83-
u16 thoff;
84-
__be16 n_proto;
85-
u8 ip_proto;
86-
};
87-
8862
void skb_flow_dissector_init(struct flow_dissector *flow_dissector,
8963
const struct flow_dissector_key *key,
9064
unsigned int key_count);
91-
bool __skb_flow_dissect(const struct sk_buff *skb, struct flow_keys *flow,
65+
66+
bool __skb_flow_dissect(const struct sk_buff *skb,
67+
struct flow_dissector *flow_dissector,
68+
void *target_container,
9269
void *data, __be16 proto, int nhoff, int hlen);
9370

9471
static inline bool skb_flow_dissect(const struct sk_buff *skb,
95-
struct flow_keys *flow)
72+
struct flow_dissector *flow_dissector,
73+
void *target_container)
74+
{
75+
return __skb_flow_dissect(skb, flow_dissector, target_container,
76+
NULL, 0, 0, 0);
77+
}
78+
79+
struct flow_keys {
80+
struct flow_dissector_key_addrs addrs;
81+
struct flow_dissector_key_ports ports;
82+
struct flow_dissector_key_basic basic;
83+
};
84+
85+
extern struct flow_dissector flow_keys_dissector;
86+
extern struct flow_dissector flow_keys_buf_dissector;
87+
88+
static inline bool skb_flow_dissect_flow_keys(const struct sk_buff *skb,
89+
struct flow_keys *flow)
90+
{
91+
memset(flow, 0, sizeof(*flow));
92+
return __skb_flow_dissect(skb, &flow_keys_dissector, flow,
93+
NULL, 0, 0, 0);
94+
}
95+
96+
static inline bool skb_flow_dissect_flow_keys_buf(struct flow_keys *flow,
97+
void *data, __be16 proto,
98+
int nhoff, int hlen)
9699
{
97-
return __skb_flow_dissect(skb, flow, NULL, 0, 0, 0);
100+
memset(flow, 0, sizeof(*flow));
101+
return __skb_flow_dissect(NULL, &flow_keys_buf_dissector, flow,
102+
data, proto, nhoff, hlen);
98103
}
99104

100105
__be32 __skb_flow_get_ports(const struct sk_buff *skb, int thoff, u8 ip_proto,

include/net/ip.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -360,10 +360,10 @@ static inline void inet_set_txhash(struct sock *sk)
360360
struct inet_sock *inet = inet_sk(sk);
361361
struct flow_keys keys;
362362

363-
keys.src = inet->inet_saddr;
364-
keys.dst = inet->inet_daddr;
365-
keys.port16[0] = inet->inet_sport;
366-
keys.port16[1] = inet->inet_dport;
363+
keys.addrs.src = inet->inet_saddr;
364+
keys.addrs.dst = inet->inet_daddr;
365+
keys.ports.port16[0] = inet->inet_sport;
366+
keys.ports.port16[1] = inet->inet_dport;
367367

368368
sk->sk_txhash = flow_hash_from_keys(&keys);
369369
}

include/net/ipv6.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -698,10 +698,10 @@ static inline void ip6_set_txhash(struct sock *sk)
698698
struct ipv6_pinfo *np = inet6_sk(sk);
699699
struct flow_keys keys;
700700

701-
keys.src = (__force __be32)ipv6_addr_hash(&np->saddr);
702-
keys.dst = (__force __be32)ipv6_addr_hash(&sk->sk_v6_daddr);
703-
keys.port16[0] = inet->inet_sport;
704-
keys.port16[1] = inet->inet_dport;
701+
keys.addrs.src = (__force __be32)ipv6_addr_hash(&np->saddr);
702+
keys.addrs.dst = (__force __be32)ipv6_addr_hash(&sk->sk_v6_daddr);
703+
keys.ports.port16[0] = inet->inet_sport;
704+
keys.ports.port16[1] = inet->inet_dport;
705705

706706
sk->sk_txhash = flow_hash_from_keys(&keys);
707707
}

0 commit comments

Comments
 (0)