On Tue, Feb 5, 2019 at 12:57 PM Stanislav Fomichev <s...@google.com> wrote: > > When flow_dissector is called without skb (with only data and hlen), > construct on-stack skb (which has a linear chunk of data passed > to the flow dissector). This should let us handle eth_get_headlen > case where only data is provided and we don't want to (yet) allocate > an skb. > > Since this on-stack skb doesn't allocate its own data, we can't > add shinfo and need to be careful to avoid any code paths that use > it. Flow dissector BPF programs can only call bpf_skb_load_bytes helper, > which doesn't touch shinfo in our case (skb->len is the length of the > linear header so it exits early). > > Signed-off-by: Stanislav Fomichev <s...@google.com> > --- > include/linux/skbuff.h | 5 +++ > net/core/flow_dissector.c | 95 +++++++++++++++++++++++++++++---------- > 2 files changed, 76 insertions(+), 24 deletions(-) > > diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h > index aa9a9983de80..5f1c085cb34c 100644 > --- a/include/linux/skbuff.h > +++ b/include/linux/skbuff.h > @@ -1227,6 +1227,11 @@ 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 __flow_bpf_dissect(struct bpf_prog *prog, > + void *data, __be16 proto, > + int nhoff, int hlen, > + struct flow_dissector *flow_dissector, > + struct bpf_flow_keys *flow_keys);
nit: please use more descriptive name. Perhaps bpf_flow_dissect_raw and rename __skb_flow_bpf_dissect to bpf_flow_dissect_skb. > +bool __flow_bpf_dissect(struct bpf_prog *prog, > + void *data, __be16 proto, > + int nhoff, int hlen, > + struct flow_dissector *flow_dissector, > + struct bpf_flow_keys *flow_keys) > +{ > + struct bpf_skb_data_end *cb; > + struct sk_buff skb; > + u32 result; > + > + __init_skb(&skb, data, hlen); > + skb_put(&skb, hlen); > + skb.protocol = proto; > + > + init_flow_keys(flow_keys, &skb, nhoff); > + > + cb = (struct bpf_skb_data_end *)skb.cb; > + cb->data_meta = skb.data; > + cb->data_end = skb.data + skb_headlen(&skb); > + > + result = BPF_PROG_RUN(prog, &skb); > + > + clamp_flow_keys(flow_keys, hlen); > > return result == BPF_OK; > } Can__flow_bpf_dissect just construct an skb and then call __skb_flow_bpf_dissect? It will unnecessarily save and restore the control block, but that is a relatively small cost (compared to, say, zeroing the entire skb).