Re: [bpf-next, v2 1/3] flow_dissector: implements flow dissector BPF hook

2018-09-12 Thread Willem de Bruijn
On Wed, Sep 12, 2018 at 6:25 PM Alexei Starovoitov
 wrote:
>
> On Wed, Sep 12, 2018 at 02:43:37PM -0400, Willem de Bruijn wrote:
> > On Tue, Sep 11, 2018 at 11:47 PM Alexei Starovoitov
> >  wrote:
> > >
> > > On Fri, Sep 07, 2018 at 05:11:08PM -0700, Petar Penkov wrote:
> > > > From: Petar Penkov 
> > > >
> > > > Adds a hook for programs of type BPF_PROG_TYPE_FLOW_DISSECTOR and
> > > > attach type BPF_FLOW_DISSECTOR that is executed in the flow dissector
> > > > path. The BPF program is per-network namespace.
> > > >
> > > > Signed-off-by: Petar Penkov 
> > > > Signed-off-by: Willem de Bruijn 
> > > > ---
> > > >  include/linux/bpf.h|   1 +
> > > >  include/linux/bpf_types.h  |   1 +
> > > >  include/linux/skbuff.h |   7 ++
> > > >  include/net/net_namespace.h|   3 +
> > > >  include/net/sch_generic.h  |  12 ++-
> > > >  include/uapi/linux/bpf.h   |  25 ++
> > > >  kernel/bpf/syscall.c   |   8 ++
> > > >  kernel/bpf/verifier.c  |  32 
> > > >  net/core/filter.c  |  67 
> > > >  net/core/flow_dissector.c  | 136 +
> > > >  tools/bpf/bpftool/prog.c   |   1 +
> > > >  tools/include/uapi/linux/bpf.h |  25 ++
> > > >  tools/lib/bpf/libbpf.c |   2 +
> > >
> > > please split up update to tools/include/uapi/linux/bpf.h as a separate 
> > > patch 2.
> > > We often have conflicts in there, so best to have a separate.
> > > Also please split tools/lib and tools/bpf chnages into patch 3.
> >
> > Will do in v3.
> >
> > > >  struct qdisc_skb_cb {
> > > > - unsigned intpkt_len;
> > > > - u16 slave_dev_queue_mapping;
> > > > - u16 tc_classid;
> > > > + union {
> > > > + struct {
> > > > + unsigned intpkt_len;
> > > > + u16 slave_dev_queue_mapping;
> > > > + u16 tc_classid;
> > > > + };
> > > > + struct bpf_flow_keys *flow_keys;
> > > > + };
> > >
> > > is this magic really necessary? flow_dissector runs very early in recv 
> > > path.
> > > There is no qdisc or conflicts with tcp/ip use of cb.
> > > I think the whole cb block can be used.
> >
> > The flow dissector also runs in the context of TC, from flower.
> > But that is not a reason to use this struct.
> >
> > We need both (a) data shared with the BPF application and between
> > applications using tail-calls, to pass along the parse offset (nhoff),
> > and (b) data not accessible by the program, to store the flow_keys
> > pointer.
> >
> > qdisc_skb_cb already has this split, exposing only the 20B .data
> > field to the application. Flow dissection currently reuses the existing
> > bpf_convert_ctx_access logic for this field.
> >
> > We could create a separate flowdissect_skb_cb struct with the
> > same split setup, but a second constraint is that relevant internal
> > BPF interfaces already expect qdisc_skb_cb, notably
> > bkf_skb_data_end. So the union was easier.
>
> got it. all makes sense.
>
> >
> > There is another way to pass nhoff besides cb[] (see below). But
> > I don't immediately see another place to store the flow_keys ptr.
> >
> > At least, if we pass skb as context. One larger change would
> > be to introduce another ctx struct, similar to sk_reuseport_(kern|md).
>
> yeah. thought about this too, but your approach looks easier and faster.
> Accesses to skb have one less dereference.
>
> > > > @@ -2333,6 +2335,7 @@ struct __sk_buff {
> > > >   /* ... here. */
> > > >
> > > >   __u32 data_meta;
> > > > + __u32 flow_keys;
> > >
> > > please use
> > > struct bpf_flow_keys *flow_keys;
> > > instead.
> > >
> > > See what we did in 'struct sk_msg_md' and in 'struct sk_reuseport_md'.
> > > There is no need to hide pointers in u32.
> > >
> >
> > Will do in v3.
> >
> > > > @@ -658,6 +754,46 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
> > > > FLOW_DISSECTOR_KEY_BASIC,
> > > > target_container);
> > > >
> > > > + rcu_read_lock();
> > > > + attached = skb ? 
> > > > rcu_dereference(dev_net(skb->dev)->flow_dissector_prog)
> > > > +: NULL;
> > > > + if (attached) {
> > > > + /* Note that even though the const qualifier is discarded
> > > > +  * throughout the execution of the BPF program, all 
> > > > changes(the
> > > > +  * control block) are reverted after the BPF program 
> > > > returns.
> > > > +  * Therefore, __skb_flow_dissect does not alter the skb.
> > > > +  */
> > > > + struct bpf_flow_keys flow_keys = {};
> > > > + struct qdisc_skb_cb cb_saved;
> > > > + struct qdisc_skb_cb *cb;
> > > > + u16 *pseudo_cb;
> > > > + u32 result;
> > > > +
> > > 

Re: [bpf-next, v2 1/3] flow_dissector: implements flow dissector BPF hook

2018-09-12 Thread Alexei Starovoitov
On Wed, Sep 12, 2018 at 02:43:37PM -0400, Willem de Bruijn wrote:
> On Tue, Sep 11, 2018 at 11:47 PM Alexei Starovoitov
>  wrote:
> >
> > On Fri, Sep 07, 2018 at 05:11:08PM -0700, Petar Penkov wrote:
> > > From: Petar Penkov 
> > >
> > > Adds a hook for programs of type BPF_PROG_TYPE_FLOW_DISSECTOR and
> > > attach type BPF_FLOW_DISSECTOR that is executed in the flow dissector
> > > path. The BPF program is per-network namespace.
> > >
> > > Signed-off-by: Petar Penkov 
> > > Signed-off-by: Willem de Bruijn 
> > > ---
> > >  include/linux/bpf.h|   1 +
> > >  include/linux/bpf_types.h  |   1 +
> > >  include/linux/skbuff.h |   7 ++
> > >  include/net/net_namespace.h|   3 +
> > >  include/net/sch_generic.h  |  12 ++-
> > >  include/uapi/linux/bpf.h   |  25 ++
> > >  kernel/bpf/syscall.c   |   8 ++
> > >  kernel/bpf/verifier.c  |  32 
> > >  net/core/filter.c  |  67 
> > >  net/core/flow_dissector.c  | 136 +
> > >  tools/bpf/bpftool/prog.c   |   1 +
> > >  tools/include/uapi/linux/bpf.h |  25 ++
> > >  tools/lib/bpf/libbpf.c |   2 +
> >
> > please split up update to tools/include/uapi/linux/bpf.h as a separate 
> > patch 2.
> > We often have conflicts in there, so best to have a separate.
> > Also please split tools/lib and tools/bpf chnages into patch 3.
> 
> Will do in v3.
> 
> > >  struct qdisc_skb_cb {
> > > - unsigned intpkt_len;
> > > - u16 slave_dev_queue_mapping;
> > > - u16 tc_classid;
> > > + union {
> > > + struct {
> > > + unsigned intpkt_len;
> > > + u16 slave_dev_queue_mapping;
> > > + u16 tc_classid;
> > > + };
> > > + struct bpf_flow_keys *flow_keys;
> > > + };
> >
> > is this magic really necessary? flow_dissector runs very early in recv path.
> > There is no qdisc or conflicts with tcp/ip use of cb.
> > I think the whole cb block can be used.
> 
> The flow dissector also runs in the context of TC, from flower.
> But that is not a reason to use this struct.
> 
> We need both (a) data shared with the BPF application and between
> applications using tail-calls, to pass along the parse offset (nhoff),
> and (b) data not accessible by the program, to store the flow_keys
> pointer.
> 
> qdisc_skb_cb already has this split, exposing only the 20B .data
> field to the application. Flow dissection currently reuses the existing
> bpf_convert_ctx_access logic for this field.
> 
> We could create a separate flowdissect_skb_cb struct with the
> same split setup, but a second constraint is that relevant internal
> BPF interfaces already expect qdisc_skb_cb, notably
> bkf_skb_data_end. So the union was easier.

got it. all makes sense.

> 
> There is another way to pass nhoff besides cb[] (see below). But
> I don't immediately see another place to store the flow_keys ptr.
> 
> At least, if we pass skb as context. One larger change would
> be to introduce another ctx struct, similar to sk_reuseport_(kern|md).

yeah. thought about this too, but your approach looks easier and faster.
Accesses to skb have one less dereference.

> > > @@ -2333,6 +2335,7 @@ struct __sk_buff {
> > >   /* ... here. */
> > >
> > >   __u32 data_meta;
> > > + __u32 flow_keys;
> >
> > please use
> > struct bpf_flow_keys *flow_keys;
> > instead.
> >
> > See what we did in 'struct sk_msg_md' and in 'struct sk_reuseport_md'.
> > There is no need to hide pointers in u32.
> >
> 
> Will do in v3.
> 
> > > @@ -658,6 +754,46 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
> > > FLOW_DISSECTOR_KEY_BASIC,
> > > target_container);
> > >
> > > + rcu_read_lock();
> > > + attached = skb ? 
> > > rcu_dereference(dev_net(skb->dev)->flow_dissector_prog)
> > > +: NULL;
> > > + if (attached) {
> > > + /* Note that even though the const qualifier is discarded
> > > +  * throughout the execution of the BPF program, all 
> > > changes(the
> > > +  * control block) are reverted after the BPF program 
> > > returns.
> > > +  * Therefore, __skb_flow_dissect does not alter the skb.
> > > +  */
> > > + struct bpf_flow_keys flow_keys = {};
> > > + struct qdisc_skb_cb cb_saved;
> > > + struct qdisc_skb_cb *cb;
> > > + u16 *pseudo_cb;
> > > + u32 result;
> > > +
> > > + cb = qdisc_skb_cb(skb);
> > > + pseudo_cb = (u16 *)bpf_skb_cb((struct sk_buff *)skb);
> > > +
> > > + /* Save Control Block */
> > > + memcpy(_saved, cb, sizeof(cb_saved));
> > > + memset(cb, 0, sizeof(cb_saved));
> > > +
> > > + 

Re: [bpf-next, v2 1/3] flow_dissector: implements flow dissector BPF hook

2018-09-12 Thread Willem de Bruijn
On Tue, Sep 11, 2018 at 11:47 PM Alexei Starovoitov
 wrote:
>
> On Fri, Sep 07, 2018 at 05:11:08PM -0700, Petar Penkov wrote:
> > From: Petar Penkov 
> >
> > Adds a hook for programs of type BPF_PROG_TYPE_FLOW_DISSECTOR and
> > attach type BPF_FLOW_DISSECTOR that is executed in the flow dissector
> > path. The BPF program is per-network namespace.
> >
> > Signed-off-by: Petar Penkov 
> > Signed-off-by: Willem de Bruijn 
> > ---
> >  include/linux/bpf.h|   1 +
> >  include/linux/bpf_types.h  |   1 +
> >  include/linux/skbuff.h |   7 ++
> >  include/net/net_namespace.h|   3 +
> >  include/net/sch_generic.h  |  12 ++-
> >  include/uapi/linux/bpf.h   |  25 ++
> >  kernel/bpf/syscall.c   |   8 ++
> >  kernel/bpf/verifier.c  |  32 
> >  net/core/filter.c  |  67 
> >  net/core/flow_dissector.c  | 136 +
> >  tools/bpf/bpftool/prog.c   |   1 +
> >  tools/include/uapi/linux/bpf.h |  25 ++
> >  tools/lib/bpf/libbpf.c |   2 +
>
> please split up update to tools/include/uapi/linux/bpf.h as a separate patch 
> 2.
> We often have conflicts in there, so best to have a separate.
> Also please split tools/lib and tools/bpf chnages into patch 3.

Will do in v3.

> >  struct qdisc_skb_cb {
> > - unsigned intpkt_len;
> > - u16 slave_dev_queue_mapping;
> > - u16 tc_classid;
> > + union {
> > + struct {
> > + unsigned intpkt_len;
> > + u16 slave_dev_queue_mapping;
> > + u16 tc_classid;
> > + };
> > + struct bpf_flow_keys *flow_keys;
> > + };
>
> is this magic really necessary? flow_dissector runs very early in recv path.
> There is no qdisc or conflicts with tcp/ip use of cb.
> I think the whole cb block can be used.

The flow dissector also runs in the context of TC, from flower.
But that is not a reason to use this struct.

We need both (a) data shared with the BPF application and between
applications using tail-calls, to pass along the parse offset (nhoff),
and (b) data not accessible by the program, to store the flow_keys
pointer.

qdisc_skb_cb already has this split, exposing only the 20B .data
field to the application. Flow dissection currently reuses the existing
bpf_convert_ctx_access logic for this field.

We could create a separate flowdissect_skb_cb struct with the
same split setup, but a second constraint is that relevant internal
BPF interfaces already expect qdisc_skb_cb, notably
bkf_skb_data_end. So the union was easier.

There is another way to pass nhoff besides cb[] (see below). But
I don't immediately see another place to store the flow_keys ptr.

At least, if we pass skb as context. One larger change would
be to introduce another ctx struct, similar to sk_reuseport_(kern|md).

> > @@ -2333,6 +2335,7 @@ struct __sk_buff {
> >   /* ... here. */
> >
> >   __u32 data_meta;
> > + __u32 flow_keys;
>
> please use
> struct bpf_flow_keys *flow_keys;
> instead.
>
> See what we did in 'struct sk_msg_md' and in 'struct sk_reuseport_md'.
> There is no need to hide pointers in u32.
>

Will do in v3.

> > @@ -658,6 +754,46 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
> > FLOW_DISSECTOR_KEY_BASIC,
> > target_container);
> >
> > + rcu_read_lock();
> > + attached = skb ? 
> > rcu_dereference(dev_net(skb->dev)->flow_dissector_prog)
> > +: NULL;
> > + if (attached) {
> > + /* Note that even though the const qualifier is discarded
> > +  * throughout the execution of the BPF program, all 
> > changes(the
> > +  * control block) are reverted after the BPF program returns.
> > +  * Therefore, __skb_flow_dissect does not alter the skb.
> > +  */
> > + struct bpf_flow_keys flow_keys = {};
> > + struct qdisc_skb_cb cb_saved;
> > + struct qdisc_skb_cb *cb;
> > + u16 *pseudo_cb;
> > + u32 result;
> > +
> > + cb = qdisc_skb_cb(skb);
> > + pseudo_cb = (u16 *)bpf_skb_cb((struct sk_buff *)skb);
> > +
> > + /* Save Control Block */
> > + memcpy(_saved, cb, sizeof(cb_saved));
> > + memset(cb, 0, sizeof(cb_saved));
> > +
> > + /* Pass parameters to the BPF program */
> > + cb->flow_keys = _keys;
> > + *pseudo_cb = nhoff;
>
> I don't understand this bit.
> What is this pseudo_cb and why nhoff goes in there?
> Some odd way to pass it into the prog?

Yes. nhoff passes the offset to the program to start parsing from.
Applications also pass this during tail calls.

Alternatively we can just add a new field to struct bpf_flow_keys.


Re: [bpf-next, v2 1/3] flow_dissector: implements flow dissector BPF hook

2018-09-11 Thread Alexei Starovoitov
On Fri, Sep 07, 2018 at 05:11:08PM -0700, Petar Penkov wrote:
> From: Petar Penkov 
> 
> Adds a hook for programs of type BPF_PROG_TYPE_FLOW_DISSECTOR and
> attach type BPF_FLOW_DISSECTOR that is executed in the flow dissector
> path. The BPF program is per-network namespace.
> 
> Signed-off-by: Petar Penkov 
> Signed-off-by: Willem de Bruijn 
> ---
>  include/linux/bpf.h|   1 +
>  include/linux/bpf_types.h  |   1 +
>  include/linux/skbuff.h |   7 ++
>  include/net/net_namespace.h|   3 +
>  include/net/sch_generic.h  |  12 ++-
>  include/uapi/linux/bpf.h   |  25 ++
>  kernel/bpf/syscall.c   |   8 ++
>  kernel/bpf/verifier.c  |  32 
>  net/core/filter.c  |  67 
>  net/core/flow_dissector.c  | 136 +
>  tools/bpf/bpftool/prog.c   |   1 +
>  tools/include/uapi/linux/bpf.h |  25 ++
>  tools/lib/bpf/libbpf.c |   2 +

please split up update to tools/include/uapi/linux/bpf.h as a separate patch 2.
We often have conflicts in there, so best to have a separate.
Also please split tools/lib and tools/bpf chnages into patch 3.

>  13 files changed, 317 insertions(+), 3 deletions(-)
> 
> diff --git a/include/linux/bpf.h b/include/linux/bpf.h
> index 523481a3471b..988a00797bcd 100644
> --- a/include/linux/bpf.h
> +++ b/include/linux/bpf.h
> @@ -212,6 +212,7 @@ enum bpf_reg_type {
>   PTR_TO_PACKET_META,  /* skb->data - meta_len */
>   PTR_TO_PACKET,   /* reg points to skb->data */
>   PTR_TO_PACKET_END,   /* skb->data + headlen */
> + PTR_TO_FLOW_KEYS,/* reg points to bpf_flow_keys */
>  };
>  
>  /* The information passed from prog-specific *_is_valid_access
> diff --git a/include/linux/bpf_types.h b/include/linux/bpf_types.h
> index cd26c090e7c0..22083712dd18 100644
> --- a/include/linux/bpf_types.h
> +++ b/include/linux/bpf_types.h
> @@ -32,6 +32,7 @@ BPF_PROG_TYPE(BPF_PROG_TYPE_LIRC_MODE2, lirc_mode2)
>  #ifdef CONFIG_INET
>  BPF_PROG_TYPE(BPF_PROG_TYPE_SK_REUSEPORT, sk_reuseport)
>  #endif
> +BPF_PROG_TYPE(BPF_PROG_TYPE_FLOW_DISSECTOR, flow_dissector)
>  
>  BPF_MAP_TYPE(BPF_MAP_TYPE_ARRAY, array_map_ops)
>  BPF_MAP_TYPE(BPF_MAP_TYPE_PERCPU_ARRAY, percpu_array_map_ops)
> diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
> index 17a13e4785fc..ce0e863f02a2 100644
> --- a/include/linux/skbuff.h
> +++ b/include/linux/skbuff.h
> @@ -243,6 +243,8 @@ struct scatterlist;
>  struct pipe_inode_info;
>  struct iov_iter;
>  struct napi_struct;
> +struct bpf_prog;
> +union bpf_attr;
>  
>  #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
>  struct nf_conntrack {
> @@ -1192,6 +1194,11 @@ void skb_flow_dissector_init(struct flow_dissector 
> *flow_dissector,
>const struct flow_dissector_key *key,
>unsigned int key_count);
>  
> +int skb_flow_dissector_bpf_prog_attach(const union bpf_attr *attr,
> +struct bpf_prog *prog);
> +
> +int skb_flow_dissector_bpf_prog_detach(const union bpf_attr *attr);
> +
>  bool __skb_flow_dissect(const struct sk_buff *skb,
>   struct flow_dissector *flow_dissector,
>   void *target_container,
> diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
> index 9b5fdc50519a..99d4148e0f90 100644
> --- a/include/net/net_namespace.h
> +++ b/include/net/net_namespace.h
> @@ -43,6 +43,7 @@ struct ctl_table_header;
>  struct net_generic;
>  struct uevent_sock;
>  struct netns_ipvs;
> +struct bpf_prog;
>  
>  
>  #define NETDEV_HASHBITS8
> @@ -145,6 +146,8 @@ struct net {
>  #endif
>   struct net_generic __rcu*gen;
>  
> + struct bpf_prog __rcu   *flow_dissector_prog;
> +
>   /* Note : following structs are cache line aligned */
>  #ifdef CONFIG_XFRM
>   struct netns_xfrm   xfrm;
> diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
> index a6d00093f35e..1b81ba85fd2d 100644
> --- a/include/net/sch_generic.h
> +++ b/include/net/sch_generic.h
> @@ -19,6 +19,7 @@ struct Qdisc_ops;
>  struct qdisc_walker;
>  struct tcf_walker;
>  struct module;
> +struct bpf_flow_keys;
>  
>  typedef int tc_setup_cb_t(enum tc_setup_type type,
> void *type_data, void *cb_priv);
> @@ -307,9 +308,14 @@ struct tcf_proto {
>  };
>  
>  struct qdisc_skb_cb {
> - unsigned intpkt_len;
> - u16 slave_dev_queue_mapping;
> - u16 tc_classid;
> + union {
> + struct {
> + unsigned intpkt_len;
> + u16 slave_dev_queue_mapping;
> + u16 tc_classid;
> + };
> + struct bpf_flow_keys *flow_keys;
> + };

is this magic really necessary? flow_dissector runs very early in recv path.
There is no qdisc or conflicts 

[bpf-next, v2 1/3] flow_dissector: implements flow dissector BPF hook

2018-09-07 Thread Petar Penkov
From: Petar Penkov 

Adds a hook for programs of type BPF_PROG_TYPE_FLOW_DISSECTOR and
attach type BPF_FLOW_DISSECTOR that is executed in the flow dissector
path. The BPF program is per-network namespace.

Signed-off-by: Petar Penkov 
Signed-off-by: Willem de Bruijn 
---
 include/linux/bpf.h|   1 +
 include/linux/bpf_types.h  |   1 +
 include/linux/skbuff.h |   7 ++
 include/net/net_namespace.h|   3 +
 include/net/sch_generic.h  |  12 ++-
 include/uapi/linux/bpf.h   |  25 ++
 kernel/bpf/syscall.c   |   8 ++
 kernel/bpf/verifier.c  |  32 
 net/core/filter.c  |  67 
 net/core/flow_dissector.c  | 136 +
 tools/bpf/bpftool/prog.c   |   1 +
 tools/include/uapi/linux/bpf.h |  25 ++
 tools/lib/bpf/libbpf.c |   2 +
 13 files changed, 317 insertions(+), 3 deletions(-)

diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 523481a3471b..988a00797bcd 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -212,6 +212,7 @@ enum bpf_reg_type {
PTR_TO_PACKET_META,  /* skb->data - meta_len */
PTR_TO_PACKET,   /* reg points to skb->data */
PTR_TO_PACKET_END,   /* skb->data + headlen */
+   PTR_TO_FLOW_KEYS,/* reg points to bpf_flow_keys */
 };
 
 /* The information passed from prog-specific *_is_valid_access
diff --git a/include/linux/bpf_types.h b/include/linux/bpf_types.h
index cd26c090e7c0..22083712dd18 100644
--- a/include/linux/bpf_types.h
+++ b/include/linux/bpf_types.h
@@ -32,6 +32,7 @@ BPF_PROG_TYPE(BPF_PROG_TYPE_LIRC_MODE2, lirc_mode2)
 #ifdef CONFIG_INET
 BPF_PROG_TYPE(BPF_PROG_TYPE_SK_REUSEPORT, sk_reuseport)
 #endif
+BPF_PROG_TYPE(BPF_PROG_TYPE_FLOW_DISSECTOR, flow_dissector)
 
 BPF_MAP_TYPE(BPF_MAP_TYPE_ARRAY, array_map_ops)
 BPF_MAP_TYPE(BPF_MAP_TYPE_PERCPU_ARRAY, percpu_array_map_ops)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 17a13e4785fc..ce0e863f02a2 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -243,6 +243,8 @@ struct scatterlist;
 struct pipe_inode_info;
 struct iov_iter;
 struct napi_struct;
+struct bpf_prog;
+union bpf_attr;
 
 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
 struct nf_conntrack {
@@ -1192,6 +1194,11 @@ void skb_flow_dissector_init(struct flow_dissector 
*flow_dissector,
 const struct flow_dissector_key *key,
 unsigned int key_count);
 
+int skb_flow_dissector_bpf_prog_attach(const union bpf_attr *attr,
+  struct bpf_prog *prog);
+
+int skb_flow_dissector_bpf_prog_detach(const union bpf_attr *attr);
+
 bool __skb_flow_dissect(const struct sk_buff *skb,
struct flow_dissector *flow_dissector,
void *target_container,
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index 9b5fdc50519a..99d4148e0f90 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -43,6 +43,7 @@ struct ctl_table_header;
 struct net_generic;
 struct uevent_sock;
 struct netns_ipvs;
+struct bpf_prog;
 
 
 #define NETDEV_HASHBITS8
@@ -145,6 +146,8 @@ struct net {
 #endif
struct net_generic __rcu*gen;
 
+   struct bpf_prog __rcu   *flow_dissector_prog;
+
/* Note : following structs are cache line aligned */
 #ifdef CONFIG_XFRM
struct netns_xfrm   xfrm;
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index a6d00093f35e..1b81ba85fd2d 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -19,6 +19,7 @@ struct Qdisc_ops;
 struct qdisc_walker;
 struct tcf_walker;
 struct module;
+struct bpf_flow_keys;
 
 typedef int tc_setup_cb_t(enum tc_setup_type type,
  void *type_data, void *cb_priv);
@@ -307,9 +308,14 @@ struct tcf_proto {
 };
 
 struct qdisc_skb_cb {
-   unsigned intpkt_len;
-   u16 slave_dev_queue_mapping;
-   u16 tc_classid;
+   union {
+   struct {
+   unsigned intpkt_len;
+   u16 slave_dev_queue_mapping;
+   u16 tc_classid;
+   };
+   struct bpf_flow_keys *flow_keys;
+   };
 #define QDISC_CB_PRIV_LEN 20
unsigned char   data[QDISC_CB_PRIV_LEN];
 };
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index 66917a4eba27..3064706fcaaa 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -152,6 +152,7 @@ enum bpf_prog_type {
BPF_PROG_TYPE_LWT_SEG6LOCAL,
BPF_PROG_TYPE_LIRC_MODE2,
BPF_PROG_TYPE_SK_REUSEPORT,
+   BPF_PROG_TYPE_FLOW_DISSECTOR,
 };
 
 enum bpf_attach_type {
@@ -172,6 +173,7 @@ enum bpf_attach_type {
BPF_CGROUP_UDP4_SENDMSG,