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@xxxxxxxxxx> --- net/core/flow_dissector.c | 54 +++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 31 deletions(-) diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index 1e2e4a9330af..ec8ebafe333f 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -683,26 +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, - .protocol = skb->protocol, - .vlan_tci = skb->vlan_tci, - .vlan_proto = skb->vlan_proto, - .vlan_present = skb->vlan_present, - .data = skb->data, - .data_end = skb->data + skb_headlen(skb), - }; - - return bpf_flow_dissect(prog, &ctx, skb_network_offset(skb), - skb_headlen(skb)); -} - bool bpf_flow_dissect(struct bpf_prog *prog, struct bpf_flow_dissector *ctx, int nhoff, int hlen) { @@ -754,6 +734,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; @@ -796,26 +777,37 @@ 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, + .protocol = proto, + }; + + if (skb) { + ctx.skb = skb; + ctx.protocol = skb->protocol; + ctx.vlan_tci = skb->vlan_tci; + ctx.vlan_proto = skb->vlan_proto; + ctx.vlan_present = skb->vlan_present; + } + + ret = bpf_flow_dissect(attached, &ctx, nhoff, hlen); __skb_flow_bpf_to_target(&flow_keys, flow_dissector, target_container); rcu_read_unlock(); -- 2.21.0.392.gf8f6787159e-goog