diff mbox series

[net-next,01/13] net: sched: Pass qdisc reference in struct flow_block_offload

Message ID 20200710135706.601409-2-idosch@idosch.org
State Changes Requested
Delegated to: David Miller
Headers show
Series mlxsw: Add support for buffer drops mirroring | expand

Commit Message

Ido Schimmel July 10, 2020, 1:56 p.m. UTC
From: Petr Machata <petrm@mellanox.com>

Previously, shared blocks were only relevant for the pseudo-qdiscs ingress
and clsact. Recently, a qevent facility was introduced, which allows to
bind blocks to well-defined slots of a qdisc instance. RED in particular
got two qevents: early_drop and mark. Drivers that wish to offload these
blocks will be sent the usual notification, and need to know which qdisc it
is related to.

To that end, extend flow_block_offload with a "sch" pointer, and initialize
as appropriate. This prompts changes in the indirect block facility, which
now tracks the scheduler instead of the netdevice. Update signatures of
several functions similarly. Deduce the device from the scheduler when
necessary.

Signed-off-by: Petr Machata <petrm@mellanox.com>
Reviewed-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
---
 drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c  | 11 ++++++----
 .../ethernet/mellanox/mlx5/core/en/rep/tc.c   | 11 +++++-----
 .../net/ethernet/netronome/nfp/flower/main.h  |  2 +-
 .../ethernet/netronome/nfp/flower/offload.c   | 11 ++++++----
 include/net/flow_offload.h                    |  9 ++++----
 net/core/flow_offload.c                       | 12 +++++------
 net/netfilter/nf_flow_table_offload.c         | 17 +++++++--------
 net/netfilter/nf_tables_offload.c             | 20 ++++++++++--------
 net/sched/cls_api.c                           | 21 +++++++++++--------
 9 files changed, 63 insertions(+), 51 deletions(-)

Comments

Pablo Neira Ayuso July 10, 2020, 2:15 p.m. UTC | #1
On Fri, Jul 10, 2020 at 04:56:54PM +0300, Ido Schimmel wrote:
> From: Petr Machata <petrm@mellanox.com>
> 
> Previously, shared blocks were only relevant for the pseudo-qdiscs ingress
> and clsact. Recently, a qevent facility was introduced, which allows to
> bind blocks to well-defined slots of a qdisc instance. RED in particular
> got two qevents: early_drop and mark. Drivers that wish to offload these
> blocks will be sent the usual notification, and need to know which qdisc it
> is related to.
> 
> To that end, extend flow_block_offload with a "sch" pointer, and initialize
> as appropriate. This prompts changes in the indirect block facility, which
> now tracks the scheduler instead of the netdevice. Update signatures of
> several functions similarly. Deduce the device from the scheduler when
> necessary.
> 
> Signed-off-by: Petr Machata <petrm@mellanox.com>
> Reviewed-by: Jiri Pirko <jiri@mellanox.com>
> Signed-off-by: Ido Schimmel <idosch@mellanox.com>
> ---
>  drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c  | 11 ++++++----
>  .../ethernet/mellanox/mlx5/core/en/rep/tc.c   | 11 +++++-----
>  .../net/ethernet/netronome/nfp/flower/main.h  |  2 +-
>  .../ethernet/netronome/nfp/flower/offload.c   | 11 ++++++----
>  include/net/flow_offload.h                    |  9 ++++----
>  net/core/flow_offload.c                       | 12 +++++------
>  net/netfilter/nf_flow_table_offload.c         | 17 +++++++--------
>  net/netfilter/nf_tables_offload.c             | 20 ++++++++++--------
>  net/sched/cls_api.c                           | 21 +++++++++++--------
>  9 files changed, 63 insertions(+), 51 deletions(-)
> 
[...]
> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/tc.c
> index eefeb1cdc2ee..4fc42c1955ff 100644
> --- a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/tc.c
> +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/tc.c
> @@ -404,7 +404,7 @@ static void mlx5e_rep_indr_block_unbind(void *cb_priv)
>  static LIST_HEAD(mlx5e_block_cb_list);
>  
>  static int
> -mlx5e_rep_indr_setup_block(struct net_device *netdev,
> +mlx5e_rep_indr_setup_block(struct Qdisc *sch,
>  			   struct mlx5e_rep_priv *rpriv,
>  			   struct flow_block_offload *f,
>  			   flow_setup_cb_t *setup_cb,
> @@ -412,6 +412,7 @@ mlx5e_rep_indr_setup_block(struct net_device *netdev,
>  			   void (*cleanup)(struct flow_block_cb *block_cb))
>  {
>  	struct mlx5e_priv *priv = netdev_priv(rpriv->netdev);
> +	struct net_device *netdev = sch->dev_queue->dev;

This break indirect block support for netfilter since the driver
is assuming a Qdisc object.
Petr Machata July 10, 2020, 3:15 p.m. UTC | #2
Pablo Neira Ayuso <pablo@netfilter.org> writes:

> On Fri, Jul 10, 2020 at 04:56:54PM +0300, Ido Schimmel wrote:
>> From: Petr Machata <petrm@mellanox.com>
>>
>> Previously, shared blocks were only relevant for the pseudo-qdiscs ingress
>> and clsact. Recently, a qevent facility was introduced, which allows to
>> bind blocks to well-defined slots of a qdisc instance. RED in particular
>> got two qevents: early_drop and mark. Drivers that wish to offload these
>> blocks will be sent the usual notification, and need to know which qdisc it
>> is related to.
>>
>> To that end, extend flow_block_offload with a "sch" pointer, and initialize
>> as appropriate. This prompts changes in the indirect block facility, which
>> now tracks the scheduler instead of the netdevice. Update signatures of
>> several functions similarly. Deduce the device from the scheduler when
>> necessary.
>>
>> Signed-off-by: Petr Machata <petrm@mellanox.com>
>> Reviewed-by: Jiri Pirko <jiri@mellanox.com>
>> Signed-off-by: Ido Schimmel <idosch@mellanox.com>
>> ---
>>  drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c  | 11 ++++++----
>>  .../ethernet/mellanox/mlx5/core/en/rep/tc.c   | 11 +++++-----
>>  .../net/ethernet/netronome/nfp/flower/main.h  |  2 +-
>>  .../ethernet/netronome/nfp/flower/offload.c   | 11 ++++++----
>>  include/net/flow_offload.h                    |  9 ++++----
>>  net/core/flow_offload.c                       | 12 +++++------
>>  net/netfilter/nf_flow_table_offload.c         | 17 +++++++--------
>>  net/netfilter/nf_tables_offload.c             | 20 ++++++++++--------
>>  net/sched/cls_api.c                           | 21 +++++++++++--------
>>  9 files changed, 63 insertions(+), 51 deletions(-)
>>
> [...]
>> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/tc.c
>> index eefeb1cdc2ee..4fc42c1955ff 100644
>> --- a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/tc.c
>> +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/tc.c
>> @@ -404,7 +404,7 @@ static void mlx5e_rep_indr_block_unbind(void *cb_priv)
>>  static LIST_HEAD(mlx5e_block_cb_list);
>>
>>  static int
>> -mlx5e_rep_indr_setup_block(struct net_device *netdev,
>> +mlx5e_rep_indr_setup_block(struct Qdisc *sch,
>>  			   struct mlx5e_rep_priv *rpriv,
>>  			   struct flow_block_offload *f,
>>  			   flow_setup_cb_t *setup_cb,
>> @@ -412,6 +412,7 @@ mlx5e_rep_indr_setup_block(struct net_device *netdev,
>>  			   void (*cleanup)(struct flow_block_cb *block_cb))
>>  {
>>  	struct mlx5e_priv *priv = netdev_priv(rpriv->netdev);
>> +	struct net_device *netdev = sch->dev_queue->dev;
>
> This break indirect block support for netfilter since the driver
> is assuming a Qdisc object.

Sorry, I don't follow. You mean mlx5 driver? What does it mean to
"assume a qdisc object"?

Is it incorrect to rely on the fact that the netdevice can be deduced
from a qdisc, or that there is always a qdisc associated with a block
binding point?
Pablo Neira Ayuso July 10, 2020, 3:26 p.m. UTC | #3
On Fri, Jul 10, 2020 at 05:15:39PM +0200, Petr Machata wrote:
> 
> Pablo Neira Ayuso <pablo@netfilter.org> writes:
> 
> > On Fri, Jul 10, 2020 at 04:56:54PM +0300, Ido Schimmel wrote:
> >> From: Petr Machata <petrm@mellanox.com>
> >>
> >> Previously, shared blocks were only relevant for the pseudo-qdiscs ingress
> >> and clsact. Recently, a qevent facility was introduced, which allows to
> >> bind blocks to well-defined slots of a qdisc instance. RED in particular
> >> got two qevents: early_drop and mark. Drivers that wish to offload these
> >> blocks will be sent the usual notification, and need to know which qdisc it
> >> is related to.
> >>
> >> To that end, extend flow_block_offload with a "sch" pointer, and initialize
> >> as appropriate. This prompts changes in the indirect block facility, which
> >> now tracks the scheduler instead of the netdevice. Update signatures of
> >> several functions similarly. Deduce the device from the scheduler when
> >> necessary.
> >>
> >> Signed-off-by: Petr Machata <petrm@mellanox.com>
> >> Reviewed-by: Jiri Pirko <jiri@mellanox.com>
> >> Signed-off-by: Ido Schimmel <idosch@mellanox.com>
> >> ---
> >>  drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c  | 11 ++++++----
> >>  .../ethernet/mellanox/mlx5/core/en/rep/tc.c   | 11 +++++-----
> >>  .../net/ethernet/netronome/nfp/flower/main.h  |  2 +-
> >>  .../ethernet/netronome/nfp/flower/offload.c   | 11 ++++++----
> >>  include/net/flow_offload.h                    |  9 ++++----
> >>  net/core/flow_offload.c                       | 12 +++++------
> >>  net/netfilter/nf_flow_table_offload.c         | 17 +++++++--------
> >>  net/netfilter/nf_tables_offload.c             | 20 ++++++++++--------
> >>  net/sched/cls_api.c                           | 21 +++++++++++--------
> >>  9 files changed, 63 insertions(+), 51 deletions(-)
> >>
> > [...]
> >> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/tc.c
> >> index eefeb1cdc2ee..4fc42c1955ff 100644
> >> --- a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/tc.c
> >> +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/tc.c
> >> @@ -404,7 +404,7 @@ static void mlx5e_rep_indr_block_unbind(void *cb_priv)
> >>  static LIST_HEAD(mlx5e_block_cb_list);
> >>
> >>  static int
> >> -mlx5e_rep_indr_setup_block(struct net_device *netdev,
> >> +mlx5e_rep_indr_setup_block(struct Qdisc *sch,
> >>  			   struct mlx5e_rep_priv *rpriv,
> >>  			   struct flow_block_offload *f,
> >>  			   flow_setup_cb_t *setup_cb,
> >> @@ -412,6 +412,7 @@ mlx5e_rep_indr_setup_block(struct net_device *netdev,
> >>  			   void (*cleanup)(struct flow_block_cb *block_cb))
> >>  {
> >>  	struct mlx5e_priv *priv = netdev_priv(rpriv->netdev);
> >> +	struct net_device *netdev = sch->dev_queue->dev;
> >
> > This break indirect block support for netfilter since the driver
> > is assuming a Qdisc object.
> 
> Sorry, I don't follow. You mean mlx5 driver? What does it mean to
> "assume a qdisc object"?
> 
> Is it incorrect to rely on the fact that the netdevice can be deduced
> from a qdisc, or that there is always a qdisc associated with a block
> binding point?

The drivers assume that the xyz_indr_setup_block() always gets a sch
object, which is not always true. Are you really sure this will work
for the TC CT offload?

--- a/net/netfilter/nf_flow_table_offload.c
+++ b/net/netfilter/nf_flow_table_offload.c
@@ -928,26 +928,27 @@ static int nf_flow_table_block_setup(struct nf_flowtable *flowtable,
 }

 static void nf_flow_table_block_offload_init(struct flow_block_offload *bo,
-                                            struct net *net,
+                                            struct net_device *dev,
                                             enum flow_block_command cmd,
                                             struct nf_flowtable *flowtable,
                                             struct netlink_ext_ack *extack)
 {
        memset(bo, 0, sizeof(*bo));
-       bo->net         = net;
+       bo->net         = dev_net(dev);
        bo->block       = &flowtable->flow_block;
        bo->command     = cmd;
        bo->binder_type = FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS;
        bo->extack      = extack;
+       bo->sch         = dev_ingress_queue(dev)->qdisc_sleeping;
        INIT_LIST_HEAD(&bo->cb_list);
 }

 static void nf_flow_table_indr_cleanup(struct flow_block_cb *block_cb)
 {
        struct nf_flowtable *flowtable = block_cb->indr.data;
-       struct net_device *dev = block_cb->indr.dev;
+       struct Qdisc *sch = block_cb->indr.sch;

-       nf_flow_table_gc_cleanup(flowtable, dev);
+       nf_flow_table_gc_cleanup(flowtable, sch->dev_queue->dev);
        down_write(&flowtable->flow_block_lock);
        list_del(&block_cb->list);
        list_del(&block_cb->driver_list);

Moreover, the flow_offload infrastructure should also remain
independent from the front-end, either tc/netfilter/ethtool, this is
pulling in tc specific stuff into it, eg.

diff --git a/include/net/flow_offload.h b/include/net/flow_offload.h
index de395498440d..fda29140bdc5 100644
--- a/include/net/flow_offload.h
+++ b/include/net/flow_offload.h
@@ -444,6 +444,7 @@ struct flow_block_offload {
        struct list_head cb_list;
        struct list_head *driver_block_list;
        struct netlink_ext_ack *extack;
+       struct Qdisc *sch;
 };

 enum tc_setup_type;
@@ -454,7 +455,7 @@ struct flow_block_cb;

 struct flow_block_indr {
        struct list_head                list;
-       struct net_device               *dev;
+       struct Qdisc                    *sch;
        enum flow_block_binder_type     binder_type;
        void                            *data;
        void                            *cb_priv;
@@ -479,7 +480,7 @@ struct flow_block_cb *flow_indr_block_cb_alloc(flow_setup_cb_t *cb,
                                               void *cb_ident, void *cb_priv,
                                               void (*release)(void *cb_priv),
                                               struct flow_block_offload *bo,
-                                              struct net_device *dev, void *data,
+                                              struct Qdisc *sch, void *data,
                                               void *indr_cb_priv,
                                               void (*cleanup)(struct flow_block_cb *block_cb));
 void flow_block_cb_free(struct flow_block_cb *block_cb);
Petr Machata July 10, 2020, 4:22 p.m. UTC | #4
Pablo Neira Ayuso <pablo@netfilter.org> writes:

>> >> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/tc.c
>> >> index eefeb1cdc2ee..4fc42c1955ff 100644
>> >> --- a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/tc.c
>> >> +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/tc.c
>> >> @@ -404,7 +404,7 @@ static void mlx5e_rep_indr_block_unbind(void *cb_priv)
>> >>  static LIST_HEAD(mlx5e_block_cb_list);
>> >>
>> >>  static int
>> >> -mlx5e_rep_indr_setup_block(struct net_device *netdev,
>> >> +mlx5e_rep_indr_setup_block(struct Qdisc *sch,
>> >>  			   struct mlx5e_rep_priv *rpriv,
>> >>  			   struct flow_block_offload *f,
>> >>  			   flow_setup_cb_t *setup_cb,
>> >> @@ -412,6 +412,7 @@ mlx5e_rep_indr_setup_block(struct net_device *netdev,
>> >>  			   void (*cleanup)(struct flow_block_cb *block_cb))
>> >>  {
>> >>  	struct mlx5e_priv *priv = netdev_priv(rpriv->netdev);
>> >> +	struct net_device *netdev = sch->dev_queue->dev;
>> >
>> > This break indirect block support for netfilter since the driver
>> > is assuming a Qdisc object.
>>
>> Sorry, I don't follow. You mean mlx5 driver? What does it mean to
>> "assume a qdisc object"?
>>
>> Is it incorrect to rely on the fact that the netdevice can be deduced
>> from a qdisc, or that there is always a qdisc associated with a block
>> binding point?
>
> The drivers assume that the xyz_indr_setup_block() always gets a sch
> object, which is not always true. Are you really sure this will work
> for the TC CT offload?

I tested indirect blocks in general, but not CT offload.

> --- a/net/netfilter/nf_flow_table_offload.c
> +++ b/net/netfilter/nf_flow_table_offload.c
> @@ -928,26 +928,27 @@ static int nf_flow_table_block_setup(struct nf_flowtable *flowtable,
>  }
>
>  static void nf_flow_table_block_offload_init(struct flow_block_offload *bo,
> -                                            struct net *net,
> +                                            struct net_device *dev,
>                                              enum flow_block_command cmd,
>                                              struct nf_flowtable *flowtable,
>                                              struct netlink_ext_ack *extack)
>  {
>         memset(bo, 0, sizeof(*bo));
> -       bo->net         = net;
> +       bo->net         = dev_net(dev);
>         bo->block       = &flowtable->flow_block;
>         bo->command     = cmd;
>         bo->binder_type = FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS;
>         bo->extack      = extack;
> +       bo->sch         = dev_ingress_queue(dev)->qdisc_sleeping;
>         INIT_LIST_HEAD(&bo->cb_list);
>  }
>
>  static void nf_flow_table_indr_cleanup(struct flow_block_cb *block_cb)
>  {
>         struct nf_flowtable *flowtable = block_cb->indr.data;
> -       struct net_device *dev = block_cb->indr.dev;
> +       struct Qdisc *sch = block_cb->indr.sch;
>
> -       nf_flow_table_gc_cleanup(flowtable, dev);
> +       nf_flow_table_gc_cleanup(flowtable, sch->dev_queue->dev);
>         down_write(&flowtable->flow_block_lock);
>         list_del(&block_cb->list);
>         list_del(&block_cb->driver_list);
>
> Moreover, the flow_offload infrastructure should also remain
> independent from the front-end, either tc/netfilter/ethtool, this is
> pulling in tc specific stuff into it, eg.

Hmm, OK, so I should not have assumed there is always a qdisc associated
with a blocks.

I'm not sure how strong your objection to pulling in TC is. Would it be
OK, instead of replacing the device with a qdisc in flow_block_indr, to
put in both? The qdisc can be NULL for the "normal" binder types,
because there the block is uniquely identified just by the type. For the
"non-normal" ones it would be obvious how to initialize it.

> diff --git a/include/net/flow_offload.h b/include/net/flow_offload.h
> index de395498440d..fda29140bdc5 100644
> --- a/include/net/flow_offload.h
> +++ b/include/net/flow_offload.h
> @@ -444,6 +444,7 @@ struct flow_block_offload {
>         struct list_head cb_list;
>         struct list_head *driver_block_list;
>         struct netlink_ext_ack *extack;
> +       struct Qdisc *sch;
>  };
>
>  enum tc_setup_type;
> @@ -454,7 +455,7 @@ struct flow_block_cb;
>
>  struct flow_block_indr {
>         struct list_head                list;
> -       struct net_device               *dev;
> +       struct Qdisc                    *sch;
>         enum flow_block_binder_type     binder_type;
>         void                            *data;
>         void                            *cb_priv;
> @@ -479,7 +480,7 @@ struct flow_block_cb *flow_indr_block_cb_alloc(flow_setup_cb_t *cb,
>                                                void *cb_ident, void *cb_priv,
>                                                void (*release)(void *cb_priv),
>                                                struct flow_block_offload *bo,
> -                                              struct net_device *dev, void *data,
> +                                              struct Qdisc *sch, void *data,
>                                                void *indr_cb_priv,
>                                                void (*cleanup)(struct flow_block_cb *block_cb));
>  void flow_block_cb_free(struct flow_block_cb *block_cb);
Pablo Neira Ayuso July 10, 2020, 5:13 p.m. UTC | #5
On Fri, Jul 10, 2020 at 06:22:03PM +0200, Petr Machata wrote:
> 
> Pablo Neira Ayuso <pablo@netfilter.org> writes:
> 
> >> >> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/tc.c
> >> >> index eefeb1cdc2ee..4fc42c1955ff 100644
> >> >> --- a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/tc.c
> >> >> +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/tc.c
> >> >> @@ -404,7 +404,7 @@ static void mlx5e_rep_indr_block_unbind(void *cb_priv)
> >> >>  static LIST_HEAD(mlx5e_block_cb_list);
> >> >>
> >> >>  static int
> >> >> -mlx5e_rep_indr_setup_block(struct net_device *netdev,
> >> >> +mlx5e_rep_indr_setup_block(struct Qdisc *sch,
> >> >>  			   struct mlx5e_rep_priv *rpriv,
> >> >>  			   struct flow_block_offload *f,
> >> >>  			   flow_setup_cb_t *setup_cb,
> >> >> @@ -412,6 +412,7 @@ mlx5e_rep_indr_setup_block(struct net_device *netdev,
> >> >>  			   void (*cleanup)(struct flow_block_cb *block_cb))
> >> >>  {
> >> >>  	struct mlx5e_priv *priv = netdev_priv(rpriv->netdev);
> >> >> +	struct net_device *netdev = sch->dev_queue->dev;
> >> >
> >> > This break indirect block support for netfilter since the driver
> >> > is assuming a Qdisc object.
> >>
> >> Sorry, I don't follow. You mean mlx5 driver? What does it mean to
> >> "assume a qdisc object"?
> >>
> >> Is it incorrect to rely on the fact that the netdevice can be deduced
> >> from a qdisc, or that there is always a qdisc associated with a block
> >> binding point?
> >
> > The drivers assume that the xyz_indr_setup_block() always gets a sch
> > object, which is not always true. Are you really sure this will work
> > for the TC CT offload?
> 
> I tested indirect blocks in general, but not CT offload.
> 
> > --- a/net/netfilter/nf_flow_table_offload.c
> > +++ b/net/netfilter/nf_flow_table_offload.c
> > @@ -928,26 +928,27 @@ static int nf_flow_table_block_setup(struct nf_flowtable *flowtable,
> >  }
> >
> >  static void nf_flow_table_block_offload_init(struct flow_block_offload *bo,
> > -                                            struct net *net,
> > +                                            struct net_device *dev,
> >                                              enum flow_block_command cmd,
> >                                              struct nf_flowtable *flowtable,
> >                                              struct netlink_ext_ack *extack)
> >  {
> >         memset(bo, 0, sizeof(*bo));
> > -       bo->net         = net;
> > +       bo->net         = dev_net(dev);
> >         bo->block       = &flowtable->flow_block;
> >         bo->command     = cmd;
> >         bo->binder_type = FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS;
> >         bo->extack      = extack;
> > +       bo->sch         = dev_ingress_queue(dev)->qdisc_sleeping;
> >         INIT_LIST_HEAD(&bo->cb_list);
> >  }
> >
> >  static void nf_flow_table_indr_cleanup(struct flow_block_cb *block_cb)
> >  {
> >         struct nf_flowtable *flowtable = block_cb->indr.data;
> > -       struct net_device *dev = block_cb->indr.dev;
> > +       struct Qdisc *sch = block_cb->indr.sch;
> >
> > -       nf_flow_table_gc_cleanup(flowtable, dev);
> > +       nf_flow_table_gc_cleanup(flowtable, sch->dev_queue->dev);
> >         down_write(&flowtable->flow_block_lock);
> >         list_del(&block_cb->list);
> >         list_del(&block_cb->driver_list);
> >
> > Moreover, the flow_offload infrastructure should also remain
> > independent from the front-end, either tc/netfilter/ethtool, this is
> > pulling in tc specific stuff into it, eg.
> 
> Hmm, OK, so I should not have assumed there is always a qdisc associated
> with a blocks.
> 
> I'm not sure how strong your objection to pulling in TC is. Would it be
> OK, instead of replacing the device with a qdisc in flow_block_indr, to
> put in both? The qdisc can be NULL for the "normal" binder types,
> because there the block is uniquely identified just by the type. For the
> "non-normal" ones it would be obvious how to initialize it.

Adding an extra field to flow_block_indr instead of replacing struct
net_device should be ok for your new qevent use-case, right? This new
Qdisc field will be NULL for the existing use-cases, that is what you
mean, correct?

I still did not have a look at this new qevent infrastructure, so I
don't have a better proposal right now.

Thanks.
Petr Machata July 10, 2020, 6:01 p.m. UTC | #6
Pablo Neira Ayuso <pablo@netfilter.org> writes:

> On Fri, Jul 10, 2020 at 06:22:03PM +0200, Petr Machata wrote:
>> 
>> Pablo Neira Ayuso <pablo@netfilter.org> writes:
>> 
>> > Moreover, the flow_offload infrastructure should also remain
>> > independent from the front-end, either tc/netfilter/ethtool, this is
>> > pulling in tc specific stuff into it, eg.
>> 
>> Hmm, OK, so I should not have assumed there is always a qdisc associated
>> with a block.
>> 
>> I'm not sure how strong your objection to pulling in TC is. Would it be
>> OK, instead of replacing the device with a qdisc in flow_block_indr, to
>> put in both? The qdisc can be NULL for the "normal" binder types,
>> because there the block is uniquely identified just by the type. For the
>> "non-normal" ones it would be obvious how to initialize it.
>
> Adding an extra field to flow_block_indr instead of replacing struct
> net_device should be ok for your new qevent use-case, right? This new
> Qdisc field will be NULL for the existing use-cases, that is what you
> mean, correct?

Yes, that is what I have in mind.

OK, I'll update the patches accordingly. Thanks!

> I still did not have a look at this new qevent infrastructure, so I
> don't have a better proposal right now.
diff mbox series

Patch

diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
index 0a9a4467d7c7..fd016adfde5d 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
@@ -1888,10 +1888,11 @@  static void bnxt_tc_setup_indr_rel(void *cb_priv)
 	kfree(priv);
 }
 
-static int bnxt_tc_setup_indr_block(struct net_device *netdev, struct bnxt *bp,
+static int bnxt_tc_setup_indr_block(struct Qdisc *sch, struct bnxt *bp,
 				    struct flow_block_offload *f, void *data,
 				    void (*cleanup)(struct flow_block_cb *block_cb))
 {
+	struct net_device *netdev = sch->dev_queue->dev;
 	struct bnxt_flower_indr_block_cb_priv *cb_priv;
 	struct flow_block_cb *block_cb;
 
@@ -1911,7 +1912,7 @@  static int bnxt_tc_setup_indr_block(struct net_device *netdev, struct bnxt *bp,
 		block_cb = flow_indr_block_cb_alloc(bnxt_tc_setup_indr_block_cb,
 						    cb_priv, cb_priv,
 						    bnxt_tc_setup_indr_rel, f,
-						    netdev, data, bp, cleanup);
+						    sch, data, bp, cleanup);
 		if (IS_ERR(block_cb)) {
 			list_del(&cb_priv->list);
 			kfree(cb_priv);
@@ -1946,17 +1947,19 @@  static bool bnxt_is_netdev_indr_offload(struct net_device *netdev)
 	return netif_is_vxlan(netdev);
 }
 
-static int bnxt_tc_setup_indr_cb(struct net_device *netdev, void *cb_priv,
+static int bnxt_tc_setup_indr_cb(struct Qdisc *sch, void *cb_priv,
 				 enum tc_setup_type type, void *type_data,
 				 void *data,
 				 void (*cleanup)(struct flow_block_cb *block_cb))
 {
+	struct net_device *netdev = sch->dev_queue->dev;
+
 	if (!bnxt_is_netdev_indr_offload(netdev))
 		return -EOPNOTSUPP;
 
 	switch (type) {
 	case TC_SETUP_BLOCK:
-		return bnxt_tc_setup_indr_block(netdev, cb_priv, type_data, data,
+		return bnxt_tc_setup_indr_block(sch, cb_priv, type_data, data,
 						cleanup);
 	default:
 		break;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/tc.c
index eefeb1cdc2ee..4fc42c1955ff 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/tc.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/tc.c
@@ -404,7 +404,7 @@  static void mlx5e_rep_indr_block_unbind(void *cb_priv)
 static LIST_HEAD(mlx5e_block_cb_list);
 
 static int
-mlx5e_rep_indr_setup_block(struct net_device *netdev,
+mlx5e_rep_indr_setup_block(struct Qdisc *sch,
 			   struct mlx5e_rep_priv *rpriv,
 			   struct flow_block_offload *f,
 			   flow_setup_cb_t *setup_cb,
@@ -412,6 +412,7 @@  mlx5e_rep_indr_setup_block(struct net_device *netdev,
 			   void (*cleanup)(struct flow_block_cb *block_cb))
 {
 	struct mlx5e_priv *priv = netdev_priv(rpriv->netdev);
+	struct net_device *netdev = sch->dev_queue->dev;
 	struct mlx5e_rep_indr_block_priv *indr_priv;
 	struct flow_block_cb *block_cb;
 
@@ -442,7 +443,7 @@  mlx5e_rep_indr_setup_block(struct net_device *netdev,
 
 		block_cb = flow_indr_block_cb_alloc(setup_cb, indr_priv, indr_priv,
 						    mlx5e_rep_indr_block_unbind,
-						    f, netdev, data, rpriv,
+						    f, sch, data, rpriv,
 						    cleanup);
 		if (IS_ERR(block_cb)) {
 			list_del(&indr_priv->list);
@@ -472,18 +473,18 @@  mlx5e_rep_indr_setup_block(struct net_device *netdev,
 }
 
 static
-int mlx5e_rep_indr_setup_cb(struct net_device *netdev, void *cb_priv,
+int mlx5e_rep_indr_setup_cb(struct Qdisc *sch, void *cb_priv,
 			    enum tc_setup_type type, void *type_data,
 			    void *data,
 			    void (*cleanup)(struct flow_block_cb *block_cb))
 {
 	switch (type) {
 	case TC_SETUP_BLOCK:
-		return mlx5e_rep_indr_setup_block(netdev, cb_priv, type_data,
+		return mlx5e_rep_indr_setup_block(sch, cb_priv, type_data,
 						  mlx5e_rep_indr_setup_tc_cb,
 						  data, cleanup);
 	case TC_SETUP_FT:
-		return mlx5e_rep_indr_setup_block(netdev, cb_priv, type_data,
+		return mlx5e_rep_indr_setup_block(sch, cb_priv, type_data,
 						  mlx5e_rep_indr_setup_ft_cb,
 						  data, cleanup);
 	default:
diff --git a/drivers/net/ethernet/netronome/nfp/flower/main.h b/drivers/net/ethernet/netronome/nfp/flower/main.h
index 7f54a620acad..84f1b69bc6dd 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/main.h
+++ b/drivers/net/ethernet/netronome/nfp/flower/main.h
@@ -458,7 +458,7 @@  void nfp_flower_qos_cleanup(struct nfp_app *app);
 int nfp_flower_setup_qos_offload(struct nfp_app *app, struct net_device *netdev,
 				 struct tc_cls_matchall_offload *flow);
 void nfp_flower_stats_rlim_reply(struct nfp_app *app, struct sk_buff *skb);
-int nfp_flower_indr_setup_tc_cb(struct net_device *netdev, void *cb_priv,
+int nfp_flower_indr_setup_tc_cb(struct Qdisc *sch, void *cb_priv,
 				enum tc_setup_type type, void *type_data,
 				void *data,
 				void (*cleanup)(struct flow_block_cb *block_cb));
diff --git a/drivers/net/ethernet/netronome/nfp/flower/offload.c b/drivers/net/ethernet/netronome/nfp/flower/offload.c
index 3af27bb5f4b0..f2acce64613c 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/offload.c
+++ b/drivers/net/ethernet/netronome/nfp/flower/offload.c
@@ -1646,10 +1646,11 @@  void nfp_flower_setup_indr_tc_release(void *cb_priv)
 }
 
 static int
-nfp_flower_setup_indr_tc_block(struct net_device *netdev, struct nfp_app *app,
+nfp_flower_setup_indr_tc_block(struct Qdisc *sch, struct nfp_app *app,
 			       struct flow_block_offload *f, void *data,
 			       void (*cleanup)(struct flow_block_cb *block_cb))
 {
+	struct net_device *netdev = sch->dev_queue->dev;
 	struct nfp_flower_indr_block_cb_priv *cb_priv;
 	struct nfp_flower_priv *priv = app->priv;
 	struct flow_block_cb *block_cb;
@@ -1680,7 +1681,7 @@  nfp_flower_setup_indr_tc_block(struct net_device *netdev, struct nfp_app *app,
 		block_cb = flow_indr_block_cb_alloc(nfp_flower_setup_indr_block_cb,
 						    cb_priv, cb_priv,
 						    nfp_flower_setup_indr_tc_release,
-						    f, netdev, data, app, cleanup);
+						    f, sch, data, app, cleanup);
 		if (IS_ERR(block_cb)) {
 			list_del(&cb_priv->list);
 			kfree(cb_priv);
@@ -1711,17 +1712,19 @@  nfp_flower_setup_indr_tc_block(struct net_device *netdev, struct nfp_app *app,
 }
 
 int
-nfp_flower_indr_setup_tc_cb(struct net_device *netdev, void *cb_priv,
+nfp_flower_indr_setup_tc_cb(struct Qdisc *sch, void *cb_priv,
 			    enum tc_setup_type type, void *type_data,
 			    void *data,
 			    void (*cleanup)(struct flow_block_cb *block_cb))
 {
+	struct net_device *netdev = sch->dev_queue->dev;
+
 	if (!nfp_fl_is_netdev_to_offload(netdev))
 		return -EOPNOTSUPP;
 
 	switch (type) {
 	case TC_SETUP_BLOCK:
-		return nfp_flower_setup_indr_tc_block(netdev, cb_priv,
+		return nfp_flower_setup_indr_tc_block(sch, cb_priv,
 						      type_data, data, cleanup);
 	default:
 		return -EOPNOTSUPP;
diff --git a/include/net/flow_offload.h b/include/net/flow_offload.h
index de395498440d..fda29140bdc5 100644
--- a/include/net/flow_offload.h
+++ b/include/net/flow_offload.h
@@ -444,6 +444,7 @@  struct flow_block_offload {
 	struct list_head cb_list;
 	struct list_head *driver_block_list;
 	struct netlink_ext_ack *extack;
+	struct Qdisc *sch;
 };
 
 enum tc_setup_type;
@@ -454,7 +455,7 @@  struct flow_block_cb;
 
 struct flow_block_indr {
 	struct list_head		list;
-	struct net_device		*dev;
+	struct Qdisc			*sch;
 	enum flow_block_binder_type	binder_type;
 	void				*data;
 	void				*cb_priv;
@@ -479,7 +480,7 @@  struct flow_block_cb *flow_indr_block_cb_alloc(flow_setup_cb_t *cb,
 					       void *cb_ident, void *cb_priv,
 					       void (*release)(void *cb_priv),
 					       struct flow_block_offload *bo,
-					       struct net_device *dev, void *data,
+					       struct Qdisc *sch, void *data,
 					       void *indr_cb_priv,
 					       void (*cleanup)(struct flow_block_cb *block_cb));
 void flow_block_cb_free(struct flow_block_cb *block_cb);
@@ -553,7 +554,7 @@  static inline void flow_block_init(struct flow_block *flow_block)
 	INIT_LIST_HEAD(&flow_block->cb_list);
 }
 
-typedef int flow_indr_block_bind_cb_t(struct net_device *dev, void *cb_priv,
+typedef int flow_indr_block_bind_cb_t(struct Qdisc *sch, void *cb_priv,
 				      enum tc_setup_type type, void *type_data,
 				      void *data,
 				      void (*cleanup)(struct flow_block_cb *block_cb));
@@ -561,7 +562,7 @@  typedef int flow_indr_block_bind_cb_t(struct net_device *dev, void *cb_priv,
 int flow_indr_dev_register(flow_indr_block_bind_cb_t *cb, void *cb_priv);
 void flow_indr_dev_unregister(flow_indr_block_bind_cb_t *cb, void *cb_priv,
 			      void (*release)(void *cb_priv));
-int flow_indr_dev_setup_offload(struct net_device *dev,
+int flow_indr_dev_setup_offload(struct Qdisc *sch,
 				enum tc_setup_type type, void *data,
 				struct flow_block_offload *bo,
 				void (*cleanup)(struct flow_block_cb *block_cb));
diff --git a/net/core/flow_offload.c b/net/core/flow_offload.c
index b739cfab796e..9877c55f3e77 100644
--- a/net/core/flow_offload.c
+++ b/net/core/flow_offload.c
@@ -429,14 +429,14 @@  EXPORT_SYMBOL(flow_indr_dev_unregister);
 
 static void flow_block_indr_init(struct flow_block_cb *flow_block,
 				 struct flow_block_offload *bo,
-				 struct net_device *dev, void *data,
+				 struct Qdisc *sch, void *data,
 				 void *cb_priv,
 				 void (*cleanup)(struct flow_block_cb *block_cb))
 {
 	flow_block->indr.binder_type = bo->binder_type;
 	flow_block->indr.data = data;
 	flow_block->indr.cb_priv = cb_priv;
-	flow_block->indr.dev = dev;
+	flow_block->indr.sch = sch;
 	flow_block->indr.cleanup = cleanup;
 }
 
@@ -444,7 +444,7 @@  struct flow_block_cb *flow_indr_block_cb_alloc(flow_setup_cb_t *cb,
 					       void *cb_ident, void *cb_priv,
 					       void (*release)(void *cb_priv),
 					       struct flow_block_offload *bo,
-					       struct net_device *dev, void *data,
+					       struct Qdisc *sch, void *data,
 					       void *indr_cb_priv,
 					       void (*cleanup)(struct flow_block_cb *block_cb))
 {
@@ -454,7 +454,7 @@  struct flow_block_cb *flow_indr_block_cb_alloc(flow_setup_cb_t *cb,
 	if (IS_ERR(block_cb))
 		goto out;
 
-	flow_block_indr_init(block_cb, bo, dev, data, indr_cb_priv, cleanup);
+	flow_block_indr_init(block_cb, bo, sch, data, indr_cb_priv, cleanup);
 	list_add(&block_cb->indr.list, &flow_block_indr_list);
 
 out:
@@ -462,7 +462,7 @@  struct flow_block_cb *flow_indr_block_cb_alloc(flow_setup_cb_t *cb,
 }
 EXPORT_SYMBOL(flow_indr_block_cb_alloc);
 
-int flow_indr_dev_setup_offload(struct net_device *dev,
+int flow_indr_dev_setup_offload(struct Qdisc *sch,
 				enum tc_setup_type type, void *data,
 				struct flow_block_offload *bo,
 				void (*cleanup)(struct flow_block_cb *block_cb))
@@ -471,7 +471,7 @@  int flow_indr_dev_setup_offload(struct net_device *dev,
 
 	mutex_lock(&flow_indr_block_lock);
 	list_for_each_entry(this, &flow_block_indr_dev_list, list)
-		this->cb(dev, this->cb_priv, type, bo, data, cleanup);
+		this->cb(sch, this->cb_priv, type, bo, data, cleanup);
 
 	mutex_unlock(&flow_indr_block_lock);
 
diff --git a/net/netfilter/nf_flow_table_offload.c b/net/netfilter/nf_flow_table_offload.c
index 5fff1e040168..2319190b1364 100644
--- a/net/netfilter/nf_flow_table_offload.c
+++ b/net/netfilter/nf_flow_table_offload.c
@@ -928,26 +928,27 @@  static int nf_flow_table_block_setup(struct nf_flowtable *flowtable,
 }
 
 static void nf_flow_table_block_offload_init(struct flow_block_offload *bo,
-					     struct net *net,
+					     struct net_device *dev,
 					     enum flow_block_command cmd,
 					     struct nf_flowtable *flowtable,
 					     struct netlink_ext_ack *extack)
 {
 	memset(bo, 0, sizeof(*bo));
-	bo->net		= net;
+	bo->net		= dev_net(dev);
 	bo->block	= &flowtable->flow_block;
 	bo->command	= cmd;
 	bo->binder_type	= FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS;
 	bo->extack	= extack;
+	bo->sch		= dev_ingress_queue(dev)->qdisc_sleeping;
 	INIT_LIST_HEAD(&bo->cb_list);
 }
 
 static void nf_flow_table_indr_cleanup(struct flow_block_cb *block_cb)
 {
 	struct nf_flowtable *flowtable = block_cb->indr.data;
-	struct net_device *dev = block_cb->indr.dev;
+	struct Qdisc *sch = block_cb->indr.sch;
 
-	nf_flow_table_gc_cleanup(flowtable, dev);
+	nf_flow_table_gc_cleanup(flowtable, sch->dev_queue->dev);
 	down_write(&flowtable->flow_block_lock);
 	list_del(&block_cb->list);
 	list_del(&block_cb->driver_list);
@@ -961,10 +962,9 @@  static int nf_flow_table_indr_offload_cmd(struct flow_block_offload *bo,
 					  enum flow_block_command cmd,
 					  struct netlink_ext_ack *extack)
 {
-	nf_flow_table_block_offload_init(bo, dev_net(dev), cmd, flowtable,
-					 extack);
+	nf_flow_table_block_offload_init(bo, dev, cmd, flowtable, extack);
 
-	return flow_indr_dev_setup_offload(dev, TC_SETUP_FT, flowtable, bo,
+	return flow_indr_dev_setup_offload(bo->sch, TC_SETUP_FT, flowtable, bo,
 					   nf_flow_table_indr_cleanup);
 }
 
@@ -976,8 +976,7 @@  static int nf_flow_table_offload_cmd(struct flow_block_offload *bo,
 {
 	int err;
 
-	nf_flow_table_block_offload_init(bo, dev_net(dev), cmd, flowtable,
-					 extack);
+	nf_flow_table_block_offload_init(bo, dev, cmd, flowtable, extack);
 	err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_FT, bo);
 	if (err < 0)
 		return err;
diff --git a/net/netfilter/nf_tables_offload.c b/net/netfilter/nf_tables_offload.c
index c7cf1cde46de..78dc93607d09 100644
--- a/net/netfilter/nf_tables_offload.c
+++ b/net/netfilter/nf_tables_offload.c
@@ -254,17 +254,18 @@  static int nft_block_setup(struct nft_base_chain *basechain,
 }
 
 static void nft_flow_block_offload_init(struct flow_block_offload *bo,
-					struct net *net,
+					struct net_device *dev,
 					enum flow_block_command cmd,
 					struct nft_base_chain *basechain,
 					struct netlink_ext_ack *extack)
 {
 	memset(bo, 0, sizeof(*bo));
-	bo->net		= net;
+	bo->net		= dev_net(dev);
 	bo->block	= &basechain->flow_block;
 	bo->command	= cmd;
 	bo->binder_type	= FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS;
 	bo->extack	= extack;
+	bo->sch		= dev_ingress_queue(dev)->qdisc_sleeping;
 	INIT_LIST_HEAD(&bo->cb_list);
 }
 
@@ -276,7 +277,7 @@  static int nft_block_offload_cmd(struct nft_base_chain *chain,
 	struct flow_block_offload bo;
 	int err;
 
-	nft_flow_block_offload_init(&bo, dev_net(dev), cmd, chain, &extack);
+	nft_flow_block_offload_init(&bo, dev, cmd, chain, &extack);
 
 	err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_BLOCK, &bo);
 	if (err < 0)
@@ -288,13 +289,14 @@  static int nft_block_offload_cmd(struct nft_base_chain *chain,
 static void nft_indr_block_cleanup(struct flow_block_cb *block_cb)
 {
 	struct nft_base_chain *basechain = block_cb->indr.data;
-	struct net_device *dev = block_cb->indr.dev;
+	struct Qdisc *sch = block_cb->indr.sch;
 	struct netlink_ext_ack extack = {};
-	struct net *net = dev_net(dev);
+	struct net *net = qdisc_net(sch);
 	struct flow_block_offload bo;
+	struct net_device *dev;
 
-	nft_flow_block_offload_init(&bo, dev_net(dev), FLOW_BLOCK_UNBIND,
-				    basechain, &extack);
+	dev = sch->dev_queue->dev;
+	nft_flow_block_offload_init(&bo, dev, FLOW_BLOCK_UNBIND, basechain, &extack);
 	mutex_lock(&net->nft.commit_mutex);
 	list_del(&block_cb->driver_list);
 	list_move(&block_cb->list, &bo.cb_list);
@@ -310,9 +312,9 @@  static int nft_indr_block_offload_cmd(struct nft_base_chain *basechain,
 	struct flow_block_offload bo;
 	int err;
 
-	nft_flow_block_offload_init(&bo, dev_net(dev), cmd, basechain, &extack);
+	nft_flow_block_offload_init(&bo, dev, cmd, basechain, &extack);
 
-	err = flow_indr_dev_setup_offload(dev, TC_SETUP_BLOCK, basechain, &bo,
+	err = flow_indr_dev_setup_offload(bo.sch, TC_SETUP_BLOCK, basechain, &bo,
 					  nft_indr_block_cleanup);
 	if (err < 0)
 		return err;
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index e9e119ea6813..0e80b4a7f5fd 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -622,18 +622,21 @@  static int tcf_block_setup(struct tcf_block *block,
 			   struct flow_block_offload *bo);
 
 static void tcf_block_offload_init(struct flow_block_offload *bo,
-				   struct net_device *dev,
+				   struct Qdisc *sch,
 				   enum flow_block_command command,
 				   enum flow_block_binder_type binder_type,
 				   struct flow_block *flow_block,
 				   bool shared, struct netlink_ext_ack *extack)
 {
+	struct net_device *dev = sch->dev_queue->dev;
+
 	bo->net = dev_net(dev);
 	bo->command = command;
 	bo->binder_type = binder_type;
 	bo->block = flow_block;
 	bo->block_shared = shared;
 	bo->extack = extack;
+	bo->sch = sch;
 	INIT_LIST_HEAD(&bo->cb_list);
 }
 
@@ -643,11 +646,11 @@  static void tcf_block_unbind(struct tcf_block *block,
 static void tc_block_indr_cleanup(struct flow_block_cb *block_cb)
 {
 	struct tcf_block *block = block_cb->indr.data;
-	struct net_device *dev = block_cb->indr.dev;
+	struct Qdisc *sch = block_cb->indr.sch;
 	struct netlink_ext_ack extack = {};
 	struct flow_block_offload bo;
 
-	tcf_block_offload_init(&bo, dev, FLOW_BLOCK_UNBIND,
+	tcf_block_offload_init(&bo, sch, FLOW_BLOCK_UNBIND,
 			       block_cb->indr.binder_type,
 			       &block->flow_block, tcf_block_shared(block),
 			       &extack);
@@ -666,14 +669,15 @@  static bool tcf_block_offload_in_use(struct tcf_block *block)
 }
 
 static int tcf_block_offload_cmd(struct tcf_block *block,
-				 struct net_device *dev,
+				 struct Qdisc *sch,
 				 struct tcf_block_ext_info *ei,
 				 enum flow_block_command command,
 				 struct netlink_ext_ack *extack)
 {
+	struct net_device *dev = sch->dev_queue->dev;
 	struct flow_block_offload bo = {};
 
-	tcf_block_offload_init(&bo, dev, command, ei->binder_type,
+	tcf_block_offload_init(&bo, sch, command, ei->binder_type,
 			       &block->flow_block, tcf_block_shared(block),
 			       extack);
 
@@ -690,7 +694,7 @@  static int tcf_block_offload_cmd(struct tcf_block *block,
 		return tcf_block_setup(block, &bo);
 	}
 
-	flow_indr_dev_setup_offload(dev, TC_SETUP_BLOCK, block, &bo,
+	flow_indr_dev_setup_offload(sch, TC_SETUP_BLOCK, block, &bo,
 				    tc_block_indr_cleanup);
 	tcf_block_setup(block, &bo);
 
@@ -717,7 +721,7 @@  static int tcf_block_offload_bind(struct tcf_block *block, struct Qdisc *q,
 		goto err_unlock;
 	}
 
-	err = tcf_block_offload_cmd(block, dev, ei, FLOW_BLOCK_BIND, extack);
+	err = tcf_block_offload_cmd(block, q, ei, FLOW_BLOCK_BIND, extack);
 	if (err == -EOPNOTSUPP)
 		goto no_offload_dev_inc;
 	if (err)
@@ -740,11 +744,10 @@  static int tcf_block_offload_bind(struct tcf_block *block, struct Qdisc *q,
 static void tcf_block_offload_unbind(struct tcf_block *block, struct Qdisc *q,
 				     struct tcf_block_ext_info *ei)
 {
-	struct net_device *dev = q->dev_queue->dev;
 	int err;
 
 	down_write(&block->cb_lock);
-	err = tcf_block_offload_cmd(block, dev, ei, FLOW_BLOCK_UNBIND, NULL);
+	err = tcf_block_offload_cmd(block, q, ei, FLOW_BLOCK_UNBIND, NULL);
 	if (err == -EOPNOTSUPP)
 		goto no_offload_dev_dec;
 	up_write(&block->cb_lock);