Skip to content

Commit 72a338b

Browse files
Paolo Abenidavem330
authored andcommitted
net: core: rework basic flow dissection helper
When the core networking needs to detect the transport offset in a given packet and parse it explicitly, a full-blown flow_keys struct is used for storage. This patch introduces a smaller keys store, rework the basic flow dissect helper to use it, and apply this new helper where possible - namely in skb_probe_transport_header(). The used flow dissector data structures are renamed to match more closely the new role. The above gives ~50% performance improvement in micro benchmarking around skb_probe_transport_header() and ~30% around eth_get_headlen(), mostly due to the smaller memset. Small, but measurable improvement is measured also in macro benchmarking. v1 -> v2: use the new helper in eth_get_headlen() and skb_get_poff(), as per DaveM suggestion Suggested-by: David Miller <[email protected]> Signed-off-by: Paolo Abeni <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 62515f9 commit 72a338b

File tree

4 files changed

+28
-20
lines changed

4 files changed

+28
-20
lines changed

include/linux/skbuff.h

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1171,7 +1171,7 @@ void __skb_get_hash(struct sk_buff *skb);
11711171
u32 __skb_get_hash_symmetric(const struct sk_buff *skb);
11721172
u32 skb_get_poff(const struct sk_buff *skb);
11731173
u32 __skb_get_poff(const struct sk_buff *skb, void *data,
1174-
const struct flow_keys *keys, int hlen);
1174+
const struct flow_keys_basic *keys, int hlen);
11751175
__be32 __skb_flow_get_ports(const struct sk_buff *skb, int thoff, u8 ip_proto,
11761176
void *data, int hlen_proto);
11771177

@@ -1208,13 +1208,14 @@ static inline bool skb_flow_dissect_flow_keys(const struct sk_buff *skb,
12081208
NULL, 0, 0, 0, flags);
12091209
}
12101210

1211-
static inline bool skb_flow_dissect_flow_keys_buf(struct flow_keys *flow,
1212-
void *data, __be16 proto,
1213-
int nhoff, int hlen,
1214-
unsigned int flags)
1211+
static inline bool
1212+
skb_flow_dissect_flow_keys_basic(const struct sk_buff *skb,
1213+
struct flow_keys_basic *flow, void *data,
1214+
__be16 proto, int nhoff, int hlen,
1215+
unsigned int flags)
12151216
{
12161217
memset(flow, 0, sizeof(*flow));
1217-
return __skb_flow_dissect(NULL, &flow_keys_buf_dissector, flow,
1218+
return __skb_flow_dissect(skb, &flow_keys_basic_dissector, flow,
12181219
data, proto, nhoff, hlen, flags);
12191220
}
12201221

@@ -2350,11 +2351,12 @@ static inline void skb_pop_mac_header(struct sk_buff *skb)
23502351
static inline void skb_probe_transport_header(struct sk_buff *skb,
23512352
const int offset_hint)
23522353
{
2353-
struct flow_keys keys;
2354+
struct flow_keys_basic keys;
23542355

23552356
if (skb_transport_header_was_set(skb))
23562357
return;
2357-
else if (skb_flow_dissect_flow_keys(skb, &keys, 0))
2358+
2359+
if (skb_flow_dissect_flow_keys_basic(skb, &keys, 0, 0, 0, 0, 0))
23582360
skb_set_transport_header(skb, keys.control.thoff);
23592361
else
23602362
skb_set_transport_header(skb, offset_hint);

include/net/flow_dissector.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,11 @@ struct flow_dissector {
226226
unsigned short int offset[FLOW_DISSECTOR_KEY_MAX];
227227
};
228228

229+
struct flow_keys_basic {
230+
struct flow_dissector_key_control control;
231+
struct flow_dissector_key_basic basic;
232+
};
233+
229234
struct flow_keys {
230235
struct flow_dissector_key_control control;
231236
#define FLOW_KEYS_HASH_START_FIELD basic
@@ -244,7 +249,7 @@ __be32 flow_get_u32_src(const struct flow_keys *flow);
244249
__be32 flow_get_u32_dst(const struct flow_keys *flow);
245250

246251
extern struct flow_dissector flow_keys_dissector;
247-
extern struct flow_dissector flow_keys_buf_dissector;
252+
extern struct flow_dissector flow_keys_basic_dissector;
248253

249254
/* struct flow_keys_digest:
250255
*

net/core/flow_dissector.c

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1253,7 +1253,7 @@ __u32 skb_get_hash_perturb(const struct sk_buff *skb, u32 perturb)
12531253
EXPORT_SYMBOL(skb_get_hash_perturb);
12541254

12551255
u32 __skb_get_poff(const struct sk_buff *skb, void *data,
1256-
const struct flow_keys *keys, int hlen)
1256+
const struct flow_keys_basic *keys, int hlen)
12571257
{
12581258
u32 poff = keys->control.thoff;
12591259

@@ -1314,9 +1314,9 @@ u32 __skb_get_poff(const struct sk_buff *skb, void *data,
13141314
*/
13151315
u32 skb_get_poff(const struct sk_buff *skb)
13161316
{
1317-
struct flow_keys keys;
1317+
struct flow_keys_basic keys;
13181318

1319-
if (!skb_flow_dissect_flow_keys(skb, &keys, 0))
1319+
if (!skb_flow_dissect_flow_keys_basic(skb, &keys, 0, 0, 0, 0, 0))
13201320
return 0;
13211321

13221322
return __skb_get_poff(skb, skb->data, &keys, skb_headlen(skb));
@@ -1403,7 +1403,7 @@ static const struct flow_dissector_key flow_keys_dissector_symmetric_keys[] = {
14031403
},
14041404
};
14051405

1406-
static const struct flow_dissector_key flow_keys_buf_dissector_keys[] = {
1406+
static const struct flow_dissector_key flow_keys_basic_dissector_keys[] = {
14071407
{
14081408
.key_id = FLOW_DISSECTOR_KEY_CONTROL,
14091409
.offset = offsetof(struct flow_keys, control),
@@ -1417,7 +1417,8 @@ static const struct flow_dissector_key flow_keys_buf_dissector_keys[] = {
14171417
struct flow_dissector flow_keys_dissector __read_mostly;
14181418
EXPORT_SYMBOL(flow_keys_dissector);
14191419

1420-
struct flow_dissector flow_keys_buf_dissector __read_mostly;
1420+
struct flow_dissector flow_keys_basic_dissector __read_mostly;
1421+
EXPORT_SYMBOL(flow_keys_basic_dissector);
14211422

14221423
static int __init init_default_flow_dissectors(void)
14231424
{
@@ -1427,9 +1428,9 @@ static int __init init_default_flow_dissectors(void)
14271428
skb_flow_dissector_init(&flow_keys_dissector_symmetric,
14281429
flow_keys_dissector_symmetric_keys,
14291430
ARRAY_SIZE(flow_keys_dissector_symmetric_keys));
1430-
skb_flow_dissector_init(&flow_keys_buf_dissector,
1431-
flow_keys_buf_dissector_keys,
1432-
ARRAY_SIZE(flow_keys_buf_dissector_keys));
1431+
skb_flow_dissector_init(&flow_keys_basic_dissector,
1432+
flow_keys_basic_dissector_keys,
1433+
ARRAY_SIZE(flow_keys_basic_dissector_keys));
14331434
return 0;
14341435
}
14351436

net/ethernet/eth.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,15 +128,15 @@ u32 eth_get_headlen(void *data, unsigned int len)
128128
{
129129
const unsigned int flags = FLOW_DISSECTOR_F_PARSE_1ST_FRAG;
130130
const struct ethhdr *eth = (const struct ethhdr *)data;
131-
struct flow_keys keys;
131+
struct flow_keys_basic keys;
132132

133133
/* this should never happen, but better safe than sorry */
134134
if (unlikely(len < sizeof(*eth)))
135135
return len;
136136

137137
/* parse any remaining L2/L3 headers, check for L4 */
138-
if (!skb_flow_dissect_flow_keys_buf(&keys, data, eth->h_proto,
139-
sizeof(*eth), len, flags))
138+
if (!skb_flow_dissect_flow_keys_basic(NULL, &keys, data, eth->h_proto,
139+
sizeof(*eth), len, flags))
140140
return max_t(u32, keys.control.thoff, sizeof(*eth));
141141

142142
/* parse for any L4 headers */

0 commit comments

Comments
 (0)