Skip to content

Commit fbff949

Browse files
jpirkodavem330
authored andcommitted
flow_dissector: introduce programable flow_dissector
Introduce dissector infrastructure which allows user to specify which parts of skb he wants to dissect. Signed-off-by: Jiri Pirko <jiri@resnulli.us> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 0db89b8 commit fbff949

File tree

2 files changed

+109
-0
lines changed

2 files changed

+109
-0
lines changed

include/net/flow_dissector.h

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,64 @@
11
#ifndef _NET_FLOW_DISSECTOR_H
22
#define _NET_FLOW_DISSECTOR_H
33

4+
/**
5+
* struct flow_dissector_key_basic:
6+
* @thoff: Transport header offset
7+
* @n_proto: Network header protocol (eg. IPv4/IPv6)
8+
* @ip_proto: Transport header protocol (eg. TCP/UDP)
9+
*/
10+
struct flow_dissector_key_basic {
11+
u16 thoff;
12+
__be16 n_proto;
13+
u8 ip_proto;
14+
};
15+
16+
/**
17+
* struct flow_dissector_key_addrs:
18+
* @src: source ip address in case of IPv4
19+
* For IPv6 it contains 32bit hash of src address
20+
* @dst: destination ip address in case of IPv4
21+
* For IPv6 it contains 32bit hash of dst address
22+
*/
23+
struct flow_dissector_key_addrs {
24+
/* (src,dst) must be grouped, in the same way than in IP header */
25+
__be32 src;
26+
__be32 dst;
27+
};
28+
29+
/**
30+
* flow_dissector_key_tp_ports:
31+
* @ports: port numbers of Transport header
32+
* port16[0]: src port number
33+
* port16[1]: dst port number
34+
*/
35+
struct flow_dissector_key_ports {
36+
union {
37+
__be32 ports;
38+
__be16 port16[2];
39+
};
40+
};
41+
42+
enum flow_dissector_key_id {
43+
FLOW_DISSECTOR_KEY_BASIC, /* struct flow_dissector_key_basic */
44+
FLOW_DISSECTOR_KEY_IPV4_ADDRS, /* struct flow_dissector_key_addrs */
45+
FLOW_DISSECTOR_KEY_IPV6_HASH_ADDRS, /* struct flow_dissector_key_addrs */
46+
FLOW_DISSECTOR_KEY_PORTS, /* struct flow_dissector_key_ports */
47+
48+
FLOW_DISSECTOR_KEY_MAX,
49+
};
50+
51+
struct flow_dissector_key {
52+
enum flow_dissector_key_id key_id;
53+
size_t offset; /* offset of struct flow_dissector_key_*
54+
in target the struct */
55+
};
56+
57+
struct flow_dissector {
58+
unsigned int used_keys; /* each bit repesents presence of one key id */
59+
unsigned short int offset[FLOW_DISSECTOR_KEY_MAX];
60+
};
61+
462
/* struct flow_keys:
563
* @src: source ip address in case of IPv4
664
* For IPv6 it contains 32bit hash of src address
@@ -27,6 +85,9 @@ struct flow_keys {
2785
u8 ip_proto;
2886
};
2987

88+
void skb_flow_dissector_init(struct flow_dissector *flow_dissector,
89+
const struct flow_dissector_key *key,
90+
unsigned int key_count);
3091
bool __skb_flow_dissect(const struct sk_buff *skb, struct flow_keys *flow,
3192
void *data, __be16 proto, int nhoff, int hlen);
3293

net/core/flow_dissector.c

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#include <linux/kernel.h>
12
#include <linux/skbuff.h>
23
#include <linux/export.h>
34
#include <linux/ip.h>
@@ -15,6 +16,53 @@
1516
#include <net/flow_dissector.h>
1617
#include <scsi/fc/fc_fcoe.h>
1718

19+
static bool skb_flow_dissector_uses_key(struct flow_dissector *flow_dissector,
20+
enum flow_dissector_key_id key_id)
21+
{
22+
return flow_dissector->used_keys & (1 << key_id);
23+
}
24+
25+
static void skb_flow_dissector_set_key(struct flow_dissector *flow_dissector,
26+
enum flow_dissector_key_id key_id)
27+
{
28+
flow_dissector->used_keys |= (1 << key_id);
29+
}
30+
31+
static void *skb_flow_dissector_target(struct flow_dissector *flow_dissector,
32+
enum flow_dissector_key_id key_id,
33+
void *target_container)
34+
{
35+
return ((char *) target_container) + flow_dissector->offset[key_id];
36+
}
37+
38+
void skb_flow_dissector_init(struct flow_dissector *flow_dissector,
39+
const struct flow_dissector_key *key,
40+
unsigned int key_count)
41+
{
42+
unsigned int i;
43+
44+
memset(flow_dissector, 0, sizeof(*flow_dissector));
45+
46+
for (i = 0; i < key_count; i++, key++) {
47+
/* User should make sure that every key target offset is withing
48+
* boundaries of unsigned short.
49+
*/
50+
BUG_ON(key->offset > USHRT_MAX);
51+
BUG_ON(skb_flow_dissector_uses_key(flow_dissector,
52+
key->key_id));
53+
54+
skb_flow_dissector_set_key(flow_dissector, key->key_id);
55+
flow_dissector->offset[key->key_id] = key->offset;
56+
}
57+
58+
/* Ensure that the dissector always includes basic key. That way
59+
* we are able to avoid handling lack of it in fast path.
60+
*/
61+
BUG_ON(!skb_flow_dissector_uses_key(flow_dissector,
62+
FLOW_DISSECTOR_KEY_BASIC));
63+
}
64+
EXPORT_SYMBOL(skb_flow_dissector_init);
65+
1866
/* copy saddr & daddr, possibly using 64bit load/store
1967
* Equivalent to : flow->src = iph->saddr;
2068
* flow->dst = iph->daddr;

0 commit comments

Comments
 (0)