Skip to content

Commit

Permalink
net: plumb network namespace into __skb_flow_dissect
Browse files Browse the repository at this point in the history
This new argument will be used in the next patches for the
eth_get_headlen use case. eth_get_headlen calls flow dissector
with only data (without skb) so there is currently no way to
pull attached BPF flow dissector program. With this new argument,
we can amend the callers to explicitly pass network namespace
so we can use attached BPF program.

Signed-off-by: Stanislav Fomichev <[email protected]>
Reviewed-by: Saeed Mahameed <[email protected]>
Signed-off-by: Daniel Borkmann <[email protected]>
  • Loading branch information
fomichev authored and borkmann committed Apr 23, 2019
1 parent 7b8a130 commit 3cbf4ff
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 20 deletions.
19 changes: 11 additions & 8 deletions include/linux/skbuff.h
Original file line number Diff line number Diff line change
Expand Up @@ -1284,7 +1284,8 @@ bool __skb_flow_bpf_dissect(struct bpf_prog *prog,
const struct sk_buff *skb,
struct flow_dissector *flow_dissector,
struct bpf_flow_keys *flow_keys);
bool __skb_flow_dissect(const struct sk_buff *skb,
bool __skb_flow_dissect(const struct net *net,
const struct sk_buff *skb,
struct flow_dissector *flow_dissector,
void *target_container,
void *data, __be16 proto, int nhoff, int hlen,
Expand All @@ -1294,27 +1295,28 @@ static inline bool skb_flow_dissect(const struct sk_buff *skb,
struct flow_dissector *flow_dissector,
void *target_container, unsigned int flags)
{
return __skb_flow_dissect(skb, flow_dissector, target_container,
NULL, 0, 0, 0, flags);
return __skb_flow_dissect(NULL, skb, flow_dissector,
target_container, NULL, 0, 0, 0, flags);
}

static inline bool skb_flow_dissect_flow_keys(const struct sk_buff *skb,
struct flow_keys *flow,
unsigned int flags)
{
memset(flow, 0, sizeof(*flow));
return __skb_flow_dissect(skb, &flow_keys_dissector, flow,
NULL, 0, 0, 0, flags);
return __skb_flow_dissect(NULL, skb, &flow_keys_dissector,
flow, NULL, 0, 0, 0, flags);
}

static inline bool
skb_flow_dissect_flow_keys_basic(const struct sk_buff *skb,
skb_flow_dissect_flow_keys_basic(const struct net *net,
const struct sk_buff *skb,
struct flow_keys_basic *flow, void *data,
__be16 proto, int nhoff, int hlen,
unsigned int flags)
{
memset(flow, 0, sizeof(*flow));
return __skb_flow_dissect(skb, &flow_keys_basic_dissector, flow,
return __skb_flow_dissect(net, skb, &flow_keys_basic_dissector, flow,
data, proto, nhoff, hlen, flags);
}

Expand Down Expand Up @@ -2492,7 +2494,8 @@ static inline void skb_probe_transport_header(struct sk_buff *skb)
if (skb_transport_header_was_set(skb))
return;

if (skb_flow_dissect_flow_keys_basic(skb, &keys, NULL, 0, 0, 0, 0))
if (skb_flow_dissect_flow_keys_basic(NULL, skb, &keys,
NULL, 0, 0, 0, 0))
skb_set_transport_header(skb, keys.control.thoff);
}

Expand Down
27 changes: 17 additions & 10 deletions net/core/flow_dissector.c
Original file line number Diff line number Diff line change
Expand Up @@ -722,6 +722,7 @@ bool bpf_flow_dissect(struct bpf_prog *prog, struct bpf_flow_dissector *ctx,

/**
* __skb_flow_dissect - extract the flow_keys struct and return it
* @net: associated network namespace, derived from @skb if NULL
* @skb: sk_buff to extract the flow from, can be NULL if the rest are specified
* @flow_dissector: list of keys to dissect
* @target_container: target structure to put dissected values into
Expand All @@ -738,7 +739,8 @@ bool bpf_flow_dissect(struct bpf_prog *prog, struct bpf_flow_dissector *ctx,
*
* Caller must take care of zeroing target container memory.
*/
bool __skb_flow_dissect(const struct sk_buff *skb,
bool __skb_flow_dissect(const struct net *net,
const struct sk_buff *skb,
struct flow_dissector *flow_dissector,
void *target_container,
void *data, __be16 proto, int nhoff, int hlen,
Expand Down Expand Up @@ -797,13 +799,17 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
struct bpf_prog *attached = NULL;

rcu_read_lock();
if (!net) {
if (skb->dev)
net = dev_net(skb->dev);
else if (skb->sk)
net = sock_net(skb->sk);
else
WARN_ON_ONCE(1);
}

if (skb->dev)
attached = rcu_dereference(dev_net(skb->dev)->flow_dissector_prog);
else if (skb->sk)
attached = rcu_dereference(sock_net(skb->sk)->flow_dissector_prog);
else
WARN_ON_ONCE(1);
if (net)
attached = rcu_dereference(net->flow_dissector_prog);

if (attached) {
ret = __skb_flow_bpf_dissect(attached, skb,
Expand Down Expand Up @@ -1405,8 +1411,8 @@ u32 __skb_get_hash_symmetric(const struct sk_buff *skb)
__flow_hash_secret_init();

memset(&keys, 0, sizeof(keys));
__skb_flow_dissect(skb, &flow_keys_dissector_symmetric, &keys,
NULL, 0, 0, 0,
__skb_flow_dissect(NULL, skb, &flow_keys_dissector_symmetric,
&keys, NULL, 0, 0, 0,
FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL);

return __flow_hash_from_keys(&keys, hashrnd);
Expand Down Expand Up @@ -1507,7 +1513,8 @@ u32 skb_get_poff(const struct sk_buff *skb)
{
struct flow_keys_basic keys;

if (!skb_flow_dissect_flow_keys_basic(skb, &keys, NULL, 0, 0, 0, 0))
if (!skb_flow_dissect_flow_keys_basic(NULL, skb, &keys,
NULL, 0, 0, 0, 0))
return 0;

return __skb_get_poff(skb, skb->data, &keys, skb_headlen(skb));
Expand Down
5 changes: 3 additions & 2 deletions net/ethernet/eth.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,9 @@ u32 eth_get_headlen(void *data, unsigned int len)
return len;

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

/* parse for any L4 headers */
Expand Down

0 comments on commit 3cbf4ff

Please sign in to comment.