flow_offload: move tc indirect block to flow offload
authorwenxu <wenxu@ucloud.cn>
Wed, 7 Aug 2019 01:13:52 +0000 (09:13 +0800)
committerDavid S. Miller <davem@davemloft.net>
Fri, 9 Aug 2019 01:44:30 +0000 (18:44 -0700)
move tc indirect block to flow_offload and rename
it to flow indirect block.The nf_tables can use the
indr block architecture.

Signed-off-by: wenxu <wenxu@ucloud.cn>
Acked-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
drivers/net/ethernet/netronome/nfp/flower/offload.c
include/net/flow_offload.h
include/net/pkt_cls.h
include/net/sch_generic.h
net/core/flow_offload.c
net/sched/cls_api.c

index fbb9de633578a0f967a1bb7f5ad890000d98082b..b7f113e996e5422a0d4a526b0a08e4e146930c4a 100644 (file)
@@ -781,9 +781,9 @@ static int mlx5e_rep_indr_register_block(struct mlx5e_rep_priv *rpriv,
 {
        int err;
 
-       err = __tc_indr_block_cb_register(netdev, rpriv,
-                                         mlx5e_rep_indr_setup_tc_cb,
-                                         rpriv);
+       err = __flow_indr_block_cb_register(netdev, rpriv,
+                                           mlx5e_rep_indr_setup_tc_cb,
+                                           rpriv);
        if (err) {
                struct mlx5e_priv *priv = netdev_priv(rpriv->netdev);
 
@@ -796,8 +796,8 @@ static int mlx5e_rep_indr_register_block(struct mlx5e_rep_priv *rpriv,
 static void mlx5e_rep_indr_unregister_block(struct mlx5e_rep_priv *rpriv,
                                            struct net_device *netdev)
 {
-       __tc_indr_block_cb_unregister(netdev, mlx5e_rep_indr_setup_tc_cb,
-                                     rpriv);
+       __flow_indr_block_cb_unregister(netdev, mlx5e_rep_indr_setup_tc_cb,
+                                       rpriv);
 }
 
 static int mlx5e_nic_rep_netdevice_event(struct notifier_block *nb,
index ff8a9f1a38f85cbce22bbfda175a6c7e1cf12c34..3a4f4f042ae789fbae51055664cfa5cebf5a4125 100644 (file)
@@ -1649,16 +1649,17 @@ int nfp_flower_reg_indir_block_handler(struct nfp_app *app,
                return NOTIFY_OK;
 
        if (event == NETDEV_REGISTER) {
-               err = __tc_indr_block_cb_register(netdev, app,
-                                                 nfp_flower_indr_setup_tc_cb,
-                                                 app);
+               err = __flow_indr_block_cb_register(netdev, app,
+                                                   nfp_flower_indr_setup_tc_cb,
+                                                   app);
                if (err)
                        nfp_flower_cmsg_warn(app,
                                             "Indirect block reg failed - %s\n",
                                             netdev->name);
        } else if (event == NETDEV_UNREGISTER) {
-               __tc_indr_block_cb_unregister(netdev,
-                                             nfp_flower_indr_setup_tc_cb, app);
+               __flow_indr_block_cb_unregister(netdev,
+                                               nfp_flower_indr_setup_tc_cb,
+                                               app);
        }
 
        return NOTIFY_OK;
index d3b12bc8a114a77c154e61cab68661865bcd04e4..46b8777ad05dc7af58638fe926911f7323c18045 100644 (file)
@@ -4,6 +4,7 @@
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <net/flow_dissector.h>
+#include <linux/rhashtable.h>
 
 struct flow_match {
        struct flow_dissector   *dissector;
@@ -370,4 +371,32 @@ 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,
+                                     enum tc_setup_type type, void *type_data);
+
+typedef void flow_indr_block_ing_cmd_t(struct net_device *dev,
+                                       flow_indr_block_bind_cb_t *cb,
+                                       void *cb_priv,
+                                       enum flow_block_command command);
+
+int __flow_indr_block_cb_register(struct net_device *dev, void *cb_priv,
+                                 flow_indr_block_bind_cb_t *cb,
+                                 void *cb_ident);
+
+void __flow_indr_block_cb_unregister(struct net_device *dev,
+                                    flow_indr_block_bind_cb_t *cb,
+                                    void *cb_ident);
+
+int flow_indr_block_cb_register(struct net_device *dev, void *cb_priv,
+                               flow_indr_block_bind_cb_t *cb, void *cb_ident);
+
+void flow_indr_block_cb_unregister(struct net_device *dev,
+                                  flow_indr_block_bind_cb_t *cb,
+                                  void *cb_ident);
+
+void flow_indr_block_call(struct net_device *dev,
+                         flow_indr_block_ing_cmd_t *cb,
+                         struct flow_block_offload *bo,
+                         enum flow_block_command command);
+
 #endif /* _NET_FLOW_OFFLOAD_H */
index e429809ca90d84b167749195126b0c8004d5223c..0790a4ed909cb1e98688c649e9006458307db837 100644 (file)
@@ -70,15 +70,6 @@ static inline struct Qdisc *tcf_block_q(struct tcf_block *block)
        return block->q;
 }
 
-int __tc_indr_block_cb_register(struct net_device *dev, void *cb_priv,
-                               tc_indr_block_bind_cb_t *cb, void *cb_ident);
-int tc_indr_block_cb_register(struct net_device *dev, void *cb_priv,
-                             tc_indr_block_bind_cb_t *cb, void *cb_ident);
-void __tc_indr_block_cb_unregister(struct net_device *dev,
-                                  tc_indr_block_bind_cb_t *cb, void *cb_ident);
-void tc_indr_block_cb_unregister(struct net_device *dev,
-                                tc_indr_block_bind_cb_t *cb, void *cb_ident);
-
 int tcf_classify(struct sk_buff *skb, const struct tcf_proto *tp,
                 struct tcf_result *res, bool compat_mode);
 
@@ -137,32 +128,6 @@ void tc_setup_cb_block_unregister(struct tcf_block *block, flow_setup_cb_t *cb,
 {
 }
 
-static inline
-int __tc_indr_block_cb_register(struct net_device *dev, void *cb_priv,
-                               tc_indr_block_bind_cb_t *cb, void *cb_ident)
-{
-       return 0;
-}
-
-static inline
-int tc_indr_block_cb_register(struct net_device *dev, void *cb_priv,
-                             tc_indr_block_bind_cb_t *cb, void *cb_ident)
-{
-       return 0;
-}
-
-static inline
-void __tc_indr_block_cb_unregister(struct net_device *dev,
-                                  tc_indr_block_bind_cb_t *cb, void *cb_ident)
-{
-}
-
-static inline
-void tc_indr_block_cb_unregister(struct net_device *dev,
-                                tc_indr_block_bind_cb_t *cb, void *cb_ident)
-{
-}
-
 static inline int tcf_classify(struct sk_buff *skb, const struct tcf_proto *tp,
                               struct tcf_result *res, bool compat_mode)
 {
index 6b6b01234dd9d916d969baced8b784bc2740d805..d9f359af0b93e8463158d354e0a9ad3351efa3a1 100644 (file)
@@ -23,9 +23,6 @@ struct tcf_walker;
 struct module;
 struct bpf_flow_keys;
 
-typedef int tc_indr_block_bind_cb_t(struct net_device *dev, void *cb_priv,
-                                   enum tc_setup_type type, void *type_data);
-
 struct qdisc_rate_table {
        struct tc_ratespec rate;
        u32             data[256];
index d63b970784dc74e41d431ef70379f9cb38e53915..4cc18e462d503529416965a1f9326cd8f1022ee6 100644 (file)
@@ -2,6 +2,7 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <net/flow_offload.h>
+#include <linux/rtnetlink.h>
 
 struct flow_rule *flow_rule_alloc(unsigned int num_actions)
 {
@@ -280,3 +281,217 @@ int flow_block_cb_setup_simple(struct flow_block_offload *f,
        }
 }
 EXPORT_SYMBOL(flow_block_cb_setup_simple);
+
+static struct rhashtable indr_setup_block_ht;
+
+struct flow_indr_block_cb {
+       struct list_head list;
+       void *cb_priv;
+       flow_indr_block_bind_cb_t *cb;
+       void *cb_ident;
+};
+
+struct flow_indr_block_dev {
+       struct rhash_head ht_node;
+       struct net_device *dev;
+       unsigned int refcnt;
+       flow_indr_block_ing_cmd_t  *block_ing_cmd_cb;
+       struct list_head cb_list;
+};
+
+static const struct rhashtable_params flow_indr_setup_block_ht_params = {
+       .key_offset     = offsetof(struct flow_indr_block_dev, dev),
+       .head_offset    = offsetof(struct flow_indr_block_dev, ht_node),
+       .key_len        = sizeof(struct net_device *),
+};
+
+static struct flow_indr_block_dev *
+flow_indr_block_dev_lookup(struct net_device *dev)
+{
+       return rhashtable_lookup_fast(&indr_setup_block_ht, &dev,
+                                     flow_indr_setup_block_ht_params);
+}
+
+static struct flow_indr_block_dev *
+flow_indr_block_dev_get(struct net_device *dev)
+{
+       struct flow_indr_block_dev *indr_dev;
+
+       indr_dev = flow_indr_block_dev_lookup(dev);
+       if (indr_dev)
+               goto inc_ref;
+
+       indr_dev = kzalloc(sizeof(*indr_dev), GFP_KERNEL);
+       if (!indr_dev)
+               return NULL;
+
+       INIT_LIST_HEAD(&indr_dev->cb_list);
+       indr_dev->dev = dev;
+       if (rhashtable_insert_fast(&indr_setup_block_ht, &indr_dev->ht_node,
+                                  flow_indr_setup_block_ht_params)) {
+               kfree(indr_dev);
+               return NULL;
+       }
+
+inc_ref:
+       indr_dev->refcnt++;
+       return indr_dev;
+}
+
+static void flow_indr_block_dev_put(struct flow_indr_block_dev *indr_dev)
+{
+       if (--indr_dev->refcnt)
+               return;
+
+       rhashtable_remove_fast(&indr_setup_block_ht, &indr_dev->ht_node,
+                              flow_indr_setup_block_ht_params);
+       kfree(indr_dev);
+}
+
+static struct flow_indr_block_cb *
+flow_indr_block_cb_lookup(struct flow_indr_block_dev *indr_dev,
+                         flow_indr_block_bind_cb_t *cb, void *cb_ident)
+{
+       struct flow_indr_block_cb *indr_block_cb;
+
+       list_for_each_entry(indr_block_cb, &indr_dev->cb_list, list)
+               if (indr_block_cb->cb == cb &&
+                   indr_block_cb->cb_ident == cb_ident)
+                       return indr_block_cb;
+       return NULL;
+}
+
+static struct flow_indr_block_cb *
+flow_indr_block_cb_add(struct flow_indr_block_dev *indr_dev, void *cb_priv,
+                      flow_indr_block_bind_cb_t *cb, void *cb_ident)
+{
+       struct flow_indr_block_cb *indr_block_cb;
+
+       indr_block_cb = flow_indr_block_cb_lookup(indr_dev, cb, cb_ident);
+       if (indr_block_cb)
+               return ERR_PTR(-EEXIST);
+
+       indr_block_cb = kzalloc(sizeof(*indr_block_cb), GFP_KERNEL);
+       if (!indr_block_cb)
+               return ERR_PTR(-ENOMEM);
+
+       indr_block_cb->cb_priv = cb_priv;
+       indr_block_cb->cb = cb;
+       indr_block_cb->cb_ident = cb_ident;
+       list_add(&indr_block_cb->list, &indr_dev->cb_list);
+
+       return indr_block_cb;
+}
+
+static void flow_indr_block_cb_del(struct flow_indr_block_cb *indr_block_cb)
+{
+       list_del(&indr_block_cb->list);
+       kfree(indr_block_cb);
+}
+
+int __flow_indr_block_cb_register(struct net_device *dev, void *cb_priv,
+                                 flow_indr_block_bind_cb_t *cb,
+                                 void *cb_ident)
+{
+       struct flow_indr_block_cb *indr_block_cb;
+       struct flow_indr_block_dev *indr_dev;
+       int err;
+
+       indr_dev = flow_indr_block_dev_get(dev);
+       if (!indr_dev)
+               return -ENOMEM;
+
+       indr_block_cb = flow_indr_block_cb_add(indr_dev, cb_priv, cb, cb_ident);
+       err = PTR_ERR_OR_ZERO(indr_block_cb);
+       if (err)
+               goto err_dev_put;
+
+       if (indr_dev->block_ing_cmd_cb)
+               indr_dev->block_ing_cmd_cb(dev, indr_block_cb->cb,
+                                          indr_block_cb->cb_priv,
+                                          FLOW_BLOCK_BIND);
+
+       return 0;
+
+err_dev_put:
+       flow_indr_block_dev_put(indr_dev);
+       return err;
+}
+EXPORT_SYMBOL_GPL(__flow_indr_block_cb_register);
+
+int flow_indr_block_cb_register(struct net_device *dev, void *cb_priv,
+                               flow_indr_block_bind_cb_t *cb,
+                               void *cb_ident)
+{
+       int err;
+
+       rtnl_lock();
+       err = __flow_indr_block_cb_register(dev, cb_priv, cb, cb_ident);
+       rtnl_unlock();
+
+       return err;
+}
+EXPORT_SYMBOL_GPL(flow_indr_block_cb_register);
+
+void __flow_indr_block_cb_unregister(struct net_device *dev,
+                                    flow_indr_block_bind_cb_t *cb,
+                                    void *cb_ident)
+{
+       struct flow_indr_block_cb *indr_block_cb;
+       struct flow_indr_block_dev *indr_dev;
+
+       indr_dev = flow_indr_block_dev_lookup(dev);
+       if (!indr_dev)
+               return;
+
+       indr_block_cb = flow_indr_block_cb_lookup(indr_dev, cb, cb_ident);
+       if (!indr_block_cb)
+               return;
+
+       if (indr_dev->block_ing_cmd_cb)
+               indr_dev->block_ing_cmd_cb(dev, indr_block_cb->cb,
+                                          indr_block_cb->cb_priv,
+                                          FLOW_BLOCK_UNBIND);
+
+       flow_indr_block_cb_del(indr_block_cb);
+       flow_indr_block_dev_put(indr_dev);
+}
+EXPORT_SYMBOL_GPL(__flow_indr_block_cb_unregister);
+
+void flow_indr_block_cb_unregister(struct net_device *dev,
+                                  flow_indr_block_bind_cb_t *cb,
+                                  void *cb_ident)
+{
+       rtnl_lock();
+       __flow_indr_block_cb_unregister(dev, cb, cb_ident);
+       rtnl_unlock();
+}
+EXPORT_SYMBOL_GPL(flow_indr_block_cb_unregister);
+
+void flow_indr_block_call(struct net_device *dev,
+                         flow_indr_block_ing_cmd_t cb,
+                         struct flow_block_offload *bo,
+                         enum flow_block_command command)
+{
+       struct flow_indr_block_cb *indr_block_cb;
+       struct flow_indr_block_dev *indr_dev;
+
+       indr_dev = flow_indr_block_dev_lookup(dev);
+       if (!indr_dev)
+               return;
+
+       indr_dev->block_ing_cmd_cb = command == FLOW_BLOCK_BIND
+                                    ? cb : NULL;
+
+       list_for_each_entry(indr_block_cb, &indr_dev->cb_list, list)
+               indr_block_cb->cb(dev, indr_block_cb->cb_priv, TC_SETUP_BLOCK,
+                                 bo);
+}
+EXPORT_SYMBOL_GPL(flow_indr_block_call);
+
+static int __init init_flow_indr_rhashtable(void)
+{
+       return rhashtable_init(&indr_setup_block_ht,
+                              &flow_indr_setup_block_ht_params);
+}
+subsys_initcall(init_flow_indr_rhashtable);
index 7c34fc6851c378d874f5568cbaeff4a6f023d84f..0b0dde26783d2c98a3afae7288e68cb9de8ca90d 100644 (file)
@@ -37,6 +37,7 @@
 #include <net/tc_act/tc_skbedit.h>
 #include <net/tc_act/tc_ct.h>
 #include <net/tc_act/tc_mpls.h>
+#include <net/flow_offload.h>
 
 extern const struct nla_policy rtm_tca_policy[TCA_MAX + 1];
 
@@ -545,139 +546,12 @@ static void tcf_chain_flush(struct tcf_chain *chain, bool rtnl_held)
        }
 }
 
-static struct tcf_block *tc_dev_ingress_block(struct net_device *dev)
-{
-       const struct Qdisc_class_ops *cops;
-       struct Qdisc *qdisc;
-
-       if (!dev_ingress_queue(dev))
-               return NULL;
-
-       qdisc = dev_ingress_queue(dev)->qdisc_sleeping;
-       if (!qdisc)
-               return NULL;
-
-       cops = qdisc->ops->cl_ops;
-       if (!cops)
-               return NULL;
-
-       if (!cops->tcf_block)
-               return NULL;
-
-       return cops->tcf_block(qdisc, TC_H_MIN_INGRESS, NULL);
-}
-
-static struct rhashtable indr_setup_block_ht;
-
-struct tc_indr_block_dev {
-       struct rhash_head ht_node;
-       struct net_device *dev;
-       unsigned int refcnt;
-       struct list_head cb_list;
-};
-
-struct tc_indr_block_cb {
-       struct list_head list;
-       void *cb_priv;
-       tc_indr_block_bind_cb_t *cb;
-       void *cb_ident;
-};
-
-static const struct rhashtable_params tc_indr_setup_block_ht_params = {
-       .key_offset     = offsetof(struct tc_indr_block_dev, dev),
-       .head_offset    = offsetof(struct tc_indr_block_dev, ht_node),
-       .key_len        = sizeof(struct net_device *),
-};
-
-static struct tc_indr_block_dev *
-tc_indr_block_dev_lookup(struct net_device *dev)
-{
-       return rhashtable_lookup_fast(&indr_setup_block_ht, &dev,
-                                     tc_indr_setup_block_ht_params);
-}
-
-static struct tc_indr_block_dev *tc_indr_block_dev_get(struct net_device *dev)
-{
-       struct tc_indr_block_dev *indr_dev;
-
-       indr_dev = tc_indr_block_dev_lookup(dev);
-       if (indr_dev)
-               goto inc_ref;
-
-       indr_dev = kzalloc(sizeof(*indr_dev), GFP_KERNEL);
-       if (!indr_dev)
-               return NULL;
-
-       INIT_LIST_HEAD(&indr_dev->cb_list);
-       indr_dev->dev = dev;
-       if (rhashtable_insert_fast(&indr_setup_block_ht, &indr_dev->ht_node,
-                                  tc_indr_setup_block_ht_params)) {
-               kfree(indr_dev);
-               return NULL;
-       }
-
-inc_ref:
-       indr_dev->refcnt++;
-       return indr_dev;
-}
-
-static void tc_indr_block_dev_put(struct tc_indr_block_dev *indr_dev)
-{
-       if (--indr_dev->refcnt)
-               return;
-
-       rhashtable_remove_fast(&indr_setup_block_ht, &indr_dev->ht_node,
-                              tc_indr_setup_block_ht_params);
-       kfree(indr_dev);
-}
-
-static struct tc_indr_block_cb *
-tc_indr_block_cb_lookup(struct tc_indr_block_dev *indr_dev,
-                       tc_indr_block_bind_cb_t *cb, void *cb_ident)
-{
-       struct tc_indr_block_cb *indr_block_cb;
-
-       list_for_each_entry(indr_block_cb, &indr_dev->cb_list, list)
-               if (indr_block_cb->cb == cb &&
-                   indr_block_cb->cb_ident == cb_ident)
-                       return indr_block_cb;
-       return NULL;
-}
-
-static struct tc_indr_block_cb *
-tc_indr_block_cb_add(struct tc_indr_block_dev *indr_dev, void *cb_priv,
-                    tc_indr_block_bind_cb_t *cb, void *cb_ident)
-{
-       struct tc_indr_block_cb *indr_block_cb;
-
-       indr_block_cb = tc_indr_block_cb_lookup(indr_dev, cb, cb_ident);
-       if (indr_block_cb)
-               return ERR_PTR(-EEXIST);
-
-       indr_block_cb = kzalloc(sizeof(*indr_block_cb), GFP_KERNEL);
-       if (!indr_block_cb)
-               return ERR_PTR(-ENOMEM);
-
-       indr_block_cb->cb_priv = cb_priv;
-       indr_block_cb->cb = cb;
-       indr_block_cb->cb_ident = cb_ident;
-       list_add(&indr_block_cb->list, &indr_dev->cb_list);
-
-       return indr_block_cb;
-}
-
-static void tc_indr_block_cb_del(struct tc_indr_block_cb *indr_block_cb)
-{
-       list_del(&indr_block_cb->list);
-       kfree(indr_block_cb);
-}
-
 static int tcf_block_setup(struct tcf_block *block,
                           struct flow_block_offload *bo);
 
 static void tc_indr_block_ing_cmd(struct net_device *dev,
                                  struct tcf_block *block,
-                                 tc_indr_block_bind_cb_t *cb,
+                                 flow_indr_block_bind_cb_t *cb,
                                  void *cb_priv,
                                  enum flow_block_command command)
 {
@@ -699,97 +573,40 @@ static void tc_indr_block_ing_cmd(struct net_device *dev,
        tcf_block_setup(block, &bo);
 }
 
-int __tc_indr_block_cb_register(struct net_device *dev, void *cb_priv,
-                               tc_indr_block_bind_cb_t *cb, void *cb_ident)
-{
-       struct tc_indr_block_cb *indr_block_cb;
-       struct tc_indr_block_dev *indr_dev;
-       struct tcf_block *block;
-       int err;
-
-       indr_dev = tc_indr_block_dev_get(dev);
-       if (!indr_dev)
-               return -ENOMEM;
-
-       indr_block_cb = tc_indr_block_cb_add(indr_dev, cb_priv, cb, cb_ident);
-       err = PTR_ERR_OR_ZERO(indr_block_cb);
-       if (err)
-               goto err_dev_put;
-
-       block = tc_dev_ingress_block(dev);
-       tc_indr_block_ing_cmd(dev, block, indr_block_cb->cb,
-                             indr_block_cb->cb_priv, FLOW_BLOCK_BIND);
-       return 0;
-
-err_dev_put:
-       tc_indr_block_dev_put(indr_dev);
-       return err;
-}
-EXPORT_SYMBOL_GPL(__tc_indr_block_cb_register);
-
-int tc_indr_block_cb_register(struct net_device *dev, void *cb_priv,
-                             tc_indr_block_bind_cb_t *cb, void *cb_ident)
+static struct tcf_block *tc_dev_ingress_block(struct net_device *dev)
 {
-       int err;
-
-       rtnl_lock();
-       err = __tc_indr_block_cb_register(dev, cb_priv, cb, cb_ident);
-       rtnl_unlock();
-
-       return err;
-}
-EXPORT_SYMBOL_GPL(tc_indr_block_cb_register);
+       const struct Qdisc_class_ops *cops;
+       struct Qdisc *qdisc;
 
-void __tc_indr_block_cb_unregister(struct net_device *dev,
-                                  tc_indr_block_bind_cb_t *cb, void *cb_ident)
-{
-       struct tc_indr_block_cb *indr_block_cb;
-       struct tc_indr_block_dev *indr_dev;
-       struct tcf_block *block;
+       if (!dev_ingress_queue(dev))
+               return NULL;
 
-       indr_dev = tc_indr_block_dev_lookup(dev);
-       if (!indr_dev)
-               return;
+       qdisc = dev_ingress_queue(dev)->qdisc_sleeping;
+       if (!qdisc)
+               return NULL;
 
-       indr_block_cb = tc_indr_block_cb_lookup(indr_dev, cb, cb_ident);
-       if (!indr_block_cb)
-               return;
+       cops = qdisc->ops->cl_ops;
+       if (!cops)
+               return NULL;
 
-       /* Send unbind message if required to free any block cbs. */
-       block = tc_dev_ingress_block(dev);
-       tc_indr_block_ing_cmd(dev, block, indr_block_cb->cb,
-                             indr_block_cb->cb_priv, FLOW_BLOCK_UNBIND);
-       tc_indr_block_cb_del(indr_block_cb);
-       tc_indr_block_dev_put(indr_dev);
-}
-EXPORT_SYMBOL_GPL(__tc_indr_block_cb_unregister);
+       if (!cops->tcf_block)
+               return NULL;
 
-void tc_indr_block_cb_unregister(struct net_device *dev,
-                                tc_indr_block_bind_cb_t *cb, void *cb_ident)
-{
-       rtnl_lock();
-       __tc_indr_block_cb_unregister(dev, cb, cb_ident);
-       rtnl_unlock();
+       return cops->tcf_block(qdisc, TC_H_MIN_INGRESS, NULL);
 }
-EXPORT_SYMBOL_GPL(tc_indr_block_cb_unregister);
 
-static void flow_indr_block_call(struct net_device *dev,
-                                struct flow_block_offload *bo,
-                                enum flow_block_command command)
+static void tc_indr_block_get_and_ing_cmd(struct net_device *dev,
+                                         flow_indr_block_bind_cb_t *cb,
+                                         void *cb_priv,
+                                         enum flow_block_command command)
 {
-       struct tc_indr_block_cb *indr_block_cb;
-       struct tc_indr_block_dev *indr_dev;
-
-       indr_dev = tc_indr_block_dev_lookup(dev);
-       if (!indr_dev)
-               return;
+       struct tcf_block *block = tc_dev_ingress_block(dev);
 
-       list_for_each_entry(indr_block_cb, &indr_dev->cb_list, list)
-               indr_block_cb->cb(dev, indr_block_cb->cb_priv, TC_SETUP_BLOCK,
-                                 bo);
+       tc_indr_block_ing_cmd(dev, block, cb, cb_priv, command);
 }
 
-static void tc_indr_block_call(struct tcf_block *block, struct net_device *dev,
+static void tc_indr_block_call(struct tcf_block *block,
+                              struct net_device *dev,
                               struct tcf_block_ext_info *ei,
                               enum flow_block_command command,
                               struct netlink_ext_ack *extack)
@@ -804,7 +621,7 @@ static void tc_indr_block_call(struct tcf_block *block, struct net_device *dev,
        };
        INIT_LIST_HEAD(&bo.cb_list);
 
-       flow_indr_block_call(dev, &bo, command);
+       flow_indr_block_call(dev, tc_indr_block_get_and_ing_cmd, &bo, command);
        tcf_block_setup(block, &bo);
 }
 
@@ -3378,11 +3195,6 @@ static int __init tc_filter_init(void)
        if (err)
                goto err_register_pernet_subsys;
 
-       err = rhashtable_init(&indr_setup_block_ht,
-                             &tc_indr_setup_block_ht_params);
-       if (err)
-               goto err_rhash_setup_block_ht;
-
        rtnl_register(PF_UNSPEC, RTM_NEWTFILTER, tc_new_tfilter, NULL,
                      RTNL_FLAG_DOIT_UNLOCKED);
        rtnl_register(PF_UNSPEC, RTM_DELTFILTER, tc_del_tfilter, NULL,
@@ -3396,8 +3208,6 @@ static int __init tc_filter_init(void)
 
        return 0;
 
-err_rhash_setup_block_ht:
-       unregister_pernet_subsys(&tcf_net_ops);
 err_register_pernet_subsys:
        destroy_workqueue(tc_filter_wq);
        return err;