diff options
author | Stanislav Fomichev <sdf@google.com> | 2019-04-22 08:55:47 -0700 |
---|---|---|
committer | Daniel Borkmann <daniel@iogearbox.net> | 2019-04-23 18:36:34 +0200 |
commit | 9b52e3f267a6835efd50ed9002d530666d16a411 (patch) | |
tree | 4081fba58a7686bfe6c10955772b32d93f1df3a9 | |
parent | 3cbf4ffba5eeec60f82868a5facc1962d8a44d00 (diff) | |
download | linux-next-9b52e3f267a6835efd50ed9002d530666d16a411.tar.gz |
flow_dissector: handle no-skb use case
When called without skb, gather all required data from the
__skb_flow_dissect's arguments and use recently introduces
no-skb mode of bpf flow dissector.
Note: WARN_ON_ONCE(!net) will now trigger for eth_get_headlen users.
Signed-off-by: Stanislav Fomichev <sdf@google.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
-rw-r--r-- | include/linux/skbuff.h | 5 | ||||
-rw-r--r-- | net/core/flow_dissector.c | 52 |
2 files changed, 25 insertions, 32 deletions
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index b466fbface2e..998256c2820b 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -1279,11 +1279,6 @@ struct bpf_flow_dissector; bool bpf_flow_dissect(struct bpf_prog *prog, struct bpf_flow_dissector *ctx, __be16 proto, int nhoff, int hlen); -struct bpf_flow_keys; -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 net *net, const struct sk_buff *skb, struct flow_dissector *flow_dissector, diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index f32c7e737fc6..fac712cee9d5 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -683,22 +683,6 @@ static void __skb_flow_bpf_to_target(const struct bpf_flow_keys *flow_keys, } } -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) -{ - struct bpf_flow_dissector ctx = { - .flow_keys = flow_keys, - .skb = skb, - .data = skb->data, - .data_end = skb->data + skb_headlen(skb), - }; - - return bpf_flow_dissect(prog, &ctx, skb->protocol, - skb_network_offset(skb), skb_headlen(skb)); -} - bool bpf_flow_dissect(struct bpf_prog *prog, struct bpf_flow_dissector *ctx, __be16 proto, int nhoff, int hlen) { @@ -753,6 +737,7 @@ bool __skb_flow_dissect(const struct net *net, struct flow_dissector_key_icmp *key_icmp; struct flow_dissector_key_tags *key_tags; struct flow_dissector_key_vlan *key_vlan; + struct bpf_prog *attached = NULL; enum flow_dissect_ret fdret; enum flow_dissector_key_id dissector_vlan = FLOW_DISSECTOR_KEY_MAX; int num_hdrs = 0; @@ -795,26 +780,39 @@ bool __skb_flow_dissect(const struct net *net, target_container); if (skb) { - struct bpf_flow_keys flow_keys; - 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 (net) - attached = rcu_dereference(net->flow_dissector_prog); + WARN_ON_ONCE(!net); + if (net) { + rcu_read_lock(); + attached = rcu_dereference(net->flow_dissector_prog); if (attached) { - ret = __skb_flow_bpf_dissect(attached, skb, - flow_dissector, - &flow_keys); + struct bpf_flow_keys flow_keys; + struct bpf_flow_dissector ctx = { + .flow_keys = &flow_keys, + .data = data, + .data_end = data + hlen, + }; + __be16 n_proto = proto; + + if (skb) { + ctx.skb = skb; + /* we can't use 'proto' in the skb case + * because it might be set to skb->vlan_proto + * which has been pulled from the data + */ + n_proto = skb->protocol; + } + + ret = bpf_flow_dissect(attached, &ctx, n_proto, nhoff, + hlen); __skb_flow_bpf_to_target(&flow_keys, flow_dissector, target_container); rcu_read_unlock(); |