* [PATCH 01/15 net-next,v2] net: sched: move tcf_block_cb before indr_block
2019-07-04 23:48 [PATCH 00/15 net-next,v2] netfilter: add hardware offload infrastructure Pablo Neira Ayuso
@ 2019-07-04 23:48 ` Pablo Neira Ayuso
2019-07-04 23:48 ` [PATCH 02/15 net-next,v2] net: sched: add tcf_block_cb_alloc() Pablo Neira Ayuso
` (13 subsequent siblings)
14 siblings, 0 replies; 21+ messages in thread
From: Pablo Neira Ayuso @ 2019-07-04 23:48 UTC (permalink / raw)
To: netdev
Cc: netfilter-devel, davem, thomas.lendacky, f.fainelli, ariel.elior,
michael.chan, madalin.bucur, yisen.zhuang, salil.mehta,
jeffrey.t.kirsher, tariqt, saeedm, jiri, idosch, jakub.kicinski,
peppe.cavallaro, grygorii.strashko, andrew, vivien.didelot,
alexandre.torgue, joabreu, linux-net-drivers, ogerlitz,
Manish.Chopra, marcelo.leitner, mkubecek, venkatkumar.duvvuru,
maxime.chevallier, cphealy
The indr_block infrastructure will depend on the tcf_block_cb object,
move this code on top to avoid forward declarations.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
v2: no changes.
net/sched/cls_api.c | 484 ++++++++++++++++++++++++++--------------------------
1 file changed, 242 insertions(+), 242 deletions(-)
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index ad36bbcc583e..b2417fda26ec 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -565,6 +565,248 @@ static struct tcf_block *tc_dev_ingress_block(struct net_device *dev)
return cops->tcf_block(qdisc, TC_H_MIN_INGRESS, NULL);
}
+static struct tcf_chain *
+__tcf_get_next_chain(struct tcf_block *block, struct tcf_chain *chain)
+{
+ mutex_lock(&block->lock);
+ if (chain)
+ chain = list_is_last(&chain->list, &block->chain_list) ?
+ NULL : list_next_entry(chain, list);
+ else
+ chain = list_first_entry_or_null(&block->chain_list,
+ struct tcf_chain, list);
+
+ /* skip all action-only chains */
+ while (chain && tcf_chain_held_by_acts_only(chain))
+ chain = list_is_last(&chain->list, &block->chain_list) ?
+ NULL : list_next_entry(chain, list);
+
+ if (chain)
+ tcf_chain_hold(chain);
+ mutex_unlock(&block->lock);
+
+ return chain;
+}
+
+/* Function to be used by all clients that want to iterate over all chains on
+ * block. It properly obtains block->lock and takes reference to chain before
+ * returning it. Users of this function must be tolerant to concurrent chain
+ * insertion/deletion or ensure that no concurrent chain modification is
+ * possible. Note that all netlink dump callbacks cannot guarantee to provide
+ * consistent dump because rtnl lock is released each time skb is filled with
+ * data and sent to user-space.
+ */
+
+struct tcf_chain *
+tcf_get_next_chain(struct tcf_block *block, struct tcf_chain *chain)
+{
+ struct tcf_chain *chain_next = __tcf_get_next_chain(block, chain);
+
+ if (chain)
+ tcf_chain_put(chain);
+
+ return chain_next;
+}
+EXPORT_SYMBOL(tcf_get_next_chain);
+
+static struct tcf_proto *
+__tcf_get_next_proto(struct tcf_chain *chain, struct tcf_proto *tp)
+{
+ u32 prio = 0;
+
+ ASSERT_RTNL();
+ mutex_lock(&chain->filter_chain_lock);
+
+ if (!tp) {
+ tp = tcf_chain_dereference(chain->filter_chain, chain);
+ } else if (tcf_proto_is_deleting(tp)) {
+ /* 'deleting' flag is set and chain->filter_chain_lock was
+ * unlocked, which means next pointer could be invalid. Restart
+ * search.
+ */
+ prio = tp->prio + 1;
+ tp = tcf_chain_dereference(chain->filter_chain, chain);
+
+ for (; tp; tp = tcf_chain_dereference(tp->next, chain))
+ if (!tp->deleting && tp->prio >= prio)
+ break;
+ } else {
+ tp = tcf_chain_dereference(tp->next, chain);
+ }
+
+ if (tp)
+ tcf_proto_get(tp);
+
+ mutex_unlock(&chain->filter_chain_lock);
+
+ return tp;
+}
+
+/* Function to be used by all clients that want to iterate over all tp's on
+ * chain. Users of this function must be tolerant to concurrent tp
+ * insertion/deletion or ensure that no concurrent chain modification is
+ * possible. Note that all netlink dump callbacks cannot guarantee to provide
+ * consistent dump because rtnl lock is released each time skb is filled with
+ * data and sent to user-space.
+ */
+
+struct tcf_proto *
+tcf_get_next_proto(struct tcf_chain *chain, struct tcf_proto *tp,
+ bool rtnl_held)
+{
+ struct tcf_proto *tp_next = __tcf_get_next_proto(chain, tp);
+
+ if (tp)
+ tcf_proto_put(tp, rtnl_held, NULL);
+
+ return tp_next;
+}
+EXPORT_SYMBOL(tcf_get_next_proto);
+
+static int
+tcf_block_playback_offloads(struct tcf_block *block, tc_setup_cb_t *cb,
+ void *cb_priv, bool add, bool offload_in_use,
+ struct netlink_ext_ack *extack)
+{
+ struct tcf_chain *chain, *chain_prev;
+ struct tcf_proto *tp, *tp_prev;
+ int err;
+
+ for (chain = __tcf_get_next_chain(block, NULL);
+ chain;
+ chain_prev = chain,
+ chain = __tcf_get_next_chain(block, chain),
+ tcf_chain_put(chain_prev)) {
+ for (tp = __tcf_get_next_proto(chain, NULL); tp;
+ tp_prev = tp,
+ tp = __tcf_get_next_proto(chain, tp),
+ tcf_proto_put(tp_prev, true, NULL)) {
+ if (tp->ops->reoffload) {
+ err = tp->ops->reoffload(tp, add, cb, cb_priv,
+ extack);
+ if (err && add)
+ goto err_playback_remove;
+ } else if (add && offload_in_use) {
+ err = -EOPNOTSUPP;
+ NL_SET_ERR_MSG(extack, "Filter HW offload failed - classifier without re-offloading support");
+ goto err_playback_remove;
+ }
+ }
+ }
+
+ return 0;
+
+err_playback_remove:
+ tcf_proto_put(tp, true, NULL);
+ tcf_chain_put(chain);
+ tcf_block_playback_offloads(block, cb, cb_priv, false, offload_in_use,
+ extack);
+ return err;
+}
+
+static bool tcf_block_offload_in_use(struct tcf_block *block)
+{
+ return block->offloadcnt;
+}
+
+struct tcf_block_cb {
+ struct list_head list;
+ tc_setup_cb_t *cb;
+ void *cb_ident;
+ void *cb_priv;
+ unsigned int refcnt;
+};
+
+void *tcf_block_cb_priv(struct tcf_block_cb *block_cb)
+{
+ return block_cb->cb_priv;
+}
+EXPORT_SYMBOL(tcf_block_cb_priv);
+
+struct tcf_block_cb *tcf_block_cb_lookup(struct tcf_block *block,
+ tc_setup_cb_t *cb, void *cb_ident)
+{ struct tcf_block_cb *block_cb;
+
+ list_for_each_entry(block_cb, &block->cb_list, list)
+ if (block_cb->cb == cb && block_cb->cb_ident == cb_ident)
+ return block_cb;
+ return NULL;
+}
+EXPORT_SYMBOL(tcf_block_cb_lookup);
+
+void tcf_block_cb_incref(struct tcf_block_cb *block_cb)
+{
+ block_cb->refcnt++;
+}
+EXPORT_SYMBOL(tcf_block_cb_incref);
+
+unsigned int tcf_block_cb_decref(struct tcf_block_cb *block_cb)
+{
+ return --block_cb->refcnt;
+}
+EXPORT_SYMBOL(tcf_block_cb_decref);
+
+struct tcf_block_cb *__tcf_block_cb_register(struct tcf_block *block,
+ tc_setup_cb_t *cb, void *cb_ident,
+ void *cb_priv,
+ struct netlink_ext_ack *extack)
+{
+ struct tcf_block_cb *block_cb;
+ int err;
+
+ /* Replay any already present rules */
+ err = tcf_block_playback_offloads(block, cb, cb_priv, true,
+ tcf_block_offload_in_use(block),
+ extack);
+ if (err)
+ return ERR_PTR(err);
+
+ block_cb = kzalloc(sizeof(*block_cb), GFP_KERNEL);
+ if (!block_cb)
+ return ERR_PTR(-ENOMEM);
+ block_cb->cb = cb;
+ block_cb->cb_ident = cb_ident;
+ block_cb->cb_priv = cb_priv;
+ list_add(&block_cb->list, &block->cb_list);
+ return block_cb;
+}
+EXPORT_SYMBOL(__tcf_block_cb_register);
+
+int tcf_block_cb_register(struct tcf_block *block,
+ tc_setup_cb_t *cb, void *cb_ident,
+ void *cb_priv, struct netlink_ext_ack *extack)
+{
+ struct tcf_block_cb *block_cb;
+
+ block_cb = __tcf_block_cb_register(block, cb, cb_ident, cb_priv,
+ extack);
+ return PTR_ERR_OR_ZERO(block_cb);
+}
+EXPORT_SYMBOL(tcf_block_cb_register);
+
+void __tcf_block_cb_unregister(struct tcf_block *block,
+ struct tcf_block_cb *block_cb)
+{
+ tcf_block_playback_offloads(block, block_cb->cb, block_cb->cb_priv,
+ false, tcf_block_offload_in_use(block),
+ NULL);
+ list_del(&block_cb->list);
+ kfree(block_cb);
+}
+EXPORT_SYMBOL(__tcf_block_cb_unregister);
+
+void tcf_block_cb_unregister(struct tcf_block *block,
+ tc_setup_cb_t *cb, void *cb_ident)
+{
+ struct tcf_block_cb *block_cb;
+
+ block_cb = tcf_block_cb_lookup(block, cb, cb_ident);
+ if (!block_cb)
+ return;
+ __tcf_block_cb_unregister(block, block_cb);
+}
+EXPORT_SYMBOL(tcf_block_cb_unregister);
+
static struct rhashtable indr_setup_block_ht;
struct tc_indr_block_dev {
@@ -782,11 +1024,6 @@ static void tc_indr_block_call(struct tcf_block *block, struct net_device *dev,
&bo);
}
-static bool tcf_block_offload_in_use(struct tcf_block *block)
-{
- return block->offloadcnt;
-}
-
static int tcf_block_offload_cmd(struct tcf_block *block,
struct net_device *dev,
struct tcf_block_ext_info *ei,
@@ -1003,104 +1240,6 @@ static struct tcf_block *tcf_block_refcnt_get(struct net *net, u32 block_index)
return block;
}
-static struct tcf_chain *
-__tcf_get_next_chain(struct tcf_block *block, struct tcf_chain *chain)
-{
- mutex_lock(&block->lock);
- if (chain)
- chain = list_is_last(&chain->list, &block->chain_list) ?
- NULL : list_next_entry(chain, list);
- else
- chain = list_first_entry_or_null(&block->chain_list,
- struct tcf_chain, list);
-
- /* skip all action-only chains */
- while (chain && tcf_chain_held_by_acts_only(chain))
- chain = list_is_last(&chain->list, &block->chain_list) ?
- NULL : list_next_entry(chain, list);
-
- if (chain)
- tcf_chain_hold(chain);
- mutex_unlock(&block->lock);
-
- return chain;
-}
-
-/* Function to be used by all clients that want to iterate over all chains on
- * block. It properly obtains block->lock and takes reference to chain before
- * returning it. Users of this function must be tolerant to concurrent chain
- * insertion/deletion or ensure that no concurrent chain modification is
- * possible. Note that all netlink dump callbacks cannot guarantee to provide
- * consistent dump because rtnl lock is released each time skb is filled with
- * data and sent to user-space.
- */
-
-struct tcf_chain *
-tcf_get_next_chain(struct tcf_block *block, struct tcf_chain *chain)
-{
- struct tcf_chain *chain_next = __tcf_get_next_chain(block, chain);
-
- if (chain)
- tcf_chain_put(chain);
-
- return chain_next;
-}
-EXPORT_SYMBOL(tcf_get_next_chain);
-
-static struct tcf_proto *
-__tcf_get_next_proto(struct tcf_chain *chain, struct tcf_proto *tp)
-{
- u32 prio = 0;
-
- ASSERT_RTNL();
- mutex_lock(&chain->filter_chain_lock);
-
- if (!tp) {
- tp = tcf_chain_dereference(chain->filter_chain, chain);
- } else if (tcf_proto_is_deleting(tp)) {
- /* 'deleting' flag is set and chain->filter_chain_lock was
- * unlocked, which means next pointer could be invalid. Restart
- * search.
- */
- prio = tp->prio + 1;
- tp = tcf_chain_dereference(chain->filter_chain, chain);
-
- for (; tp; tp = tcf_chain_dereference(tp->next, chain))
- if (!tp->deleting && tp->prio >= prio)
- break;
- } else {
- tp = tcf_chain_dereference(tp->next, chain);
- }
-
- if (tp)
- tcf_proto_get(tp);
-
- mutex_unlock(&chain->filter_chain_lock);
-
- return tp;
-}
-
-/* Function to be used by all clients that want to iterate over all tp's on
- * chain. Users of this function must be tolerant to concurrent tp
- * insertion/deletion or ensure that no concurrent chain modification is
- * possible. Note that all netlink dump callbacks cannot guarantee to provide
- * consistent dump because rtnl lock is released each time skb is filled with
- * data and sent to user-space.
- */
-
-struct tcf_proto *
-tcf_get_next_proto(struct tcf_chain *chain, struct tcf_proto *tp,
- bool rtnl_held)
-{
- struct tcf_proto *tp_next = __tcf_get_next_proto(chain, tp);
-
- if (tp)
- tcf_proto_put(tp, rtnl_held, NULL);
-
- return tp_next;
-}
-EXPORT_SYMBOL(tcf_get_next_proto);
-
static void tcf_block_flush_all_chains(struct tcf_block *block, bool rtnl_held)
{
struct tcf_chain *chain;
@@ -1494,145 +1633,6 @@ void tcf_block_put(struct tcf_block *block)
EXPORT_SYMBOL(tcf_block_put);
-struct tcf_block_cb {
- struct list_head list;
- tc_setup_cb_t *cb;
- void *cb_ident;
- void *cb_priv;
- unsigned int refcnt;
-};
-
-void *tcf_block_cb_priv(struct tcf_block_cb *block_cb)
-{
- return block_cb->cb_priv;
-}
-EXPORT_SYMBOL(tcf_block_cb_priv);
-
-struct tcf_block_cb *tcf_block_cb_lookup(struct tcf_block *block,
- tc_setup_cb_t *cb, void *cb_ident)
-{ struct tcf_block_cb *block_cb;
-
- list_for_each_entry(block_cb, &block->cb_list, list)
- if (block_cb->cb == cb && block_cb->cb_ident == cb_ident)
- return block_cb;
- return NULL;
-}
-EXPORT_SYMBOL(tcf_block_cb_lookup);
-
-void tcf_block_cb_incref(struct tcf_block_cb *block_cb)
-{
- block_cb->refcnt++;
-}
-EXPORT_SYMBOL(tcf_block_cb_incref);
-
-unsigned int tcf_block_cb_decref(struct tcf_block_cb *block_cb)
-{
- return --block_cb->refcnt;
-}
-EXPORT_SYMBOL(tcf_block_cb_decref);
-
-static int
-tcf_block_playback_offloads(struct tcf_block *block, tc_setup_cb_t *cb,
- void *cb_priv, bool add, bool offload_in_use,
- struct netlink_ext_ack *extack)
-{
- struct tcf_chain *chain, *chain_prev;
- struct tcf_proto *tp, *tp_prev;
- int err;
-
- for (chain = __tcf_get_next_chain(block, NULL);
- chain;
- chain_prev = chain,
- chain = __tcf_get_next_chain(block, chain),
- tcf_chain_put(chain_prev)) {
- for (tp = __tcf_get_next_proto(chain, NULL); tp;
- tp_prev = tp,
- tp = __tcf_get_next_proto(chain, tp),
- tcf_proto_put(tp_prev, true, NULL)) {
- if (tp->ops->reoffload) {
- err = tp->ops->reoffload(tp, add, cb, cb_priv,
- extack);
- if (err && add)
- goto err_playback_remove;
- } else if (add && offload_in_use) {
- err = -EOPNOTSUPP;
- NL_SET_ERR_MSG(extack, "Filter HW offload failed - classifier without re-offloading support");
- goto err_playback_remove;
- }
- }
- }
-
- return 0;
-
-err_playback_remove:
- tcf_proto_put(tp, true, NULL);
- tcf_chain_put(chain);
- tcf_block_playback_offloads(block, cb, cb_priv, false, offload_in_use,
- extack);
- return err;
-}
-
-struct tcf_block_cb *__tcf_block_cb_register(struct tcf_block *block,
- tc_setup_cb_t *cb, void *cb_ident,
- void *cb_priv,
- struct netlink_ext_ack *extack)
-{
- struct tcf_block_cb *block_cb;
- int err;
-
- /* Replay any already present rules */
- err = tcf_block_playback_offloads(block, cb, cb_priv, true,
- tcf_block_offload_in_use(block),
- extack);
- if (err)
- return ERR_PTR(err);
-
- block_cb = kzalloc(sizeof(*block_cb), GFP_KERNEL);
- if (!block_cb)
- return ERR_PTR(-ENOMEM);
- block_cb->cb = cb;
- block_cb->cb_ident = cb_ident;
- block_cb->cb_priv = cb_priv;
- list_add(&block_cb->list, &block->cb_list);
- return block_cb;
-}
-EXPORT_SYMBOL(__tcf_block_cb_register);
-
-int tcf_block_cb_register(struct tcf_block *block,
- tc_setup_cb_t *cb, void *cb_ident,
- void *cb_priv, struct netlink_ext_ack *extack)
-{
- struct tcf_block_cb *block_cb;
-
- block_cb = __tcf_block_cb_register(block, cb, cb_ident, cb_priv,
- extack);
- return PTR_ERR_OR_ZERO(block_cb);
-}
-EXPORT_SYMBOL(tcf_block_cb_register);
-
-void __tcf_block_cb_unregister(struct tcf_block *block,
- struct tcf_block_cb *block_cb)
-{
- tcf_block_playback_offloads(block, block_cb->cb, block_cb->cb_priv,
- false, tcf_block_offload_in_use(block),
- NULL);
- list_del(&block_cb->list);
- kfree(block_cb);
-}
-EXPORT_SYMBOL(__tcf_block_cb_unregister);
-
-void tcf_block_cb_unregister(struct tcf_block *block,
- tc_setup_cb_t *cb, void *cb_ident)
-{
- struct tcf_block_cb *block_cb;
-
- block_cb = tcf_block_cb_lookup(block, cb, cb_ident);
- if (!block_cb)
- return;
- __tcf_block_cb_unregister(block, block_cb);
-}
-EXPORT_SYMBOL(tcf_block_cb_unregister);
-
/* Main classifier routine: scans classifier chain attached
* to this qdisc, (optionally) tests for protocol and asks
* specific classifiers.
--
2.11.0
^ permalink raw reply related [flat|nested] 21+ messages in thread* [PATCH 02/15 net-next,v2] net: sched: add tcf_block_cb_alloc()
2019-07-04 23:48 [PATCH 00/15 net-next,v2] netfilter: add hardware offload infrastructure Pablo Neira Ayuso
2019-07-04 23:48 ` [PATCH 01/15 net-next,v2] net: sched: move tcf_block_cb before indr_block Pablo Neira Ayuso
@ 2019-07-04 23:48 ` Pablo Neira Ayuso
2019-07-04 23:48 ` [PATCH 03/15 net-next,v2] net: sched: add tcf_block_cb_free() Pablo Neira Ayuso
` (12 subsequent siblings)
14 siblings, 0 replies; 21+ messages in thread
From: Pablo Neira Ayuso @ 2019-07-04 23:48 UTC (permalink / raw)
To: netdev
Cc: netfilter-devel, davem, thomas.lendacky, f.fainelli, ariel.elior,
michael.chan, madalin.bucur, yisen.zhuang, salil.mehta,
jeffrey.t.kirsher, tariqt, saeedm, jiri, idosch, jakub.kicinski,
peppe.cavallaro, grygorii.strashko, andrew, vivien.didelot,
alexandre.torgue, joabreu, linux-net-drivers, ogerlitz,
Manish.Chopra, marcelo.leitner, mkubecek, venkatkumar.duvvuru,
maxime.chevallier, cphealy
Add a new helper function to allocate tcf_block_cb objects.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
v2: return -EOPNOTSUPP if sched/cls_api is disabled, per Marcelo Ricardo Leitner .
include/net/pkt_cls.h | 8 ++++++++
net/sched/cls_api.c | 27 +++++++++++++++++++++------
2 files changed, 29 insertions(+), 6 deletions(-)
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index 1a7596ba0dbe..a756d895c7a4 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -72,6 +72,8 @@ static inline struct Qdisc *tcf_block_q(struct tcf_block *block)
return block->q;
}
+struct tcf_block_cb *tcf_block_cb_alloc(tc_setup_cb_t *cb,
+ void *cb_ident, void *cb_priv);
void *tcf_block_cb_priv(struct tcf_block_cb *block_cb);
struct tcf_block_cb *tcf_block_cb_lookup(struct tcf_block *block,
tc_setup_cb_t *cb, void *cb_ident);
@@ -150,6 +152,12 @@ void tc_setup_cb_block_unregister(struct tcf_block *block, tc_setup_cb_t *cb,
{
}
+static inline struct tcf_block_cb *
+tcf_block_cb_alloc(tc_setup_cb_t *cb, void *cb_ident, void *cb_priv)
+{
+ return ERR_PTR(-EOPNOTSUPP);
+}
+
static inline
void *tcf_block_cb_priv(struct tcf_block_cb *block_cb)
{
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index b2417fda26ec..6cd76e3df2be 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -746,6 +746,23 @@ unsigned int tcf_block_cb_decref(struct tcf_block_cb *block_cb)
}
EXPORT_SYMBOL(tcf_block_cb_decref);
+struct tcf_block_cb *tcf_block_cb_alloc(tc_setup_cb_t *cb,
+ void *cb_ident, void *cb_priv)
+{
+ struct tcf_block_cb *block_cb;
+
+ block_cb = kzalloc(sizeof(*block_cb), GFP_KERNEL);
+ if (!block_cb)
+ return ERR_PTR(-ENOMEM);
+
+ block_cb->cb = cb;
+ block_cb->cb_ident = cb_ident;
+ block_cb->cb_priv = cb_priv;
+
+ return block_cb;
+}
+EXPORT_SYMBOL(tcf_block_cb_alloc);
+
struct tcf_block_cb *__tcf_block_cb_register(struct tcf_block *block,
tc_setup_cb_t *cb, void *cb_ident,
void *cb_priv,
@@ -761,12 +778,10 @@ struct tcf_block_cb *__tcf_block_cb_register(struct tcf_block *block,
if (err)
return ERR_PTR(err);
- block_cb = kzalloc(sizeof(*block_cb), GFP_KERNEL);
- if (!block_cb)
- return ERR_PTR(-ENOMEM);
- block_cb->cb = cb;
- block_cb->cb_ident = cb_ident;
- block_cb->cb_priv = cb_priv;
+ block_cb = tcf_block_cb_alloc(cb, cb_ident, cb_priv);
+ if (IS_ERR(block_cb))
+ return block_cb;
+
list_add(&block_cb->list, &block->cb_list);
return block_cb;
}
--
2.11.0
^ permalink raw reply related [flat|nested] 21+ messages in thread* [PATCH 03/15 net-next,v2] net: sched: add tcf_block_cb_free()
2019-07-04 23:48 [PATCH 00/15 net-next,v2] netfilter: add hardware offload infrastructure Pablo Neira Ayuso
2019-07-04 23:48 ` [PATCH 01/15 net-next,v2] net: sched: move tcf_block_cb before indr_block Pablo Neira Ayuso
2019-07-04 23:48 ` [PATCH 02/15 net-next,v2] net: sched: add tcf_block_cb_alloc() Pablo Neira Ayuso
@ 2019-07-04 23:48 ` Pablo Neira Ayuso
2019-07-04 23:48 ` [PATCH 04/15 net-next,v2] net: sched: add tcf_block_setup() Pablo Neira Ayuso
` (11 subsequent siblings)
14 siblings, 0 replies; 21+ messages in thread
From: Pablo Neira Ayuso @ 2019-07-04 23:48 UTC (permalink / raw)
To: netdev
Cc: netfilter-devel, davem, thomas.lendacky, f.fainelli, ariel.elior,
michael.chan, madalin.bucur, yisen.zhuang, salil.mehta,
jeffrey.t.kirsher, tariqt, saeedm, jiri, idosch, jakub.kicinski,
peppe.cavallaro, grygorii.strashko, andrew, vivien.didelot,
alexandre.torgue, joabreu, linux-net-drivers, ogerlitz,
Manish.Chopra, marcelo.leitner, mkubecek, venkatkumar.duvvuru,
maxime.chevallier, cphealy
Just a stub to release tcf_block_cb objects, follow up patch extends it
to have a release callback in it for the private data.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
v2: no changes.
include/net/pkt_cls.h | 5 +++++
net/sched/cls_api.c | 6 ++++++
2 files changed, 11 insertions(+)
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index a756d895c7a4..b50df3b9456c 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -74,6 +74,7 @@ static inline struct Qdisc *tcf_block_q(struct tcf_block *block)
struct tcf_block_cb *tcf_block_cb_alloc(tc_setup_cb_t *cb,
void *cb_ident, void *cb_priv);
+void tcf_block_cb_free(struct tcf_block_cb *block_cb);
void *tcf_block_cb_priv(struct tcf_block_cb *block_cb);
struct tcf_block_cb *tcf_block_cb_lookup(struct tcf_block *block,
tc_setup_cb_t *cb, void *cb_ident);
@@ -158,6 +159,10 @@ tcf_block_cb_alloc(tc_setup_cb_t *cb, void *cb_ident, void *cb_priv)
return ERR_PTR(-EOPNOTSUPP);
}
+static inline void tcf_block_cb_free(struct tcf_block_cb *block_cb)
+{
+}
+
static inline
void *tcf_block_cb_priv(struct tcf_block_cb *block_cb)
{
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 6cd76e3df2be..93b74a15e7ac 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -763,6 +763,12 @@ struct tcf_block_cb *tcf_block_cb_alloc(tc_setup_cb_t *cb,
}
EXPORT_SYMBOL(tcf_block_cb_alloc);
+void tcf_block_cb_free(struct tcf_block_cb *block_cb)
+{
+ kfree(block_cb);
+}
+EXPORT_SYMBOL(tcf_block_cb_free);
+
struct tcf_block_cb *__tcf_block_cb_register(struct tcf_block *block,
tc_setup_cb_t *cb, void *cb_ident,
void *cb_priv,
--
2.11.0
^ permalink raw reply related [flat|nested] 21+ messages in thread* [PATCH 04/15 net-next,v2] net: sched: add tcf_block_setup()
2019-07-04 23:48 [PATCH 00/15 net-next,v2] netfilter: add hardware offload infrastructure Pablo Neira Ayuso
` (2 preceding siblings ...)
2019-07-04 23:48 ` [PATCH 03/15 net-next,v2] net: sched: add tcf_block_cb_free() Pablo Neira Ayuso
@ 2019-07-04 23:48 ` Pablo Neira Ayuso
2019-07-05 22:31 ` Jakub Kicinski
2019-07-05 22:58 ` Jakub Kicinski
2019-07-04 23:48 ` [PATCH 05/15 net-next,v2] net: sched: add release callback to struct tcf_block_cb Pablo Neira Ayuso
` (10 subsequent siblings)
14 siblings, 2 replies; 21+ messages in thread
From: Pablo Neira Ayuso @ 2019-07-04 23:48 UTC (permalink / raw)
To: netdev
Cc: netfilter-devel, davem, thomas.lendacky, f.fainelli, ariel.elior,
michael.chan, madalin.bucur, yisen.zhuang, salil.mehta,
jeffrey.t.kirsher, tariqt, saeedm, jiri, idosch, jakub.kicinski,
peppe.cavallaro, grygorii.strashko, andrew, vivien.didelot,
alexandre.torgue, joabreu, linux-net-drivers, ogerlitz,
Manish.Chopra, marcelo.leitner, mkubecek, venkatkumar.duvvuru,
maxime.chevallier, cphealy
This new function allows us to handle tcf_block_cb registrations /
unregistrations from the core, in order to remove a dependency with the
tcf_block object and the .reoffload cls_api callback.
The tcf_block_cb_add() call places the tcf_block_cb object, which has
been set up by the driver, in the tc_block_offload->cb_list. This is a
temporary list that is used to convey the tcf_block_cb objects back to
the core for registration.
Note that this patch introduces a global tcf_block_cb_list, however,
this is a temporary artifact to make it easy for me to update the code
to use this new infrastructure. This global list goes away in a follow
up patch to add per-driver flow block lists.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
v2: no changes.
include/net/pkt_cls.h | 19 ++++++++++
net/sched/cls_api.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 120 insertions(+), 1 deletion(-)
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index b50df3b9456c..d660cb4fad75 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -75,6 +75,13 @@ static inline struct Qdisc *tcf_block_q(struct tcf_block *block)
struct tcf_block_cb *tcf_block_cb_alloc(tc_setup_cb_t *cb,
void *cb_ident, void *cb_priv);
void tcf_block_cb_free(struct tcf_block_cb *block_cb);
+
+struct tc_block_offload;
+void tcf_block_cb_add(struct tcf_block_cb *block_cb,
+ struct tc_block_offload *offload);
+void tcf_block_cb_remove(struct tcf_block_cb *block_cb,
+ struct tc_block_offload *offload);
+
void *tcf_block_cb_priv(struct tcf_block_cb *block_cb);
struct tcf_block_cb *tcf_block_cb_lookup(struct tcf_block *block,
tc_setup_cb_t *cb, void *cb_ident);
@@ -163,6 +170,17 @@ static inline void tcf_block_cb_free(struct tcf_block_cb *block_cb)
{
}
+struct tc_block_offload;
+static inline void tcf_block_cb_add(struct tcf_block_cb *block_cb,
+ struct tc_block_offload *offload)
+{
+}
+
+static inline void tcf_block_cb_remove(struct tcf_block_cb *block_cb,
+ struct tc_block_offload *offload)
+{
+}
+
static inline
void *tcf_block_cb_priv(struct tcf_block_cb *block_cb)
{
@@ -631,6 +649,7 @@ enum tc_block_command {
struct tc_block_offload {
enum tc_block_command command;
enum tcf_block_binder_type binder_type;
+ struct list_head cb_list;
struct tcf_block *block;
struct netlink_ext_ack *extack;
};
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 93b74a15e7ac..a2c1258cc8dc 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -710,6 +710,7 @@ static bool tcf_block_offload_in_use(struct tcf_block *block)
}
struct tcf_block_cb {
+ struct list_head global_list;
struct list_head list;
tc_setup_cb_t *cb;
void *cb_ident;
@@ -723,6 +724,8 @@ void *tcf_block_cb_priv(struct tcf_block_cb *block_cb)
}
EXPORT_SYMBOL(tcf_block_cb_priv);
+static LIST_HEAD(tcf_block_cb_list);
+
struct tcf_block_cb *tcf_block_cb_lookup(struct tcf_block *block,
tc_setup_cb_t *cb, void *cb_ident)
{ struct tcf_block_cb *block_cb;
@@ -769,6 +772,20 @@ void tcf_block_cb_free(struct tcf_block_cb *block_cb)
}
EXPORT_SYMBOL(tcf_block_cb_free);
+void tcf_block_cb_add(struct tcf_block_cb *block_cb,
+ struct tc_block_offload *offload)
+{
+ list_add_tail(&block_cb->global_list, &offload->cb_list);
+}
+EXPORT_SYMBOL(tcf_block_cb_add);
+
+void tcf_block_cb_remove(struct tcf_block_cb *block_cb,
+ struct tc_block_offload *offload)
+{
+ list_move(&block_cb->global_list, &offload->cb_list);
+}
+EXPORT_SYMBOL(tcf_block_cb_remove);
+
struct tcf_block_cb *__tcf_block_cb_register(struct tcf_block *block,
tc_setup_cb_t *cb, void *cb_ident,
void *cb_priv,
@@ -828,6 +845,77 @@ void tcf_block_cb_unregister(struct tcf_block *block,
}
EXPORT_SYMBOL(tcf_block_cb_unregister);
+static int tcf_block_bind(struct tcf_block *block, struct tc_block_offload *bo)
+{
+ struct tcf_block_cb *block_cb, *next;
+ int err, i = 0;
+
+ list_for_each_entry(block_cb, &bo->cb_list, global_list) {
+ err = tcf_block_playback_offloads(block, block_cb->cb,
+ block_cb->cb_priv, true,
+ tcf_block_offload_in_use(block),
+ bo->extack);
+ if (err)
+ goto err_unroll;
+
+ list_add(&block_cb->list, &block->cb_list);
+ i++;
+ }
+ list_splice(&bo->cb_list, &tcf_block_cb_list);
+
+ return 0;
+
+err_unroll:
+ list_for_each_entry_safe(block_cb, next, &bo->cb_list, global_list) {
+ if (i-- > 0) {
+ list_del(&block_cb->list);
+ tcf_block_playback_offloads(block, block_cb->cb,
+ block_cb->cb_priv, false,
+ tcf_block_offload_in_use(block),
+ NULL);
+ }
+ kfree(block_cb);
+ }
+
+ return err;
+}
+
+static void tcf_block_unbind(struct tcf_block *block,
+ struct tc_block_offload *bo)
+{
+ struct tcf_block_cb *block_cb, *next;
+
+ list_for_each_entry_safe(block_cb, next, &bo->cb_list, global_list) {
+ list_del(&block_cb->global_list);
+ tcf_block_playback_offloads(block, block_cb->cb,
+ block_cb->cb_priv, false,
+ tcf_block_offload_in_use(block),
+ NULL);
+ list_del(&block_cb->list);
+ tcf_block_cb_free(block_cb);
+ }
+}
+
+static int tcf_block_setup(struct tcf_block *block, struct tc_block_offload *bo)
+{
+ int err;
+
+ switch (bo->command) {
+ case TC_BLOCK_BIND:
+ err = tcf_block_bind(block, bo);
+ break;
+ case TC_BLOCK_UNBIND:
+ err = 0;
+ tcf_block_unbind(block, bo);
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ err = -EOPNOTSUPP;
+ }
+
+ return err;
+}
+
static struct rhashtable indr_setup_block_ht;
struct tc_indr_block_dev {
@@ -944,12 +1032,14 @@ static void tc_indr_block_ing_cmd(struct tc_indr_block_dev *indr_dev,
.binder_type = TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS,
.block = indr_dev->block,
};
+ INIT_LIST_HEAD(&bo.cb_list);
if (!indr_dev->block)
return;
indr_block_cb->cb(indr_dev->dev, indr_block_cb->cb_priv, TC_SETUP_BLOCK,
&bo);
+ tcf_block_setup(indr_dev->block, &bo);
}
int __tc_indr_block_cb_register(struct net_device *dev, void *cb_priv,
@@ -1033,6 +1123,7 @@ static void tc_indr_block_call(struct tcf_block *block, struct net_device *dev,
.block = block,
.extack = extack,
};
+ INIT_LIST_HEAD(&bo.cb_list);
indr_dev = tc_indr_block_dev_lookup(dev);
if (!indr_dev)
@@ -1043,6 +1134,8 @@ static void tc_indr_block_call(struct tcf_block *block, struct net_device *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);
+
+ tcf_block_setup(block, &bo);
}
static int tcf_block_offload_cmd(struct tcf_block *block,
@@ -1052,12 +1145,19 @@ static int tcf_block_offload_cmd(struct tcf_block *block,
struct netlink_ext_ack *extack)
{
struct tc_block_offload bo = {};
+ int err;
bo.command = command;
bo.binder_type = ei->binder_type;
bo.block = block;
bo.extack = extack;
- return dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_BLOCK, &bo);
+ INIT_LIST_HEAD(&bo.cb_list);
+
+ err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_BLOCK, &bo);
+ if (err < 0)
+ return err;
+
+ return tcf_block_setup(block, &bo);
}
static int tcf_block_offload_bind(struct tcf_block *block, struct Qdisc *q,
--
2.11.0
^ permalink raw reply related [flat|nested] 21+ messages in thread* Re: [PATCH 04/15 net-next,v2] net: sched: add tcf_block_setup()
2019-07-04 23:48 ` [PATCH 04/15 net-next,v2] net: sched: add tcf_block_setup() Pablo Neira Ayuso
@ 2019-07-05 22:31 ` Jakub Kicinski
2019-07-05 22:58 ` Jakub Kicinski
1 sibling, 0 replies; 21+ messages in thread
From: Jakub Kicinski @ 2019-07-05 22:31 UTC (permalink / raw)
To: Pablo Neira Ayuso
Cc: netdev, netfilter-devel, davem, thomas.lendacky, f.fainelli,
ariel.elior, michael.chan, madalin.bucur, yisen.zhuang,
salil.mehta, jeffrey.t.kirsher, tariqt, saeedm, jiri, idosch,
peppe.cavallaro, grygorii.strashko, andrew, vivien.didelot,
alexandre.torgue, joabreu, linux-net-drivers, ogerlitz,
Manish.Chopra, marcelo.leitner, mkubecek, venkatkumar.duvvuru,
maxime.chevallier, cphealy
On Fri, 5 Jul 2019 01:48:32 +0200, Pablo Neira Ayuso wrote:
> +static int tcf_block_bind(struct tcf_block *block, struct tc_block_offload *bo)
> +{
> + struct tcf_block_cb *block_cb, *next;
> + int err, i = 0;
> +
> + list_for_each_entry(block_cb, &bo->cb_list, global_list) {
> + err = tcf_block_playback_offloads(block, block_cb->cb,
> + block_cb->cb_priv, true,
> + tcf_block_offload_in_use(block),
> + bo->extack);
> + if (err)
> + goto err_unroll;
> +
> + list_add(&block_cb->list, &block->cb_list);
> + i++;
> + }
> + list_splice(&bo->cb_list, &tcf_block_cb_list);
> +
> + return 0;
> +
> +err_unroll:
> + list_for_each_entry_safe(block_cb, next, &bo->cb_list, global_list) {
> + if (i-- > 0) {
> + list_del(&block_cb->list);
> + tcf_block_playback_offloads(block, block_cb->cb,
> + block_cb->cb_priv, false,
> + tcf_block_offload_in_use(block),
> + NULL);
> + }
> + kfree(block_cb);
Is this not a tcf_block_cb_free() on purpose?
> + }
> +
> + return err;
> +}
^ permalink raw reply [flat|nested] 21+ messages in thread* Re: [PATCH 04/15 net-next,v2] net: sched: add tcf_block_setup()
2019-07-04 23:48 ` [PATCH 04/15 net-next,v2] net: sched: add tcf_block_setup() Pablo Neira Ayuso
2019-07-05 22:31 ` Jakub Kicinski
@ 2019-07-05 22:58 ` Jakub Kicinski
1 sibling, 0 replies; 21+ messages in thread
From: Jakub Kicinski @ 2019-07-05 22:58 UTC (permalink / raw)
To: Pablo Neira Ayuso
Cc: netdev, netfilter-devel, davem, thomas.lendacky, f.fainelli,
ariel.elior, michael.chan, madalin.bucur, yisen.zhuang,
salil.mehta, jeffrey.t.kirsher, tariqt, saeedm, jiri, idosch,
peppe.cavallaro, grygorii.strashko, andrew, vivien.didelot,
alexandre.torgue, joabreu, linux-net-drivers, ogerlitz,
Manish.Chopra, marcelo.leitner, mkubecek, venkatkumar.duvvuru,
maxime.chevallier, cphealy
On Fri, 5 Jul 2019 01:48:32 +0200, Pablo Neira Ayuso wrote:
> @@ -1052,12 +1145,19 @@ static int tcf_block_offload_cmd(struct tcf_block *block,
> struct netlink_ext_ack *extack)
> {
> struct tc_block_offload bo = {};
> + int err;
>
> bo.command = command;
> bo.binder_type = ei->binder_type;
> bo.block = block;
> bo.extack = extack;
> - return dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_BLOCK, &bo);
> + INIT_LIST_HEAD(&bo.cb_list);
> +
> + err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_BLOCK, &bo);
> + if (err < 0)
> + return err;
> +
> + return tcf_block_setup(block, &bo);
If this fails nothing will undo the old ndo call, no?
> }
>
> static int tcf_block_offload_bind(struct tcf_block *block, struct Qdisc *q,
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 05/15 net-next,v2] net: sched: add release callback to struct tcf_block_cb
2019-07-04 23:48 [PATCH 00/15 net-next,v2] netfilter: add hardware offload infrastructure Pablo Neira Ayuso
` (3 preceding siblings ...)
2019-07-04 23:48 ` [PATCH 04/15 net-next,v2] net: sched: add tcf_block_setup() Pablo Neira Ayuso
@ 2019-07-04 23:48 ` Pablo Neira Ayuso
2019-07-04 23:48 ` [PATCH 06/15 net-next,v2] net: sched: add tcf_setup_block_offload() Pablo Neira Ayuso
` (9 subsequent siblings)
14 siblings, 0 replies; 21+ messages in thread
From: Pablo Neira Ayuso @ 2019-07-04 23:48 UTC (permalink / raw)
To: netdev
Cc: netfilter-devel, davem, thomas.lendacky, f.fainelli, ariel.elior,
michael.chan, madalin.bucur, yisen.zhuang, salil.mehta,
jeffrey.t.kirsher, tariqt, saeedm, jiri, idosch, jakub.kicinski,
peppe.cavallaro, grygorii.strashko, andrew, vivien.didelot,
alexandre.torgue, joabreu, linux-net-drivers, ogerlitz,
Manish.Chopra, marcelo.leitner, mkubecek, venkatkumar.duvvuru,
maxime.chevallier, cphealy
Call it on tcf_block_cb object to release the driver private block area.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
v2: no changes.
include/net/pkt_cls.h | 6 ++++--
net/sched/cls_api.c | 10 ++++++++--
2 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index d660cb4fad75..fd0bfb63ab70 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -73,7 +73,8 @@ static inline struct Qdisc *tcf_block_q(struct tcf_block *block)
}
struct tcf_block_cb *tcf_block_cb_alloc(tc_setup_cb_t *cb,
- void *cb_ident, void *cb_priv);
+ void *cb_ident, void *cb_priv,
+ void (*release)(void *cb_priv));
void tcf_block_cb_free(struct tcf_block_cb *block_cb);
struct tc_block_offload;
@@ -161,7 +162,8 @@ void tc_setup_cb_block_unregister(struct tcf_block *block, tc_setup_cb_t *cb,
}
static inline struct tcf_block_cb *
-tcf_block_cb_alloc(tc_setup_cb_t *cb, void *cb_ident, void *cb_priv)
+tcf_block_cb_alloc(tc_setup_cb_t *cb, void *cb_ident, void *cb_priv,
+ void (*release)(void *cb_priv))
{
return ERR_PTR(-EOPNOTSUPP);
}
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index a2c1258cc8dc..534a545ea51e 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -713,6 +713,7 @@ struct tcf_block_cb {
struct list_head global_list;
struct list_head list;
tc_setup_cb_t *cb;
+ void (*release)(void *cb_priv);
void *cb_ident;
void *cb_priv;
unsigned int refcnt;
@@ -750,7 +751,8 @@ unsigned int tcf_block_cb_decref(struct tcf_block_cb *block_cb)
EXPORT_SYMBOL(tcf_block_cb_decref);
struct tcf_block_cb *tcf_block_cb_alloc(tc_setup_cb_t *cb,
- void *cb_ident, void *cb_priv)
+ void *cb_ident, void *cb_priv,
+ void (*release)(void *cb_priv))
{
struct tcf_block_cb *block_cb;
@@ -760,6 +762,7 @@ struct tcf_block_cb *tcf_block_cb_alloc(tc_setup_cb_t *cb,
block_cb->cb = cb;
block_cb->cb_ident = cb_ident;
+ block_cb->release = release;
block_cb->cb_priv = cb_priv;
return block_cb;
@@ -768,6 +771,9 @@ EXPORT_SYMBOL(tcf_block_cb_alloc);
void tcf_block_cb_free(struct tcf_block_cb *block_cb)
{
+ if (block_cb->release)
+ block_cb->release(block_cb->cb_priv);
+
kfree(block_cb);
}
EXPORT_SYMBOL(tcf_block_cb_free);
@@ -801,7 +807,7 @@ struct tcf_block_cb *__tcf_block_cb_register(struct tcf_block *block,
if (err)
return ERR_PTR(err);
- block_cb = tcf_block_cb_alloc(cb, cb_ident, cb_priv);
+ block_cb = tcf_block_cb_alloc(cb, cb_ident, cb_priv, NULL);
if (IS_ERR(block_cb))
return block_cb;
--
2.11.0
^ permalink raw reply related [flat|nested] 21+ messages in thread* [PATCH 06/15 net-next,v2] net: sched: add tcf_setup_block_offload()
2019-07-04 23:48 [PATCH 00/15 net-next,v2] netfilter: add hardware offload infrastructure Pablo Neira Ayuso
` (4 preceding siblings ...)
2019-07-04 23:48 ` [PATCH 05/15 net-next,v2] net: sched: add release callback to struct tcf_block_cb Pablo Neira Ayuso
@ 2019-07-04 23:48 ` Pablo Neira Ayuso
2019-07-05 23:27 ` Jakub Kicinski
2019-07-04 23:48 ` [PATCH 07/15 net-next,v2] net: use tcf_block_setup() infrastructure Pablo Neira Ayuso
` (8 subsequent siblings)
14 siblings, 1 reply; 21+ messages in thread
From: Pablo Neira Ayuso @ 2019-07-04 23:48 UTC (permalink / raw)
To: netdev
Cc: netfilter-devel, davem, thomas.lendacky, f.fainelli, ariel.elior,
michael.chan, madalin.bucur, yisen.zhuang, salil.mehta,
jeffrey.t.kirsher, tariqt, saeedm, jiri, idosch, jakub.kicinski,
peppe.cavallaro, grygorii.strashko, andrew, vivien.didelot,
alexandre.torgue, joabreu, linux-net-drivers, ogerlitz,
Manish.Chopra, marcelo.leitner, mkubecek, venkatkumar.duvvuru,
maxime.chevallier, cphealy
Most drivers do the same thing to set up the block, add a helper
function to do this.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
v2: no changes.
drivers/net/ethernet/broadcom/bnxt/bnxt.c | 26 ++++-------------
drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c | 28 ++++--------------
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 26 ++++-------------
drivers/net/ethernet/intel/i40e/i40e_main.c | 26 ++++-------------
drivers/net/ethernet/intel/iavf/iavf_main.c | 35 ++++-------------------
drivers/net/ethernet/intel/igb/igb_main.c | 23 ++-------------
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 27 ++++-------------
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 27 ++++-------------
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 26 ++++-------------
drivers/net/ethernet/netronome/nfp/abm/cls.c | 17 ++---------
drivers/net/ethernet/netronome/nfp/bpf/main.c | 29 ++++---------------
drivers/net/ethernet/qlogic/qede/qede_main.c | 23 ++-------------
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 22 ++------------
drivers/net/netdevsim/netdev.c | 26 ++++-------------
include/net/pkt_cls.h | 10 +++++++
net/sched/cls_api.c | 20 +++++++++++++
16 files changed, 91 insertions(+), 300 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index b7b62273c955..bda732ab6538 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -9847,32 +9847,16 @@ static int bnxt_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
}
}
-static int bnxt_setup_tc_block(struct net_device *dev,
- struct tc_block_offload *f)
-{
- struct bnxt *bp = netdev_priv(dev);
-
- if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
- return -EOPNOTSUPP;
-
- switch (f->command) {
- case TC_BLOCK_BIND:
- return tcf_block_cb_register(f->block, bnxt_setup_tc_block_cb,
- bp, bp, f->extack);
- case TC_BLOCK_UNBIND:
- tcf_block_cb_unregister(f->block, bnxt_setup_tc_block_cb, bp);
- return 0;
- default:
- return -EOPNOTSUPP;
- }
-}
-
static int bnxt_setup_tc(struct net_device *dev, enum tc_setup_type type,
void *type_data)
{
+ struct bnxt *bp = netdev_priv(dev);
+
switch (type) {
case TC_SETUP_BLOCK:
- return bnxt_setup_tc_block(dev, type_data);
+ return tcf_setup_block_offload(type_data,
+ bnxt_setup_tc_block_cb, bp, bp,
+ true);
case TC_SETUP_QDISC_MQPRIO: {
struct tc_mqprio_qopt *mqprio = type_data;
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
index f760921389a3..c8bb104f28d4 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
@@ -161,34 +161,16 @@ static int bnxt_vf_rep_setup_tc_block_cb(enum tc_setup_type type,
}
}
-static int bnxt_vf_rep_setup_tc_block(struct net_device *dev,
- struct tc_block_offload *f)
-{
- struct bnxt_vf_rep *vf_rep = netdev_priv(dev);
-
- if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
- return -EOPNOTSUPP;
-
- switch (f->command) {
- case TC_BLOCK_BIND:
- return tcf_block_cb_register(f->block,
- bnxt_vf_rep_setup_tc_block_cb,
- vf_rep, vf_rep, f->extack);
- case TC_BLOCK_UNBIND:
- tcf_block_cb_unregister(f->block,
- bnxt_vf_rep_setup_tc_block_cb, vf_rep);
- return 0;
- default:
- return -EOPNOTSUPP;
- }
-}
-
static int bnxt_vf_rep_setup_tc(struct net_device *dev, enum tc_setup_type type,
void *type_data)
{
+ struct bnxt_vf_rep *vf_rep = netdev_priv(dev);
+
switch (type) {
case TC_SETUP_BLOCK:
- return bnxt_vf_rep_setup_tc_block(dev, type_data);
+ return tcf_setup_block_offload(type_data,
+ bnxt_vf_rep_setup_tc_block_cb,
+ vf_rep, vf_rep, true);
default:
return -EOPNOTSUPP;
}
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index b08efc48d42f..a09b9c909be1 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -3190,32 +3190,16 @@ static int cxgb_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
}
}
-static int cxgb_setup_tc_block(struct net_device *dev,
- struct tc_block_offload *f)
-{
- struct port_info *pi = netdev2pinfo(dev);
-
- if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
- return -EOPNOTSUPP;
-
- switch (f->command) {
- case TC_BLOCK_BIND:
- return tcf_block_cb_register(f->block, cxgb_setup_tc_block_cb,
- pi, dev, f->extack);
- case TC_BLOCK_UNBIND:
- tcf_block_cb_unregister(f->block, cxgb_setup_tc_block_cb, pi);
- return 0;
- default:
- return -EOPNOTSUPP;
- }
-}
-
static int cxgb_setup_tc(struct net_device *dev, enum tc_setup_type type,
void *type_data)
{
+ struct port_info *pi = netdev2pinfo(dev);
+
switch (type) {
case TC_SETUP_BLOCK:
- return cxgb_setup_tc_block(dev, type_data);
+ return tcf_setup_block_offload(type_data,
+ cxgb_setup_tc_block_cb, pi, dev,
+ true);
default:
return -EOPNOTSUPP;
}
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 5361c08328f7..1e703daa50fd 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -8177,34 +8177,18 @@ static int i40e_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
}
}
-static int i40e_setup_tc_block(struct net_device *dev,
- struct tc_block_offload *f)
-{
- struct i40e_netdev_priv *np = netdev_priv(dev);
-
- if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
- return -EOPNOTSUPP;
-
- switch (f->command) {
- case TC_BLOCK_BIND:
- return tcf_block_cb_register(f->block, i40e_setup_tc_block_cb,
- np, np, f->extack);
- case TC_BLOCK_UNBIND:
- tcf_block_cb_unregister(f->block, i40e_setup_tc_block_cb, np);
- return 0;
- default:
- return -EOPNOTSUPP;
- }
-}
-
static int __i40e_setup_tc(struct net_device *netdev, enum tc_setup_type type,
void *type_data)
{
+ struct i40e_netdev_priv *np = netdev_priv(netdev);
+
switch (type) {
case TC_SETUP_QDISC_MQPRIO:
return i40e_setup_tc(netdev, type_data);
case TC_SETUP_BLOCK:
- return i40e_setup_tc_block(netdev, type_data);
+ return tcf_setup_block_offload(type_data,
+ i40e_setup_tc_block_cb, np, np,
+ true);
default:
return -EOPNOTSUPP;
}
diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
index 881561b36083..29640e4b15f2 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -3114,35 +3114,6 @@ static int iavf_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
}
/**
- * iavf_setup_tc_block - register callbacks for tc
- * @netdev: network interface device structure
- * @f: tc offload data
- *
- * This function registers block callbacks for tc
- * offloads
- **/
-static int iavf_setup_tc_block(struct net_device *dev,
- struct tc_block_offload *f)
-{
- struct iavf_adapter *adapter = netdev_priv(dev);
-
- if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
- return -EOPNOTSUPP;
-
- switch (f->command) {
- case TC_BLOCK_BIND:
- return tcf_block_cb_register(f->block, iavf_setup_tc_block_cb,
- adapter, adapter, f->extack);
- case TC_BLOCK_UNBIND:
- tcf_block_cb_unregister(f->block, iavf_setup_tc_block_cb,
- adapter);
- return 0;
- default:
- return -EOPNOTSUPP;
- }
-}
-
-/**
* iavf_setup_tc - configure multiple traffic classes
* @netdev: network interface device structure
* @type: type of offload
@@ -3156,11 +3127,15 @@ static int iavf_setup_tc_block(struct net_device *dev,
static int iavf_setup_tc(struct net_device *netdev, enum tc_setup_type type,
void *type_data)
{
+ struct iavf_adapter *adapter = netdev_priv(netdev);
+
switch (type) {
case TC_SETUP_QDISC_MQPRIO:
return __iavf_setup_tc(netdev, type_data);
case TC_SETUP_BLOCK:
- return iavf_setup_tc_block(netdev, type_data);
+ return tcf_setup_block_offload(type_data,
+ iavf_setup_tc_block_cb, adapter,
+ adapter, true);
default:
return -EOPNOTSUPP;
}
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index f66dae72fe37..75a29adce0ce 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -2783,25 +2783,6 @@ static int igb_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
}
}
-static int igb_setup_tc_block(struct igb_adapter *adapter,
- struct tc_block_offload *f)
-{
- if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
- return -EOPNOTSUPP;
-
- switch (f->command) {
- case TC_BLOCK_BIND:
- return tcf_block_cb_register(f->block, igb_setup_tc_block_cb,
- adapter, adapter, f->extack);
- case TC_BLOCK_UNBIND:
- tcf_block_cb_unregister(f->block, igb_setup_tc_block_cb,
- adapter);
- return 0;
- default:
- return -EOPNOTSUPP;
- }
-}
-
static int igb_offload_txtime(struct igb_adapter *adapter,
struct tc_etf_qopt_offload *qopt)
{
@@ -2834,7 +2815,9 @@ static int igb_setup_tc(struct net_device *dev, enum tc_setup_type type,
case TC_SETUP_QDISC_CBS:
return igb_offload_cbs(adapter, type_data);
case TC_SETUP_BLOCK:
- return igb_setup_tc_block(adapter, type_data);
+ return tcf_setup_block_offload(type_data, igb_setup_tc_block_cb,
+ adapter, adapter, true);
+
case TC_SETUP_QDISC_ETF:
return igb_offload_txtime(adapter, type_data);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index b613e72c8ee4..7d3fe89ce807 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -9607,27 +9607,6 @@ static int ixgbe_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
}
}
-static int ixgbe_setup_tc_block(struct net_device *dev,
- struct tc_block_offload *f)
-{
- struct ixgbe_adapter *adapter = netdev_priv(dev);
-
- if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
- return -EOPNOTSUPP;
-
- switch (f->command) {
- case TC_BLOCK_BIND:
- return tcf_block_cb_register(f->block, ixgbe_setup_tc_block_cb,
- adapter, adapter, f->extack);
- case TC_BLOCK_UNBIND:
- tcf_block_cb_unregister(f->block, ixgbe_setup_tc_block_cb,
- adapter);
- return 0;
- default:
- return -EOPNOTSUPP;
- }
-}
-
static int ixgbe_setup_tc_mqprio(struct net_device *dev,
struct tc_mqprio_qopt *mqprio)
{
@@ -9638,9 +9617,13 @@ static int ixgbe_setup_tc_mqprio(struct net_device *dev,
static int __ixgbe_setup_tc(struct net_device *dev, enum tc_setup_type type,
void *type_data)
{
+ struct ixgbe_adapter *adapter = netdev_priv(dev);
+
switch (type) {
case TC_SETUP_BLOCK:
- return ixgbe_setup_tc_block(dev, type_data);
+ return tcf_setup_block_offload(type_data,
+ ixgbe_setup_tc_block_cb,
+ adapter, adapter, true);
case TC_SETUP_QDISC_MQPRIO:
return ixgbe_setup_tc_mqprio(dev, type_data);
default:
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index 1085040675ae..ffb501cfbc8d 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -3345,36 +3345,19 @@ static int mlx5e_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
return -EOPNOTSUPP;
}
}
-
-static int mlx5e_setup_tc_block(struct net_device *dev,
- struct tc_block_offload *f)
-{
- struct mlx5e_priv *priv = netdev_priv(dev);
-
- if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
- return -EOPNOTSUPP;
-
- switch (f->command) {
- case TC_BLOCK_BIND:
- return tcf_block_cb_register(f->block, mlx5e_setup_tc_block_cb,
- priv, priv, f->extack);
- case TC_BLOCK_UNBIND:
- tcf_block_cb_unregister(f->block, mlx5e_setup_tc_block_cb,
- priv);
- return 0;
- default:
- return -EOPNOTSUPP;
- }
-}
#endif
static int mlx5e_setup_tc(struct net_device *dev, enum tc_setup_type type,
void *type_data)
{
+ struct mlx5e_priv *priv = netdev_priv(dev);
+
switch (type) {
#ifdef CONFIG_MLX5_ESWITCH
case TC_SETUP_BLOCK:
- return mlx5e_setup_tc_block(dev, type_data);
+ return tcf_setup_block_offload(type_data,
+ mlx5e_setup_tc_block_cb,
+ priv, priv, true);
#endif
case TC_SETUP_QDISC_MQPRIO:
return mlx5e_setup_tc_mqprio(dev, type_data);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
index 330034fcdfc5..120de25c63c8 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
@@ -1178,32 +1178,16 @@ static int mlx5e_rep_setup_tc_cb(enum tc_setup_type type, void *type_data,
}
}
-static int mlx5e_rep_setup_tc_block(struct net_device *dev,
- struct tc_block_offload *f)
-{
- struct mlx5e_priv *priv = netdev_priv(dev);
-
- if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
- return -EOPNOTSUPP;
-
- switch (f->command) {
- case TC_BLOCK_BIND:
- return tcf_block_cb_register(f->block, mlx5e_rep_setup_tc_cb,
- priv, priv, f->extack);
- case TC_BLOCK_UNBIND:
- tcf_block_cb_unregister(f->block, mlx5e_rep_setup_tc_cb, priv);
- return 0;
- default:
- return -EOPNOTSUPP;
- }
-}
-
static int mlx5e_rep_setup_tc(struct net_device *dev, enum tc_setup_type type,
void *type_data)
{
+ struct mlx5e_priv *priv = netdev_priv(dev);
+
switch (type) {
case TC_SETUP_BLOCK:
- return mlx5e_rep_setup_tc_block(dev, type_data);
+ return tcf_setup_block_offload(type_data,
+ mlx5e_rep_setup_tc_cb,
+ priv, priv, true);
default:
return -EOPNOTSUPP;
}
diff --git a/drivers/net/ethernet/netronome/nfp/abm/cls.c b/drivers/net/ethernet/netronome/nfp/abm/cls.c
index ff3913085665..d99981ec04a3 100644
--- a/drivers/net/ethernet/netronome/nfp/abm/cls.c
+++ b/drivers/net/ethernet/netronome/nfp/abm/cls.c
@@ -265,19 +265,6 @@ static int nfp_abm_setup_tc_block_cb(enum tc_setup_type type,
int nfp_abm_setup_cls_block(struct net_device *netdev, struct nfp_repr *repr,
struct tc_block_offload *f)
{
- if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_EGRESS)
- return -EOPNOTSUPP;
-
- switch (f->command) {
- case TC_BLOCK_BIND:
- return tcf_block_cb_register(f->block,
- nfp_abm_setup_tc_block_cb,
- repr, repr, f->extack);
- case TC_BLOCK_UNBIND:
- tcf_block_cb_unregister(f->block, nfp_abm_setup_tc_block_cb,
- repr);
- return 0;
- default:
- return -EOPNOTSUPP;
- }
+ return tcf_setup_block_offload(f, nfp_abm_setup_tc_block_cb, repr, repr,
+ true);
}
diff --git a/drivers/net/ethernet/netronome/nfp/bpf/main.c b/drivers/net/ethernet/netronome/nfp/bpf/main.c
index 9c136da25221..fac38899dc23 100644
--- a/drivers/net/ethernet/netronome/nfp/bpf/main.c
+++ b/drivers/net/ethernet/netronome/nfp/bpf/main.c
@@ -160,35 +160,16 @@ static int nfp_bpf_setup_tc_block_cb(enum tc_setup_type type,
return 0;
}
-static int nfp_bpf_setup_tc_block(struct net_device *netdev,
- struct tc_block_offload *f)
-{
- struct nfp_net *nn = netdev_priv(netdev);
-
- if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
- return -EOPNOTSUPP;
-
- switch (f->command) {
- case TC_BLOCK_BIND:
- return tcf_block_cb_register(f->block,
- nfp_bpf_setup_tc_block_cb,
- nn, nn, f->extack);
- case TC_BLOCK_UNBIND:
- tcf_block_cb_unregister(f->block,
- nfp_bpf_setup_tc_block_cb,
- nn);
- return 0;
- default:
- return -EOPNOTSUPP;
- }
-}
-
static int nfp_bpf_setup_tc(struct nfp_app *app, struct net_device *netdev,
enum tc_setup_type type, void *type_data)
{
+ struct nfp_net *nn = netdev_priv(netdev);
+
switch (type) {
case TC_SETUP_BLOCK:
- return nfp_bpf_setup_tc_block(netdev, type_data);
+ return tcf_setup_block_offload(type_data,
+ nfp_bpf_setup_tc_block_cb,
+ nn, nn, true);
default:
return -EOPNOTSUPP;
}
diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c
index d4a29660751d..013046a30732 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_main.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_main.c
@@ -579,25 +579,6 @@ static int qede_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
}
}
-static int qede_setup_tc_block(struct qede_dev *edev,
- struct tc_block_offload *f)
-{
- if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
- return -EOPNOTSUPP;
-
- switch (f->command) {
- case TC_BLOCK_BIND:
- return tcf_block_cb_register(f->block,
- qede_setup_tc_block_cb,
- edev, edev, f->extack);
- case TC_BLOCK_UNBIND:
- tcf_block_cb_unregister(f->block, qede_setup_tc_block_cb, edev);
- return 0;
- default:
- return -EOPNOTSUPP;
- }
-}
-
static int
qede_setup_tc_offload(struct net_device *dev, enum tc_setup_type type,
void *type_data)
@@ -607,7 +588,9 @@ qede_setup_tc_offload(struct net_device *dev, enum tc_setup_type type,
switch (type) {
case TC_SETUP_BLOCK:
- return qede_setup_tc_block(edev, type_data);
+ return tcf_setup_block_offload(type_data,
+ qede_setup_tc_block_cb,
+ edev, edev, true);
case TC_SETUP_QDISC_MQPRIO:
mqprio = type_data;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 3425d4dda03d..ffed6b51040a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -3853,24 +3853,6 @@ static int stmmac_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
return ret;
}
-static int stmmac_setup_tc_block(struct stmmac_priv *priv,
- struct tc_block_offload *f)
-{
- if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
- return -EOPNOTSUPP;
-
- switch (f->command) {
- case TC_BLOCK_BIND:
- return tcf_block_cb_register(f->block, stmmac_setup_tc_block_cb,
- priv, priv, f->extack);
- case TC_BLOCK_UNBIND:
- tcf_block_cb_unregister(f->block, stmmac_setup_tc_block_cb, priv);
- return 0;
- default:
- return -EOPNOTSUPP;
- }
-}
-
static int stmmac_setup_tc(struct net_device *ndev, enum tc_setup_type type,
void *type_data)
{
@@ -3878,7 +3860,9 @@ static int stmmac_setup_tc(struct net_device *ndev, enum tc_setup_type type,
switch (type) {
case TC_SETUP_BLOCK:
- return stmmac_setup_tc_block(priv, type_data);
+ return tcf_setup_block_offload(type_data,
+ stmmac_setup_tc_block_cb,
+ priv, priv, true);
case TC_SETUP_QDISC_CBS:
return stmmac_tc_setup_cbs(priv, priv, type_data);
default:
diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c
index e5c8aa08e1cd..240727623e9b 100644
--- a/drivers/net/netdevsim/netdev.c
+++ b/drivers/net/netdevsim/netdev.c
@@ -78,26 +78,6 @@ nsim_setup_tc_block_cb(enum tc_setup_type type, void *type_data, void *cb_priv)
return nsim_bpf_setup_tc_block_cb(type, type_data, cb_priv);
}
-static int
-nsim_setup_tc_block(struct net_device *dev, struct tc_block_offload *f)
-{
- struct netdevsim *ns = netdev_priv(dev);
-
- if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
- return -EOPNOTSUPP;
-
- switch (f->command) {
- case TC_BLOCK_BIND:
- return tcf_block_cb_register(f->block, nsim_setup_tc_block_cb,
- ns, ns, f->extack);
- case TC_BLOCK_UNBIND:
- tcf_block_cb_unregister(f->block, nsim_setup_tc_block_cb, ns);
- return 0;
- default:
- return -EOPNOTSUPP;
- }
-}
-
static int nsim_set_vf_mac(struct net_device *dev, int vf, u8 *mac)
{
struct netdevsim *ns = netdev_priv(dev);
@@ -226,9 +206,13 @@ static int nsim_set_vf_link_state(struct net_device *dev, int vf, int state)
static int
nsim_setup_tc(struct net_device *dev, enum tc_setup_type type, void *type_data)
{
+ struct netdevsim *ns = netdev_priv(dev);
+
switch (type) {
case TC_SETUP_BLOCK:
- return nsim_setup_tc_block(dev, type_data);
+ return tcf_setup_block_offload(type_data,
+ nsim_setup_tc_block_cb, ns, ns,
+ true);
default:
return -EOPNOTSUPP;
}
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index fd0bfb63ab70..d35711758ddb 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -111,6 +111,8 @@ void tc_indr_block_cb_unregister(struct net_device *dev,
int tcf_classify(struct sk_buff *skb, const struct tcf_proto *tp,
struct tcf_result *res, bool compat_mode);
+int tcf_setup_block_offload(struct tc_block_offload *f, tc_setup_cb_t *cb,
+ void *cb_ident, void *cb_priv, bool ingress_only);
#else
static inline bool tcf_block_shared(struct tcf_block *block)
{
@@ -161,6 +163,14 @@ void tc_setup_cb_block_unregister(struct tcf_block *block, tc_setup_cb_t *cb,
{
}
+static inline int tcf_setup_block_offload(struct tc_block_offload *f,
+ tc_setup_cb_t *cb,
+ void *cb_ident, void *cb_priv,
+ bool ingress_only)
+{
+ return -EOPNOTSUPP;
+}
+
static inline struct tcf_block_cb *
tcf_block_cb_alloc(tc_setup_cb_t *cb, void *cb_ident, void *cb_priv,
void (*release)(void *cb_priv))
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 534a545ea51e..003f24a1323f 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -922,6 +922,26 @@ static int tcf_block_setup(struct tcf_block *block, struct tc_block_offload *bo)
return err;
}
+int tcf_setup_block_offload(struct tc_block_offload *f, tc_setup_cb_t *cb,
+ void *cb_ident, void *cb_priv, bool ingress_only)
+{
+ if (ingress_only &&
+ f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
+ return -EOPNOTSUPP;
+
+ switch (f->command) {
+ case TC_BLOCK_BIND:
+ return tcf_block_cb_register(f->block, cb, cb_ident, cb_priv,
+ f->extack);
+ case TC_BLOCK_UNBIND:
+ tcf_block_cb_unregister(f->block, cb, cb_ident);
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+EXPORT_SYMBOL(tcf_setup_block_offload);
+
static struct rhashtable indr_setup_block_ht;
struct tc_indr_block_dev {
--
2.11.0
^ permalink raw reply related [flat|nested] 21+ messages in thread* Re: [PATCH 06/15 net-next,v2] net: sched: add tcf_setup_block_offload()
2019-07-04 23:48 ` [PATCH 06/15 net-next,v2] net: sched: add tcf_setup_block_offload() Pablo Neira Ayuso
@ 2019-07-05 23:27 ` Jakub Kicinski
0 siblings, 0 replies; 21+ messages in thread
From: Jakub Kicinski @ 2019-07-05 23:27 UTC (permalink / raw)
To: Pablo Neira Ayuso
Cc: netdev, netfilter-devel, davem, thomas.lendacky, f.fainelli,
ariel.elior, michael.chan, madalin.bucur, yisen.zhuang,
salil.mehta, jeffrey.t.kirsher, tariqt, saeedm, jiri, idosch,
peppe.cavallaro, grygorii.strashko, andrew, vivien.didelot,
alexandre.torgue, joabreu, linux-net-drivers, ogerlitz,
Manish.Chopra, marcelo.leitner, mkubecek, venkatkumar.duvvuru,
maxime.chevallier, cphealy
On Fri, 5 Jul 2019 01:48:34 +0200, Pablo Neira Ayuso wrote:
> Most drivers do the same thing to set up the block, add a helper
> function to do this.
>
> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
> diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
> index 534a545ea51e..003f24a1323f 100644
> --- a/net/sched/cls_api.c
> +++ b/net/sched/cls_api.c
> @@ -922,6 +922,26 @@ static int tcf_block_setup(struct tcf_block *block, struct tc_block_offload *bo)
> return err;
> }
>
> +int tcf_setup_block_offload(struct tc_block_offload *f, tc_setup_cb_t *cb,
> + void *cb_ident, void *cb_priv, bool ingress_only)
> +{
> + if (ingress_only &&
> + f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
> + return -EOPNOTSUPP;
> +
> + switch (f->command) {
> + case TC_BLOCK_BIND:
> + return tcf_block_cb_register(f->block, cb, cb_ident, cb_priv,
> + f->extack);
> + case TC_BLOCK_UNBIND:
> + tcf_block_cb_unregister(f->block, cb, cb_ident);
> + return 0;
> + default:
> + return -EOPNOTSUPP;
> + }
> +}
> +EXPORT_SYMBOL(tcf_setup_block_offload);
> +
> static struct rhashtable indr_setup_block_ht;
>
> struct tc_indr_block_dev {
This change is pretty much unrelated to the rest of the series, isn't
it? Can you please post it separately and make the series smaller
this way?
Perhaps tcf_setup_block_offload_simple() would be a good name for this
helper?
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 07/15 net-next,v2] net: use tcf_block_setup() infrastructure
2019-07-04 23:48 [PATCH 00/15 net-next,v2] netfilter: add hardware offload infrastructure Pablo Neira Ayuso
` (5 preceding siblings ...)
2019-07-04 23:48 ` [PATCH 06/15 net-next,v2] net: sched: add tcf_setup_block_offload() Pablo Neira Ayuso
@ 2019-07-04 23:48 ` Pablo Neira Ayuso
2019-07-04 23:48 ` [PATCH 08/15 net-next,v2] net: cls_api: do not expose tcf_block to drivers Pablo Neira Ayuso
` (7 subsequent siblings)
14 siblings, 0 replies; 21+ messages in thread
From: Pablo Neira Ayuso @ 2019-07-04 23:48 UTC (permalink / raw)
To: netdev
Cc: netfilter-devel, davem, thomas.lendacky, f.fainelli, ariel.elior,
michael.chan, madalin.bucur, yisen.zhuang, salil.mehta,
jeffrey.t.kirsher, tariqt, saeedm, jiri, idosch, jakub.kicinski,
peppe.cavallaro, grygorii.strashko, andrew, vivien.didelot,
alexandre.torgue, joabreu, linux-net-drivers, ogerlitz,
Manish.Chopra, marcelo.leitner, mkubecek, venkatkumar.duvvuru,
maxime.chevallier, cphealy
This allows us to register / unregister tcf_block_cb objects from the
core. The idea is to allocate and to set up the tcf_block_cb objects
from the driver, attach them to the tc_block_offload->cb_list, then the
core iterates over this block list to registers them.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
v2: check for IS_ERR() after tcf_block_cb_alloc(), since change in patch 2/15.
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 34 +++++++----
drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 70 +++++++++++++---------
drivers/net/ethernet/mscc/ocelot_flower.c | 33 +++++-----
drivers/net/ethernet/mscc/ocelot_tc.c | 24 +++++---
.../net/ethernet/netronome/nfp/flower/offload.c | 57 ++++++++++++------
include/net/pkt_cls.h | 13 ++--
net/dsa/slave.c | 14 ++++-
net/sched/cls_api.c | 41 +++++++++----
8 files changed, 190 insertions(+), 96 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
index 120de25c63c8..b6ffaec4becb 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
@@ -692,13 +692,21 @@ static int mlx5e_rep_indr_setup_block_cb(enum tc_setup_type type,
}
}
+static void mlx5e_rep_indr_tc_block_unbind(void *cb_priv)
+{
+ struct mlx5e_rep_indr_block_priv *indr_priv = cb_priv;
+
+ list_del(&indr_priv->list);
+ kfree(indr_priv);
+}
+
static int
mlx5e_rep_indr_setup_tc_block(struct net_device *netdev,
struct mlx5e_rep_priv *rpriv,
struct tc_block_offload *f)
{
struct mlx5e_rep_indr_block_priv *indr_priv;
- int err = 0;
+ struct tcf_block_cb *block_cb;
if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
return -EOPNOTSUPP;
@@ -718,26 +726,30 @@ mlx5e_rep_indr_setup_tc_block(struct net_device *netdev,
list_add(&indr_priv->list,
&rpriv->uplink_priv.tc_indr_block_priv_list);
- err = tcf_block_cb_register(f->block,
- mlx5e_rep_indr_setup_block_cb,
- indr_priv, indr_priv, f->extack);
- if (err) {
+ block_cb = tcf_block_cb_alloc(f->net,
+ mlx5e_rep_indr_setup_block_cb,
+ indr_priv, indr_priv,
+ mlx5e_rep_indr_tc_block_unbind);
+ if (IS_ERR(block_cb)) {
list_del(&indr_priv->list);
kfree(indr_priv);
+ return PTR_ERR(block_cb);
}
+ tcf_block_cb_add(block_cb, f);
- return err;
+ return 0;
case TC_BLOCK_UNBIND:
indr_priv = mlx5e_rep_indr_block_priv_lookup(rpriv, netdev);
if (!indr_priv)
return -ENOENT;
- tcf_block_cb_unregister(f->block,
- mlx5e_rep_indr_setup_block_cb,
- indr_priv);
- list_del(&indr_priv->list);
- kfree(indr_priv);
+ block_cb = tcf_block_cb_lookup(f->net,
+ mlx5e_rep_indr_setup_block_cb,
+ indr_priv);
+ if (!block_cb)
+ return -ENOENT;
+ tcf_block_cb_remove(block_cb, f);
return 0;
default:
return -EOPNOTSUPP;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 755b14b82c8f..950d09f3ecb1 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -1584,29 +1584,40 @@ static int mlxsw_sp_setup_tc_block_cb_flower(enum tc_setup_type type,
}
}
+static void mlxsw_sp_tc_block_flower_release(void *cb_priv)
+{
+ struct mlxsw_sp_acl_block *acl_block = cb_priv;
+
+ mlxsw_sp_acl_block_destroy(acl_block);
+}
+
static int
mlxsw_sp_setup_tc_block_flower_bind(struct mlxsw_sp_port *mlxsw_sp_port,
- struct tcf_block *block, bool ingress,
- struct netlink_ext_ack *extack)
+ struct tc_block_offload *f, bool ingress)
{
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
struct mlxsw_sp_acl_block *acl_block;
struct tcf_block_cb *block_cb;
+ bool register_block = false;
int err;
- block_cb = tcf_block_cb_lookup(block, mlxsw_sp_setup_tc_block_cb_flower,
+ block_cb = tcf_block_cb_lookup(f->net,
+ mlxsw_sp_setup_tc_block_cb_flower,
mlxsw_sp);
if (!block_cb) {
- acl_block = mlxsw_sp_acl_block_create(mlxsw_sp, block->net);
+ acl_block = mlxsw_sp_acl_block_create(mlxsw_sp, f->net);
if (!acl_block)
return -ENOMEM;
- block_cb = __tcf_block_cb_register(block,
- mlxsw_sp_setup_tc_block_cb_flower,
- mlxsw_sp, acl_block, extack);
+ block_cb = tcf_block_cb_alloc(f->net,
+ mlxsw_sp_setup_tc_block_cb_flower,
+ mlxsw_sp, acl_block,
+ mlxsw_sp_tc_block_flower_release);
if (IS_ERR(block_cb)) {
+ mlxsw_sp_acl_block_destroy(acl_block);
err = PTR_ERR(block_cb);
goto err_cb_register;
}
+ register_block = true;
} else {
acl_block = tcf_block_cb_priv(block_cb);
}
@@ -1621,27 +1632,29 @@ mlxsw_sp_setup_tc_block_flower_bind(struct mlxsw_sp_port *mlxsw_sp_port,
else
mlxsw_sp_port->eg_acl_block = acl_block;
+ if (register_block)
+ tcf_block_cb_add(block_cb, f);
+
return 0;
err_block_bind:
- if (!tcf_block_cb_decref(block_cb)) {
- __tcf_block_cb_unregister(block, block_cb);
+ if (!tcf_block_cb_decref(block_cb))
+ tcf_block_cb_free(block_cb);
err_cb_register:
- mlxsw_sp_acl_block_destroy(acl_block);
- }
return err;
}
static void
mlxsw_sp_setup_tc_block_flower_unbind(struct mlxsw_sp_port *mlxsw_sp_port,
- struct tcf_block *block, bool ingress)
+ struct tc_block_offload *f, bool ingress)
{
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
struct mlxsw_sp_acl_block *acl_block;
struct tcf_block_cb *block_cb;
int err;
- block_cb = tcf_block_cb_lookup(block, mlxsw_sp_setup_tc_block_cb_flower,
+ block_cb = tcf_block_cb_lookup(f->net,
+ mlxsw_sp_setup_tc_block_cb_flower,
mlxsw_sp);
if (!block_cb)
return;
@@ -1654,15 +1667,14 @@ mlxsw_sp_setup_tc_block_flower_unbind(struct mlxsw_sp_port *mlxsw_sp_port,
acl_block = tcf_block_cb_priv(block_cb);
err = mlxsw_sp_acl_block_unbind(mlxsw_sp, acl_block,
mlxsw_sp_port, ingress);
- if (!err && !tcf_block_cb_decref(block_cb)) {
- __tcf_block_cb_unregister(block, block_cb);
- mlxsw_sp_acl_block_destroy(acl_block);
- }
+ if (!err && !tcf_block_cb_decref(block_cb))
+ tcf_block_cb_remove(block_cb, f);
}
static int mlxsw_sp_setup_tc_block(struct mlxsw_sp_port *mlxsw_sp_port,
struct tc_block_offload *f)
{
+ struct tcf_block_cb *block_cb;
tc_setup_cb_t *cb;
bool ingress;
int err;
@@ -1679,22 +1691,26 @@ static int mlxsw_sp_setup_tc_block(struct mlxsw_sp_port *mlxsw_sp_port,
switch (f->command) {
case TC_BLOCK_BIND:
- err = tcf_block_cb_register(f->block, cb, mlxsw_sp_port,
- mlxsw_sp_port, f->extack);
- if (err)
- return err;
- err = mlxsw_sp_setup_tc_block_flower_bind(mlxsw_sp_port,
- f->block, ingress,
- f->extack);
+ block_cb = tcf_block_cb_alloc(f->net, cb, mlxsw_sp_port,
+ mlxsw_sp_port, NULL);
+ if (IS_ERR(block_cb))
+ return PTR_ERR(block_cb);
+ err = mlxsw_sp_setup_tc_block_flower_bind(mlxsw_sp_port, f,
+ ingress);
if (err) {
- tcf_block_cb_unregister(f->block, cb, mlxsw_sp_port);
+ tcf_block_cb_free(block_cb);
return err;
}
+ tcf_block_cb_add(block_cb, f);
return 0;
case TC_BLOCK_UNBIND:
mlxsw_sp_setup_tc_block_flower_unbind(mlxsw_sp_port,
- f->block, ingress);
- tcf_block_cb_unregister(f->block, cb, mlxsw_sp_port);
+ f, ingress);
+ block_cb = tcf_block_cb_lookup(f->net, cb, mlxsw_sp_port);
+ if (!block_cb)
+ return -ENOENT;
+
+ tcf_block_cb_remove(block_cb, f);
return 0;
default:
return -EOPNOTSUPP;
diff --git a/drivers/net/ethernet/mscc/ocelot_flower.c b/drivers/net/ethernet/mscc/ocelot_flower.c
index 8778dee5a471..e62a7e56ec3e 100644
--- a/drivers/net/ethernet/mscc/ocelot_flower.c
+++ b/drivers/net/ethernet/mscc/ocelot_flower.c
@@ -299,6 +299,13 @@ static void ocelot_port_block_destroy(struct ocelot_port_block *block)
kfree(block);
}
+static void ocelot_tc_block_unbind(void *cb_priv)
+{
+ struct ocelot_port_block *port_block = cb_priv;
+
+ ocelot_port_block_destroy(port_block);
+}
+
int ocelot_setup_tc_block_flower_bind(struct ocelot_port *port,
struct tc_block_offload *f)
{
@@ -309,21 +316,22 @@ int ocelot_setup_tc_block_flower_bind(struct ocelot_port *port,
if (f->binder_type == TCF_BLOCK_BINDER_TYPE_CLSACT_EGRESS)
return -EOPNOTSUPP;
- block_cb = tcf_block_cb_lookup(f->block,
- ocelot_setup_tc_block_cb_flower, port);
+ block_cb = tcf_block_cb_lookup(f->net, ocelot_setup_tc_block_cb_flower,
+ port);
if (!block_cb) {
port_block = ocelot_port_block_create(port);
if (!port_block)
return -ENOMEM;
- block_cb =
- __tcf_block_cb_register(f->block,
- ocelot_setup_tc_block_cb_flower,
- port, port_block, f->extack);
+ block_cb = tcf_block_cb_alloc(f->net,
+ ocelot_setup_tc_block_cb_flower,
+ port, port_block,
+ ocelot_tc_block_unbind);
if (IS_ERR(block_cb)) {
ret = PTR_ERR(block_cb);
goto err_cb_register;
}
+ tcf_block_cb_add(block_cb, f);
} else {
port_block = tcf_block_cb_priv(block_cb);
}
@@ -340,18 +348,13 @@ int ocelot_setup_tc_block_flower_bind(struct ocelot_port *port,
void ocelot_setup_tc_block_flower_unbind(struct ocelot_port *port,
struct tc_block_offload *f)
{
- struct ocelot_port_block *port_block;
struct tcf_block_cb *block_cb;
- block_cb = tcf_block_cb_lookup(f->block,
- ocelot_setup_tc_block_cb_flower, port);
+ block_cb = tcf_block_cb_lookup(f->net, ocelot_setup_tc_block_cb_flower,
+ port);
if (!block_cb)
return;
- port_block = tcf_block_cb_priv(block_cb);
- if (!tcf_block_cb_decref(block_cb)) {
- tcf_block_cb_unregister(f->block,
- ocelot_setup_tc_block_cb_flower, port);
- ocelot_port_block_destroy(port_block);
- }
+ if (!tcf_block_cb_decref(block_cb))
+ tcf_block_cb_remove(block_cb, f);
}
diff --git a/drivers/net/ethernet/mscc/ocelot_tc.c b/drivers/net/ethernet/mscc/ocelot_tc.c
index 72084306240d..5c3bf639f87c 100644
--- a/drivers/net/ethernet/mscc/ocelot_tc.c
+++ b/drivers/net/ethernet/mscc/ocelot_tc.c
@@ -131,8 +131,9 @@ static int ocelot_setup_tc_block_cb_eg(enum tc_setup_type type,
static int ocelot_setup_tc_block(struct ocelot_port *port,
struct tc_block_offload *f)
{
+ struct tcf_block_cb *block_cb;
tc_setup_cb_t *cb;
- int ret;
+ int err;
netdev_dbg(port->dev, "tc_block command %d, binder_type %d\n",
f->command, f->binder_type);
@@ -148,15 +149,24 @@ static int ocelot_setup_tc_block(struct ocelot_port *port,
switch (f->command) {
case TC_BLOCK_BIND:
- ret = tcf_block_cb_register(f->block, cb, port,
- port, f->extack);
- if (ret)
- return ret;
+ block_cb = tcf_block_cb_alloc(f->net, cb, port, port, NULL);
+ if (IS_ERR(block_cb))
+ return PTR_ERR(block_cb);
- return ocelot_setup_tc_block_flower_bind(port, f);
+ err = ocelot_setup_tc_block_flower_bind(port, f);
+ if (err < 0) {
+ tcf_block_cb_free(block_cb);
+ return err;
+ }
+ tcf_block_cb_add(block_cb, f);
+ return 0;
case TC_BLOCK_UNBIND:
+ block_cb = tcf_block_cb_lookup(f->net, cb, port);
+ if (!block_cb)
+ return -ENOENT;
+
ocelot_setup_tc_block_flower_unbind(port, f);
- tcf_block_cb_unregister(f->block, cb, port);
+ tcf_block_cb_remove(block_cb, f);
return 0;
default:
return -EOPNOTSUPP;
diff --git a/drivers/net/ethernet/netronome/nfp/flower/offload.c b/drivers/net/ethernet/netronome/nfp/flower/offload.c
index 6dbe947269c3..fa44dce810ed 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/offload.c
+++ b/drivers/net/ethernet/netronome/nfp/flower/offload.c
@@ -1307,6 +1307,7 @@ static int nfp_flower_setup_tc_block(struct net_device *netdev,
{
struct nfp_repr *repr = netdev_priv(netdev);
struct nfp_flower_repr_priv *repr_priv;
+ struct tcf_block_cb *block_cb;
if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
return -EOPNOTSUPP;
@@ -1316,13 +1317,22 @@ static int nfp_flower_setup_tc_block(struct net_device *netdev,
switch (f->command) {
case TC_BLOCK_BIND:
- return tcf_block_cb_register(f->block,
- nfp_flower_setup_tc_block_cb,
- repr, repr, f->extack);
+ block_cb = tcf_block_cb_alloc(f->net,
+ nfp_flower_setup_tc_block_cb,
+ repr, repr, NULL);
+ if (IS_ERR(block_cb))
+ return PTR_ERR(block_cb);
+
+ tcf_block_cb_add(block_cb, f);
+ return 0;
case TC_BLOCK_UNBIND:
- tcf_block_cb_unregister(f->block,
- nfp_flower_setup_tc_block_cb,
- repr);
+ block_cb = tcf_block_cb_lookup(f->net,
+ nfp_flower_setup_tc_block_cb,
+ repr);
+ if (!block_cb)
+ return -ENOENT;
+
+ tcf_block_cb_remove(block_cb, f);
return 0;
default:
return -EOPNOTSUPP;
@@ -1381,13 +1391,22 @@ static int nfp_flower_setup_indr_block_cb(enum tc_setup_type type,
}
}
+static void nfp_flower_setup_indr_tc_release(void *cb_priv)
+{
+ struct nfp_flower_indr_block_cb_priv *priv = cb_priv;
+
+ list_del(&priv->list);
+ kfree(priv);
+}
+
static int
nfp_flower_setup_indr_tc_block(struct net_device *netdev, struct nfp_app *app,
struct tc_block_offload *f)
{
struct nfp_flower_indr_block_cb_priv *cb_priv;
struct nfp_flower_priv *priv = app->priv;
- int err;
+ struct net *net = dev_net(netdev);
+ struct tcf_block_cb *block_cb;
if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS &&
!(f->binder_type == TCF_BLOCK_BINDER_TYPE_CLSACT_EGRESS &&
@@ -1404,26 +1423,30 @@ nfp_flower_setup_indr_tc_block(struct net_device *netdev, struct nfp_app *app,
cb_priv->app = app;
list_add(&cb_priv->list, &priv->indr_block_cb_priv);
- err = tcf_block_cb_register(f->block,
- nfp_flower_setup_indr_block_cb,
- cb_priv, cb_priv, f->extack);
- if (err) {
+ block_cb = tcf_block_cb_alloc(net,
+ nfp_flower_setup_indr_block_cb,
+ cb_priv, cb_priv,
+ nfp_flower_setup_indr_tc_release);
+ if (IS_ERR(block_cb)) {
list_del(&cb_priv->list);
kfree(cb_priv);
+ return PTR_ERR(block_cb);
}
- return err;
+ tcf_block_cb_add(block_cb, f);
+ return 0;
case TC_BLOCK_UNBIND:
cb_priv = nfp_flower_indr_block_cb_priv_lookup(app, netdev);
if (!cb_priv)
return -ENOENT;
- tcf_block_cb_unregister(f->block,
- nfp_flower_setup_indr_block_cb,
- cb_priv);
- list_del(&cb_priv->list);
- kfree(cb_priv);
+ block_cb = tcf_block_cb_lookup(net,
+ nfp_flower_setup_indr_block_cb,
+ cb_priv);
+ if (!block_cb)
+ return -ENOENT;
+ tcf_block_cb_remove(block_cb, f);
return 0;
default:
return -EOPNOTSUPP;
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index d35711758ddb..cb899c4552f4 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -72,7 +72,7 @@ static inline struct Qdisc *tcf_block_q(struct tcf_block *block)
return block->q;
}
-struct tcf_block_cb *tcf_block_cb_alloc(tc_setup_cb_t *cb,
+struct tcf_block_cb *tcf_block_cb_alloc(struct net *net, tc_setup_cb_t *cb,
void *cb_ident, void *cb_priv,
void (*release)(void *cb_priv));
void tcf_block_cb_free(struct tcf_block_cb *block_cb);
@@ -84,8 +84,8 @@ void tcf_block_cb_remove(struct tcf_block_cb *block_cb,
struct tc_block_offload *offload);
void *tcf_block_cb_priv(struct tcf_block_cb *block_cb);
-struct tcf_block_cb *tcf_block_cb_lookup(struct tcf_block *block,
- tc_setup_cb_t *cb, void *cb_ident);
+struct tcf_block_cb *tcf_block_cb_lookup(struct net *net, tc_setup_cb_t *cb,
+ void *cb_ident);
void tcf_block_cb_incref(struct tcf_block_cb *block_cb);
unsigned int tcf_block_cb_decref(struct tcf_block_cb *block_cb);
struct tcf_block_cb *__tcf_block_cb_register(struct tcf_block *block,
@@ -172,8 +172,8 @@ static inline int tcf_setup_block_offload(struct tc_block_offload *f,
}
static inline struct tcf_block_cb *
-tcf_block_cb_alloc(tc_setup_cb_t *cb, void *cb_ident, void *cb_priv,
- void (*release)(void *cb_priv))
+tcf_block_cb_alloc(struct net *net, tc_setup_cb_t *cb, void *cb_ident,
+ void *cb_priv, void (*release)(void *cb_priv))
{
return ERR_PTR(-EOPNOTSUPP);
}
@@ -200,7 +200,7 @@ void *tcf_block_cb_priv(struct tcf_block_cb *block_cb)
}
static inline
-struct tcf_block_cb *tcf_block_cb_lookup(struct tcf_block *block,
+struct tcf_block_cb *tcf_block_cb_lookup(struct net *net, struct tcf_block *block,
tc_setup_cb_t *cb, void *cb_ident)
{
return NULL;
@@ -662,6 +662,7 @@ struct tc_block_offload {
enum tc_block_command command;
enum tcf_block_binder_type binder_type;
struct list_head cb_list;
+ struct net *net;
struct tcf_block *block;
struct netlink_ext_ack *extack;
};
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 99673f6b07f6..01be6dc20ba3 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -945,6 +945,7 @@ static int dsa_slave_setup_tc_block_cb_eg(enum tc_setup_type type,
static int dsa_slave_setup_tc_block(struct net_device *dev,
struct tc_block_offload *f)
{
+ struct tcf_block_cb *block_cb;
tc_setup_cb_t *cb;
if (f->binder_type == TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
@@ -956,9 +957,18 @@ static int dsa_slave_setup_tc_block(struct net_device *dev,
switch (f->command) {
case TC_BLOCK_BIND:
- return tcf_block_cb_register(f->block, cb, dev, dev, f->extack);
+ block_cb = tcf_block_cb_alloc(f->net, cb, dev, dev, NULL);
+ if (IS_ERR(block_cb))
+ return PTR_ERR(block_cb);
+
+ tcf_block_cb_add(block_cb, f);
+ return 0;
case TC_BLOCK_UNBIND:
- tcf_block_cb_unregister(f->block, cb, dev);
+ block_cb = tcf_block_cb_lookup(f->net, cb, dev);
+ if (!block_cb)
+ return -ENOENT;
+
+ tcf_block_cb_remove(block_cb, f);
return 0;
default:
return -EOPNOTSUPP;
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 003f24a1323f..3f036d50af65 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -712,6 +712,7 @@ static bool tcf_block_offload_in_use(struct tcf_block *block)
struct tcf_block_cb {
struct list_head global_list;
struct list_head list;
+ struct net *net;
tc_setup_cb_t *cb;
void (*release)(void *cb_priv);
void *cb_ident;
@@ -727,12 +728,15 @@ EXPORT_SYMBOL(tcf_block_cb_priv);
static LIST_HEAD(tcf_block_cb_list);
-struct tcf_block_cb *tcf_block_cb_lookup(struct tcf_block *block,
- tc_setup_cb_t *cb, void *cb_ident)
-{ struct tcf_block_cb *block_cb;
+struct tcf_block_cb *tcf_block_cb_lookup(struct net *net, tc_setup_cb_t *cb,
+ void *cb_ident)
+{
+ struct tcf_block_cb *block_cb;
- list_for_each_entry(block_cb, &block->cb_list, list)
- if (block_cb->cb == cb && block_cb->cb_ident == cb_ident)
+ list_for_each_entry(block_cb, &tcf_block_cb_list, global_list)
+ if (block_cb->net == net &&
+ block_cb->cb == cb &&
+ block_cb->cb_ident == cb_ident)
return block_cb;
return NULL;
}
@@ -750,7 +754,7 @@ unsigned int tcf_block_cb_decref(struct tcf_block_cb *block_cb)
}
EXPORT_SYMBOL(tcf_block_cb_decref);
-struct tcf_block_cb *tcf_block_cb_alloc(tc_setup_cb_t *cb,
+struct tcf_block_cb *tcf_block_cb_alloc(struct net *net, tc_setup_cb_t *cb,
void *cb_ident, void *cb_priv,
void (*release)(void *cb_priv))
{
@@ -760,6 +764,7 @@ struct tcf_block_cb *tcf_block_cb_alloc(tc_setup_cb_t *cb,
if (!block_cb)
return ERR_PTR(-ENOMEM);
+ block_cb->net = net;
block_cb->cb = cb;
block_cb->cb_ident = cb_ident;
block_cb->release = release;
@@ -807,7 +812,7 @@ struct tcf_block_cb *__tcf_block_cb_register(struct tcf_block *block,
if (err)
return ERR_PTR(err);
- block_cb = tcf_block_cb_alloc(cb, cb_ident, cb_priv, NULL);
+ block_cb = tcf_block_cb_alloc(block->net, cb, cb_ident, cb_priv, NULL);
if (IS_ERR(block_cb))
return block_cb;
@@ -844,7 +849,7 @@ void tcf_block_cb_unregister(struct tcf_block *block,
{
struct tcf_block_cb *block_cb;
- block_cb = tcf_block_cb_lookup(block, cb, cb_ident);
+ block_cb = tcf_block_cb_lookup(block->net, cb, cb_ident);
if (!block_cb)
return;
__tcf_block_cb_unregister(block, block_cb);
@@ -925,16 +930,27 @@ static int tcf_block_setup(struct tcf_block *block, struct tc_block_offload *bo)
int tcf_setup_block_offload(struct tc_block_offload *f, tc_setup_cb_t *cb,
void *cb_ident, void *cb_priv, bool ingress_only)
{
+ struct tcf_block_cb *block_cb;
+
if (ingress_only &&
f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
return -EOPNOTSUPP;
switch (f->command) {
case TC_BLOCK_BIND:
- return tcf_block_cb_register(f->block, cb, cb_ident, cb_priv,
- f->extack);
+ block_cb = tcf_block_cb_alloc(f->net, cb, cb_ident,
+ cb_priv, NULL);
+ if (IS_ERR(block_cb))
+ return PTR_ERR(block_cb);
+
+ tcf_block_cb_add(block_cb, f);
+ return 0;
case TC_BLOCK_UNBIND:
- tcf_block_cb_unregister(f->block, cb, cb_ident);
+ block_cb = tcf_block_cb_lookup(f->net, cb, cb_ident);
+ if (!block_cb)
+ return -ENOENT;
+
+ tcf_block_cb_remove(block_cb, f);
return 0;
default:
return -EOPNOTSUPP;
@@ -1056,6 +1072,7 @@ static void tc_indr_block_ing_cmd(struct tc_indr_block_dev *indr_dev,
struct tc_block_offload bo = {
.command = command,
.binder_type = TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS,
+ .net = dev_net(indr_dev->dev),
.block = indr_dev->block,
};
INIT_LIST_HEAD(&bo.cb_list);
@@ -1146,6 +1163,7 @@ static void tc_indr_block_call(struct tcf_block *block, struct net_device *dev,
struct tc_block_offload bo = {
.command = command,
.binder_type = ei->binder_type,
+ .net = dev_net(dev),
.block = block,
.extack = extack,
};
@@ -1173,6 +1191,7 @@ static int tcf_block_offload_cmd(struct tcf_block *block,
struct tc_block_offload bo = {};
int err;
+ bo.net = dev_net(dev);
bo.command = command;
bo.binder_type = ei->binder_type;
bo.block = block;
--
2.11.0
^ permalink raw reply related [flat|nested] 21+ messages in thread* [PATCH 08/15 net-next,v2] net: cls_api: do not expose tcf_block to drivers
2019-07-04 23:48 [PATCH 00/15 net-next,v2] netfilter: add hardware offload infrastructure Pablo Neira Ayuso
` (6 preceding siblings ...)
2019-07-04 23:48 ` [PATCH 07/15 net-next,v2] net: use tcf_block_setup() infrastructure Pablo Neira Ayuso
@ 2019-07-04 23:48 ` Pablo Neira Ayuso
2019-07-04 23:48 ` [PATCH 09/15 net-next,v2] net: sched: remove tcf_block_cb_{register,unregister}() Pablo Neira Ayuso
` (6 subsequent siblings)
14 siblings, 0 replies; 21+ messages in thread
From: Pablo Neira Ayuso @ 2019-07-04 23:48 UTC (permalink / raw)
To: netdev
Cc: netfilter-devel, davem, thomas.lendacky, f.fainelli, ariel.elior,
michael.chan, madalin.bucur, yisen.zhuang, salil.mehta,
jeffrey.t.kirsher, tariqt, saeedm, jiri, idosch, jakub.kicinski,
peppe.cavallaro, grygorii.strashko, andrew, vivien.didelot,
alexandre.torgue, joabreu, linux-net-drivers, ogerlitz,
Manish.Chopra, marcelo.leitner, mkubecek, venkatkumar.duvvuru,
maxime.chevallier, cphealy
Expose the block_shared flag which is what drivers.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
v2: fix incorrect correction of block_shared in net/sched/cls_api.c
drivers/net/ethernet/mscc/ocelot_tc.c | 2 +-
drivers/net/ethernet/netronome/nfp/flower/offload.c | 2 +-
include/net/pkt_cls.h | 2 +-
net/sched/cls_api.c | 6 +++---
4 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/mscc/ocelot_tc.c b/drivers/net/ethernet/mscc/ocelot_tc.c
index 5c3bf639f87c..a52c233da571 100644
--- a/drivers/net/ethernet/mscc/ocelot_tc.c
+++ b/drivers/net/ethernet/mscc/ocelot_tc.c
@@ -140,7 +140,7 @@ static int ocelot_setup_tc_block(struct ocelot_port *port,
if (f->binder_type == TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS) {
cb = ocelot_setup_tc_block_cb_ig;
- port->tc.block_shared = tcf_block_shared(f->block);
+ port->tc.block_shared = f->block_shared;
} else if (f->binder_type == TCF_BLOCK_BINDER_TYPE_CLSACT_EGRESS) {
cb = ocelot_setup_tc_block_cb_eg;
} else {
diff --git a/drivers/net/ethernet/netronome/nfp/flower/offload.c b/drivers/net/ethernet/netronome/nfp/flower/offload.c
index fa44dce810ed..a19f4aafc3af 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/offload.c
+++ b/drivers/net/ethernet/netronome/nfp/flower/offload.c
@@ -1313,7 +1313,7 @@ static int nfp_flower_setup_tc_block(struct net_device *netdev,
return -EOPNOTSUPP;
repr_priv = repr->app_priv;
- repr_priv->block_shared = tcf_block_shared(f->block);
+ repr_priv->block_shared = f->block_shared;
switch (f->command) {
case TC_BLOCK_BIND:
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index cb899c4552f4..cc64dd45dfc2 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -663,7 +663,7 @@ struct tc_block_offload {
enum tcf_block_binder_type binder_type;
struct list_head cb_list;
struct net *net;
- struct tcf_block *block;
+ bool block_shared;
struct netlink_ext_ack *extack;
};
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 3f036d50af65..e546d56c1a39 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -1073,7 +1073,7 @@ static void tc_indr_block_ing_cmd(struct tc_indr_block_dev *indr_dev,
.command = command,
.binder_type = TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS,
.net = dev_net(indr_dev->dev),
- .block = indr_dev->block,
+ .block_shared = tcf_block_shared(indr_dev->block),
};
INIT_LIST_HEAD(&bo.cb_list);
@@ -1164,7 +1164,7 @@ static void tc_indr_block_call(struct tcf_block *block, struct net_device *dev,
.command = command,
.binder_type = ei->binder_type,
.net = dev_net(dev),
- .block = block,
+ .block_shared = tcf_block_shared(block),
.extack = extack,
};
INIT_LIST_HEAD(&bo.cb_list);
@@ -1194,7 +1194,7 @@ static int tcf_block_offload_cmd(struct tcf_block *block,
bo.net = dev_net(dev);
bo.command = command;
bo.binder_type = ei->binder_type;
- bo.block = block;
+ bo.block_shared = tcf_block_shared(block);
bo.extack = extack;
INIT_LIST_HEAD(&bo.cb_list);
--
2.11.0
^ permalink raw reply related [flat|nested] 21+ messages in thread* [PATCH 09/15 net-next,v2] net: sched: remove tcf_block_cb_{register,unregister}()
2019-07-04 23:48 [PATCH 00/15 net-next,v2] netfilter: add hardware offload infrastructure Pablo Neira Ayuso
` (7 preceding siblings ...)
2019-07-04 23:48 ` [PATCH 08/15 net-next,v2] net: cls_api: do not expose tcf_block to drivers Pablo Neira Ayuso
@ 2019-07-04 23:48 ` Pablo Neira Ayuso
2019-07-04 23:48 ` [PATCH 10/15 net-next,v2] net: flow_offload: add flow_block_cb API Pablo Neira Ayuso
` (5 subsequent siblings)
14 siblings, 0 replies; 21+ messages in thread
From: Pablo Neira Ayuso @ 2019-07-04 23:48 UTC (permalink / raw)
To: netdev
Cc: netfilter-devel, davem, thomas.lendacky, f.fainelli, ariel.elior,
michael.chan, madalin.bucur, yisen.zhuang, salil.mehta,
jeffrey.t.kirsher, tariqt, saeedm, jiri, idosch, jakub.kicinski,
peppe.cavallaro, grygorii.strashko, andrew, vivien.didelot,
alexandre.torgue, joabreu, linux-net-drivers, ogerlitz,
Manish.Chopra, marcelo.leitner, mkubecek, venkatkumar.duvvuru,
maxime.chevallier, cphealy
Now replaced by the tcf_block_setup() core registration, remove this.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
v2: no changes.
include/net/pkt_cls.h | 41 +----------------------------------
net/sched/cls_api.c | 59 ---------------------------------------------------
2 files changed, 1 insertion(+), 99 deletions(-)
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index cc64dd45dfc2..52c11e390d9e 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -88,17 +88,7 @@ struct tcf_block_cb *tcf_block_cb_lookup(struct net *net, tc_setup_cb_t *cb,
void *cb_ident);
void tcf_block_cb_incref(struct tcf_block_cb *block_cb);
unsigned int tcf_block_cb_decref(struct tcf_block_cb *block_cb);
-struct tcf_block_cb *__tcf_block_cb_register(struct tcf_block *block,
- tc_setup_cb_t *cb, void *cb_ident,
- void *cb_priv,
- struct netlink_ext_ack *extack);
-int tcf_block_cb_register(struct tcf_block *block,
- tc_setup_cb_t *cb, void *cb_ident,
- void *cb_priv, struct netlink_ext_ack *extack);
-void __tcf_block_cb_unregister(struct tcf_block *block,
- struct tcf_block_cb *block_cb);
-void tcf_block_cb_unregister(struct tcf_block *block,
- tc_setup_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);
int tc_indr_block_cb_register(struct net_device *dev, void *cb_priv,
@@ -218,35 +208,6 @@ unsigned int tcf_block_cb_decref(struct tcf_block_cb *block_cb)
}
static inline
-struct tcf_block_cb *__tcf_block_cb_register(struct tcf_block *block,
- tc_setup_cb_t *cb, void *cb_ident,
- void *cb_priv,
- struct netlink_ext_ack *extack)
-{
- return NULL;
-}
-
-static inline
-int tcf_block_cb_register(struct tcf_block *block,
- tc_setup_cb_t *cb, void *cb_ident,
- void *cb_priv, struct netlink_ext_ack *extack)
-{
- return 0;
-}
-
-static inline
-void __tcf_block_cb_unregister(struct tcf_block *block,
- struct tcf_block_cb *block_cb)
-{
-}
-
-static inline
-void tcf_block_cb_unregister(struct tcf_block *block,
- tc_setup_cb_t *cb, void *cb_ident)
-{
-}
-
-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)
{
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index e546d56c1a39..aa7ab707c399 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -797,65 +797,6 @@ void tcf_block_cb_remove(struct tcf_block_cb *block_cb,
}
EXPORT_SYMBOL(tcf_block_cb_remove);
-struct tcf_block_cb *__tcf_block_cb_register(struct tcf_block *block,
- tc_setup_cb_t *cb, void *cb_ident,
- void *cb_priv,
- struct netlink_ext_ack *extack)
-{
- struct tcf_block_cb *block_cb;
- int err;
-
- /* Replay any already present rules */
- err = tcf_block_playback_offloads(block, cb, cb_priv, true,
- tcf_block_offload_in_use(block),
- extack);
- if (err)
- return ERR_PTR(err);
-
- block_cb = tcf_block_cb_alloc(block->net, cb, cb_ident, cb_priv, NULL);
- if (IS_ERR(block_cb))
- return block_cb;
-
- list_add(&block_cb->list, &block->cb_list);
- return block_cb;
-}
-EXPORT_SYMBOL(__tcf_block_cb_register);
-
-int tcf_block_cb_register(struct tcf_block *block,
- tc_setup_cb_t *cb, void *cb_ident,
- void *cb_priv, struct netlink_ext_ack *extack)
-{
- struct tcf_block_cb *block_cb;
-
- block_cb = __tcf_block_cb_register(block, cb, cb_ident, cb_priv,
- extack);
- return PTR_ERR_OR_ZERO(block_cb);
-}
-EXPORT_SYMBOL(tcf_block_cb_register);
-
-void __tcf_block_cb_unregister(struct tcf_block *block,
- struct tcf_block_cb *block_cb)
-{
- tcf_block_playback_offloads(block, block_cb->cb, block_cb->cb_priv,
- false, tcf_block_offload_in_use(block),
- NULL);
- list_del(&block_cb->list);
- kfree(block_cb);
-}
-EXPORT_SYMBOL(__tcf_block_cb_unregister);
-
-void tcf_block_cb_unregister(struct tcf_block *block,
- tc_setup_cb_t *cb, void *cb_ident)
-{
- struct tcf_block_cb *block_cb;
-
- block_cb = tcf_block_cb_lookup(block->net, cb, cb_ident);
- if (!block_cb)
- return;
- __tcf_block_cb_unregister(block, block_cb);
-}
-EXPORT_SYMBOL(tcf_block_cb_unregister);
-
static int tcf_block_bind(struct tcf_block *block, struct tc_block_offload *bo)
{
struct tcf_block_cb *block_cb, *next;
--
2.11.0
^ permalink raw reply related [flat|nested] 21+ messages in thread* [PATCH 10/15 net-next,v2] net: flow_offload: add flow_block_cb API
2019-07-04 23:48 [PATCH 00/15 net-next,v2] netfilter: add hardware offload infrastructure Pablo Neira Ayuso
` (8 preceding siblings ...)
2019-07-04 23:48 ` [PATCH 09/15 net-next,v2] net: sched: remove tcf_block_cb_{register,unregister}() Pablo Neira Ayuso
@ 2019-07-04 23:48 ` Pablo Neira Ayuso
2019-07-04 23:48 ` [PATCH 11/15 net-next,v2] net: flow_offload: don't allow subsystem to reuse blocks Pablo Neira Ayuso
` (4 subsequent siblings)
14 siblings, 0 replies; 21+ messages in thread
From: Pablo Neira Ayuso @ 2019-07-04 23:48 UTC (permalink / raw)
To: netdev
Cc: netfilter-devel, davem, thomas.lendacky, f.fainelli, ariel.elior,
michael.chan, madalin.bucur, yisen.zhuang, salil.mehta,
jeffrey.t.kirsher, tariqt, saeedm, jiri, idosch, jakub.kicinski,
peppe.cavallaro, grygorii.strashko, andrew, vivien.didelot,
alexandre.torgue, joabreu, linux-net-drivers, ogerlitz,
Manish.Chopra, marcelo.leitner, mkubecek, venkatkumar.duvvuru,
maxime.chevallier, cphealy
This patch renames:
* struct tcf_block_cb to flow_block_cb.
* struct tc_block_offload to flow_block_offload.
And it exposes the flow_block_cb API through net/flow_offload.h. This
renames the existing codebase to adapt it to this name.
This patch also adds flow_block_cb_splice().
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
v2: no changes.
drivers/net/ethernet/broadcom/bnxt/bnxt.c | 6 +-
drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c | 6 +-
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 6 +-
drivers/net/ethernet/intel/i40e/i40e_main.c | 6 +-
drivers/net/ethernet/intel/iavf/iavf_main.c | 6 +-
drivers/net/ethernet/intel/igb/igb_main.c | 5 +-
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 6 +-
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 6 +-
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 28 ++--
drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 62 ++++----
drivers/net/ethernet/mscc/ocelot_ace.h | 4 +-
drivers/net/ethernet/mscc/ocelot_flower.c | 34 ++---
drivers/net/ethernet/mscc/ocelot_tc.c | 14 +-
drivers/net/ethernet/netronome/nfp/abm/cls.c | 6 +-
drivers/net/ethernet/netronome/nfp/abm/main.h | 2 +-
drivers/net/ethernet/netronome/nfp/bpf/main.c | 6 +-
.../net/ethernet/netronome/nfp/flower/offload.c | 42 +++---
drivers/net/ethernet/qlogic/qede/qede_main.c | 6 +-
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 6 +-
drivers/net/netdevsim/netdev.c | 6 +-
include/net/flow_offload.h | 52 +++++++
include/net/pkt_cls.h | 96 +------------
net/core/flow_offload.c | 115 +++++++++++++++
net/dsa/slave.c | 12 +-
net/sched/cls_api.c | 157 +++------------------
25 files changed, 328 insertions(+), 367 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index bda732ab6538..7b8d71252093 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -9854,9 +9854,9 @@ static int bnxt_setup_tc(struct net_device *dev, enum tc_setup_type type,
switch (type) {
case TC_SETUP_BLOCK:
- return tcf_setup_block_offload(type_data,
- bnxt_setup_tc_block_cb, bp, bp,
- true);
+ return flow_block_setup_offload(type_data,
+ bnxt_setup_tc_block_cb, bp, bp,
+ true);
case TC_SETUP_QDISC_MQPRIO: {
struct tc_mqprio_qopt *mqprio = type_data;
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
index c8bb104f28d4..1b78615a1384 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
@@ -168,9 +168,9 @@ static int bnxt_vf_rep_setup_tc(struct net_device *dev, enum tc_setup_type type,
switch (type) {
case TC_SETUP_BLOCK:
- return tcf_setup_block_offload(type_data,
- bnxt_vf_rep_setup_tc_block_cb,
- vf_rep, vf_rep, true);
+ return flow_block_setup_offload(type_data,
+ bnxt_vf_rep_setup_tc_block_cb,
+ vf_rep, vf_rep, true);
default:
return -EOPNOTSUPP;
}
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index a09b9c909be1..3d8acabb8bfd 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -3197,9 +3197,9 @@ static int cxgb_setup_tc(struct net_device *dev, enum tc_setup_type type,
switch (type) {
case TC_SETUP_BLOCK:
- return tcf_setup_block_offload(type_data,
- cxgb_setup_tc_block_cb, pi, dev,
- true);
+ return flow_block_setup_offload(type_data,
+ cxgb_setup_tc_block_cb, pi, dev,
+ true);
default:
return -EOPNOTSUPP;
}
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 1e703daa50fd..f7d2616854ec 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -8186,9 +8186,9 @@ static int __i40e_setup_tc(struct net_device *netdev, enum tc_setup_type type,
case TC_SETUP_QDISC_MQPRIO:
return i40e_setup_tc(netdev, type_data);
case TC_SETUP_BLOCK:
- return tcf_setup_block_offload(type_data,
- i40e_setup_tc_block_cb, np, np,
- true);
+ return flow_block_setup_offload(type_data,
+ i40e_setup_tc_block_cb, np, np,
+ true);
default:
return -EOPNOTSUPP;
}
diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
index 29640e4b15f2..8ef6aca34edd 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -3133,9 +3133,9 @@ static int iavf_setup_tc(struct net_device *netdev, enum tc_setup_type type,
case TC_SETUP_QDISC_MQPRIO:
return __iavf_setup_tc(netdev, type_data);
case TC_SETUP_BLOCK:
- return tcf_setup_block_offload(type_data,
- iavf_setup_tc_block_cb, adapter,
- adapter, true);
+ return flow_block_setup_offload(type_data,
+ iavf_setup_tc_block_cb, adapter,
+ adapter, true);
default:
return -EOPNOTSUPP;
}
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index 75a29adce0ce..830b950f423b 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -2815,8 +2815,9 @@ static int igb_setup_tc(struct net_device *dev, enum tc_setup_type type,
case TC_SETUP_QDISC_CBS:
return igb_offload_cbs(adapter, type_data);
case TC_SETUP_BLOCK:
- return tcf_setup_block_offload(type_data, igb_setup_tc_block_cb,
- adapter, adapter, true);
+ return flow_block_setup_offload(type_data,
+ igb_setup_tc_block_cb,
+ adapter, adapter, true);
case TC_SETUP_QDISC_ETF:
return igb_offload_txtime(adapter, type_data);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 7d3fe89ce807..144f2cca686a 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -9621,9 +9621,9 @@ static int __ixgbe_setup_tc(struct net_device *dev, enum tc_setup_type type,
switch (type) {
case TC_SETUP_BLOCK:
- return tcf_setup_block_offload(type_data,
- ixgbe_setup_tc_block_cb,
- adapter, adapter, true);
+ return flow_block_setup_offload(type_data,
+ ixgbe_setup_tc_block_cb,
+ adapter, adapter, true);
case TC_SETUP_QDISC_MQPRIO:
return ixgbe_setup_tc_mqprio(dev, type_data);
default:
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index ffb501cfbc8d..fa9c04129eb6 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -3355,9 +3355,9 @@ static int mlx5e_setup_tc(struct net_device *dev, enum tc_setup_type type,
switch (type) {
#ifdef CONFIG_MLX5_ESWITCH
case TC_SETUP_BLOCK:
- return tcf_setup_block_offload(type_data,
- mlx5e_setup_tc_block_cb,
- priv, priv, true);
+ return flow_block_setup_offload(type_data,
+ mlx5e_setup_tc_block_cb,
+ priv, priv, true);
#endif
case TC_SETUP_QDISC_MQPRIO:
return mlx5e_setup_tc_mqprio(dev, type_data);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
index b6ffaec4becb..925aa589a818 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
@@ -703,10 +703,10 @@ static void mlx5e_rep_indr_tc_block_unbind(void *cb_priv)
static int
mlx5e_rep_indr_setup_tc_block(struct net_device *netdev,
struct mlx5e_rep_priv *rpriv,
- struct tc_block_offload *f)
+ struct flow_block_offload *f)
{
struct mlx5e_rep_indr_block_priv *indr_priv;
- struct tcf_block_cb *block_cb;
+ struct flow_block_cb *block_cb;
if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
return -EOPNOTSUPP;
@@ -726,16 +726,16 @@ mlx5e_rep_indr_setup_tc_block(struct net_device *netdev,
list_add(&indr_priv->list,
&rpriv->uplink_priv.tc_indr_block_priv_list);
- block_cb = tcf_block_cb_alloc(f->net,
- mlx5e_rep_indr_setup_block_cb,
- indr_priv, indr_priv,
- mlx5e_rep_indr_tc_block_unbind);
+ block_cb = flow_block_cb_alloc(f->net,
+ mlx5e_rep_indr_setup_block_cb,
+ indr_priv, indr_priv,
+ mlx5e_rep_indr_tc_block_unbind);
if (IS_ERR(block_cb)) {
list_del(&indr_priv->list);
kfree(indr_priv);
return PTR_ERR(block_cb);
}
- tcf_block_cb_add(block_cb, f);
+ flow_block_cb_add(block_cb, f);
return 0;
case TC_BLOCK_UNBIND:
@@ -743,13 +743,13 @@ mlx5e_rep_indr_setup_tc_block(struct net_device *netdev,
if (!indr_priv)
return -ENOENT;
- block_cb = tcf_block_cb_lookup(f->net,
- mlx5e_rep_indr_setup_block_cb,
- indr_priv);
+ block_cb = flow_block_cb_lookup(f->net,
+ mlx5e_rep_indr_setup_block_cb,
+ indr_priv);
if (!block_cb)
return -ENOENT;
- tcf_block_cb_remove(block_cb, f);
+ flow_block_cb_remove(block_cb, f);
return 0;
default:
return -EOPNOTSUPP;
@@ -1197,9 +1197,9 @@ static int mlx5e_rep_setup_tc(struct net_device *dev, enum tc_setup_type type,
switch (type) {
case TC_SETUP_BLOCK:
- return tcf_setup_block_offload(type_data,
- mlx5e_rep_setup_tc_cb,
- priv, priv, true);
+ return flow_block_setup_offload(type_data,
+ mlx5e_rep_setup_tc_cb,
+ priv, priv, true);
default:
return -EOPNOTSUPP;
}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 950d09f3ecb1..6970738c070b 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -1593,25 +1593,26 @@ static void mlxsw_sp_tc_block_flower_release(void *cb_priv)
static int
mlxsw_sp_setup_tc_block_flower_bind(struct mlxsw_sp_port *mlxsw_sp_port,
- struct tc_block_offload *f, bool ingress)
+ struct flow_block_offload *f, bool ingress)
{
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
struct mlxsw_sp_acl_block *acl_block;
- struct tcf_block_cb *block_cb;
+ struct flow_block_cb *block_cb;
bool register_block = false;
int err;
- block_cb = tcf_block_cb_lookup(f->net,
- mlxsw_sp_setup_tc_block_cb_flower,
- mlxsw_sp);
+ block_cb = flow_block_cb_lookup(f->net,
+ mlxsw_sp_setup_tc_block_cb_flower,
+ mlxsw_sp);
if (!block_cb) {
acl_block = mlxsw_sp_acl_block_create(mlxsw_sp, f->net);
if (!acl_block)
return -ENOMEM;
- block_cb = tcf_block_cb_alloc(f->net,
- mlxsw_sp_setup_tc_block_cb_flower,
- mlxsw_sp, acl_block,
- mlxsw_sp_tc_block_flower_release);
+
+ block_cb = flow_block_cb_alloc(f->net,
+ mlxsw_sp_setup_tc_block_cb_flower,
+ mlxsw_sp, acl_block,
+ mlxsw_sp_tc_block_flower_release);
if (IS_ERR(block_cb)) {
mlxsw_sp_acl_block_destroy(acl_block);
err = PTR_ERR(block_cb);
@@ -1619,9 +1620,9 @@ mlxsw_sp_setup_tc_block_flower_bind(struct mlxsw_sp_port *mlxsw_sp_port,
}
register_block = true;
} else {
- acl_block = tcf_block_cb_priv(block_cb);
+ acl_block = flow_block_cb_priv(block_cb);
}
- tcf_block_cb_incref(block_cb);
+ flow_block_cb_incref(block_cb);
err = mlxsw_sp_acl_block_bind(mlxsw_sp, acl_block,
mlxsw_sp_port, ingress);
if (err)
@@ -1633,29 +1634,30 @@ mlxsw_sp_setup_tc_block_flower_bind(struct mlxsw_sp_port *mlxsw_sp_port,
mlxsw_sp_port->eg_acl_block = acl_block;
if (register_block)
- tcf_block_cb_add(block_cb, f);
+ flow_block_cb_add(block_cb, f);
return 0;
err_block_bind:
- if (!tcf_block_cb_decref(block_cb))
- tcf_block_cb_free(block_cb);
+ if (!flow_block_cb_decref(block_cb))
+ flow_block_cb_free(block_cb);
err_cb_register:
return err;
}
static void
mlxsw_sp_setup_tc_block_flower_unbind(struct mlxsw_sp_port *mlxsw_sp_port,
- struct tc_block_offload *f, bool ingress)
+ struct flow_block_offload *f,
+ bool ingress)
{
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
struct mlxsw_sp_acl_block *acl_block;
- struct tcf_block_cb *block_cb;
+ struct flow_block_cb *block_cb;
int err;
- block_cb = tcf_block_cb_lookup(f->net,
- mlxsw_sp_setup_tc_block_cb_flower,
- mlxsw_sp);
+ block_cb = flow_block_cb_lookup(f->net,
+ mlxsw_sp_setup_tc_block_cb_flower,
+ mlxsw_sp);
if (!block_cb)
return;
@@ -1664,17 +1666,17 @@ mlxsw_sp_setup_tc_block_flower_unbind(struct mlxsw_sp_port *mlxsw_sp_port,
else
mlxsw_sp_port->eg_acl_block = NULL;
- acl_block = tcf_block_cb_priv(block_cb);
+ acl_block = flow_block_cb_priv(block_cb);
err = mlxsw_sp_acl_block_unbind(mlxsw_sp, acl_block,
mlxsw_sp_port, ingress);
- if (!err && !tcf_block_cb_decref(block_cb))
- tcf_block_cb_remove(block_cb, f);
+ if (!err && !flow_block_cb_decref(block_cb))
+ flow_block_cb_remove(block_cb, f);
}
static int mlxsw_sp_setup_tc_block(struct mlxsw_sp_port *mlxsw_sp_port,
- struct tc_block_offload *f)
+ struct flow_block_offload *f)
{
- struct tcf_block_cb *block_cb;
+ struct flow_block_cb *block_cb;
tc_setup_cb_t *cb;
bool ingress;
int err;
@@ -1691,26 +1693,26 @@ static int mlxsw_sp_setup_tc_block(struct mlxsw_sp_port *mlxsw_sp_port,
switch (f->command) {
case TC_BLOCK_BIND:
- block_cb = tcf_block_cb_alloc(f->net, cb, mlxsw_sp_port,
- mlxsw_sp_port, NULL);
+ block_cb = flow_block_cb_alloc(f->net, cb, mlxsw_sp_port,
+ mlxsw_sp_port, NULL);
if (IS_ERR(block_cb))
return PTR_ERR(block_cb);
err = mlxsw_sp_setup_tc_block_flower_bind(mlxsw_sp_port, f,
ingress);
if (err) {
- tcf_block_cb_free(block_cb);
+ flow_block_cb_free(block_cb);
return err;
}
- tcf_block_cb_add(block_cb, f);
+ flow_block_cb_add(block_cb, f);
return 0;
case TC_BLOCK_UNBIND:
mlxsw_sp_setup_tc_block_flower_unbind(mlxsw_sp_port,
f, ingress);
- block_cb = tcf_block_cb_lookup(f->net, cb, mlxsw_sp_port);
+ block_cb = flow_block_cb_lookup(f->net, cb, mlxsw_sp_port);
if (!block_cb)
return -ENOENT;
- tcf_block_cb_remove(block_cb, f);
+ flow_block_cb_remove(block_cb, f);
return 0;
default:
return -EOPNOTSUPP;
diff --git a/drivers/net/ethernet/mscc/ocelot_ace.h b/drivers/net/ethernet/mscc/ocelot_ace.h
index d621683643e1..e98944c87259 100644
--- a/drivers/net/ethernet/mscc/ocelot_ace.h
+++ b/drivers/net/ethernet/mscc/ocelot_ace.h
@@ -225,8 +225,8 @@ int ocelot_ace_init(struct ocelot *ocelot);
void ocelot_ace_deinit(void);
int ocelot_setup_tc_block_flower_bind(struct ocelot_port *port,
- struct tc_block_offload *f);
+ struct flow_block_offload *f);
void ocelot_setup_tc_block_flower_unbind(struct ocelot_port *port,
- struct tc_block_offload *f);
+ struct flow_block_offload *f);
#endif /* _MSCC_OCELOT_ACE_H_ */
diff --git a/drivers/net/ethernet/mscc/ocelot_flower.c b/drivers/net/ethernet/mscc/ocelot_flower.c
index e62a7e56ec3e..3b9e4219ac7a 100644
--- a/drivers/net/ethernet/mscc/ocelot_flower.c
+++ b/drivers/net/ethernet/mscc/ocelot_flower.c
@@ -307,36 +307,36 @@ static void ocelot_tc_block_unbind(void *cb_priv)
}
int ocelot_setup_tc_block_flower_bind(struct ocelot_port *port,
- struct tc_block_offload *f)
+ struct flow_block_offload *f)
{
struct ocelot_port_block *port_block;
- struct tcf_block_cb *block_cb;
+ struct flow_block_cb *block_cb;
int ret;
if (f->binder_type == TCF_BLOCK_BINDER_TYPE_CLSACT_EGRESS)
return -EOPNOTSUPP;
- block_cb = tcf_block_cb_lookup(f->net, ocelot_setup_tc_block_cb_flower,
- port);
+ block_cb = flow_block_cb_lookup(f->net, ocelot_setup_tc_block_cb_flower,
+ port);
if (!block_cb) {
port_block = ocelot_port_block_create(port);
if (!port_block)
return -ENOMEM;
- block_cb = tcf_block_cb_alloc(f->net,
- ocelot_setup_tc_block_cb_flower,
- port, port_block,
- ocelot_tc_block_unbind);
+ block_cb = flow_block_cb_alloc(f->net,
+ ocelot_setup_tc_block_cb_flower,
+ port, port_block,
+ ocelot_tc_block_unbind);
if (IS_ERR(block_cb)) {
ret = PTR_ERR(block_cb);
goto err_cb_register;
}
- tcf_block_cb_add(block_cb, f);
+ flow_block_cb_add(block_cb, f);
} else {
- port_block = tcf_block_cb_priv(block_cb);
+ port_block = flow_block_cb_priv(block_cb);
}
- tcf_block_cb_incref(block_cb);
+ flow_block_cb_incref(block_cb);
return 0;
err_cb_register:
@@ -346,15 +346,15 @@ int ocelot_setup_tc_block_flower_bind(struct ocelot_port *port,
}
void ocelot_setup_tc_block_flower_unbind(struct ocelot_port *port,
- struct tc_block_offload *f)
+ struct flow_block_offload *f)
{
- struct tcf_block_cb *block_cb;
+ struct flow_block_cb *block_cb;
- block_cb = tcf_block_cb_lookup(f->net, ocelot_setup_tc_block_cb_flower,
- port);
+ block_cb = flow_block_cb_lookup(f->net, ocelot_setup_tc_block_cb_flower,
+ port);
if (!block_cb)
return;
- if (!tcf_block_cb_decref(block_cb))
- tcf_block_cb_remove(block_cb, f);
+ if (!flow_block_cb_decref(block_cb))
+ flow_block_cb_remove(block_cb, f);
}
diff --git a/drivers/net/ethernet/mscc/ocelot_tc.c b/drivers/net/ethernet/mscc/ocelot_tc.c
index a52c233da571..14a9e178c3b8 100644
--- a/drivers/net/ethernet/mscc/ocelot_tc.c
+++ b/drivers/net/ethernet/mscc/ocelot_tc.c
@@ -129,9 +129,9 @@ static int ocelot_setup_tc_block_cb_eg(enum tc_setup_type type,
}
static int ocelot_setup_tc_block(struct ocelot_port *port,
- struct tc_block_offload *f)
+ struct flow_block_offload *f)
{
- struct tcf_block_cb *block_cb;
+ struct flow_block_cb *block_cb;
tc_setup_cb_t *cb;
int err;
@@ -149,24 +149,24 @@ static int ocelot_setup_tc_block(struct ocelot_port *port,
switch (f->command) {
case TC_BLOCK_BIND:
- block_cb = tcf_block_cb_alloc(f->net, cb, port, port, NULL);
+ block_cb = flow_block_cb_alloc(f->net, cb, port, port, NULL);
if (IS_ERR(block_cb))
return PTR_ERR(block_cb);
err = ocelot_setup_tc_block_flower_bind(port, f);
if (err < 0) {
- tcf_block_cb_free(block_cb);
+ flow_block_cb_free(block_cb);
return err;
}
- tcf_block_cb_add(block_cb, f);
+ flow_block_cb_add(block_cb, f);
return 0;
case TC_BLOCK_UNBIND:
- block_cb = tcf_block_cb_lookup(f->net, cb, port);
+ block_cb = flow_block_cb_lookup(f->net, cb, port);
if (!block_cb)
return -ENOENT;
ocelot_setup_tc_block_flower_unbind(port, f);
- tcf_block_cb_remove(block_cb, f);
+ flow_block_cb_remove(block_cb, f);
return 0;
default:
return -EOPNOTSUPP;
diff --git a/drivers/net/ethernet/netronome/nfp/abm/cls.c b/drivers/net/ethernet/netronome/nfp/abm/cls.c
index d99981ec04a3..96b89a7c468b 100644
--- a/drivers/net/ethernet/netronome/nfp/abm/cls.c
+++ b/drivers/net/ethernet/netronome/nfp/abm/cls.c
@@ -263,8 +263,8 @@ static int nfp_abm_setup_tc_block_cb(enum tc_setup_type type,
}
int nfp_abm_setup_cls_block(struct net_device *netdev, struct nfp_repr *repr,
- struct tc_block_offload *f)
+ struct flow_block_offload *f)
{
- return tcf_setup_block_offload(f, nfp_abm_setup_tc_block_cb, repr, repr,
- true);
+ return flow_block_setup_offload(f, nfp_abm_setup_tc_block_cb,
+ repr, repr, true);
}
diff --git a/drivers/net/ethernet/netronome/nfp/abm/main.h b/drivers/net/ethernet/netronome/nfp/abm/main.h
index 49749c60885e..48746c9c6224 100644
--- a/drivers/net/ethernet/netronome/nfp/abm/main.h
+++ b/drivers/net/ethernet/netronome/nfp/abm/main.h
@@ -247,7 +247,7 @@ int nfp_abm_setup_tc_mq(struct net_device *netdev, struct nfp_abm_link *alink,
int nfp_abm_setup_tc_gred(struct net_device *netdev, struct nfp_abm_link *alink,
struct tc_gred_qopt_offload *opt);
int nfp_abm_setup_cls_block(struct net_device *netdev, struct nfp_repr *repr,
- struct tc_block_offload *opt);
+ struct flow_block_offload *opt);
int nfp_abm_ctrl_read_params(struct nfp_abm_link *alink);
int nfp_abm_ctrl_find_addrs(struct nfp_abm *abm);
diff --git a/drivers/net/ethernet/netronome/nfp/bpf/main.c b/drivers/net/ethernet/netronome/nfp/bpf/main.c
index fac38899dc23..3897cc4f7a7e 100644
--- a/drivers/net/ethernet/netronome/nfp/bpf/main.c
+++ b/drivers/net/ethernet/netronome/nfp/bpf/main.c
@@ -167,9 +167,9 @@ static int nfp_bpf_setup_tc(struct nfp_app *app, struct net_device *netdev,
switch (type) {
case TC_SETUP_BLOCK:
- return tcf_setup_block_offload(type_data,
- nfp_bpf_setup_tc_block_cb,
- nn, nn, true);
+ return flow_block_setup_offload(type_data,
+ nfp_bpf_setup_tc_block_cb,
+ nn, nn, true);
default:
return -EOPNOTSUPP;
}
diff --git a/drivers/net/ethernet/netronome/nfp/flower/offload.c b/drivers/net/ethernet/netronome/nfp/flower/offload.c
index a19f4aafc3af..9b99f6936f90 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/offload.c
+++ b/drivers/net/ethernet/netronome/nfp/flower/offload.c
@@ -1303,11 +1303,11 @@ static int nfp_flower_setup_tc_block_cb(enum tc_setup_type type,
}
static int nfp_flower_setup_tc_block(struct net_device *netdev,
- struct tc_block_offload *f)
+ struct flow_block_offload *f)
{
struct nfp_repr *repr = netdev_priv(netdev);
struct nfp_flower_repr_priv *repr_priv;
- struct tcf_block_cb *block_cb;
+ struct flow_block_cb *block_cb;
if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
return -EOPNOTSUPP;
@@ -1317,22 +1317,22 @@ static int nfp_flower_setup_tc_block(struct net_device *netdev,
switch (f->command) {
case TC_BLOCK_BIND:
- block_cb = tcf_block_cb_alloc(f->net,
- nfp_flower_setup_tc_block_cb,
- repr, repr, NULL);
+ block_cb = flow_block_cb_alloc(f->net,
+ nfp_flower_setup_tc_block_cb,
+ repr, repr, NULL);
if (IS_ERR(block_cb))
return PTR_ERR(block_cb);
- tcf_block_cb_add(block_cb, f);
+ flow_block_cb_add(block_cb, f);
return 0;
case TC_BLOCK_UNBIND:
- block_cb = tcf_block_cb_lookup(f->net,
- nfp_flower_setup_tc_block_cb,
- repr);
+ block_cb = flow_block_cb_lookup(f->net,
+ nfp_flower_setup_tc_block_cb,
+ repr);
if (!block_cb)
return -ENOENT;
- tcf_block_cb_remove(block_cb, f);
+ flow_block_cb_remove(block_cb, f);
return 0;
default:
return -EOPNOTSUPP;
@@ -1401,12 +1401,12 @@ static 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,
- struct tc_block_offload *f)
+ struct flow_block_offload *f)
{
struct nfp_flower_indr_block_cb_priv *cb_priv;
struct nfp_flower_priv *priv = app->priv;
struct net *net = dev_net(netdev);
- struct tcf_block_cb *block_cb;
+ struct flow_block_cb *block_cb;
if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS &&
!(f->binder_type == TCF_BLOCK_BINDER_TYPE_CLSACT_EGRESS &&
@@ -1423,30 +1423,30 @@ nfp_flower_setup_indr_tc_block(struct net_device *netdev, struct nfp_app *app,
cb_priv->app = app;
list_add(&cb_priv->list, &priv->indr_block_cb_priv);
- block_cb = tcf_block_cb_alloc(net,
- nfp_flower_setup_indr_block_cb,
- cb_priv, cb_priv,
- nfp_flower_setup_indr_tc_release);
+ block_cb = flow_block_cb_alloc(net,
+ nfp_flower_setup_indr_block_cb,
+ cb_priv, cb_priv,
+ nfp_flower_setup_indr_tc_release);
if (IS_ERR(block_cb)) {
list_del(&cb_priv->list);
kfree(cb_priv);
return PTR_ERR(block_cb);
}
- tcf_block_cb_add(block_cb, f);
+ flow_block_cb_add(block_cb, f);
return 0;
case TC_BLOCK_UNBIND:
cb_priv = nfp_flower_indr_block_cb_priv_lookup(app, netdev);
if (!cb_priv)
return -ENOENT;
- block_cb = tcf_block_cb_lookup(net,
- nfp_flower_setup_indr_block_cb,
- cb_priv);
+ block_cb = flow_block_cb_lookup(net,
+ nfp_flower_setup_indr_block_cb,
+ cb_priv);
if (!block_cb)
return -ENOENT;
- tcf_block_cb_remove(block_cb, f);
+ flow_block_cb_remove(block_cb, f);
return 0;
default:
return -EOPNOTSUPP;
diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c
index 013046a30732..00db21d9407f 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_main.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_main.c
@@ -588,9 +588,9 @@ qede_setup_tc_offload(struct net_device *dev, enum tc_setup_type type,
switch (type) {
case TC_SETUP_BLOCK:
- return tcf_setup_block_offload(type_data,
- qede_setup_tc_block_cb,
- edev, edev, true);
+ return flow_block_setup_offload(type_data,
+ qede_setup_tc_block_cb,
+ edev, edev, true);
case TC_SETUP_QDISC_MQPRIO:
mqprio = type_data;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index ffed6b51040a..341db1eed108 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -3860,9 +3860,9 @@ static int stmmac_setup_tc(struct net_device *ndev, enum tc_setup_type type,
switch (type) {
case TC_SETUP_BLOCK:
- return tcf_setup_block_offload(type_data,
- stmmac_setup_tc_block_cb,
- priv, priv, true);
+ return flow_block_setup_offload(type_data,
+ stmmac_setup_tc_block_cb,
+ priv, priv, true);
case TC_SETUP_QDISC_CBS:
return stmmac_tc_setup_cbs(priv, priv, type_data);
default:
diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c
index 240727623e9b..710b03fc8db1 100644
--- a/drivers/net/netdevsim/netdev.c
+++ b/drivers/net/netdevsim/netdev.c
@@ -210,9 +210,9 @@ nsim_setup_tc(struct net_device *dev, enum tc_setup_type type, void *type_data)
switch (type) {
case TC_SETUP_BLOCK:
- return tcf_setup_block_offload(type_data,
- nsim_setup_tc_block_cb, ns, ns,
- true);
+ return flow_block_setup_offload(type_data,
+ nsim_setup_tc_block_cb, ns, ns,
+ true);
default:
return -EOPNOTSUPP;
}
diff --git a/include/net/flow_offload.h b/include/net/flow_offload.h
index 36127c1858a4..728ded7e4361 100644
--- a/include/net/flow_offload.h
+++ b/include/net/flow_offload.h
@@ -232,4 +232,56 @@ static inline void flow_stats_update(struct flow_stats *flow_stats,
flow_stats->lastused = max_t(u64, flow_stats->lastused, lastused);
}
+#include <net/sch_generic.h> /* for tc_setup_cb_t. */
+
+enum flow_block_command {
+ TC_BLOCK_BIND,
+ TC_BLOCK_UNBIND,
+};
+
+enum flow_block_binder_type {
+ TCF_BLOCK_BINDER_TYPE_UNSPEC,
+ TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS,
+ TCF_BLOCK_BINDER_TYPE_CLSACT_EGRESS,
+};
+
+struct flow_block_offload {
+ enum flow_block_command command;
+ enum flow_block_binder_type binder_type;
+ struct list_head cb_list;
+ struct net *net;
+ bool block_shared;
+ struct netlink_ext_ack *extack;
+};
+
+struct flow_block_cb {
+ struct list_head global_list;
+ struct list_head list;
+ struct net *net;
+ tc_setup_cb_t *cb;
+ void (*release)(void *cb_priv);
+ void *cb_ident;
+ void *cb_priv;
+ u32 block_index;
+ unsigned int refcnt;
+};
+
+struct flow_block_cb *flow_block_cb_alloc(struct net *net, tc_setup_cb_t *cb,
+ void *cb_ident, void *cb_priv,
+ void (*release)(void *cb_priv));
+void flow_block_cb_free(struct flow_block_cb *block_cb);
+void *flow_block_cb_priv(struct flow_block_cb *block_cb);
+struct flow_block_cb *flow_block_cb_lookup(struct net *net, tc_setup_cb_t *cb,
+ void *cb_ident);
+void flow_block_cb_incref(struct flow_block_cb *block_cb);
+unsigned int flow_block_cb_decref(struct flow_block_cb *block_cb);
+void flow_block_cb_add(struct flow_block_cb *block_cb,
+ struct flow_block_offload *offload);
+void flow_block_cb_remove(struct flow_block_cb *block_cb,
+ struct flow_block_offload *offload);
+void flow_block_cb_splice(struct flow_block_offload *offload);
+
+int flow_block_setup_offload(struct flow_block_offload *f, tc_setup_cb_t *cb,
+ void *cb_ident, void *cb_priv, bool ingress_only);
+
#endif /* _NET_FLOW_OFFLOAD_H */
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index 52c11e390d9e..a60c9b19f660 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -26,14 +26,8 @@ struct tcf_walker {
int register_tcf_proto_ops(struct tcf_proto_ops *ops);
int unregister_tcf_proto_ops(struct tcf_proto_ops *ops);
-enum tcf_block_binder_type {
- TCF_BLOCK_BINDER_TYPE_UNSPEC,
- TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS,
- TCF_BLOCK_BINDER_TYPE_CLSACT_EGRESS,
-};
-
struct tcf_block_ext_info {
- enum tcf_block_binder_type binder_type;
+ enum flow_block_binder_type binder_type;
tcf_chain_head_change_t *chain_head_change;
void *chain_head_change_priv;
u32 block_index;
@@ -72,23 +66,6 @@ static inline struct Qdisc *tcf_block_q(struct tcf_block *block)
return block->q;
}
-struct tcf_block_cb *tcf_block_cb_alloc(struct net *net, tc_setup_cb_t *cb,
- void *cb_ident, void *cb_priv,
- void (*release)(void *cb_priv));
-void tcf_block_cb_free(struct tcf_block_cb *block_cb);
-
-struct tc_block_offload;
-void tcf_block_cb_add(struct tcf_block_cb *block_cb,
- struct tc_block_offload *offload);
-void tcf_block_cb_remove(struct tcf_block_cb *block_cb,
- struct tc_block_offload *offload);
-
-void *tcf_block_cb_priv(struct tcf_block_cb *block_cb);
-struct tcf_block_cb *tcf_block_cb_lookup(struct net *net, tc_setup_cb_t *cb,
- void *cb_ident);
-void tcf_block_cb_incref(struct tcf_block_cb *block_cb);
-unsigned int tcf_block_cb_decref(struct tcf_block_cb *block_cb);
-
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,
@@ -100,9 +77,6 @@ void tc_indr_block_cb_unregister(struct net_device *dev,
int tcf_classify(struct sk_buff *skb, const struct tcf_proto *tp,
struct tcf_result *res, bool compat_mode);
-
-int tcf_setup_block_offload(struct tc_block_offload *f, tc_setup_cb_t *cb,
- void *cb_ident, void *cb_priv, bool ingress_only);
#else
static inline bool tcf_block_shared(struct tcf_block *block)
{
@@ -153,60 +127,6 @@ void tc_setup_cb_block_unregister(struct tcf_block *block, tc_setup_cb_t *cb,
{
}
-static inline int tcf_setup_block_offload(struct tc_block_offload *f,
- tc_setup_cb_t *cb,
- void *cb_ident, void *cb_priv,
- bool ingress_only)
-{
- return -EOPNOTSUPP;
-}
-
-static inline struct tcf_block_cb *
-tcf_block_cb_alloc(struct net *net, tc_setup_cb_t *cb, void *cb_ident,
- void *cb_priv, void (*release)(void *cb_priv))
-{
- return ERR_PTR(-EOPNOTSUPP);
-}
-
-static inline void tcf_block_cb_free(struct tcf_block_cb *block_cb)
-{
-}
-
-struct tc_block_offload;
-static inline void tcf_block_cb_add(struct tcf_block_cb *block_cb,
- struct tc_block_offload *offload)
-{
-}
-
-static inline void tcf_block_cb_remove(struct tcf_block_cb *block_cb,
- struct tc_block_offload *offload)
-{
-}
-
-static inline
-void *tcf_block_cb_priv(struct tcf_block_cb *block_cb)
-{
- return NULL;
-}
-
-static inline
-struct tcf_block_cb *tcf_block_cb_lookup(struct net *net, struct tcf_block *block,
- tc_setup_cb_t *cb, void *cb_ident)
-{
- return NULL;
-}
-
-static inline
-void tcf_block_cb_incref(struct tcf_block_cb *block_cb)
-{
-}
-
-static inline
-unsigned int tcf_block_cb_decref(struct tcf_block_cb *block_cb)
-{
- 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)
@@ -614,19 +534,7 @@ int tc_setup_cb_call(struct tcf_block *block, enum tc_setup_type type,
void *type_data, bool err_stop);
unsigned int tcf_exts_num_actions(struct tcf_exts *exts);
-enum tc_block_command {
- TC_BLOCK_BIND,
- TC_BLOCK_UNBIND,
-};
-
-struct tc_block_offload {
- enum tc_block_command command;
- enum tcf_block_binder_type binder_type;
- struct list_head cb_list;
- struct net *net;
- bool block_shared;
- struct netlink_ext_ack *extack;
-};
+struct flow_block_offload;
struct tc_cls_common_offload {
u32 chain_index;
diff --git a/net/core/flow_offload.c b/net/core/flow_offload.c
index f52fe0bc4017..0b8d088d822e 100644
--- a/net/core/flow_offload.c
+++ b/net/core/flow_offload.c
@@ -164,3 +164,118 @@ void flow_rule_match_enc_opts(const struct flow_rule *rule,
FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_ENC_OPTS, out);
}
EXPORT_SYMBOL(flow_rule_match_enc_opts);
+
+void *flow_block_cb_priv(struct flow_block_cb *block_cb)
+{
+ return block_cb->cb_priv;
+}
+EXPORT_SYMBOL(flow_block_cb_priv);
+
+static LIST_HEAD(flow_block_cb_list);
+
+struct flow_block_cb *flow_block_cb_lookup(struct net *net, tc_setup_cb_t *cb,
+ void *cb_ident)
+{
+ struct flow_block_cb *block_cb;
+
+ list_for_each_entry(block_cb, &flow_block_cb_list, global_list) {
+ if (block_cb->net == net &&
+ block_cb->cb == cb &&
+ block_cb->cb_ident == cb_ident)
+ return block_cb;
+ }
+ return NULL;
+}
+EXPORT_SYMBOL(flow_block_cb_lookup);
+
+void flow_block_cb_incref(struct flow_block_cb *block_cb)
+{
+ block_cb->refcnt++;
+}
+EXPORT_SYMBOL(flow_block_cb_incref);
+
+unsigned int flow_block_cb_decref(struct flow_block_cb *block_cb)
+{
+ return --block_cb->refcnt;
+}
+EXPORT_SYMBOL(flow_block_cb_decref);
+
+struct flow_block_cb *flow_block_cb_alloc(struct net *net, tc_setup_cb_t *cb,
+ void *cb_ident, void *cb_priv,
+ void (*release)(void *cb_priv))
+{
+ struct flow_block_cb *block_cb;
+
+ block_cb = kzalloc(sizeof(*block_cb), GFP_KERNEL);
+ if (IS_ERR(block_cb))
+ return block_cb;
+
+ block_cb->net = net;
+ block_cb->cb = cb;
+ block_cb->cb_ident = cb_ident;
+ block_cb->release = release;
+ block_cb->cb_priv = cb_priv;
+
+ return block_cb;
+}
+EXPORT_SYMBOL(flow_block_cb_alloc);
+
+void flow_block_cb_free(struct flow_block_cb *block_cb)
+{
+ if (block_cb->release)
+ block_cb->release(block_cb->cb_priv);
+
+ kfree(block_cb);
+}
+EXPORT_SYMBOL(flow_block_cb_free);
+
+void flow_block_cb_add(struct flow_block_cb *block_cb,
+ struct flow_block_offload *offload)
+{
+ list_add_tail(&block_cb->global_list, &offload->cb_list);
+}
+EXPORT_SYMBOL(flow_block_cb_add);
+
+void flow_block_cb_remove(struct flow_block_cb *block_cb,
+ struct flow_block_offload *offload)
+{
+ list_move(&block_cb->global_list, &offload->cb_list);
+}
+EXPORT_SYMBOL(flow_block_cb_remove);
+
+void flow_block_cb_splice(struct flow_block_offload *offload)
+{
+ list_splice(&offload->cb_list, &flow_block_cb_list);
+}
+EXPORT_SYMBOL(flow_block_cb_splice);
+
+int flow_block_setup_offload(struct flow_block_offload *f, tc_setup_cb_t *cb,
+ void *cb_ident, void *cb_priv, bool ingress_only)
+{
+ struct flow_block_cb *block_cb;
+
+ if (ingress_only &&
+ f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
+ return -EOPNOTSUPP;
+
+ switch (f->command) {
+ case TC_BLOCK_BIND:
+ block_cb = flow_block_cb_alloc(f->net, cb, cb_ident, cb_priv,
+ NULL);
+ if (IS_ERR(block_cb))
+ return PTR_ERR(block_cb);
+
+ flow_block_cb_add(block_cb, f);
+ return 0;
+ case TC_BLOCK_UNBIND:
+ block_cb = flow_block_cb_lookup(f->net, cb, cb_ident);
+ if (!block_cb)
+ return -ENOENT;
+
+ flow_block_cb_remove(block_cb, f);
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+EXPORT_SYMBOL(flow_block_setup_offload);
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 01be6dc20ba3..0323091b5cef 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -943,9 +943,9 @@ static int dsa_slave_setup_tc_block_cb_eg(enum tc_setup_type type,
}
static int dsa_slave_setup_tc_block(struct net_device *dev,
- struct tc_block_offload *f)
+ struct flow_block_offload *f)
{
- struct tcf_block_cb *block_cb;
+ struct flow_block_cb *block_cb;
tc_setup_cb_t *cb;
if (f->binder_type == TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
@@ -957,18 +957,18 @@ static int dsa_slave_setup_tc_block(struct net_device *dev,
switch (f->command) {
case TC_BLOCK_BIND:
- block_cb = tcf_block_cb_alloc(f->net, cb, dev, dev, NULL);
+ block_cb = flow_block_cb_alloc(f->net, cb, dev, dev, NULL);
if (IS_ERR(block_cb))
return PTR_ERR(block_cb);
- tcf_block_cb_add(block_cb, f);
+ flow_block_cb_add(block_cb, f);
return 0;
case TC_BLOCK_UNBIND:
- block_cb = tcf_block_cb_lookup(f->net, cb, dev);
+ block_cb = flow_block_cb_lookup(f->net, cb, dev);
if (!block_cb)
return -ENOENT;
- tcf_block_cb_remove(block_cb, f);
+ flow_block_cb_remove(block_cb, f);
return 0;
default:
return -EOPNOTSUPP;
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index aa7ab707c399..5635b6f63015 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -26,6 +26,7 @@
#include <net/netlink.h>
#include <net/pkt_sched.h>
#include <net/pkt_cls.h>
+#include <net/flow_offload.h>
#include <net/tc_act/tc_pedit.h>
#include <net/tc_act/tc_mirred.h>
#include <net/tc_act/tc_vlan.h>
@@ -709,97 +710,9 @@ static bool tcf_block_offload_in_use(struct tcf_block *block)
return block->offloadcnt;
}
-struct tcf_block_cb {
- struct list_head global_list;
- struct list_head list;
- struct net *net;
- tc_setup_cb_t *cb;
- void (*release)(void *cb_priv);
- void *cb_ident;
- void *cb_priv;
- unsigned int refcnt;
-};
-
-void *tcf_block_cb_priv(struct tcf_block_cb *block_cb)
-{
- return block_cb->cb_priv;
-}
-EXPORT_SYMBOL(tcf_block_cb_priv);
-
-static LIST_HEAD(tcf_block_cb_list);
-
-struct tcf_block_cb *tcf_block_cb_lookup(struct net *net, tc_setup_cb_t *cb,
- void *cb_ident)
-{
- struct tcf_block_cb *block_cb;
-
- list_for_each_entry(block_cb, &tcf_block_cb_list, global_list)
- if (block_cb->net == net &&
- block_cb->cb == cb &&
- block_cb->cb_ident == cb_ident)
- return block_cb;
- return NULL;
-}
-EXPORT_SYMBOL(tcf_block_cb_lookup);
-
-void tcf_block_cb_incref(struct tcf_block_cb *block_cb)
-{
- block_cb->refcnt++;
-}
-EXPORT_SYMBOL(tcf_block_cb_incref);
-
-unsigned int tcf_block_cb_decref(struct tcf_block_cb *block_cb)
-{
- return --block_cb->refcnt;
-}
-EXPORT_SYMBOL(tcf_block_cb_decref);
-
-struct tcf_block_cb *tcf_block_cb_alloc(struct net *net, tc_setup_cb_t *cb,
- void *cb_ident, void *cb_priv,
- void (*release)(void *cb_priv))
-{
- struct tcf_block_cb *block_cb;
-
- block_cb = kzalloc(sizeof(*block_cb), GFP_KERNEL);
- if (!block_cb)
- return ERR_PTR(-ENOMEM);
-
- block_cb->net = net;
- block_cb->cb = cb;
- block_cb->cb_ident = cb_ident;
- block_cb->release = release;
- block_cb->cb_priv = cb_priv;
-
- return block_cb;
-}
-EXPORT_SYMBOL(tcf_block_cb_alloc);
-
-void tcf_block_cb_free(struct tcf_block_cb *block_cb)
-{
- if (block_cb->release)
- block_cb->release(block_cb->cb_priv);
-
- kfree(block_cb);
-}
-EXPORT_SYMBOL(tcf_block_cb_free);
-
-void tcf_block_cb_add(struct tcf_block_cb *block_cb,
- struct tc_block_offload *offload)
-{
- list_add_tail(&block_cb->global_list, &offload->cb_list);
-}
-EXPORT_SYMBOL(tcf_block_cb_add);
-
-void tcf_block_cb_remove(struct tcf_block_cb *block_cb,
- struct tc_block_offload *offload)
-{
- list_move(&block_cb->global_list, &offload->cb_list);
-}
-EXPORT_SYMBOL(tcf_block_cb_remove);
-
-static int tcf_block_bind(struct tcf_block *block, struct tc_block_offload *bo)
+static int tcf_block_bind(struct tcf_block *block, struct flow_block_offload *bo)
{
- struct tcf_block_cb *block_cb, *next;
+ struct flow_block_cb *block_cb, *next;
int err, i = 0;
list_for_each_entry(block_cb, &bo->cb_list, global_list) {
@@ -813,7 +726,7 @@ static int tcf_block_bind(struct tcf_block *block, struct tc_block_offload *bo)
list_add(&block_cb->list, &block->cb_list);
i++;
}
- list_splice(&bo->cb_list, &tcf_block_cb_list);
+ flow_block_cb_splice(bo);
return 0;
@@ -833,9 +746,9 @@ static int tcf_block_bind(struct tcf_block *block, struct tc_block_offload *bo)
}
static void tcf_block_unbind(struct tcf_block *block,
- struct tc_block_offload *bo)
+ struct flow_block_offload *bo)
{
- struct tcf_block_cb *block_cb, *next;
+ struct flow_block_cb *block_cb, *next;
list_for_each_entry_safe(block_cb, next, &bo->cb_list, global_list) {
list_del(&block_cb->global_list);
@@ -844,11 +757,12 @@ static void tcf_block_unbind(struct tcf_block *block,
tcf_block_offload_in_use(block),
NULL);
list_del(&block_cb->list);
- tcf_block_cb_free(block_cb);
+ flow_block_cb_free(block_cb);
}
}
-static int tcf_block_setup(struct tcf_block *block, struct tc_block_offload *bo)
+static int tcf_block_setup(struct tcf_block *block,
+ struct flow_block_offload *bo)
{
int err;
@@ -868,37 +782,6 @@ static int tcf_block_setup(struct tcf_block *block, struct tc_block_offload *bo)
return err;
}
-int tcf_setup_block_offload(struct tc_block_offload *f, tc_setup_cb_t *cb,
- void *cb_ident, void *cb_priv, bool ingress_only)
-{
- struct tcf_block_cb *block_cb;
-
- if (ingress_only &&
- f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
- return -EOPNOTSUPP;
-
- switch (f->command) {
- case TC_BLOCK_BIND:
- block_cb = tcf_block_cb_alloc(f->net, cb, cb_ident,
- cb_priv, NULL);
- if (IS_ERR(block_cb))
- return PTR_ERR(block_cb);
-
- tcf_block_cb_add(block_cb, f);
- return 0;
- case TC_BLOCK_UNBIND:
- block_cb = tcf_block_cb_lookup(f->net, cb, cb_ident);
- if (!block_cb)
- return -ENOENT;
-
- tcf_block_cb_remove(block_cb, f);
- return 0;
- default:
- return -EOPNOTSUPP;
- }
-}
-EXPORT_SYMBOL(tcf_setup_block_offload);
-
static struct rhashtable indr_setup_block_ht;
struct tc_indr_block_dev {
@@ -1008,9 +891,9 @@ static void tc_indr_block_cb_del(struct tc_indr_block_cb *indr_block_cb)
static void tc_indr_block_ing_cmd(struct tc_indr_block_dev *indr_dev,
struct tc_indr_block_cb *indr_block_cb,
- enum tc_block_command command)
+ enum flow_block_command command)
{
- struct tc_block_offload bo = {
+ struct flow_block_offload bo = {
.command = command,
.binder_type = TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS,
.net = dev_net(indr_dev->dev),
@@ -1096,12 +979,12 @@ EXPORT_SYMBOL_GPL(tc_indr_block_cb_unregister);
static void tc_indr_block_call(struct tcf_block *block, struct net_device *dev,
struct tcf_block_ext_info *ei,
- enum tc_block_command command,
+ enum flow_block_command command,
struct netlink_ext_ack *extack)
{
struct tc_indr_block_cb *indr_block_cb;
struct tc_indr_block_dev *indr_dev;
- struct tc_block_offload bo = {
+ struct flow_block_offload bo = {
.command = command,
.binder_type = ei->binder_type,
.net = dev_net(dev),
@@ -1126,10 +1009,10 @@ static void tc_indr_block_call(struct tcf_block *block, struct net_device *dev,
static int tcf_block_offload_cmd(struct tcf_block *block,
struct net_device *dev,
struct tcf_block_ext_info *ei,
- enum tc_block_command command,
+ enum flow_block_command command,
struct netlink_ext_ack *extack)
{
- struct tc_block_offload bo = {};
+ struct flow_block_offload bo = {};
int err;
bo.net = dev_net(dev);
@@ -1586,13 +1469,13 @@ static void tcf_block_release(struct Qdisc *q, struct tcf_block *block,
struct tcf_block_owner_item {
struct list_head list;
struct Qdisc *q;
- enum tcf_block_binder_type binder_type;
+ enum flow_block_binder_type binder_type;
};
static void
tcf_block_owner_netif_keep_dst(struct tcf_block *block,
struct Qdisc *q,
- enum tcf_block_binder_type binder_type)
+ enum flow_block_binder_type binder_type)
{
if (block->keep_dst &&
binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS &&
@@ -1613,7 +1496,7 @@ EXPORT_SYMBOL(tcf_block_netif_keep_dst);
static int tcf_block_owner_add(struct tcf_block *block,
struct Qdisc *q,
- enum tcf_block_binder_type binder_type)
+ enum flow_block_binder_type binder_type)
{
struct tcf_block_owner_item *item;
@@ -1628,7 +1511,7 @@ static int tcf_block_owner_add(struct tcf_block *block,
static void tcf_block_owner_del(struct tcf_block *block,
struct Qdisc *q,
- enum tcf_block_binder_type binder_type)
+ enum flow_block_binder_type binder_type)
{
struct tcf_block_owner_item *item;
@@ -3262,7 +3145,7 @@ EXPORT_SYMBOL(tcf_exts_dump_stats);
int tc_setup_cb_call(struct tcf_block *block, enum tc_setup_type type,
void *type_data, bool err_stop)
{
- struct tcf_block_cb *block_cb;
+ struct flow_block_cb *block_cb;
int ok_count = 0;
int err;
--
2.11.0
^ permalink raw reply related [flat|nested] 21+ messages in thread* [PATCH 11/15 net-next,v2] net: flow_offload: don't allow subsystem to reuse blocks
2019-07-04 23:48 [PATCH 00/15 net-next,v2] netfilter: add hardware offload infrastructure Pablo Neira Ayuso
` (9 preceding siblings ...)
2019-07-04 23:48 ` [PATCH 10/15 net-next,v2] net: flow_offload: add flow_block_cb API Pablo Neira Ayuso
@ 2019-07-04 23:48 ` Pablo Neira Ayuso
2019-07-04 23:48 ` [PATCH 12/15 net-next,v2] net: flow_offload: make flow block callback list per-driver Pablo Neira Ayuso
` (3 subsequent siblings)
14 siblings, 0 replies; 21+ messages in thread
From: Pablo Neira Ayuso @ 2019-07-04 23:48 UTC (permalink / raw)
To: netdev
Cc: netfilter-devel, davem, thomas.lendacky, f.fainelli, ariel.elior,
michael.chan, madalin.bucur, yisen.zhuang, salil.mehta,
jeffrey.t.kirsher, tariqt, saeedm, jiri, idosch, jakub.kicinski,
peppe.cavallaro, grygorii.strashko, andrew, vivien.didelot,
alexandre.torgue, joabreu, linux-net-drivers, ogerlitz,
Manish.Chopra, marcelo.leitner, mkubecek, venkatkumar.duvvuru,
maxime.chevallier, cphealy
Drivers need to be updated to support this, return EBUSY by now.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
v2: no changes.
net/core/flow_offload.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/net/core/flow_offload.c b/net/core/flow_offload.c
index 0b8d088d822e..8c20f4740800 100644
--- a/net/core/flow_offload.c
+++ b/net/core/flow_offload.c
@@ -206,6 +206,12 @@ struct flow_block_cb *flow_block_cb_alloc(struct net *net, tc_setup_cb_t *cb,
{
struct flow_block_cb *block_cb;
+ list_for_each_entry(block_cb, &flow_block_cb_list, global_list) {
+ if (block_cb->cb == cb &&
+ block_cb->cb_ident == cb_ident)
+ return ERR_PTR(-EBUSY);
+ }
+
block_cb = kzalloc(sizeof(*block_cb), GFP_KERNEL);
if (IS_ERR(block_cb))
return block_cb;
--
2.11.0
^ permalink raw reply related [flat|nested] 21+ messages in thread* [PATCH 12/15 net-next,v2] net: flow_offload: make flow block callback list per-driver
2019-07-04 23:48 [PATCH 00/15 net-next,v2] netfilter: add hardware offload infrastructure Pablo Neira Ayuso
` (10 preceding siblings ...)
2019-07-04 23:48 ` [PATCH 11/15 net-next,v2] net: flow_offload: don't allow subsystem to reuse blocks Pablo Neira Ayuso
@ 2019-07-04 23:48 ` Pablo Neira Ayuso
2019-07-05 22:42 ` Jakub Kicinski
2019-07-05 23:25 ` Jakub Kicinski
2019-07-04 23:48 ` [PATCH 13/15 net-next,v2] net: flow_offload: rename TC_BLOCK_{UN}BIND to FLOW_BLOCK_{UN}BIND Pablo Neira Ayuso
` (2 subsequent siblings)
14 siblings, 2 replies; 21+ messages in thread
From: Pablo Neira Ayuso @ 2019-07-04 23:48 UTC (permalink / raw)
To: netdev
Cc: netfilter-devel, davem, thomas.lendacky, f.fainelli, ariel.elior,
michael.chan, madalin.bucur, yisen.zhuang, salil.mehta,
jeffrey.t.kirsher, tariqt, saeedm, jiri, idosch, jakub.kicinski,
peppe.cavallaro, grygorii.strashko, andrew, vivien.didelot,
alexandre.torgue, joabreu, linux-net-drivers, ogerlitz,
Manish.Chopra, marcelo.leitner, mkubecek, venkatkumar.duvvuru,
maxime.chevallier, cphealy
Remove the global flow_block_cb_list, replace it by per-driver list
of flow block objects. This will make it easier later on to support
for policy hardware offload of multiple subsystems.
Suggested-by: Jiri Pirko <jiri@resnulli.us>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
v2: new patch, no previous v1.
Introduce per-driver list of flow blocks as Jiri requested.
drivers/net/ethernet/broadcom/bnxt/bnxt.c | 4 ++-
drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c | 3 ++
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 4 ++-
drivers/net/ethernet/intel/i40e/i40e_main.c | 4 ++-
drivers/net/ethernet/intel/iavf/iavf_main.c | 4 ++-
drivers/net/ethernet/intel/igb/igb_main.c | 4 ++-
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 4 ++-
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 4 ++-
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 8 ++++--
drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 17 ++++++------
drivers/net/ethernet/mscc/ocelot_flower.c | 6 ++--
drivers/net/ethernet/mscc/ocelot_tc.c | 8 ++++--
drivers/net/ethernet/netronome/nfp/abm/cls.c | 5 +++-
drivers/net/ethernet/netronome/nfp/bpf/main.c | 3 ++
.../net/ethernet/netronome/nfp/flower/offload.c | 9 +++---
drivers/net/ethernet/qlogic/qede/qede_main.c | 4 ++-
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 3 ++
drivers/net/netdevsim/netdev.c | 3 ++
include/net/flow_offload.h | 14 ++++++----
net/core/flow_offload.c | 32 ++++++++++++----------
net/dsa/slave.c | 8 ++++--
21 files changed, 99 insertions(+), 52 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index 7b8d71252093..4bf13776759e 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -9847,6 +9847,8 @@ static int bnxt_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
}
}
+static LIST_HEAD(bnxt_block_cb_list);
+
static int bnxt_setup_tc(struct net_device *dev, enum tc_setup_type type,
void *type_data)
{
@@ -9854,7 +9856,7 @@ static int bnxt_setup_tc(struct net_device *dev, enum tc_setup_type type,
switch (type) {
case TC_SETUP_BLOCK:
- return flow_block_setup_offload(type_data,
+ return flow_block_setup_offload(type_data, &bnxt_block_cb_list,
bnxt_setup_tc_block_cb, bp, bp,
true);
case TC_SETUP_QDISC_MQPRIO: {
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
index 1b78615a1384..80b8d8e54f58 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
@@ -161,6 +161,8 @@ static int bnxt_vf_rep_setup_tc_block_cb(enum tc_setup_type type,
}
}
+static LIST_HEAD(bnxt_vf_block_cb_list);
+
static int bnxt_vf_rep_setup_tc(struct net_device *dev, enum tc_setup_type type,
void *type_data)
{
@@ -169,6 +171,7 @@ static int bnxt_vf_rep_setup_tc(struct net_device *dev, enum tc_setup_type type,
switch (type) {
case TC_SETUP_BLOCK:
return flow_block_setup_offload(type_data,
+ &bnxt_vf_block_cb_list,
bnxt_vf_rep_setup_tc_block_cb,
vf_rep, vf_rep, true);
default:
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 3d8acabb8bfd..ee98304ea0cd 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -3190,6 +3190,8 @@ static int cxgb_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
}
}
+static LIST_HEAD(cxgb_block_cb_list);
+
static int cxgb_setup_tc(struct net_device *dev, enum tc_setup_type type,
void *type_data)
{
@@ -3197,7 +3199,7 @@ static int cxgb_setup_tc(struct net_device *dev, enum tc_setup_type type,
switch (type) {
case TC_SETUP_BLOCK:
- return flow_block_setup_offload(type_data,
+ return flow_block_setup_offload(type_data, &cxgb_block_cb_list,
cxgb_setup_tc_block_cb, pi, dev,
true);
default:
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index f7d2616854ec..2705e46fde59 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -8177,6 +8177,8 @@ static int i40e_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
}
}
+static LIST_HEAD(i40e_block_cb_list);
+
static int __i40e_setup_tc(struct net_device *netdev, enum tc_setup_type type,
void *type_data)
{
@@ -8186,7 +8188,7 @@ static int __i40e_setup_tc(struct net_device *netdev, enum tc_setup_type type,
case TC_SETUP_QDISC_MQPRIO:
return i40e_setup_tc(netdev, type_data);
case TC_SETUP_BLOCK:
- return flow_block_setup_offload(type_data,
+ return flow_block_setup_offload(type_data, &i40e_block_cb_list,
i40e_setup_tc_block_cb, np, np,
true);
default:
diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
index 8ef6aca34edd..410cbf02e6a8 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -3113,6 +3113,8 @@ static int iavf_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
}
}
+static LIST_HEAD(iavf_block_cb_list);
+
/**
* iavf_setup_tc - configure multiple traffic classes
* @netdev: network interface device structure
@@ -3133,7 +3135,7 @@ static int iavf_setup_tc(struct net_device *netdev, enum tc_setup_type type,
case TC_SETUP_QDISC_MQPRIO:
return __iavf_setup_tc(netdev, type_data);
case TC_SETUP_BLOCK:
- return flow_block_setup_offload(type_data,
+ return flow_block_setup_offload(type_data, &iavf_block_cb_list,
iavf_setup_tc_block_cb, adapter,
adapter, true);
default:
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index 830b950f423b..c66e66f04036 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -2806,6 +2806,8 @@ static int igb_offload_txtime(struct igb_adapter *adapter,
return 0;
}
+static LIST_HEAD(igb_block_cb_list);
+
static int igb_setup_tc(struct net_device *dev, enum tc_setup_type type,
void *type_data)
{
@@ -2815,7 +2817,7 @@ static int igb_setup_tc(struct net_device *dev, enum tc_setup_type type,
case TC_SETUP_QDISC_CBS:
return igb_offload_cbs(adapter, type_data);
case TC_SETUP_BLOCK:
- return flow_block_setup_offload(type_data,
+ return flow_block_setup_offload(type_data, &igb_block_cb_list,
igb_setup_tc_block_cb,
adapter, adapter, true);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 144f2cca686a..b3d62d8e1bd0 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -9614,6 +9614,8 @@ static int ixgbe_setup_tc_mqprio(struct net_device *dev,
return ixgbe_setup_tc(dev, mqprio->num_tc);
}
+static LIST_HEAD(ixgbe_block_cb_list);
+
static int __ixgbe_setup_tc(struct net_device *dev, enum tc_setup_type type,
void *type_data)
{
@@ -9621,7 +9623,7 @@ static int __ixgbe_setup_tc(struct net_device *dev, enum tc_setup_type type,
switch (type) {
case TC_SETUP_BLOCK:
- return flow_block_setup_offload(type_data,
+ return flow_block_setup_offload(type_data, &ixgbe_block_cb_list,
ixgbe_setup_tc_block_cb,
adapter, adapter, true);
case TC_SETUP_QDISC_MQPRIO:
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index fa9c04129eb6..6324215c7800 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -3347,6 +3347,8 @@ static int mlx5e_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
}
#endif
+static LIST_HEAD(mlx5e_block_cb_list);
+
static int mlx5e_setup_tc(struct net_device *dev, enum tc_setup_type type,
void *type_data)
{
@@ -3355,7 +3357,7 @@ static int mlx5e_setup_tc(struct net_device *dev, enum tc_setup_type type,
switch (type) {
#ifdef CONFIG_MLX5_ESWITCH
case TC_SETUP_BLOCK:
- return flow_block_setup_offload(type_data,
+ return flow_block_setup_offload(type_data, &mlx5e_block_cb_list,
mlx5e_setup_tc_block_cb,
priv, priv, true);
#endif
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
index 925aa589a818..2d26af759997 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
@@ -700,6 +700,8 @@ static void mlx5e_rep_indr_tc_block_unbind(void *cb_priv)
kfree(indr_priv);
}
+static LIST_HEAD(mlx5e_rep_block_cb_list);
+
static int
mlx5e_rep_indr_setup_tc_block(struct net_device *netdev,
struct mlx5e_rep_priv *rpriv,
@@ -726,8 +728,7 @@ mlx5e_rep_indr_setup_tc_block(struct net_device *netdev,
list_add(&indr_priv->list,
&rpriv->uplink_priv.tc_indr_block_priv_list);
- block_cb = flow_block_cb_alloc(f->net,
- mlx5e_rep_indr_setup_block_cb,
+ block_cb = flow_block_cb_alloc(f, mlx5e_rep_indr_setup_block_cb,
indr_priv, indr_priv,
mlx5e_rep_indr_tc_block_unbind);
if (IS_ERR(block_cb)) {
@@ -743,7 +744,7 @@ mlx5e_rep_indr_setup_tc_block(struct net_device *netdev,
if (!indr_priv)
return -ENOENT;
- block_cb = flow_block_cb_lookup(f->net,
+ block_cb = flow_block_cb_lookup(f,
mlx5e_rep_indr_setup_block_cb,
indr_priv);
if (!block_cb)
@@ -1198,6 +1199,7 @@ static int mlx5e_rep_setup_tc(struct net_device *dev, enum tc_setup_type type,
switch (type) {
case TC_SETUP_BLOCK:
return flow_block_setup_offload(type_data,
+ &mlx5e_rep_block_cb_list,
mlx5e_rep_setup_tc_cb,
priv, priv, true);
default:
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 6970738c070b..3ecb51a05961 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -1601,15 +1601,13 @@ mlxsw_sp_setup_tc_block_flower_bind(struct mlxsw_sp_port *mlxsw_sp_port,
bool register_block = false;
int err;
- block_cb = flow_block_cb_lookup(f->net,
- mlxsw_sp_setup_tc_block_cb_flower,
+ block_cb = flow_block_cb_lookup(f, mlxsw_sp_setup_tc_block_cb_flower,
mlxsw_sp);
if (!block_cb) {
acl_block = mlxsw_sp_acl_block_create(mlxsw_sp, f->net);
if (!acl_block)
return -ENOMEM;
-
- block_cb = flow_block_cb_alloc(f->net,
+ block_cb = flow_block_cb_alloc(f,
mlxsw_sp_setup_tc_block_cb_flower,
mlxsw_sp, acl_block,
mlxsw_sp_tc_block_flower_release);
@@ -1655,8 +1653,7 @@ mlxsw_sp_setup_tc_block_flower_unbind(struct mlxsw_sp_port *mlxsw_sp_port,
struct flow_block_cb *block_cb;
int err;
- block_cb = flow_block_cb_lookup(f->net,
- mlxsw_sp_setup_tc_block_cb_flower,
+ block_cb = flow_block_cb_lookup(f, mlxsw_sp_setup_tc_block_cb_flower,
mlxsw_sp);
if (!block_cb)
return;
@@ -1673,6 +1670,8 @@ mlxsw_sp_setup_tc_block_flower_unbind(struct mlxsw_sp_port *mlxsw_sp_port,
flow_block_cb_remove(block_cb, f);
}
+static LIST_HEAD(mlxsw_block_cb_list);
+
static int mlxsw_sp_setup_tc_block(struct mlxsw_sp_port *mlxsw_sp_port,
struct flow_block_offload *f)
{
@@ -1681,6 +1680,8 @@ static int mlxsw_sp_setup_tc_block(struct mlxsw_sp_port *mlxsw_sp_port,
bool ingress;
int err;
+ f->block_cb_list = &mlxsw_block_cb_list;
+
if (f->binder_type == TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS) {
cb = mlxsw_sp_setup_tc_block_cb_matchall_ig;
ingress = true;
@@ -1693,7 +1694,7 @@ static int mlxsw_sp_setup_tc_block(struct mlxsw_sp_port *mlxsw_sp_port,
switch (f->command) {
case TC_BLOCK_BIND:
- block_cb = flow_block_cb_alloc(f->net, cb, mlxsw_sp_port,
+ block_cb = flow_block_cb_alloc(f, cb, mlxsw_sp_port,
mlxsw_sp_port, NULL);
if (IS_ERR(block_cb))
return PTR_ERR(block_cb);
@@ -1708,7 +1709,7 @@ static int mlxsw_sp_setup_tc_block(struct mlxsw_sp_port *mlxsw_sp_port,
case TC_BLOCK_UNBIND:
mlxsw_sp_setup_tc_block_flower_unbind(mlxsw_sp_port,
f, ingress);
- block_cb = flow_block_cb_lookup(f->net, cb, mlxsw_sp_port);
+ block_cb = flow_block_cb_lookup(f, cb, mlxsw_sp_port);
if (!block_cb)
return -ENOENT;
diff --git a/drivers/net/ethernet/mscc/ocelot_flower.c b/drivers/net/ethernet/mscc/ocelot_flower.c
index 3b9e4219ac7a..3dd8acc255ae 100644
--- a/drivers/net/ethernet/mscc/ocelot_flower.c
+++ b/drivers/net/ethernet/mscc/ocelot_flower.c
@@ -316,14 +316,14 @@ int ocelot_setup_tc_block_flower_bind(struct ocelot_port *port,
if (f->binder_type == TCF_BLOCK_BINDER_TYPE_CLSACT_EGRESS)
return -EOPNOTSUPP;
- block_cb = flow_block_cb_lookup(f->net, ocelot_setup_tc_block_cb_flower,
+ block_cb = flow_block_cb_lookup(f, ocelot_setup_tc_block_cb_flower,
port);
if (!block_cb) {
port_block = ocelot_port_block_create(port);
if (!port_block)
return -ENOMEM;
- block_cb = flow_block_cb_alloc(f->net,
+ block_cb = flow_block_cb_alloc(f,
ocelot_setup_tc_block_cb_flower,
port, port_block,
ocelot_tc_block_unbind);
@@ -350,7 +350,7 @@ void ocelot_setup_tc_block_flower_unbind(struct ocelot_port *port,
{
struct flow_block_cb *block_cb;
- block_cb = flow_block_cb_lookup(f->net, ocelot_setup_tc_block_cb_flower,
+ block_cb = flow_block_cb_lookup(f, ocelot_setup_tc_block_cb_flower,
port);
if (!block_cb)
return;
diff --git a/drivers/net/ethernet/mscc/ocelot_tc.c b/drivers/net/ethernet/mscc/ocelot_tc.c
index 14a9e178c3b8..17fca31206c7 100644
--- a/drivers/net/ethernet/mscc/ocelot_tc.c
+++ b/drivers/net/ethernet/mscc/ocelot_tc.c
@@ -128,6 +128,8 @@ static int ocelot_setup_tc_block_cb_eg(enum tc_setup_type type,
cb_priv, false);
}
+static LIST_HEAD(ocelot_block_cb_list);
+
static int ocelot_setup_tc_block(struct ocelot_port *port,
struct flow_block_offload *f)
{
@@ -147,9 +149,11 @@ static int ocelot_setup_tc_block(struct ocelot_port *port,
return -EOPNOTSUPP;
}
+ f->block_cb_list = &ocelot_block_cb_list;
+
switch (f->command) {
case TC_BLOCK_BIND:
- block_cb = flow_block_cb_alloc(f->net, cb, port, port, NULL);
+ block_cb = flow_block_cb_alloc(f, cb, port, port, NULL);
if (IS_ERR(block_cb))
return PTR_ERR(block_cb);
@@ -161,7 +165,7 @@ static int ocelot_setup_tc_block(struct ocelot_port *port,
flow_block_cb_add(block_cb, f);
return 0;
case TC_BLOCK_UNBIND:
- block_cb = flow_block_cb_lookup(f->net, cb, port);
+ block_cb = flow_block_cb_lookup(f, cb, port);
if (!block_cb)
return -ENOENT;
diff --git a/drivers/net/ethernet/netronome/nfp/abm/cls.c b/drivers/net/ethernet/netronome/nfp/abm/cls.c
index 96b89a7c468b..a42f92318b7a 100644
--- a/drivers/net/ethernet/netronome/nfp/abm/cls.c
+++ b/drivers/net/ethernet/netronome/nfp/abm/cls.c
@@ -262,9 +262,12 @@ static int nfp_abm_setup_tc_block_cb(enum tc_setup_type type,
}
}
+static LIST_HEAD(nfp_abm_vf_block_cb_list);
+
int nfp_abm_setup_cls_block(struct net_device *netdev, struct nfp_repr *repr,
struct flow_block_offload *f)
{
- return flow_block_setup_offload(f, nfp_abm_setup_tc_block_cb,
+ return flow_block_setup_offload(f, &nfp_abm_block_cb_list,
+ nfp_abm_setup_tc_block_cb,
repr, repr, true);
}
diff --git a/drivers/net/ethernet/netronome/nfp/bpf/main.c b/drivers/net/ethernet/netronome/nfp/bpf/main.c
index 3897cc4f7a7e..5316d85261c0 100644
--- a/drivers/net/ethernet/netronome/nfp/bpf/main.c
+++ b/drivers/net/ethernet/netronome/nfp/bpf/main.c
@@ -160,6 +160,8 @@ static int nfp_bpf_setup_tc_block_cb(enum tc_setup_type type,
return 0;
}
+static LIST_HEAD(nfp_bfp_block_cb_list);
+
static int nfp_bpf_setup_tc(struct nfp_app *app, struct net_device *netdev,
enum tc_setup_type type, void *type_data)
{
@@ -168,6 +170,7 @@ static int nfp_bpf_setup_tc(struct nfp_app *app, struct net_device *netdev,
switch (type) {
case TC_SETUP_BLOCK:
return flow_block_setup_offload(type_data,
+ &nfp_bfp_block_cb_list,
nfp_bpf_setup_tc_block_cb,
nn, nn, true);
default:
diff --git a/drivers/net/ethernet/netronome/nfp/flower/offload.c b/drivers/net/ethernet/netronome/nfp/flower/offload.c
index 9b99f6936f90..6b2f31ed2315 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/offload.c
+++ b/drivers/net/ethernet/netronome/nfp/flower/offload.c
@@ -1317,7 +1317,7 @@ static int nfp_flower_setup_tc_block(struct net_device *netdev,
switch (f->command) {
case TC_BLOCK_BIND:
- block_cb = flow_block_cb_alloc(f->net,
+ block_cb = flow_block_cb_alloc(f,
nfp_flower_setup_tc_block_cb,
repr, repr, NULL);
if (IS_ERR(block_cb))
@@ -1326,7 +1326,7 @@ static int nfp_flower_setup_tc_block(struct net_device *netdev,
flow_block_cb_add(block_cb, f);
return 0;
case TC_BLOCK_UNBIND:
- block_cb = flow_block_cb_lookup(f->net,
+ block_cb = flow_block_cb_lookup(f,
nfp_flower_setup_tc_block_cb,
repr);
if (!block_cb)
@@ -1405,7 +1405,6 @@ nfp_flower_setup_indr_tc_block(struct net_device *netdev, struct nfp_app *app,
{
struct nfp_flower_indr_block_cb_priv *cb_priv;
struct nfp_flower_priv *priv = app->priv;
- struct net *net = dev_net(netdev);
struct flow_block_cb *block_cb;
if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS &&
@@ -1423,7 +1422,7 @@ nfp_flower_setup_indr_tc_block(struct net_device *netdev, struct nfp_app *app,
cb_priv->app = app;
list_add(&cb_priv->list, &priv->indr_block_cb_priv);
- block_cb = flow_block_cb_alloc(net,
+ block_cb = flow_block_cb_alloc(f,
nfp_flower_setup_indr_block_cb,
cb_priv, cb_priv,
nfp_flower_setup_indr_tc_release);
@@ -1440,7 +1439,7 @@ nfp_flower_setup_indr_tc_block(struct net_device *netdev, struct nfp_app *app,
if (!cb_priv)
return -ENOENT;
- block_cb = flow_block_cb_lookup(net,
+ block_cb = flow_block_cb_lookup(f,
nfp_flower_setup_indr_block_cb,
cb_priv);
if (!block_cb)
diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c
index 00db21d9407f..aab9c8c25d43 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_main.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_main.c
@@ -579,6 +579,8 @@ static int qede_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
}
}
+static LIST_HEAD(qede_block_cb_list);
+
static int
qede_setup_tc_offload(struct net_device *dev, enum tc_setup_type type,
void *type_data)
@@ -588,7 +590,7 @@ qede_setup_tc_offload(struct net_device *dev, enum tc_setup_type type,
switch (type) {
case TC_SETUP_BLOCK:
- return flow_block_setup_offload(type_data,
+ return flow_block_setup_offload(type_data, &qede_block_cb_list,
qede_setup_tc_block_cb,
edev, edev, true);
case TC_SETUP_QDISC_MQPRIO:
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 341db1eed108..86fef8ac2712 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -3853,6 +3853,8 @@ static int stmmac_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
return ret;
}
+static LIST_HEAD(stmmac_block_cb_list);
+
static int stmmac_setup_tc(struct net_device *ndev, enum tc_setup_type type,
void *type_data)
{
@@ -3861,6 +3863,7 @@ static int stmmac_setup_tc(struct net_device *ndev, enum tc_setup_type type,
switch (type) {
case TC_SETUP_BLOCK:
return flow_block_setup_offload(type_data,
+ &stmmac_block_cb_list,
stmmac_setup_tc_block_cb,
priv, priv, true);
case TC_SETUP_QDISC_CBS:
diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c
index 710b03fc8db1..0612b0628cf3 100644
--- a/drivers/net/netdevsim/netdev.c
+++ b/drivers/net/netdevsim/netdev.c
@@ -203,6 +203,8 @@ static int nsim_set_vf_link_state(struct net_device *dev, int vf, int state)
return 0;
}
+static LIST_HEAD(nsim_block_cb_list);
+
static int
nsim_setup_tc(struct net_device *dev, enum tc_setup_type type, void *type_data)
{
@@ -211,6 +213,7 @@ nsim_setup_tc(struct net_device *dev, enum tc_setup_type type, void *type_data)
switch (type) {
case TC_SETUP_BLOCK:
return flow_block_setup_offload(type_data,
+ &nsim_block_cb_list,
nsim_setup_tc_block_cb, ns, ns,
true);
default:
diff --git a/include/net/flow_offload.h b/include/net/flow_offload.h
index 728ded7e4361..390e74ed42cb 100644
--- a/include/net/flow_offload.h
+++ b/include/net/flow_offload.h
@@ -249,6 +249,7 @@ struct flow_block_offload {
enum flow_block_command command;
enum flow_block_binder_type binder_type;
struct list_head cb_list;
+ struct list_head *block_cb_list;
struct net *net;
bool block_shared;
struct netlink_ext_ack *extack;
@@ -266,13 +267,14 @@ struct flow_block_cb {
unsigned int refcnt;
};
-struct flow_block_cb *flow_block_cb_alloc(struct net *net, tc_setup_cb_t *cb,
+struct flow_block_cb *flow_block_cb_alloc(struct flow_block_offload *f,
+ tc_setup_cb_t *cb,
void *cb_ident, void *cb_priv,
void (*release)(void *cb_priv));
void flow_block_cb_free(struct flow_block_cb *block_cb);
void *flow_block_cb_priv(struct flow_block_cb *block_cb);
-struct flow_block_cb *flow_block_cb_lookup(struct net *net, tc_setup_cb_t *cb,
- void *cb_ident);
+struct flow_block_cb *flow_block_cb_lookup(struct flow_block_offload *f,
+ tc_setup_cb_t *cb, void *cb_ident);
void flow_block_cb_incref(struct flow_block_cb *block_cb);
unsigned int flow_block_cb_decref(struct flow_block_cb *block_cb);
void flow_block_cb_add(struct flow_block_cb *block_cb,
@@ -281,7 +283,9 @@ void flow_block_cb_remove(struct flow_block_cb *block_cb,
struct flow_block_offload *offload);
void flow_block_cb_splice(struct flow_block_offload *offload);
-int flow_block_setup_offload(struct flow_block_offload *f, tc_setup_cb_t *cb,
- void *cb_ident, void *cb_priv, bool ingress_only);
+int flow_block_setup_offload(struct flow_block_offload *f,
+ struct list_head *block_cb_list,
+ tc_setup_cb_t *cb, void *cb_ident, void *cb_priv,
+ bool ingress_only);
#endif /* _NET_FLOW_OFFLOAD_H */
diff --git a/net/core/flow_offload.c b/net/core/flow_offload.c
index 8c20f4740800..8392cf2b5ea7 100644
--- a/net/core/flow_offload.c
+++ b/net/core/flow_offload.c
@@ -171,15 +171,13 @@ void *flow_block_cb_priv(struct flow_block_cb *block_cb)
}
EXPORT_SYMBOL(flow_block_cb_priv);
-static LIST_HEAD(flow_block_cb_list);
-
-struct flow_block_cb *flow_block_cb_lookup(struct net *net, tc_setup_cb_t *cb,
- void *cb_ident)
+struct flow_block_cb *flow_block_cb_lookup(struct flow_block_offload *f,
+ tc_setup_cb_t *cb, void *cb_ident)
{
struct flow_block_cb *block_cb;
- list_for_each_entry(block_cb, &flow_block_cb_list, global_list) {
- if (block_cb->net == net &&
+ list_for_each_entry(block_cb, f->block_cb_list, global_list) {
+ if (block_cb->net == f->net &&
block_cb->cb == cb &&
block_cb->cb_ident == cb_ident)
return block_cb;
@@ -200,13 +198,14 @@ unsigned int flow_block_cb_decref(struct flow_block_cb *block_cb)
}
EXPORT_SYMBOL(flow_block_cb_decref);
-struct flow_block_cb *flow_block_cb_alloc(struct net *net, tc_setup_cb_t *cb,
+struct flow_block_cb *flow_block_cb_alloc(struct flow_block_offload *f,
+ tc_setup_cb_t *cb,
void *cb_ident, void *cb_priv,
void (*release)(void *cb_priv))
{
struct flow_block_cb *block_cb;
- list_for_each_entry(block_cb, &flow_block_cb_list, global_list) {
+ list_for_each_entry(block_cb, f->block_cb_list, global_list) {
if (block_cb->cb == cb &&
block_cb->cb_ident == cb_ident)
return ERR_PTR(-EBUSY);
@@ -216,7 +215,7 @@ struct flow_block_cb *flow_block_cb_alloc(struct net *net, tc_setup_cb_t *cb,
if (IS_ERR(block_cb))
return block_cb;
- block_cb->net = net;
+ block_cb->net = f->net;
block_cb->cb = cb;
block_cb->cb_ident = cb_ident;
block_cb->release = release;
@@ -251,30 +250,33 @@ EXPORT_SYMBOL(flow_block_cb_remove);
void flow_block_cb_splice(struct flow_block_offload *offload)
{
- list_splice(&offload->cb_list, &flow_block_cb_list);
+ list_splice(&offload->cb_list, offload->block_cb_list);
}
EXPORT_SYMBOL(flow_block_cb_splice);
-int flow_block_setup_offload(struct flow_block_offload *f, tc_setup_cb_t *cb,
- void *cb_ident, void *cb_priv, bool ingress_only)
+int flow_block_setup_offload(struct flow_block_offload *f,
+ struct list_head *block_cb_list,
+ tc_setup_cb_t *cb, void *cb_ident, void *cb_priv,
+ bool ingress_only)
{
struct flow_block_cb *block_cb;
+ f->block_cb_list = block_cb_list;
+
if (ingress_only &&
f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
return -EOPNOTSUPP;
switch (f->command) {
case TC_BLOCK_BIND:
- block_cb = flow_block_cb_alloc(f->net, cb, cb_ident, cb_priv,
- NULL);
+ block_cb = flow_block_cb_alloc(f, cb, cb_ident, cb_priv, NULL);
if (IS_ERR(block_cb))
return PTR_ERR(block_cb);
flow_block_cb_add(block_cb, f);
return 0;
case TC_BLOCK_UNBIND:
- block_cb = flow_block_cb_lookup(f->net, cb, cb_ident);
+ block_cb = flow_block_cb_lookup(f, cb, cb_ident);
if (!block_cb)
return -ENOENT;
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 0323091b5cef..504c4183af71 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -942,12 +942,16 @@ static int dsa_slave_setup_tc_block_cb_eg(enum tc_setup_type type,
return dsa_slave_setup_tc_block_cb(type, type_data, cb_priv, false);
}
+static LIST_HEAD(dsa_slave_block_cb_list);
+
static int dsa_slave_setup_tc_block(struct net_device *dev,
struct flow_block_offload *f)
{
struct flow_block_cb *block_cb;
tc_setup_cb_t *cb;
+ f->block_cb_list = &dsa_slave_block_cb_list;
+
if (f->binder_type == TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
cb = dsa_slave_setup_tc_block_cb_ig;
else if (f->binder_type == TCF_BLOCK_BINDER_TYPE_CLSACT_EGRESS)
@@ -957,14 +961,14 @@ static int dsa_slave_setup_tc_block(struct net_device *dev,
switch (f->command) {
case TC_BLOCK_BIND:
- block_cb = flow_block_cb_alloc(f->net, cb, dev, dev, NULL);
+ block_cb = flow_block_cb_alloc(f, cb, dev, dev, NULL);
if (IS_ERR(block_cb))
return PTR_ERR(block_cb);
flow_block_cb_add(block_cb, f);
return 0;
case TC_BLOCK_UNBIND:
- block_cb = flow_block_cb_lookup(f->net, cb, dev);
+ block_cb = flow_block_cb_lookup(f, cb, dev);
if (!block_cb)
return -ENOENT;
--
2.11.0
^ permalink raw reply related [flat|nested] 21+ messages in thread* Re: [PATCH 12/15 net-next,v2] net: flow_offload: make flow block callback list per-driver
2019-07-04 23:48 ` [PATCH 12/15 net-next,v2] net: flow_offload: make flow block callback list per-driver Pablo Neira Ayuso
@ 2019-07-05 22:42 ` Jakub Kicinski
2019-07-05 23:25 ` Jakub Kicinski
1 sibling, 0 replies; 21+ messages in thread
From: Jakub Kicinski @ 2019-07-05 22:42 UTC (permalink / raw)
To: Pablo Neira Ayuso
Cc: netdev, netfilter-devel, davem, thomas.lendacky, f.fainelli,
ariel.elior, michael.chan, madalin.bucur, yisen.zhuang,
salil.mehta, jeffrey.t.kirsher, tariqt, saeedm, jiri, idosch,
peppe.cavallaro, grygorii.strashko, andrew, vivien.didelot,
alexandre.torgue, joabreu, linux-net-drivers, ogerlitz,
Manish.Chopra, marcelo.leitner, mkubecek, venkatkumar.duvvuru,
maxime.chevallier, cphealy
On Fri, 5 Jul 2019 01:48:40 +0200, Pablo Neira Ayuso wrote:
> diff --git a/drivers/net/ethernet/netronome/nfp/abm/cls.c b/drivers/net/ethernet/netronome/nfp/abm/cls.c
> index 96b89a7c468b..a42f92318b7a 100644
> --- a/drivers/net/ethernet/netronome/nfp/abm/cls.c
> +++ b/drivers/net/ethernet/netronome/nfp/abm/cls.c
> @@ -262,9 +262,12 @@ static int nfp_abm_setup_tc_block_cb(enum tc_setup_type type,
> }
> }
>
> +static LIST_HEAD(nfp_abm_vf_block_cb_list);
s/_vf//
> int nfp_abm_setup_cls_block(struct net_device *netdev, struct nfp_repr *repr,
> struct flow_block_offload *f)
> {
> - return flow_block_setup_offload(f, nfp_abm_setup_tc_block_cb,
> + return flow_block_setup_offload(f, &nfp_abm_block_cb_list,
> + nfp_abm_setup_tc_block_cb,
> repr, repr, true);
> }
> diff --git a/drivers/net/ethernet/netronome/nfp/bpf/main.c b/drivers/net/ethernet/netronome/nfp/bpf/main.c
> index 3897cc4f7a7e..5316d85261c0 100644
> --- a/drivers/net/ethernet/netronome/nfp/bpf/main.c
> +++ b/drivers/net/ethernet/netronome/nfp/bpf/main.c
> @@ -160,6 +160,8 @@ static int nfp_bpf_setup_tc_block_cb(enum tc_setup_type type,
> return 0;
> }
>
> +static LIST_HEAD(nfp_bfp_block_cb_list);
s/bfp/bpf/
> static int nfp_bpf_setup_tc(struct nfp_app *app, struct net_device *netdev,
> enum tc_setup_type type, void *type_data)
> {
> @@ -168,6 +170,7 @@ static int nfp_bpf_setup_tc(struct nfp_app *app, struct net_device *netdev,
> switch (type) {
> case TC_SETUP_BLOCK:
> return flow_block_setup_offload(type_data,
> + &nfp_bfp_block_cb_list,
> nfp_bpf_setup_tc_block_cb,
> nn, nn, true);
> default:
^ permalink raw reply [flat|nested] 21+ messages in thread* Re: [PATCH 12/15 net-next,v2] net: flow_offload: make flow block callback list per-driver
2019-07-04 23:48 ` [PATCH 12/15 net-next,v2] net: flow_offload: make flow block callback list per-driver Pablo Neira Ayuso
2019-07-05 22:42 ` Jakub Kicinski
@ 2019-07-05 23:25 ` Jakub Kicinski
1 sibling, 0 replies; 21+ messages in thread
From: Jakub Kicinski @ 2019-07-05 23:25 UTC (permalink / raw)
To: Pablo Neira Ayuso
Cc: netdev, netfilter-devel, davem, thomas.lendacky, f.fainelli,
ariel.elior, michael.chan, madalin.bucur, yisen.zhuang,
salil.mehta, jeffrey.t.kirsher, tariqt, saeedm, jiri, idosch,
peppe.cavallaro, grygorii.strashko, andrew, vivien.didelot,
alexandre.torgue, joabreu, linux-net-drivers, ogerlitz,
Manish.Chopra, marcelo.leitner, mkubecek, venkatkumar.duvvuru,
maxime.chevallier, cphealy
On Fri, 5 Jul 2019 01:48:40 +0200, Pablo Neira Ayuso wrote:
> Remove the global flow_block_cb_list, replace it by per-driver list
> of flow block objects. This will make it easier later on to support
> for policy hardware offload of multiple subsystems.
>
> Suggested-by: Jiri Pirko <jiri@resnulli.us>
> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
I don't understand the need for a per driver list of callbacks.
Your concern seems to be that drivers will get confused by multiple
subsystems trying to bind blocks. We have a feature flag for TC
offloads, why can't netfilter have one too? Way simpler.
If I may comment on the patches in general this series is really hard
to follow. Changes are split into patches in a strange way, and the
number of things called some combination of block cb and list makes my
head hurt :/
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 13/15 net-next,v2] net: flow_offload: rename TC_BLOCK_{UN}BIND to FLOW_BLOCK_{UN}BIND
2019-07-04 23:48 [PATCH 00/15 net-next,v2] netfilter: add hardware offload infrastructure Pablo Neira Ayuso
` (11 preceding siblings ...)
2019-07-04 23:48 ` [PATCH 12/15 net-next,v2] net: flow_offload: make flow block callback list per-driver Pablo Neira Ayuso
@ 2019-07-04 23:48 ` Pablo Neira Ayuso
2019-07-04 23:48 ` [PATCH 14/15 net-next,v2] net: flow_offload: rename TCF_BLOCK_BINDER_TYPE_* to FLOW_BLOCK_BINDER_TYPE_* Pablo Neira Ayuso
2019-07-04 23:48 ` [PATCH 15/15 net-next,v2] netfilter: nf_tables: add hardware offload support Pablo Neira Ayuso
14 siblings, 0 replies; 21+ messages in thread
From: Pablo Neira Ayuso @ 2019-07-04 23:48 UTC (permalink / raw)
To: netdev
Cc: netfilter-devel, davem, thomas.lendacky, f.fainelli, ariel.elior,
michael.chan, madalin.bucur, yisen.zhuang, salil.mehta,
jeffrey.t.kirsher, tariqt, saeedm, jiri, idosch, jakub.kicinski,
peppe.cavallaro, grygorii.strashko, andrew, vivien.didelot,
alexandre.torgue, joabreu, linux-net-drivers, ogerlitz,
Manish.Chopra, marcelo.leitner, mkubecek, venkatkumar.duvvuru,
maxime.chevallier, cphealy
Not tc specific anymore, rename this.
Suggested-by: Jiri Pirko <jiri@resnulli.us>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
v2: Actually a new patch (no previous v1), requested by Jiri.
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 4 ++--
drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 4 ++--
drivers/net/ethernet/mscc/ocelot_tc.c | 4 ++--
.../net/ethernet/netronome/nfp/flower/offload.c | 8 ++++----
include/net/flow_offload.h | 4 ++--
net/core/flow_offload.c | 4 ++--
net/dsa/slave.c | 4 ++--
net/sched/cls_api.c | 24 +++++++++++-----------
8 files changed, 28 insertions(+), 28 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
index 2d26af759997..d05888dff503 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
@@ -714,7 +714,7 @@ mlx5e_rep_indr_setup_tc_block(struct net_device *netdev,
return -EOPNOTSUPP;
switch (f->command) {
- case TC_BLOCK_BIND:
+ case FLOW_BLOCK_BIND:
indr_priv = mlx5e_rep_indr_block_priv_lookup(rpriv, netdev);
if (indr_priv)
return -EEXIST;
@@ -739,7 +739,7 @@ mlx5e_rep_indr_setup_tc_block(struct net_device *netdev,
flow_block_cb_add(block_cb, f);
return 0;
- case TC_BLOCK_UNBIND:
+ case FLOW_BLOCK_UNBIND:
indr_priv = mlx5e_rep_indr_block_priv_lookup(rpriv, netdev);
if (!indr_priv)
return -ENOENT;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 3ecb51a05961..8083491b2172 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -1693,7 +1693,7 @@ static int mlxsw_sp_setup_tc_block(struct mlxsw_sp_port *mlxsw_sp_port,
}
switch (f->command) {
- case TC_BLOCK_BIND:
+ case FLOW_BLOCK_BIND:
block_cb = flow_block_cb_alloc(f, cb, mlxsw_sp_port,
mlxsw_sp_port, NULL);
if (IS_ERR(block_cb))
@@ -1706,7 +1706,7 @@ static int mlxsw_sp_setup_tc_block(struct mlxsw_sp_port *mlxsw_sp_port,
}
flow_block_cb_add(block_cb, f);
return 0;
- case TC_BLOCK_UNBIND:
+ case FLOW_BLOCK_UNBIND:
mlxsw_sp_setup_tc_block_flower_unbind(mlxsw_sp_port,
f, ingress);
block_cb = flow_block_cb_lookup(f, cb, mlxsw_sp_port);
diff --git a/drivers/net/ethernet/mscc/ocelot_tc.c b/drivers/net/ethernet/mscc/ocelot_tc.c
index 17fca31206c7..d92de65176b5 100644
--- a/drivers/net/ethernet/mscc/ocelot_tc.c
+++ b/drivers/net/ethernet/mscc/ocelot_tc.c
@@ -152,7 +152,7 @@ static int ocelot_setup_tc_block(struct ocelot_port *port,
f->block_cb_list = &ocelot_block_cb_list;
switch (f->command) {
- case TC_BLOCK_BIND:
+ case FLOW_BLOCK_BIND:
block_cb = flow_block_cb_alloc(f, cb, port, port, NULL);
if (IS_ERR(block_cb))
return PTR_ERR(block_cb);
@@ -164,7 +164,7 @@ static int ocelot_setup_tc_block(struct ocelot_port *port,
}
flow_block_cb_add(block_cb, f);
return 0;
- case TC_BLOCK_UNBIND:
+ case FLOW_BLOCK_UNBIND:
block_cb = flow_block_cb_lookup(f, cb, port);
if (!block_cb)
return -ENOENT;
diff --git a/drivers/net/ethernet/netronome/nfp/flower/offload.c b/drivers/net/ethernet/netronome/nfp/flower/offload.c
index 6b2f31ed2315..c52b8349b9f1 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/offload.c
+++ b/drivers/net/ethernet/netronome/nfp/flower/offload.c
@@ -1316,7 +1316,7 @@ static int nfp_flower_setup_tc_block(struct net_device *netdev,
repr_priv->block_shared = f->block_shared;
switch (f->command) {
- case TC_BLOCK_BIND:
+ case FLOW_BLOCK_BIND:
block_cb = flow_block_cb_alloc(f,
nfp_flower_setup_tc_block_cb,
repr, repr, NULL);
@@ -1325,7 +1325,7 @@ static int nfp_flower_setup_tc_block(struct net_device *netdev,
flow_block_cb_add(block_cb, f);
return 0;
- case TC_BLOCK_UNBIND:
+ case FLOW_BLOCK_UNBIND:
block_cb = flow_block_cb_lookup(f,
nfp_flower_setup_tc_block_cb,
repr);
@@ -1413,7 +1413,7 @@ nfp_flower_setup_indr_tc_block(struct net_device *netdev, struct nfp_app *app,
return -EOPNOTSUPP;
switch (f->command) {
- case TC_BLOCK_BIND:
+ case FLOW_BLOCK_BIND:
cb_priv = kmalloc(sizeof(*cb_priv), GFP_KERNEL);
if (!cb_priv)
return -ENOMEM;
@@ -1434,7 +1434,7 @@ nfp_flower_setup_indr_tc_block(struct net_device *netdev, struct nfp_app *app,
flow_block_cb_add(block_cb, f);
return 0;
- case TC_BLOCK_UNBIND:
+ case FLOW_BLOCK_UNBIND:
cb_priv = nfp_flower_indr_block_cb_priv_lookup(app, netdev);
if (!cb_priv)
return -ENOENT;
diff --git a/include/net/flow_offload.h b/include/net/flow_offload.h
index 390e74ed42cb..744eb474c823 100644
--- a/include/net/flow_offload.h
+++ b/include/net/flow_offload.h
@@ -235,8 +235,8 @@ static inline void flow_stats_update(struct flow_stats *flow_stats,
#include <net/sch_generic.h> /* for tc_setup_cb_t. */
enum flow_block_command {
- TC_BLOCK_BIND,
- TC_BLOCK_UNBIND,
+ FLOW_BLOCK_BIND,
+ FLOW_BLOCK_UNBIND,
};
enum flow_block_binder_type {
diff --git a/net/core/flow_offload.c b/net/core/flow_offload.c
index 8392cf2b5ea7..eaff06ee313d 100644
--- a/net/core/flow_offload.c
+++ b/net/core/flow_offload.c
@@ -268,14 +268,14 @@ int flow_block_setup_offload(struct flow_block_offload *f,
return -EOPNOTSUPP;
switch (f->command) {
- case TC_BLOCK_BIND:
+ case FLOW_BLOCK_BIND:
block_cb = flow_block_cb_alloc(f, cb, cb_ident, cb_priv, NULL);
if (IS_ERR(block_cb))
return PTR_ERR(block_cb);
flow_block_cb_add(block_cb, f);
return 0;
- case TC_BLOCK_UNBIND:
+ case FLOW_BLOCK_UNBIND:
block_cb = flow_block_cb_lookup(f, cb, cb_ident);
if (!block_cb)
return -ENOENT;
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 504c4183af71..636a22201654 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -960,14 +960,14 @@ static int dsa_slave_setup_tc_block(struct net_device *dev,
return -EOPNOTSUPP;
switch (f->command) {
- case TC_BLOCK_BIND:
+ case FLOW_BLOCK_BIND:
block_cb = flow_block_cb_alloc(f, cb, dev, dev, NULL);
if (IS_ERR(block_cb))
return PTR_ERR(block_cb);
flow_block_cb_add(block_cb, f);
return 0;
- case TC_BLOCK_UNBIND:
+ case FLOW_BLOCK_UNBIND:
block_cb = flow_block_cb_lookup(f, cb, dev);
if (!block_cb)
return -ENOENT;
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 5635b6f63015..00f4303dc6e5 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -767,10 +767,10 @@ static int tcf_block_setup(struct tcf_block *block,
int err;
switch (bo->command) {
- case TC_BLOCK_BIND:
+ case FLOW_BLOCK_BIND:
err = tcf_block_bind(block, bo);
break;
- case TC_BLOCK_UNBIND:
+ case FLOW_BLOCK_UNBIND:
err = 0;
tcf_block_unbind(block, bo);
break;
@@ -904,8 +904,8 @@ static void tc_indr_block_ing_cmd(struct tc_indr_block_dev *indr_dev,
if (!indr_dev->block)
return;
- indr_block_cb->cb(indr_dev->dev, indr_block_cb->cb_priv, TC_SETUP_BLOCK,
- &bo);
+ indr_block_cb->cb(indr_dev->dev, indr_block_cb->cb_priv,
+ TC_SETUP_BLOCK, &bo);
tcf_block_setup(indr_dev->block, &bo);
}
@@ -925,7 +925,7 @@ int __tc_indr_block_cb_register(struct net_device *dev, void *cb_priv,
if (err)
goto err_dev_put;
- tc_indr_block_ing_cmd(indr_dev, indr_block_cb, TC_BLOCK_BIND);
+ tc_indr_block_ing_cmd(indr_dev, indr_block_cb, FLOW_BLOCK_BIND);
return 0;
err_dev_put:
@@ -962,7 +962,7 @@ void __tc_indr_block_cb_unregister(struct net_device *dev,
return;
/* Send unbind message if required to free any block cbs. */
- tc_indr_block_ing_cmd(indr_dev, indr_block_cb, TC_BLOCK_UNBIND);
+ tc_indr_block_ing_cmd(indr_dev, indr_block_cb, FLOW_BLOCK_UNBIND);
tc_indr_block_cb_del(indr_block_cb);
tc_indr_block_dev_put(indr_dev);
}
@@ -997,7 +997,7 @@ static void tc_indr_block_call(struct tcf_block *block, struct net_device *dev,
if (!indr_dev)
return;
- indr_dev->block = command == TC_BLOCK_BIND ? block : NULL;
+ indr_dev->block = command == FLOW_BLOCK_BIND ? block : 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,
@@ -1047,20 +1047,20 @@ static int tcf_block_offload_bind(struct tcf_block *block, struct Qdisc *q,
return -EOPNOTSUPP;
}
- err = tcf_block_offload_cmd(block, dev, ei, TC_BLOCK_BIND, extack);
+ err = tcf_block_offload_cmd(block, dev, ei, FLOW_BLOCK_BIND, extack);
if (err == -EOPNOTSUPP)
goto no_offload_dev_inc;
if (err)
return err;
- tc_indr_block_call(block, dev, ei, TC_BLOCK_BIND, extack);
+ tc_indr_block_call(block, dev, ei, FLOW_BLOCK_BIND, extack);
return 0;
no_offload_dev_inc:
if (tcf_block_offload_in_use(block))
return -EOPNOTSUPP;
block->nooffloaddevcnt++;
- tc_indr_block_call(block, dev, ei, TC_BLOCK_BIND, extack);
+ tc_indr_block_call(block, dev, ei, FLOW_BLOCK_BIND, extack);
return 0;
}
@@ -1070,11 +1070,11 @@ static void tcf_block_offload_unbind(struct tcf_block *block, struct Qdisc *q,
struct net_device *dev = q->dev_queue->dev;
int err;
- tc_indr_block_call(block, dev, ei, TC_BLOCK_UNBIND, NULL);
+ tc_indr_block_call(block, dev, ei, FLOW_BLOCK_UNBIND, NULL);
if (!dev->netdev_ops->ndo_setup_tc)
goto no_offload_dev_dec;
- err = tcf_block_offload_cmd(block, dev, ei, TC_BLOCK_UNBIND, NULL);
+ err = tcf_block_offload_cmd(block, dev, ei, FLOW_BLOCK_UNBIND, NULL);
if (err == -EOPNOTSUPP)
goto no_offload_dev_dec;
return;
--
2.11.0
^ permalink raw reply related [flat|nested] 21+ messages in thread* [PATCH 14/15 net-next,v2] net: flow_offload: rename TCF_BLOCK_BINDER_TYPE_* to FLOW_BLOCK_BINDER_TYPE_*
2019-07-04 23:48 [PATCH 00/15 net-next,v2] netfilter: add hardware offload infrastructure Pablo Neira Ayuso
` (12 preceding siblings ...)
2019-07-04 23:48 ` [PATCH 13/15 net-next,v2] net: flow_offload: rename TC_BLOCK_{UN}BIND to FLOW_BLOCK_{UN}BIND Pablo Neira Ayuso
@ 2019-07-04 23:48 ` Pablo Neira Ayuso
2019-07-04 23:48 ` [PATCH 15/15 net-next,v2] netfilter: nf_tables: add hardware offload support Pablo Neira Ayuso
14 siblings, 0 replies; 21+ messages in thread
From: Pablo Neira Ayuso @ 2019-07-04 23:48 UTC (permalink / raw)
To: netdev
Cc: netfilter-devel, davem, thomas.lendacky, f.fainelli, ariel.elior,
michael.chan, madalin.bucur, yisen.zhuang, salil.mehta,
jeffrey.t.kirsher, tariqt, saeedm, jiri, idosch, jakub.kicinski,
peppe.cavallaro, grygorii.strashko, andrew, vivien.didelot,
alexandre.torgue, joabreu, linux-net-drivers, ogerlitz,
Manish.Chopra, marcelo.leitner, mkubecek, venkatkumar.duvvuru,
maxime.chevallier, cphealy
Not tc specific anymore, rename this.
Suggested-by: Jiri Pirko <jiri@resnulli.us>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
v2: Actually a new patch (no previous v1), requested by Jiri.
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 2 +-
drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 4 ++--
drivers/net/ethernet/mscc/ocelot_flower.c | 2 +-
drivers/net/ethernet/mscc/ocelot_tc.c | 4 ++--
drivers/net/ethernet/netronome/nfp/flower/offload.c | 6 +++---
include/net/flow_offload.h | 6 +++---
net/core/flow_offload.c | 2 +-
net/dsa/slave.c | 4 ++--
net/sched/cls_api.c | 6 +++---
net/sched/sch_ingress.c | 6 +++---
10 files changed, 21 insertions(+), 21 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
index d05888dff503..bde200cbedd0 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
@@ -710,7 +710,7 @@ mlx5e_rep_indr_setup_tc_block(struct net_device *netdev,
struct mlx5e_rep_indr_block_priv *indr_priv;
struct flow_block_cb *block_cb;
- if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
+ if (f->binder_type != FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
return -EOPNOTSUPP;
switch (f->command) {
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 8083491b2172..5b1a4160dfd9 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -1682,10 +1682,10 @@ static int mlxsw_sp_setup_tc_block(struct mlxsw_sp_port *mlxsw_sp_port,
f->block_cb_list = &mlxsw_block_cb_list;
- if (f->binder_type == TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS) {
+ if (f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS) {
cb = mlxsw_sp_setup_tc_block_cb_matchall_ig;
ingress = true;
- } else if (f->binder_type == TCF_BLOCK_BINDER_TYPE_CLSACT_EGRESS) {
+ } else if (f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS) {
cb = mlxsw_sp_setup_tc_block_cb_matchall_eg;
ingress = false;
} else {
diff --git a/drivers/net/ethernet/mscc/ocelot_flower.c b/drivers/net/ethernet/mscc/ocelot_flower.c
index 3dd8acc255ae..8921953cb32c 100644
--- a/drivers/net/ethernet/mscc/ocelot_flower.c
+++ b/drivers/net/ethernet/mscc/ocelot_flower.c
@@ -313,7 +313,7 @@ int ocelot_setup_tc_block_flower_bind(struct ocelot_port *port,
struct flow_block_cb *block_cb;
int ret;
- if (f->binder_type == TCF_BLOCK_BINDER_TYPE_CLSACT_EGRESS)
+ if (f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS)
return -EOPNOTSUPP;
block_cb = flow_block_cb_lookup(f, ocelot_setup_tc_block_cb_flower,
diff --git a/drivers/net/ethernet/mscc/ocelot_tc.c b/drivers/net/ethernet/mscc/ocelot_tc.c
index d92de65176b5..b9769e4411e7 100644
--- a/drivers/net/ethernet/mscc/ocelot_tc.c
+++ b/drivers/net/ethernet/mscc/ocelot_tc.c
@@ -140,10 +140,10 @@ static int ocelot_setup_tc_block(struct ocelot_port *port,
netdev_dbg(port->dev, "tc_block command %d, binder_type %d\n",
f->command, f->binder_type);
- if (f->binder_type == TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS) {
+ if (f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS) {
cb = ocelot_setup_tc_block_cb_ig;
port->tc.block_shared = f->block_shared;
- } else if (f->binder_type == TCF_BLOCK_BINDER_TYPE_CLSACT_EGRESS) {
+ } else if (f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS) {
cb = ocelot_setup_tc_block_cb_eg;
} else {
return -EOPNOTSUPP;
diff --git a/drivers/net/ethernet/netronome/nfp/flower/offload.c b/drivers/net/ethernet/netronome/nfp/flower/offload.c
index c52b8349b9f1..b926c1639c1d 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/offload.c
+++ b/drivers/net/ethernet/netronome/nfp/flower/offload.c
@@ -1309,7 +1309,7 @@ static int nfp_flower_setup_tc_block(struct net_device *netdev,
struct nfp_flower_repr_priv *repr_priv;
struct flow_block_cb *block_cb;
- if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
+ if (f->binder_type != FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
return -EOPNOTSUPP;
repr_priv = repr->app_priv;
@@ -1407,8 +1407,8 @@ nfp_flower_setup_indr_tc_block(struct net_device *netdev, struct nfp_app *app,
struct nfp_flower_priv *priv = app->priv;
struct flow_block_cb *block_cb;
- if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS &&
- !(f->binder_type == TCF_BLOCK_BINDER_TYPE_CLSACT_EGRESS &&
+ if (f->binder_type != FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS &&
+ !(f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS &&
nfp_flower_internal_port_can_offload(app, netdev)))
return -EOPNOTSUPP;
diff --git a/include/net/flow_offload.h b/include/net/flow_offload.h
index 744eb474c823..f955c906116b 100644
--- a/include/net/flow_offload.h
+++ b/include/net/flow_offload.h
@@ -240,9 +240,9 @@ enum flow_block_command {
};
enum flow_block_binder_type {
- TCF_BLOCK_BINDER_TYPE_UNSPEC,
- TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS,
- TCF_BLOCK_BINDER_TYPE_CLSACT_EGRESS,
+ FLOW_BLOCK_BINDER_TYPE_UNSPEC,
+ FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS,
+ FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS,
};
struct flow_block_offload {
diff --git a/net/core/flow_offload.c b/net/core/flow_offload.c
index eaff06ee313d..5614a637f1fd 100644
--- a/net/core/flow_offload.c
+++ b/net/core/flow_offload.c
@@ -264,7 +264,7 @@ int flow_block_setup_offload(struct flow_block_offload *f,
f->block_cb_list = block_cb_list;
if (ingress_only &&
- f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
+ f->binder_type != FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
return -EOPNOTSUPP;
switch (f->command) {
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 636a22201654..0c1900b2f5f1 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -952,9 +952,9 @@ static int dsa_slave_setup_tc_block(struct net_device *dev,
f->block_cb_list = &dsa_slave_block_cb_list;
- if (f->binder_type == TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
+ if (f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
cb = dsa_slave_setup_tc_block_cb_ig;
- else if (f->binder_type == TCF_BLOCK_BINDER_TYPE_CLSACT_EGRESS)
+ else if (f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS)
cb = dsa_slave_setup_tc_block_cb_eg;
else
return -EOPNOTSUPP;
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 00f4303dc6e5..1f9d742345a6 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -895,7 +895,7 @@ static void tc_indr_block_ing_cmd(struct tc_indr_block_dev *indr_dev,
{
struct flow_block_offload bo = {
.command = command,
- .binder_type = TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS,
+ .binder_type = FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS,
.net = dev_net(indr_dev->dev),
.block_shared = tcf_block_shared(indr_dev->block),
};
@@ -1478,8 +1478,8 @@ tcf_block_owner_netif_keep_dst(struct tcf_block *block,
enum flow_block_binder_type binder_type)
{
if (block->keep_dst &&
- binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS &&
- binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_EGRESS)
+ binder_type != FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS &&
+ binder_type != FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS)
netif_keep_dst(qdisc_dev(q));
}
diff --git a/net/sched/sch_ingress.c b/net/sched/sch_ingress.c
index 599730f804d7..bf56aa519797 100644
--- a/net/sched/sch_ingress.c
+++ b/net/sched/sch_ingress.c
@@ -83,7 +83,7 @@ static int ingress_init(struct Qdisc *sch, struct nlattr *opt,
mini_qdisc_pair_init(&q->miniqp, sch, &dev->miniq_ingress);
- q->block_info.binder_type = TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS;
+ q->block_info.binder_type = FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS;
q->block_info.chain_head_change = clsact_chain_head_change;
q->block_info.chain_head_change_priv = &q->miniqp;
@@ -217,7 +217,7 @@ static int clsact_init(struct Qdisc *sch, struct nlattr *opt,
mini_qdisc_pair_init(&q->miniqp_ingress, sch, &dev->miniq_ingress);
- q->ingress_block_info.binder_type = TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS;
+ q->ingress_block_info.binder_type = FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS;
q->ingress_block_info.chain_head_change = clsact_chain_head_change;
q->ingress_block_info.chain_head_change_priv = &q->miniqp_ingress;
@@ -228,7 +228,7 @@ static int clsact_init(struct Qdisc *sch, struct nlattr *opt,
mini_qdisc_pair_init(&q->miniqp_egress, sch, &dev->miniq_egress);
- q->egress_block_info.binder_type = TCF_BLOCK_BINDER_TYPE_CLSACT_EGRESS;
+ q->egress_block_info.binder_type = FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS;
q->egress_block_info.chain_head_change = clsact_chain_head_change;
q->egress_block_info.chain_head_change_priv = &q->miniqp_egress;
--
2.11.0
^ permalink raw reply related [flat|nested] 21+ messages in thread* [PATCH 15/15 net-next,v2] netfilter: nf_tables: add hardware offload support
2019-07-04 23:48 [PATCH 00/15 net-next,v2] netfilter: add hardware offload infrastructure Pablo Neira Ayuso
` (13 preceding siblings ...)
2019-07-04 23:48 ` [PATCH 14/15 net-next,v2] net: flow_offload: rename TCF_BLOCK_BINDER_TYPE_* to FLOW_BLOCK_BINDER_TYPE_* Pablo Neira Ayuso
@ 2019-07-04 23:48 ` Pablo Neira Ayuso
14 siblings, 0 replies; 21+ messages in thread
From: Pablo Neira Ayuso @ 2019-07-04 23:48 UTC (permalink / raw)
To: netdev
Cc: netfilter-devel, davem, thomas.lendacky, f.fainelli, ariel.elior,
michael.chan, madalin.bucur, yisen.zhuang, salil.mehta,
jeffrey.t.kirsher, tariqt, saeedm, jiri, idosch, jakub.kicinski,
peppe.cavallaro, grygorii.strashko, andrew, vivien.didelot,
alexandre.torgue, joabreu, linux-net-drivers, ogerlitz,
Manish.Chopra, marcelo.leitner, mkubecek, venkatkumar.duvvuru,
maxime.chevallier, cphealy
This patch adds hardware offload support for nftables through the
existing netdev_ops->ndo_setup_tc() interface, the TC_SETUP_CLSFLOWER
classifier and the flow rule API. This hardware offload support is
available for the NFPROTO_NETDEV family and the ingress hook.
Each nftables expression has a new ->offload interface, that is used to
populate the flow rule object that is attached to the transaction
object.
There is a new per-table NFT_TABLE_F_HW_OFFLOAD flag, that is set on
to offload an entire table, including all of its chains.
This patch supports for basic metadata (layer 3 and 4 protocol numbers),
5-tuple payload matching and the accept/drop actions; this also includes
basechain hardware offload only.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
v2: return -EOPNOTSUPP in case of default policy is drop.
add nft_flow_offload_unbind().
include/net/netfilter/nf_tables.h | 13 ++
include/net/netfilter/nf_tables_offload.h | 76 +++++++++
include/uapi/linux/netfilter/nf_tables.h | 2 +
net/netfilter/Makefile | 2 +-
net/netfilter/nf_tables_api.c | 22 ++-
net/netfilter/nf_tables_offload.c | 261 ++++++++++++++++++++++++++++++
net/netfilter/nft_cmp.c | 53 ++++++
net/netfilter/nft_immediate.c | 31 ++++
net/netfilter/nft_meta.c | 27 ++++
net/netfilter/nft_payload.c | 187 +++++++++++++++++++++
10 files changed, 671 insertions(+), 3 deletions(-)
create mode 100644 include/net/netfilter/nf_tables_offload.h
create mode 100644 net/netfilter/nf_tables_offload.c
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index 9e8493aad49d..4f8cb85d18ce 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -161,6 +161,7 @@ struct nft_ctx {
const struct nlattr * const *nla;
u32 portid;
u32 seq;
+ u16 flags;
u8 family;
u8 level;
bool report;
@@ -735,6 +736,9 @@ enum nft_trans_phase {
NFT_TRANS_RELEASE
};
+struct nft_flow_rule;
+struct nft_offload_ctx;
+
/**
* struct nft_expr_ops - nf_tables expression operations
*
@@ -777,6 +781,10 @@ struct nft_expr_ops {
const struct nft_data **data);
bool (*gc)(struct net *net,
const struct nft_expr *expr);
+ int (*offload)(struct nft_offload_ctx *ctx,
+ struct nft_flow_rule *flow,
+ const struct nft_expr *expr);
+ u32 offload_flags;
const struct nft_expr_type *type;
void *data;
};
@@ -942,6 +950,7 @@ struct nft_stats {
* @stats: per-cpu chain stats
* @chain: the chain
* @dev_name: device name that this base chain is attached to (if any)
+ * @cb_list: list of flow block callbacks (for hardware offload)
*/
struct nft_base_chain {
struct nf_hook_ops ops;
@@ -951,6 +960,7 @@ struct nft_base_chain {
struct nft_stats __percpu *stats;
struct nft_chain chain;
char dev_name[IFNAMSIZ];
+ struct list_head cb_list;
};
static inline struct nft_base_chain *nft_base_chain(const struct nft_chain *chain)
@@ -1322,11 +1332,14 @@ struct nft_trans {
struct nft_trans_rule {
struct nft_rule *rule;
+ struct nft_flow_rule *flow;
u32 rule_id;
};
#define nft_trans_rule(trans) \
(((struct nft_trans_rule *)trans->data)->rule)
+#define nft_trans_flow_rule(trans) \
+ (((struct nft_trans_rule *)trans->data)->flow)
#define nft_trans_rule_id(trans) \
(((struct nft_trans_rule *)trans->data)->rule_id)
diff --git a/include/net/netfilter/nf_tables_offload.h b/include/net/netfilter/nf_tables_offload.h
new file mode 100644
index 000000000000..3196663a10e3
--- /dev/null
+++ b/include/net/netfilter/nf_tables_offload.h
@@ -0,0 +1,76 @@
+#ifndef _NET_NF_TABLES_OFFLOAD_H
+#define _NET_NF_TABLES_OFFLOAD_H
+
+#include <net/flow_offload.h>
+#include <net/netfilter/nf_tables.h>
+
+struct nft_offload_reg {
+ u32 key;
+ u32 len;
+ u32 base_offset;
+ u32 offset;
+ struct nft_data mask;
+};
+
+enum nft_offload_dep_type {
+ NFT_OFFLOAD_DEP_UNSPEC = 0,
+ NFT_OFFLOAD_DEP_NETWORK,
+ NFT_OFFLOAD_DEP_TRANSPORT,
+};
+
+struct nft_offload_ctx {
+ struct {
+ enum nft_offload_dep_type type;
+ __be16 l3num;
+ u8 protonum;
+ } dep;
+ unsigned int num_actions;
+ struct nft_offload_reg regs[NFT_REG32_15 + 1];
+};
+
+void nft_offload_set_dependency(struct nft_offload_ctx *ctx,
+ enum nft_offload_dep_type type);
+void nft_offload_update_dependency(struct nft_offload_ctx *ctx,
+ const void *data, u32 len);
+
+struct nft_flow_key {
+ struct flow_dissector_key_basic basic;
+ union {
+ struct flow_dissector_key_ipv4_addrs ipv4;
+ struct flow_dissector_key_ipv6_addrs ipv6;
+ };
+ struct flow_dissector_key_ports tp;
+ struct flow_dissector_key_ip ip;
+ struct flow_dissector_key_vlan vlan;
+ struct flow_dissector_key_eth_addrs eth_addrs;
+} __aligned(BITS_PER_LONG / 8); /* Ensure that we can do comparisons as longs. */
+
+struct nft_flow_match {
+ struct flow_dissector dissector;
+ struct nft_flow_key key;
+ struct nft_flow_key mask;
+};
+
+struct nft_flow_rule {
+ __be16 proto;
+ struct nft_flow_match match;
+ struct flow_rule *rule;
+};
+
+#define NFT_OFFLOAD_F_ACTION (1 << 0)
+
+struct nft_rule;
+struct nft_flow_rule *nft_flow_rule_create(const struct nft_rule *rule);
+void nft_flow_rule_destroy(struct nft_flow_rule *flow);
+int nft_flow_rule_offload_commit(struct net *net);
+
+#define NFT_OFFLOAD_MATCH(__key, __base, __field, __len, __reg) \
+ (__reg)->base_offset = \
+ offsetof(struct nft_flow_key, __base); \
+ (__reg)->offset = \
+ offsetof(struct nft_flow_key, __base.__field); \
+ (__reg)->len = __len; \
+ (__reg)->key = __key; \
+ memset(&(__reg)->mask, 0xff, (__reg)->len);
+
+#endif
diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
index c6c8ec5c7c00..1d076140dc5d 100644
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -158,9 +158,11 @@ enum nft_hook_attributes {
* enum nft_table_flags - nf_tables table flags
*
* @NFT_TABLE_F_DORMANT: this table is not active
+ * @NFT_TABLE_F_HW_OFFLOAD: enable hardware offload
*/
enum nft_table_flags {
NFT_TABLE_F_DORMANT = 0x1,
+ NFT_TABLE_F_HW_OFFLOAD = 0x2,
};
/**
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 72cca6b48960..46cb1d34e750 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -78,7 +78,7 @@ nf_tables-objs := nf_tables_core.o nf_tables_api.o nft_chain_filter.o \
nf_tables_trace.o nft_immediate.o nft_cmp.o nft_range.o \
nft_bitwise.o nft_byteorder.o nft_payload.o nft_lookup.o \
nft_dynset.o nft_meta.o nft_rt.o nft_exthdr.o \
- nft_chain_route.o
+ nft_chain_route.o nf_tables_offload.o
nf_tables_set-objs := nf_tables_set_core.o \
nft_set_hash.o nft_set_bitmap.o nft_set_rbtree.o
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index cae5c46e2dd4..11843f8656e5 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -18,6 +18,7 @@
#include <net/netfilter/nf_flow_table.h>
#include <net/netfilter/nf_tables_core.h>
#include <net/netfilter/nf_tables.h>
+#include <net/netfilter/nf_tables_offload.h>
#include <net/net_namespace.h>
#include <net/sock.h>
@@ -97,6 +98,7 @@ static void nft_ctx_init(struct nft_ctx *ctx,
ctx->nla = nla;
ctx->portid = NETLINK_CB(skb).portid;
ctx->report = nlmsg_report(nlh);
+ ctx->flags = nlh->nlmsg_flags;
ctx->seq = nlh->nlmsg_seq;
}
@@ -896,7 +898,7 @@ static int nf_tables_newtable(struct net *net, struct sock *nlsk,
if (nla[NFTA_TABLE_FLAGS]) {
flags = ntohl(nla_get_be32(nla[NFTA_TABLE_FLAGS]));
- if (flags & ~NFT_TABLE_F_DORMANT)
+ if (flags & ~(NFT_TABLE_F_DORMANT | NFT_TABLE_F_HW_OFFLOAD))
return -EINVAL;
}
@@ -1659,6 +1661,7 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
chain->flags |= NFT_BASE_CHAIN;
basechain->policy = NF_ACCEPT;
+ INIT_LIST_HEAD(&basechain->cb_list);
} else {
chain = kzalloc(sizeof(*chain), GFP_KERNEL);
if (chain == NULL)
@@ -2638,6 +2641,7 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk,
u8 genmask = nft_genmask_next(net);
struct nft_expr_info *info = NULL;
int family = nfmsg->nfgen_family;
+ struct nft_flow_rule *flow;
struct nft_table *table;
struct nft_chain *chain;
struct nft_rule *rule, *old_rule = NULL;
@@ -2784,7 +2788,8 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk,
list_add_tail_rcu(&rule->list, &old_rule->list);
} else {
- if (nft_trans_rule_add(&ctx, NFT_MSG_NEWRULE, rule) == NULL) {
+ trans = nft_trans_rule_add(&ctx, NFT_MSG_NEWRULE, rule);
+ if (!trans) {
err = -ENOMEM;
goto err2;
}
@@ -2807,6 +2812,14 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk,
if (net->nft.validate_state == NFT_VALIDATE_DO)
return nft_table_validate(net, table);
+ if (table->flags & NFT_TABLE_F_HW_OFFLOAD) {
+ flow = nft_flow_rule_create(rule);
+ if (IS_ERR(flow))
+ return PTR_ERR(flow);
+
+ nft_trans_flow_rule(trans) = flow;
+ }
+
return 0;
err2:
nf_tables_rule_release(&ctx, rule);
@@ -6604,6 +6617,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
struct nft_trans_elem *te;
struct nft_chain *chain;
struct nft_table *table;
+ int err;
if (list_empty(&net->nft.commit_list)) {
mutex_unlock(&net->nft.commit_mutex);
@@ -6614,6 +6628,10 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
if (nf_tables_validate(net) < 0)
return -EAGAIN;
+ err = nft_flow_rule_offload_commit(net);
+ if (err < 0)
+ return err;
+
/* 1. Allocate space for next generation rules_gen_X[] */
list_for_each_entry_safe(trans, next, &net->nft.commit_list, list) {
int ret;
diff --git a/net/netfilter/nf_tables_offload.c b/net/netfilter/nf_tables_offload.c
new file mode 100644
index 000000000000..99e2ef94b92a
--- /dev/null
+++ b/net/netfilter/nf_tables_offload.c
@@ -0,0 +1,261 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/netfilter.h>
+#include <net/flow_offload.h>
+#include <net/netfilter/nf_tables.h>
+#include <net/netfilter/nf_tables_offload.h>
+#include <net/pkt_cls.h>
+
+static struct nft_flow_rule *nft_flow_rule_alloc(int num_actions)
+{
+ struct nft_flow_rule *flow;
+
+ flow = kzalloc(sizeof(struct nft_flow_rule), GFP_KERNEL);
+ if (!flow)
+ return NULL;
+
+ flow->rule = flow_rule_alloc(num_actions);
+ if (!flow->rule) {
+ kfree(flow);
+ return NULL;
+ }
+
+ flow->rule->match.dissector = &flow->match.dissector;
+ flow->rule->match.mask = &flow->match.mask;
+ flow->rule->match.key = &flow->match.key;
+
+ return flow;
+}
+
+struct nft_flow_rule *nft_flow_rule_create(const struct nft_rule *rule)
+{
+ struct nft_offload_ctx ctx = {
+ .dep = {
+ .type = NFT_OFFLOAD_DEP_UNSPEC,
+ },
+ };
+ struct nft_flow_rule *flow;
+ int num_actions = 0, err;
+ struct nft_expr *expr;
+
+ expr = nft_expr_first(rule);
+ while (expr->ops && expr != nft_expr_last(rule)) {
+ if (expr->ops->offload_flags & NFT_OFFLOAD_F_ACTION)
+ num_actions++;
+
+ expr = nft_expr_next(expr);
+ }
+
+ flow = nft_flow_rule_alloc(num_actions);
+ if (!flow)
+ return ERR_PTR(-ENOMEM);
+
+ expr = nft_expr_first(rule);
+ while (expr->ops && expr != nft_expr_last(rule)) {
+ if (!expr->ops->offload) {
+ err = -EOPNOTSUPP;
+ goto err_out;
+ }
+ err = expr->ops->offload(&ctx, flow, expr);
+ if (err < 0)
+ goto err_out;
+
+ expr = nft_expr_next(expr);
+ }
+ flow->proto = ctx.dep.l3num;
+
+ return flow;
+err_out:
+ nft_flow_rule_destroy(flow);
+
+ return ERR_PTR(err);
+}
+
+void nft_flow_rule_destroy(struct nft_flow_rule *flow)
+{
+ kfree(flow->rule);
+ kfree(flow);
+}
+
+void nft_offload_set_dependency(struct nft_offload_ctx *ctx,
+ enum nft_offload_dep_type type)
+{
+ ctx->dep.type = type;
+}
+
+void nft_offload_update_dependency(struct nft_offload_ctx *ctx,
+ const void *data, u32 len)
+{
+ switch (ctx->dep.type) {
+ case NFT_OFFLOAD_DEP_NETWORK:
+ WARN_ON(len != sizeof(__u16));
+ memcpy(&ctx->dep.l3num, data, sizeof(__u16));
+ break;
+ case NFT_OFFLOAD_DEP_TRANSPORT:
+ WARN_ON(len != sizeof(__u8));
+ memcpy(&ctx->dep.protonum, data, sizeof(__u8));
+ break;
+ default:
+ break;
+ }
+ ctx->dep.type = NFT_OFFLOAD_DEP_UNSPEC;
+}
+
+static void nft_flow_offload_common_init(struct tc_cls_common_offload *common,
+ __be16 proto,
+ struct netlink_ext_ack *extack)
+{
+ common->protocol = proto;
+ common->extack = extack;
+}
+
+static int nft_setup_cb_call(struct nft_base_chain *basechain,
+ enum tc_setup_type type, void *type_data)
+{
+ struct flow_block_cb *block_cb;
+ int err;
+
+ list_for_each_entry(block_cb, &basechain->cb_list, list) {
+ err = block_cb->cb(type, type_data, block_cb->cb_priv);
+ if (err < 0)
+ return err;
+ }
+ return 0;
+}
+
+static int nft_flow_offload_rule(struct nft_trans *trans,
+ enum tc_fl_command command)
+{
+ struct nft_flow_rule *flow = nft_trans_flow_rule(trans);
+ struct nft_rule *rule = nft_trans_rule(trans);
+ struct tc_cls_flower_offload cls_flower = {};
+ struct nft_base_chain *basechain;
+ struct netlink_ext_ack extack;
+ __be16 proto = ETH_P_ALL;
+
+ if (!nft_is_base_chain(trans->ctx.chain))
+ return -EOPNOTSUPP;
+
+ basechain = nft_base_chain(trans->ctx.chain);
+
+ if (flow)
+ proto = flow->proto;
+
+ nft_flow_offload_common_init(&cls_flower.common, proto, &extack);
+ cls_flower.command = command;
+ cls_flower.cookie = (unsigned long) rule;
+ if (flow)
+ cls_flower.rule = flow->rule;
+
+ return nft_setup_cb_call(basechain, TC_SETUP_CLSFLOWER, &cls_flower);
+}
+
+static int nft_flow_offload_bind(struct flow_block_offload *bo,
+ struct nft_base_chain *basechain)
+{
+ struct flow_block_cb *block_cb;
+
+ list_for_each_entry(block_cb, &bo->cb_list, global_list)
+ list_add(&block_cb->list, &basechain->cb_list);
+
+ flow_block_cb_splice(bo);
+ return 0;
+}
+
+static int nft_flow_offload_unbind(struct flow_block_offload *bo,
+ struct nft_base_chain *basechain)
+{
+ struct flow_block_cb *block_cb, *next;
+
+ list_for_each_entry_safe(block_cb, next, &bo->cb_list, global_list) {
+ list_del(&block_cb->list);
+ flow_block_cb_free(block_cb);
+ }
+
+ return 0;
+}
+
+static int nft_flow_offload_chain(struct nft_trans *trans,
+ enum flow_block_command cmd)
+{
+ struct nft_chain *chain = trans->ctx.chain;
+ struct netlink_ext_ack extack = {};
+ struct flow_block_offload bo = {};
+ struct nft_base_chain *basechain;
+ struct net_device *dev;
+ int err;
+
+ if (!nft_is_base_chain(chain))
+ return -EOPNOTSUPP;
+
+ basechain = nft_base_chain(chain);
+ dev = basechain->ops.dev;
+ if (!dev || !dev->netdev_ops->ndo_setup_tc)
+ return -EOPNOTSUPP;
+
+ /* Only default policy to accept is supported for now. */
+ if (cmd == FLOW_BLOCK_BIND &&
+ nft_trans_chain_policy(trans) != -1 &&
+ nft_trans_chain_policy(trans) != NF_ACCEPT)
+ return -EOPNOTSUPP;
+
+ bo.command = cmd;
+ bo.binder_type = FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS;
+ bo.extack = &extack;
+ INIT_LIST_HEAD(&bo.cb_list);
+
+ err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_BLOCK, &bo);
+ if (err < 0)
+ return err;
+
+ switch (cmd) {
+ case FLOW_BLOCK_BIND:
+ err = nft_flow_offload_bind(&bo, basechain);
+ break;
+ case FLOW_BLOCK_UNBIND:
+ err = nft_flow_offload_unbind(&bo, basechain);
+ break;
+ }
+
+ return err;
+}
+
+int nft_flow_rule_offload_commit(struct net *net)
+{
+ struct nft_trans *trans;
+ int err = 0;
+
+ list_for_each_entry(trans, &net->nft.commit_list, list) {
+ if (trans->ctx.family != NFPROTO_NETDEV ||
+ !(trans->ctx.table->flags & NFT_TABLE_F_HW_OFFLOAD))
+ continue;
+
+ switch (trans->msg_type) {
+ case NFT_MSG_NEWCHAIN:
+ err = nft_flow_offload_chain(trans, FLOW_BLOCK_BIND);
+ break;
+ case NFT_MSG_DELCHAIN:
+ err = nft_flow_offload_chain(trans, FLOW_BLOCK_UNBIND);
+ break;
+ case NFT_MSG_NEWRULE:
+ if (trans->ctx.flags & NLM_F_REPLACE ||
+ !(trans->ctx.flags & NLM_F_APPEND))
+ return -EOPNOTSUPP;
+
+ err = nft_flow_offload_rule(trans,
+ TC_CLSFLOWER_REPLACE);
+ nft_flow_rule_destroy(nft_trans_flow_rule(trans));
+ break;
+ case NFT_MSG_DELRULE:
+ err = nft_flow_offload_rule(trans,
+ TC_CLSFLOWER_DESTROY);
+ break;
+ }
+
+ if (err)
+ return err;
+ }
+
+ return err;
+}
diff --git a/net/netfilter/nft_cmp.c b/net/netfilter/nft_cmp.c
index 411c0cf741e3..bd173b1824c6 100644
--- a/net/netfilter/nft_cmp.c
+++ b/net/netfilter/nft_cmp.c
@@ -12,6 +12,7 @@
#include <linux/netfilter.h>
#include <linux/netfilter/nf_tables.h>
#include <net/netfilter/nf_tables_core.h>
+#include <net/netfilter/nf_tables_offload.h>
#include <net/netfilter/nf_tables.h>
struct nft_cmp_expr {
@@ -107,12 +108,44 @@ static int nft_cmp_dump(struct sk_buff *skb, const struct nft_expr *expr)
return -1;
}
+static int __nft_cmp_offload(struct nft_offload_ctx *ctx,
+ struct nft_flow_rule *flow,
+ const struct nft_cmp_expr *priv)
+{
+ struct nft_offload_reg *reg = &ctx->regs[priv->sreg];
+ u8 *mask = (u8 *)&flow->match.mask;
+ u8 *key = (u8 *)&flow->match.key;
+
+ if (priv->op != NFT_CMP_EQ)
+ return -EOPNOTSUPP;
+
+ memcpy(key + reg->offset, &priv->data, priv->len);
+ memcpy(mask + reg->offset, ®->mask, priv->len);
+
+ flow->match.dissector.used_keys |= BIT(reg->key);
+ flow->match.dissector.offset[reg->key] = reg->base_offset;
+
+ nft_offload_update_dependency(ctx, &priv->data, priv->len);
+
+ return 0;
+}
+
+static int nft_cmp_offload(struct nft_offload_ctx *ctx,
+ struct nft_flow_rule *flow,
+ const struct nft_expr *expr)
+{
+ const struct nft_cmp_expr *priv = nft_expr_priv(expr);
+
+ return __nft_cmp_offload(ctx, flow, priv);
+}
+
static const struct nft_expr_ops nft_cmp_ops = {
.type = &nft_cmp_type,
.size = NFT_EXPR_SIZE(sizeof(struct nft_cmp_expr)),
.eval = nft_cmp_eval,
.init = nft_cmp_init,
.dump = nft_cmp_dump,
+ .offload = nft_cmp_offload,
};
static int nft_cmp_fast_init(const struct nft_ctx *ctx,
@@ -143,6 +176,25 @@ static int nft_cmp_fast_init(const struct nft_ctx *ctx,
return 0;
}
+static int nft_cmp_fast_offload(struct nft_offload_ctx *ctx,
+ struct nft_flow_rule *flow,
+ const struct nft_expr *expr)
+{
+ const struct nft_cmp_fast_expr *priv = nft_expr_priv(expr);
+ struct nft_cmp_expr cmp = {
+ .data = {
+ .data = {
+ [0] = priv->data,
+ },
+ },
+ .sreg = priv->sreg,
+ .len = priv->len / BITS_PER_BYTE,
+ .op = NFT_CMP_EQ,
+ };
+
+ return __nft_cmp_offload(ctx, flow, &cmp);
+}
+
static int nft_cmp_fast_dump(struct sk_buff *skb, const struct nft_expr *expr)
{
const struct nft_cmp_fast_expr *priv = nft_expr_priv(expr);
@@ -169,6 +221,7 @@ const struct nft_expr_ops nft_cmp_fast_ops = {
.eval = NULL, /* inlined */
.init = nft_cmp_fast_init,
.dump = nft_cmp_fast_dump,
+ .offload = nft_cmp_fast_offload,
};
static const struct nft_expr_ops *
diff --git a/net/netfilter/nft_immediate.c b/net/netfilter/nft_immediate.c
index cb8547f97220..ca2ae4b95a8d 100644
--- a/net/netfilter/nft_immediate.c
+++ b/net/netfilter/nft_immediate.c
@@ -13,6 +13,7 @@
#include <linux/netfilter/nf_tables.h>
#include <net/netfilter/nf_tables_core.h>
#include <net/netfilter/nf_tables.h>
+#include <net/netfilter/nf_tables_offload.h>
void nft_immediate_eval(const struct nft_expr *expr,
struct nft_regs *regs,
@@ -124,6 +125,34 @@ static int nft_immediate_validate(const struct nft_ctx *ctx,
return 0;
}
+static int nft_immediate_offload(struct nft_offload_ctx *ctx,
+ struct nft_flow_rule *flow,
+ const struct nft_expr *expr)
+{
+ const struct nft_immediate_expr *priv = nft_expr_priv(expr);
+ struct flow_action_entry *entry;
+ const struct nft_data *data;
+
+ if (priv->dreg != NFT_REG_VERDICT)
+ return -EOPNOTSUPP;
+
+ entry = &flow->rule->action.entries[ctx->num_actions++];
+
+ data = &priv->data;
+ switch (data->verdict.code) {
+ case NF_ACCEPT:
+ entry->id = FLOW_ACTION_ACCEPT;
+ break;
+ case NF_DROP:
+ entry->id = FLOW_ACTION_DROP;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
static const struct nft_expr_ops nft_imm_ops = {
.type = &nft_imm_type,
.size = NFT_EXPR_SIZE(sizeof(struct nft_immediate_expr)),
@@ -133,6 +162,8 @@ static const struct nft_expr_ops nft_imm_ops = {
.deactivate = nft_immediate_deactivate,
.dump = nft_immediate_dump,
.validate = nft_immediate_validate,
+ .offload = nft_immediate_offload,
+ .offload_flags = NFT_OFFLOAD_F_ACTION,
};
struct nft_expr_type nft_imm_type __read_mostly = {
diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c
index a54329b8634a..e92f365aca35 100644
--- a/net/netfilter/nft_meta.c
+++ b/net/netfilter/nft_meta.c
@@ -21,6 +21,7 @@
#include <net/tcp_states.h> /* for TCP_TIME_WAIT */
#include <net/netfilter/nf_tables.h>
#include <net/netfilter/nf_tables_core.h>
+#include <net/netfilter/nf_tables_offload.h>
#include <uapi/linux/netfilter_bridge.h> /* NF_BR_PRE_ROUTING */
@@ -515,6 +516,31 @@ static void nft_meta_set_destroy(const struct nft_ctx *ctx,
static_branch_dec(&nft_trace_enabled);
}
+static int nft_meta_get_offload(struct nft_offload_ctx *ctx,
+ struct nft_flow_rule *flow,
+ const struct nft_expr *expr)
+{
+ const struct nft_meta *priv = nft_expr_priv(expr);
+ struct nft_offload_reg *reg = &ctx->regs[priv->dreg];
+
+ switch (priv->key) {
+ case NFT_META_PROTOCOL:
+ NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_BASIC, basic, n_proto,
+ sizeof(__u16), reg);
+ nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_NETWORK);
+ break;
+ case NFT_META_L4PROTO:
+ NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_BASIC, basic, ip_proto,
+ sizeof(__u8), reg);
+ nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_TRANSPORT);
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
static const struct nft_expr_ops nft_meta_get_ops = {
.type = &nft_meta_type,
.size = NFT_EXPR_SIZE(sizeof(struct nft_meta)),
@@ -522,6 +548,7 @@ static const struct nft_expr_ops nft_meta_get_ops = {
.init = nft_meta_get_init,
.dump = nft_meta_get_dump,
.validate = nft_meta_get_validate,
+ .offload = nft_meta_get_offload,
};
static const struct nft_expr_ops nft_meta_set_ops = {
diff --git a/net/netfilter/nft_payload.c b/net/netfilter/nft_payload.c
index 1260f78a034d..22a80eb60222 100644
--- a/net/netfilter/nft_payload.c
+++ b/net/netfilter/nft_payload.c
@@ -15,10 +15,13 @@
#include <linux/netfilter/nf_tables.h>
#include <net/netfilter/nf_tables_core.h>
#include <net/netfilter/nf_tables.h>
+#include <net/netfilter/nf_tables_offload.h>
/* For layer 4 checksum field offset. */
#include <linux/tcp.h>
#include <linux/udp.h>
#include <linux/icmpv6.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
/* add vlan header into the user buffer for if tag was removed by offloads */
static bool
@@ -150,12 +153,195 @@ static int nft_payload_dump(struct sk_buff *skb, const struct nft_expr *expr)
return -1;
}
+static int nft_payload_offload_ll(struct nft_offload_ctx *ctx,
+ struct nft_flow_rule *flow,
+ const struct nft_payload *priv)
+{
+ struct nft_offload_reg *reg = &ctx->regs[priv->dreg];
+
+ switch (priv->offset) {
+ case offsetof(struct ethhdr, h_source):
+ NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_ETH_ADDRS, eth_addrs,
+ src, ETH_ALEN, reg);
+ break;
+ case offsetof(struct ethhdr, h_dest):
+ NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_ETH_ADDRS, eth_addrs,
+ dst, ETH_ALEN, reg);
+ break;
+ }
+
+ return 0;
+}
+
+static int nft_payload_offload_ip(struct nft_offload_ctx *ctx,
+ struct nft_flow_rule *flow,
+ const struct nft_payload *priv)
+{
+ struct nft_offload_reg *reg = &ctx->regs[priv->dreg];
+
+ switch (priv->offset) {
+ case offsetof(struct iphdr, saddr):
+ NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV4_ADDRS, ipv4, src,
+ sizeof(struct in_addr), reg);
+ break;
+ case offsetof(struct iphdr, daddr):
+ NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV4_ADDRS, ipv4, dst,
+ sizeof(struct in_addr), reg);
+ break;
+ case offsetof(struct iphdr, protocol):
+ NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_BASIC, basic, ip_proto,
+ sizeof(__u8), reg);
+ nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_TRANSPORT);
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+static int nft_payload_offload_ip6(struct nft_offload_ctx *ctx,
+ struct nft_flow_rule *flow,
+ const struct nft_payload *priv)
+{
+ struct nft_offload_reg *reg = &ctx->regs[priv->dreg];
+
+ switch (priv->offset) {
+ case offsetof(struct ipv6hdr, saddr):
+ NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV6_ADDRS, ipv6, src,
+ sizeof(struct in6_addr), reg);
+ break;
+ case offsetof(struct ipv6hdr, daddr):
+ NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV6_ADDRS, ipv6, dst,
+ sizeof(struct in6_addr), reg);
+ break;
+ case offsetof(struct ipv6hdr, nexthdr):
+ NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_BASIC, basic, ip_proto,
+ sizeof(__u8), reg);
+ nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_TRANSPORT);
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+static int nft_payload_offload_nh(struct nft_offload_ctx *ctx,
+ struct nft_flow_rule *flow,
+ const struct nft_payload *priv)
+{
+ int err;
+
+ switch (ctx->dep.l3num) {
+ case htons(ETH_P_IP):
+ err = nft_payload_offload_ip(ctx, flow, priv);
+ break;
+ case htons(ETH_P_IPV6):
+ err = nft_payload_offload_ip6(ctx, flow, priv);
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return err;
+}
+
+static int nft_payload_offload_tcp(struct nft_offload_ctx *ctx,
+ struct nft_flow_rule *flow,
+ const struct nft_payload *priv)
+{
+ struct nft_offload_reg *reg = &ctx->regs[priv->dreg];
+
+ switch (priv->offset) {
+ case offsetof(struct tcphdr, source):
+ NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, src,
+ sizeof(__be16), reg);
+ break;
+ case offsetof(struct tcphdr, dest):
+ NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, dst,
+ sizeof(__be16), reg);
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+static int nft_payload_offload_udp(struct nft_offload_ctx *ctx,
+ struct nft_flow_rule *flow,
+ const struct nft_payload *priv)
+{
+ struct nft_offload_reg *reg = &ctx->regs[priv->dreg];
+
+ switch (priv->offset) {
+ case offsetof(struct udphdr, source):
+ NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, src,
+ sizeof(__be16), reg);
+ break;
+ case offsetof(struct udphdr, dest):
+ NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, dst,
+ sizeof(__be16), reg);
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+static int nft_payload_offload_th(struct nft_offload_ctx *ctx,
+ struct nft_flow_rule *flow,
+ const struct nft_payload *priv)
+{
+ int err;
+
+ switch (ctx->dep.protonum) {
+ case IPPROTO_TCP:
+ err = nft_payload_offload_tcp(ctx, flow, priv);
+ break;
+ case IPPROTO_UDP:
+ err = nft_payload_offload_udp(ctx, flow, priv);
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return err;
+}
+
+static int nft_payload_offload(struct nft_offload_ctx *ctx,
+ struct nft_flow_rule *flow,
+ const struct nft_expr *expr)
+{
+ const struct nft_payload *priv = nft_expr_priv(expr);
+ int err;
+
+ switch (priv->base) {
+ case NFT_PAYLOAD_LL_HEADER:
+ err = nft_payload_offload_ll(ctx, flow, priv);
+ break;
+ case NFT_PAYLOAD_NETWORK_HEADER:
+ err = nft_payload_offload_nh(ctx, flow, priv);
+ break;
+ case NFT_PAYLOAD_TRANSPORT_HEADER:
+ err = nft_payload_offload_th(ctx, flow, priv);
+ break;
+ default:
+ err = -EOPNOTSUPP;
+ break;
+ }
+ return err;
+}
+
static const struct nft_expr_ops nft_payload_ops = {
.type = &nft_payload_type,
.size = NFT_EXPR_SIZE(sizeof(struct nft_payload)),
.eval = nft_payload_eval,
.init = nft_payload_init,
.dump = nft_payload_dump,
+ .offload = nft_payload_offload,
};
const struct nft_expr_ops nft_payload_fast_ops = {
@@ -164,6 +350,7 @@ const struct nft_expr_ops nft_payload_fast_ops = {
.eval = nft_payload_eval,
.init = nft_payload_init,
.dump = nft_payload_dump,
+ .offload = nft_payload_offload,
};
static inline void nft_csum_replace(__sum16 *sum, __wsum fsum, __wsum tsum)
--
2.11.0
^ permalink raw reply related [flat|nested] 21+ messages in thread