* [PATCH net-next v11 1/5] net: sched: act_api: Introduce P4 actions list
2024-02-23 13:17 [PATCH net-next v11 0/5] Introducing P4TC (series 1) Jamal Hadi Salim
@ 2024-02-23 13:17 ` Jamal Hadi Salim
2024-02-23 13:17 ` [PATCH net-next v11 2/5] net/sched: act_api: increase action kind string length Jamal Hadi Salim
` (4 subsequent siblings)
5 siblings, 0 replies; 9+ messages in thread
From: Jamal Hadi Salim @ 2024-02-23 13:17 UTC (permalink / raw)
To: netdev
Cc: deb.chatterjee, anjali.singhai, namrata.limaye, tom, mleitner,
Mahesh.Shirshyad, Vipin.Jain, tomasz.osinski, jiri,
xiyou.wangcong, davem, edumazet, kuba, pabeni, vladbu, horms,
khalidm, toke, mattyk, daniel, bpf, pctammela, victor
In P4 we require to generate new actions "on the fly" based on the
specified P4 action definition. P4 action kinds, like the pipeline
they are attached to, must be per net namespace, as opposed to native
action kinds which are global. For that reason, we chose to create a
separate structure to store P4 actions.
Co-developed-by: Victor Nogueira <victor@mojatatu.com>
Signed-off-by: Victor Nogueira <victor@mojatatu.com>
Co-developed-by: Pedro Tammela <pctammela@mojatatu.com>
Signed-off-by: Pedro Tammela <pctammela@mojatatu.com>
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
Reviewed-by: Vlad Buslov <vladbu@nvidia.com>
Reviewed-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
---
include/net/act_api.h | 8 ++-
net/sched/act_api.c | 123 +++++++++++++++++++++++++++++++++++++-----
net/sched/cls_api.c | 2 +-
3 files changed, 116 insertions(+), 17 deletions(-)
diff --git a/include/net/act_api.h b/include/net/act_api.h
index 77ee0c657..f22be14bb 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -105,6 +105,7 @@ typedef void (*tc_action_priv_destructor)(void *priv);
struct tc_action_ops {
struct list_head head;
+ struct list_head p4_head;
char kind[IFNAMSIZ];
enum tca_id id; /* identifier should match kind */
unsigned int net_id;
@@ -199,10 +200,12 @@ int tcf_idr_check_alloc(struct tc_action_net *tn, u32 *index,
int tcf_idr_release(struct tc_action *a, bool bind);
int tcf_register_action(struct tc_action_ops *a, struct pernet_operations *ops);
+int tcf_register_p4_action(struct net *net, struct tc_action_ops *act);
int tcf_unregister_action(struct tc_action_ops *a,
struct pernet_operations *ops);
#define NET_ACT_ALIAS_PREFIX "net-act-"
#define MODULE_ALIAS_NET_ACT(kind) MODULE_ALIAS(NET_ACT_ALIAS_PREFIX kind)
+void tcf_unregister_p4_action(struct net *net, struct tc_action_ops *act);
int tcf_action_destroy(struct tc_action *actions[], int bind);
int tcf_action_exec(struct sk_buff *skb, struct tc_action **actions,
int nr_actions, struct tcf_result *res);
@@ -210,8 +213,9 @@ int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
struct nlattr *est,
struct tc_action *actions[], int init_res[], size_t *attr_size,
u32 flags, u32 fl_flags, struct netlink_ext_ack *extack);
-struct tc_action_ops *tc_action_load_ops(struct nlattr *nla, u32 flags,
- struct netlink_ext_ack *extack);
+struct tc_action_ops *
+tc_action_load_ops(struct net *net, struct nlattr *nla,
+ u32 flags, struct netlink_ext_ack *extack);
struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
struct nlattr *nla, struct nlattr *est,
struct tc_action_ops *a_o, int *init_res,
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 9ee622fb1..23ef394f2 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -57,6 +57,40 @@ static void tcf_free_cookie_rcu(struct rcu_head *p)
kfree(cookie);
}
+static unsigned int p4_act_net_id;
+
+struct tcf_p4_act_net {
+ struct list_head act_base;
+ rwlock_t act_mod_lock;
+};
+
+static __net_init int tcf_p4_act_base_init_net(struct net *net)
+{
+ struct tcf_p4_act_net *p4_base_net = net_generic(net, p4_act_net_id);
+
+ INIT_LIST_HEAD(&p4_base_net->act_base);
+ rwlock_init(&p4_base_net->act_mod_lock);
+
+ return 0;
+}
+
+static void __net_exit tcf_p4_act_base_exit_net(struct net *net)
+{
+ struct tcf_p4_act_net *p4_base_net = net_generic(net, p4_act_net_id);
+ struct tc_action_ops *ops, *tmp;
+
+ list_for_each_entry_safe(ops, tmp, &p4_base_net->act_base, p4_head) {
+ list_del(&ops->p4_head);
+ }
+}
+
+static struct pernet_operations tcf_p4_act_base_net_ops = {
+ .init = tcf_p4_act_base_init_net,
+ .exit = tcf_p4_act_base_exit_net,
+ .id = &p4_act_net_id,
+ .size = sizeof(struct tc_action_ops),
+};
+
static void tcf_set_action_cookie(struct tc_cookie __rcu **old_cookie,
struct tc_cookie *new_cookie)
{
@@ -962,6 +996,48 @@ static void tcf_pernet_del_id_list(unsigned int id)
mutex_unlock(&act_id_mutex);
}
+static struct tc_action_ops *tc_lookup_p4_action(struct net *net, char *kind)
+{
+ struct tcf_p4_act_net *p4_base_net = net_generic(net, p4_act_net_id);
+ struct tc_action_ops *a, *res = NULL;
+
+ read_lock(&p4_base_net->act_mod_lock);
+ list_for_each_entry(a, &p4_base_net->act_base, p4_head) {
+ if (strcmp(kind, a->kind) == 0) {
+ if (try_module_get(a->owner))
+ res = a;
+ break;
+ }
+ }
+ read_unlock(&p4_base_net->act_mod_lock);
+
+ return res;
+}
+
+void tcf_unregister_p4_action(struct net *net, struct tc_action_ops *act)
+{
+ struct tcf_p4_act_net *p4_base_net = net_generic(net, p4_act_net_id);
+
+ write_lock(&p4_base_net->act_mod_lock);
+ list_del(&act->p4_head);
+ write_unlock(&p4_base_net->act_mod_lock);
+}
+EXPORT_SYMBOL(tcf_unregister_p4_action);
+
+int tcf_register_p4_action(struct net *net, struct tc_action_ops *act)
+{
+ struct tcf_p4_act_net *p4_base_net = net_generic(net, p4_act_net_id);
+
+ if (tc_lookup_p4_action(net, act->kind))
+ return -EEXIST;
+
+ write_lock(&p4_base_net->act_mod_lock);
+ list_add(&act->p4_head, &p4_base_net->act_base);
+ write_unlock(&p4_base_net->act_mod_lock);
+
+ return 0;
+}
+
int tcf_register_action(struct tc_action_ops *act,
struct pernet_operations *ops)
{
@@ -1032,7 +1108,7 @@ int tcf_unregister_action(struct tc_action_ops *act,
EXPORT_SYMBOL(tcf_unregister_action);
/* lookup by name */
-static struct tc_action_ops *tc_lookup_action_n(char *kind)
+static struct tc_action_ops *tc_lookup_action_n(struct net *net, char *kind)
{
struct tc_action_ops *a, *res = NULL;
@@ -1040,31 +1116,48 @@ static struct tc_action_ops *tc_lookup_action_n(char *kind)
read_lock(&act_mod_lock);
list_for_each_entry(a, &act_base, head) {
if (strcmp(kind, a->kind) == 0) {
- if (try_module_get(a->owner))
- res = a;
- break;
+ if (try_module_get(a->owner)) {
+ read_unlock(&act_mod_lock);
+ return a;
+ }
}
}
read_unlock(&act_mod_lock);
+
+ return tc_lookup_p4_action(net, kind);
}
+
return res;
}
/* lookup by nlattr */
-static struct tc_action_ops *tc_lookup_action(struct nlattr *kind)
+static struct tc_action_ops *tc_lookup_action(struct net *net,
+ struct nlattr *kind)
{
+ struct tcf_p4_act_net *p4_base_net = net_generic(net, p4_act_net_id);
struct tc_action_ops *a, *res = NULL;
if (kind) {
read_lock(&act_mod_lock);
list_for_each_entry(a, &act_base, head) {
+ if (nla_strcmp(kind, a->kind) == 0) {
+ if (try_module_get(a->owner)) {
+ read_unlock(&act_mod_lock);
+ return a;
+ }
+ }
+ }
+ read_unlock(&act_mod_lock);
+
+ read_lock(&p4_base_net->act_mod_lock);
+ list_for_each_entry(a, &p4_base_net->act_base, p4_head) {
if (nla_strcmp(kind, a->kind) == 0) {
if (try_module_get(a->owner))
res = a;
break;
}
}
- read_unlock(&act_mod_lock);
+ read_unlock(&p4_base_net->act_mod_lock);
}
return res;
}
@@ -1324,8 +1417,9 @@ void tcf_idr_insert_many(struct tc_action *actions[], int init_res[])
}
}
-struct tc_action_ops *tc_action_load_ops(struct nlattr *nla, u32 flags,
- struct netlink_ext_ack *extack)
+struct tc_action_ops *
+tc_action_load_ops(struct net *net, struct nlattr *nla,
+ u32 flags, struct netlink_ext_ack *extack)
{
bool police = flags & TCA_ACT_FLAGS_POLICE;
struct nlattr *tb[TCA_ACT_MAX + 1];
@@ -1356,7 +1450,7 @@ struct tc_action_ops *tc_action_load_ops(struct nlattr *nla, u32 flags,
}
}
- a_o = tc_lookup_action_n(act_name);
+ a_o = tc_lookup_action_n(net, act_name);
if (a_o == NULL) {
#ifdef CONFIG_MODULES
bool rtnl_held = !(flags & TCA_ACT_FLAGS_NO_RTNL);
@@ -1367,7 +1461,7 @@ struct tc_action_ops *tc_action_load_ops(struct nlattr *nla, u32 flags,
if (rtnl_held)
rtnl_lock();
- a_o = tc_lookup_action_n(act_name);
+ a_o = tc_lookup_action_n(net, act_name);
/* We dropped the RTNL semaphore in order to
* perform the module load. So, even if we
@@ -1477,7 +1571,7 @@ int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) {
struct tc_action_ops *a_o;
- a_o = tc_action_load_ops(tb[i], flags, extack);
+ a_o = tc_action_load_ops(net, tb[i], flags, extack);
if (IS_ERR(a_o)) {
err = PTR_ERR(a_o);
goto err_mod;
@@ -1683,7 +1777,7 @@ static struct tc_action *tcf_action_get_1(struct net *net, struct nlattr *nla,
index = nla_get_u32(tb[TCA_ACT_INDEX]);
err = -EINVAL;
- ops = tc_lookup_action(tb[TCA_ACT_KIND]);
+ ops = tc_lookup_action(net, tb[TCA_ACT_KIND]);
if (!ops) { /* could happen in batch of actions */
NL_SET_ERR_MSG(extack, "Specified TC action kind not found");
goto err_out;
@@ -1731,7 +1825,7 @@ static int tca_action_flush(struct net *net, struct nlattr *nla,
err = -EINVAL;
kind = tb[TCA_ACT_KIND];
- ops = tc_lookup_action(kind);
+ ops = tc_lookup_action(net, kind);
if (!ops) { /*some idjot trying to flush unknown action */
NL_SET_ERR_MSG(extack, "Cannot flush unknown TC action");
goto err_out;
@@ -2184,7 +2278,7 @@ static int tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb)
return 0;
}
- a_o = tc_lookup_action(kind);
+ a_o = tc_lookup_action(net, kind);
if (a_o == NULL)
return 0;
@@ -2251,6 +2345,7 @@ static int __init tc_action_init(void)
rtnl_register(PF_UNSPEC, RTM_GETACTION, tc_ctl_action, tc_dump_action,
0);
+ register_pernet_subsys(&tcf_p4_act_base_net_ops);
return 0;
}
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index ca5676b26..142f49a2c 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -3330,7 +3330,7 @@ int tcf_exts_validate_ex(struct net *net, struct tcf_proto *tp, struct nlattr **
struct tc_action_ops *a_o;
flags |= TCA_ACT_FLAGS_POLICE | TCA_ACT_FLAGS_BIND;
- a_o = tc_action_load_ops(tb[exts->police], flags,
+ a_o = tc_action_load_ops(net, tb[exts->police], flags,
extack);
if (IS_ERR(a_o))
return PTR_ERR(a_o);
--
2.34.1
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH net-next v11 2/5] net/sched: act_api: increase action kind string length
2024-02-23 13:17 [PATCH net-next v11 0/5] Introducing P4TC (series 1) Jamal Hadi Salim
2024-02-23 13:17 ` [PATCH net-next v11 1/5] net: sched: act_api: Introduce P4 actions list Jamal Hadi Salim
@ 2024-02-23 13:17 ` Jamal Hadi Salim
2024-02-23 13:17 ` [PATCH net-next v11 3/5] net/sched: act_api: Update tc_action_ops to account for P4 actions Jamal Hadi Salim
` (3 subsequent siblings)
5 siblings, 0 replies; 9+ messages in thread
From: Jamal Hadi Salim @ 2024-02-23 13:17 UTC (permalink / raw)
To: netdev
Cc: deb.chatterjee, anjali.singhai, namrata.limaye, tom, mleitner,
Mahesh.Shirshyad, Vipin.Jain, tomasz.osinski, jiri,
xiyou.wangcong, davem, edumazet, kuba, pabeni, vladbu, horms,
khalidm, toke, mattyk, daniel, bpf, pctammela, victor
Increase action kind string length from IFNAMSIZ to 64
The new P4 actions, created via templates, will have longer names
of format: "pipeline_name/act_name". IFNAMSIZ is currently 16 and is most
of the times undersized for the above format.
So, to conform to this new format, we increase the maximum name length
and change its definition from IFNAMSIZ to ACTNAMSIZ to account for this
extra string (pipeline name) and the '/' character.
Co-developed-by: Victor Nogueira <victor@mojatatu.com>
Signed-off-by: Victor Nogueira <victor@mojatatu.com>
Co-developed-by: Pedro Tammela <pctammela@mojatatu.com>
Signed-off-by: Pedro Tammela <pctammela@mojatatu.com>
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
Reviewed-by: Vlad Buslov <vladbu@nvidia.com>
Reviewed-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
---
include/net/act_api.h | 2 +-
include/uapi/linux/pkt_cls.h | 1 +
net/sched/act_api.c | 8 ++++----
3 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/include/net/act_api.h b/include/net/act_api.h
index f22be14bb..c839ff57c 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -106,7 +106,7 @@ typedef void (*tc_action_priv_destructor)(void *priv);
struct tc_action_ops {
struct list_head head;
struct list_head p4_head;
- char kind[IFNAMSIZ];
+ char kind[ACTNAMSIZ];
enum tca_id id; /* identifier should match kind */
unsigned int net_id;
size_t size;
diff --git a/include/uapi/linux/pkt_cls.h b/include/uapi/linux/pkt_cls.h
index ea277039f..dd313a727 100644
--- a/include/uapi/linux/pkt_cls.h
+++ b/include/uapi/linux/pkt_cls.h
@@ -6,6 +6,7 @@
#include <linux/pkt_sched.h>
#define TC_COOKIE_MAX_SIZE 16
+#define ACTNAMSIZ 64
/* Action attributes */
enum {
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 23ef394f2..ce10d2c6e 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -476,7 +476,7 @@ static size_t tcf_action_shared_attrs_size(const struct tc_action *act)
rcu_read_unlock();
return nla_total_size(0) /* action number nested */
- + nla_total_size(IFNAMSIZ) /* TCA_ACT_KIND */
+ + nla_total_size(ACTNAMSIZ) /* TCA_ACT_KIND */
+ cookie_len /* TCA_ACT_COOKIE */
+ nla_total_size(sizeof(struct nla_bitfield32)) /* TCA_ACT_HW_STATS */
+ nla_total_size(0) /* TCA_ACT_STATS nested */
@@ -1424,7 +1424,7 @@ tc_action_load_ops(struct net *net, struct nlattr *nla,
bool police = flags & TCA_ACT_FLAGS_POLICE;
struct nlattr *tb[TCA_ACT_MAX + 1];
struct tc_action_ops *a_o;
- char act_name[IFNAMSIZ];
+ char act_name[ACTNAMSIZ];
struct nlattr *kind;
int err;
@@ -1439,12 +1439,12 @@ tc_action_load_ops(struct net *net, struct nlattr *nla,
NL_SET_ERR_MSG(extack, "TC action kind must be specified");
return ERR_PTR(err);
}
- if (nla_strscpy(act_name, kind, IFNAMSIZ) < 0) {
+ if (nla_strscpy(act_name, kind, ACTNAMSIZ) < 0) {
NL_SET_ERR_MSG(extack, "TC action name too long");
return ERR_PTR(err);
}
} else {
- if (strscpy(act_name, "police", IFNAMSIZ) < 0) {
+ if (strscpy(act_name, "police", ACTNAMSIZ) < 0) {
NL_SET_ERR_MSG(extack, "TC action name too long");
return ERR_PTR(-EINVAL);
}
--
2.34.1
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH net-next v11 3/5] net/sched: act_api: Update tc_action_ops to account for P4 actions
2024-02-23 13:17 [PATCH net-next v11 0/5] Introducing P4TC (series 1) Jamal Hadi Salim
2024-02-23 13:17 ` [PATCH net-next v11 1/5] net: sched: act_api: Introduce P4 actions list Jamal Hadi Salim
2024-02-23 13:17 ` [PATCH net-next v11 2/5] net/sched: act_api: increase action kind string length Jamal Hadi Salim
@ 2024-02-23 13:17 ` Jamal Hadi Salim
2024-02-23 13:17 ` [PATCH net-next v11 4/5] net/sched: act_api: add struct p4tc_action_ops as a parameter to lookup callback Jamal Hadi Salim
` (2 subsequent siblings)
5 siblings, 0 replies; 9+ messages in thread
From: Jamal Hadi Salim @ 2024-02-23 13:17 UTC (permalink / raw)
To: netdev
Cc: deb.chatterjee, anjali.singhai, namrata.limaye, tom, mleitner,
Mahesh.Shirshyad, Vipin.Jain, tomasz.osinski, jiri,
xiyou.wangcong, davem, edumazet, kuba, pabeni, vladbu, horms,
khalidm, toke, mattyk, daniel, bpf, pctammela, victor
The initialisation of P4TC action instances require access to a struct
p4tc_act (which appears in later patches) to help us to retrieve
information like the P4 action parameters etc. In order to retrieve
struct p4tc_act we need the pipeline name or id and the action name or id.
Also recall that P4TC action IDs are P4 and are net namespace specific and
not global like standard tc actions.
The init callback from tc_action_ops parameters had no way of
supplying us that information. To solve this issue, we decided to create a
new tc_action_ops callback (init_ops), that provies us with the
tc_action_ops struct which then provides us with the pipeline and action
name. In addition we add a new refcount to struct tc_action_ops called
dyn_ref, which accounts for how many action instances we have of a specific
action.
Co-developed-by: Victor Nogueira <victor@mojatatu.com>
Signed-off-by: Victor Nogueira <victor@mojatatu.com>
Co-developed-by: Pedro Tammela <pctammela@mojatatu.com>
Signed-off-by: Pedro Tammela <pctammela@mojatatu.com>
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
Reviewed-by: Vlad Buslov <vladbu@nvidia.com>
Reviewed-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
---
include/net/act_api.h | 6 ++++++
net/sched/act_api.c | 14 +++++++++++---
2 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/include/net/act_api.h b/include/net/act_api.h
index c839ff57c..69be5ed83 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -109,6 +109,7 @@ struct tc_action_ops {
char kind[ACTNAMSIZ];
enum tca_id id; /* identifier should match kind */
unsigned int net_id;
+ refcount_t p4_ref;
size_t size;
struct module *owner;
int (*act)(struct sk_buff *, const struct tc_action *,
@@ -120,6 +121,11 @@ struct tc_action_ops {
struct nlattr *est, struct tc_action **act,
struct tcf_proto *tp,
u32 flags, struct netlink_ext_ack *extack);
+ /* This should be merged with the original init action */
+ int (*init_ops)(struct net *net, struct nlattr *nla,
+ struct nlattr *est, struct tc_action **act,
+ struct tcf_proto *tp, struct tc_action_ops *ops,
+ u32 flags, struct netlink_ext_ack *extack);
int (*walk)(struct net *, struct sk_buff *,
struct netlink_callback *, int,
const struct tc_action_ops *,
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index ce10d2c6e..3d1fb8da1 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -1044,7 +1044,7 @@ int tcf_register_action(struct tc_action_ops *act,
struct tc_action_ops *a;
int ret;
- if (!act->act || !act->dump || !act->init)
+ if (!act->act || !act->dump || (!act->init && !act->init_ops))
return -EINVAL;
/* We have to register pernet ops before making the action ops visible,
@@ -1517,8 +1517,16 @@ struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
}
}
- err = a_o->init(net, tb[TCA_ACT_OPTIONS], est, &a, tp,
- userflags.value | flags, extack);
+ /* When we arrive here we guarantee that a_o->init or
+ * a_o->init_ops exist.
+ */
+ if (a_o->init)
+ err = a_o->init(net, tb[TCA_ACT_OPTIONS], est, &a, tp,
+ userflags.value | flags, extack);
+ else
+ err = a_o->init_ops(net, tb[TCA_ACT_OPTIONS], est, &a,
+ tp, a_o, userflags.value | flags,
+ extack);
} else {
err = a_o->init(net, nla, est, &a, tp, userflags.value | flags,
extack);
--
2.34.1
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH net-next v11 4/5] net/sched: act_api: add struct p4tc_action_ops as a parameter to lookup callback
2024-02-23 13:17 [PATCH net-next v11 0/5] Introducing P4TC (series 1) Jamal Hadi Salim
` (2 preceding siblings ...)
2024-02-23 13:17 ` [PATCH net-next v11 3/5] net/sched: act_api: Update tc_action_ops to account for P4 actions Jamal Hadi Salim
@ 2024-02-23 13:17 ` Jamal Hadi Salim
2024-02-23 13:17 ` [PATCH net-next v11 5/5] net: sched: act_api: Add support for preallocated P4 action instances Jamal Hadi Salim
2024-02-23 15:38 ` [PATCH net-next v11 0/5] Introducing P4TC (series 1) Jakub Kicinski
5 siblings, 0 replies; 9+ messages in thread
From: Jamal Hadi Salim @ 2024-02-23 13:17 UTC (permalink / raw)
To: netdev
Cc: deb.chatterjee, anjali.singhai, namrata.limaye, tom, mleitner,
Mahesh.Shirshyad, Vipin.Jain, tomasz.osinski, jiri,
xiyou.wangcong, davem, edumazet, kuba, pabeni, vladbu, horms,
khalidm, toke, mattyk, daniel, bpf, pctammela, victor
For P4 actions, we require information from struct tc_action_ops,
specifically the action kind, to find and locate the P4 action information
for the lookup operation.
Co-developed-by: Victor Nogueira <victor@mojatatu.com>
Signed-off-by: Victor Nogueira <victor@mojatatu.com>
Co-developed-by: Pedro Tammela <pctammela@mojatatu.com>
Signed-off-by: Pedro Tammela <pctammela@mojatatu.com>
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
Reviewed-by: Vlad Buslov <vladbu@nvidia.com>
Reviewed-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
---
include/net/act_api.h | 3 ++-
net/sched/act_api.c | 2 +-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/include/net/act_api.h b/include/net/act_api.h
index 69be5ed83..49f471c58 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -116,7 +116,8 @@ struct tc_action_ops {
struct tcf_result *); /* called under RCU BH lock*/
int (*dump)(struct sk_buff *, struct tc_action *, int, int);
void (*cleanup)(struct tc_action *);
- int (*lookup)(struct net *net, struct tc_action **a, u32 index);
+ int (*lookup)(struct net *net, const struct tc_action_ops *ops,
+ struct tc_action **a, u32 index);
int (*init)(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **act,
struct tcf_proto *tp,
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 3d1fb8da1..835ead746 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -726,7 +726,7 @@ static int __tcf_idr_search(struct net *net,
struct tc_action_net *tn = net_generic(net, ops->net_id);
if (unlikely(ops->lookup))
- return ops->lookup(net, a, index);
+ return ops->lookup(net, ops, a, index);
return tcf_idr_search(tn, a, index);
}
--
2.34.1
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH net-next v11 5/5] net: sched: act_api: Add support for preallocated P4 action instances
2024-02-23 13:17 [PATCH net-next v11 0/5] Introducing P4TC (series 1) Jamal Hadi Salim
` (3 preceding siblings ...)
2024-02-23 13:17 ` [PATCH net-next v11 4/5] net/sched: act_api: add struct p4tc_action_ops as a parameter to lookup callback Jamal Hadi Salim
@ 2024-02-23 13:17 ` Jamal Hadi Salim
2024-02-23 15:38 ` [PATCH net-next v11 0/5] Introducing P4TC (series 1) Jakub Kicinski
5 siblings, 0 replies; 9+ messages in thread
From: Jamal Hadi Salim @ 2024-02-23 13:17 UTC (permalink / raw)
To: netdev
Cc: deb.chatterjee, anjali.singhai, namrata.limaye, tom, mleitner,
Mahesh.Shirshyad, Vipin.Jain, tomasz.osinski, jiri,
xiyou.wangcong, davem, edumazet, kuba, pabeni, vladbu, horms,
khalidm, toke, mattyk, daniel, bpf, pctammela, victor
In P4, actions are assumed to pre exist and have an upper bound number of
instances. Typically if you a table defined with 1M table entries you want
to allocate enough action instances to cover the 1M entries. However, this
is a big waste of memory if the action instances are not in use. So for our
case, we allow the user to specify a minimal amount of actions in the
template and then if more P4 action instances are needed then they will be
added on demand as in the current approach with tc filter-action
relationship.
Add the necessary code to preallocate actions instances for P4
actions.
We add 2 new actions flags:
- TCA_ACT_FLAGS_PREALLOC: Indicates the action instance is a P4 action
and was preallocated for future use the templating phase of P4TC
- TCA_ACT_FLAGS_UNREFERENCED: Indicates the action instance was
preallocated and is currently not being referenced by any other object.
Which means it won't show up in an action instance dump.
Once an action instance is created we don't free it when the last table
entry referring to it is deleted.
Instead we add it to the pool/cache of action instances for that specific
action kind i.e it counts as if it is preallocated.
Preallocated actions can't be deleted by the tc actions runtime commands
and a dump or a get will only show preallocated actions instances which are
being used (i.e TCA_ACT_FLAGS_UNREFERENCED == false).
The preallocated actions will be deleted once the pipeline is deleted
(which will purge the P4 action kind and its instances).
For example, if we were to create a P4 action that preallocates 128
elements and dumped:
$ tc -j p4template get action/myprog/send_nh | jq .
We'd see the following:
[
{
"obj": "action template",
"pname": "myprog",
"pipeid": 1
},
{
"templates": [
{
"aname": "myprog/send_nh",
"actid": 1,
"params": [
{
"name": "port",
"type": "dev",
"id": 1
}
],
"prealloc": 128
}
]
}
]
If we try to dump the P4 action instances, we won't see any:
$ tc -j actions ls action myprog/send_nh | jq .
[]
However, if we create a table entry which references this action kind:
$ tc p4ctrl create myprog/table/cb/FDB \
dstAddr d2:96:91:5d:02:86 action myprog/send_nh \
param port type dev dummy0
Dumping the action instance will now show this one instance which is
associated with the table entry:
$ tc -j actions ls action myprog/send_nh | jq .
[
{
"total acts": 1
},
{
"actions": [
{
"order": 0,
"kind": "myprog/send_nh",
"index": 1,
"ref": 1,
"bind": 1,
"params": [
{
"name": "port",
"type": "dev",
"value": "dummy0",
"id": 1
}
],
"not_in_hw": true
}
]
}
]
Co-developed-by: Victor Nogueira <victor@mojatatu.com>
Signed-off-by: Victor Nogueira <victor@mojatatu.com>
Co-developed-by: Pedro Tammela <pctammela@mojatatu.com>
Signed-off-by: Pedro Tammela <pctammela@mojatatu.com>
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
Reviewed-by: Vlad Buslov <vladbu@nvidia.com>
Reviewed-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
---
include/net/act_api.h | 3 +++
net/sched/act_api.c | 45 +++++++++++++++++++++++++++++++++++--------
2 files changed, 40 insertions(+), 8 deletions(-)
diff --git a/include/net/act_api.h b/include/net/act_api.h
index 49f471c58..d35870fbf 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -68,6 +68,8 @@ struct tc_action {
#define TCA_ACT_FLAGS_REPLACE (1U << (TCA_ACT_FLAGS_USER_BITS + 2))
#define TCA_ACT_FLAGS_NO_RTNL (1U << (TCA_ACT_FLAGS_USER_BITS + 3))
#define TCA_ACT_FLAGS_AT_INGRESS (1U << (TCA_ACT_FLAGS_USER_BITS + 4))
+#define TCA_ACT_FLAGS_PREALLOC (1U << (TCA_ACT_FLAGS_USER_BITS + 5))
+#define TCA_ACT_FLAGS_UNREFERENCED (1U << (TCA_ACT_FLAGS_USER_BITS + 6))
/* Update lastuse only if needed, to avoid dirtying a cache line.
* We use a temp variable to avoid fetching jiffies twice.
@@ -201,6 +203,7 @@ int tcf_idr_create_from_flags(struct tc_action_net *tn, u32 index,
const struct tc_action_ops *ops, int bind,
u32 flags);
void tcf_idr_insert_many(struct tc_action *actions[], int init_res[]);
+void tcf_idr_insert_n(struct tc_action *actions[], const u32 n);
void tcf_idr_cleanup(struct tc_action_net *tn, u32 index);
int tcf_idr_check_alloc(struct tc_action_net *tn, u32 *index,
struct tc_action **a, int bind);
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 835ead746..418e44235 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -560,6 +560,8 @@ static int tcf_dump_walker(struct tcf_idrinfo *idrinfo, struct sk_buff *skb,
continue;
if (IS_ERR(p))
continue;
+ if (p->tcfa_flags & TCA_ACT_FLAGS_UNREFERENCED)
+ continue;
if (jiffy_since &&
time_after(jiffy_since,
@@ -640,6 +642,9 @@ static int tcf_del_walker(struct tcf_idrinfo *idrinfo, struct sk_buff *skb,
idr_for_each_entry_ul(idr, p, tmp, id) {
if (IS_ERR(p))
continue;
+ if (p->tcfa_flags & TCA_ACT_FLAGS_PREALLOC)
+ continue;
+
ret = tcf_idr_release_unsafe(p);
if (ret == ACT_P_DELETED)
module_put(ops->owner);
@@ -1398,25 +1403,40 @@ static const struct nla_policy tcf_action_policy[TCA_ACT_MAX + 1] = {
[TCA_ACT_HW_STATS] = NLA_POLICY_BITFIELD32(TCA_ACT_HW_STATS_ANY),
};
+static void tcf_idr_insert_1(struct tc_action *a)
+{
+ struct tcf_idrinfo *idrinfo;
+
+ idrinfo = a->idrinfo;
+ mutex_lock(&idrinfo->lock);
+ /* Replace ERR_PTR(-EBUSY) allocated by tcf_idr_check_alloc if
+ * it is just created, otherwise this is just a nop.
+ */
+ idr_replace(&idrinfo->action_idr, a, a->tcfa_index);
+ mutex_unlock(&idrinfo->lock);
+}
+
void tcf_idr_insert_many(struct tc_action *actions[], int init_res[])
{
struct tc_action *a;
int i;
tcf_act_for_each_action(i, a, actions) {
- struct tcf_idrinfo *idrinfo;
-
if (init_res[i] == ACT_P_BOUND)
continue;
- idrinfo = a->idrinfo;
- mutex_lock(&idrinfo->lock);
- /* Replace ERR_PTR(-EBUSY) allocated by tcf_idr_check_alloc */
- idr_replace(&idrinfo->action_idr, a, a->tcfa_index);
- mutex_unlock(&idrinfo->lock);
+ tcf_idr_insert_1(a);
}
}
+void tcf_idr_insert_n(struct tc_action *actions[], const u32 n)
+{
+ int i;
+
+ for (i = 0; i < n; i++)
+ tcf_idr_insert_1(actions[i]);
+}
+
struct tc_action_ops *
tc_action_load_ops(struct net *net, struct nlattr *nla,
u32 flags, struct netlink_ext_ack *extack)
@@ -2092,8 +2112,17 @@ tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n,
ret = PTR_ERR(act);
goto err;
}
- attr_size += tcf_action_fill_size(act);
actions[i - 1] = act;
+
+ if (event == RTM_DELACTION &&
+ act->tcfa_flags & TCA_ACT_FLAGS_PREALLOC) {
+ ret = -EINVAL;
+ NL_SET_ERR_MSG_FMT(extack,
+ "Unable to delete preallocated action %s",
+ act->ops->kind);
+ goto err;
+ }
+ attr_size += tcf_action_fill_size(act);
}
attr_size = tcf_action_full_attrs_size(attr_size);
--
2.34.1
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [PATCH net-next v11 0/5] Introducing P4TC (series 1)
2024-02-23 13:17 [PATCH net-next v11 0/5] Introducing P4TC (series 1) Jamal Hadi Salim
` (4 preceding siblings ...)
2024-02-23 13:17 ` [PATCH net-next v11 5/5] net: sched: act_api: Add support for preallocated P4 action instances Jamal Hadi Salim
@ 2024-02-23 15:38 ` Jakub Kicinski
2024-02-23 16:07 ` Maciej Fijalkowski
2024-02-23 16:54 ` Jamal Hadi Salim
5 siblings, 2 replies; 9+ messages in thread
From: Jakub Kicinski @ 2024-02-23 15:38 UTC (permalink / raw)
To: Jamal Hadi Salim
Cc: netdev, deb.chatterjee, anjali.singhai, namrata.limaye, tom,
mleitner, Mahesh.Shirshyad, Vipin.Jain, tomasz.osinski, jiri,
xiyou.wangcong, davem, edumazet, pabeni, vladbu, horms, khalidm,
toke, mattyk, daniel, bpf, dan.daly, andy.fingerhut,
chris.sommers, pctammela, victor
On Fri, 23 Feb 2024 08:17:23 -0500 Jamal Hadi Salim wrote:
> This is the first patchset of two. In this patch we are only submitting 5
> patches which touch the general TC code given these are trivial. We will be
> posting a second patchset which handles the P4 objects and associated infra
> (which includes 10 patches that we have already been posting to hit the 15
> limit).
Don't use the limit as a justification for questionable tactics :|
If there's still BPF in it, it's not getting merged without BPF
maintainers's acks. So we're going to merge these 5 and then what?
BTW the diffstat at the end of the commit message is from the full set.
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [PATCH net-next v11 0/5] Introducing P4TC (series 1)
2024-02-23 15:38 ` [PATCH net-next v11 0/5] Introducing P4TC (series 1) Jakub Kicinski
@ 2024-02-23 16:07 ` Maciej Fijalkowski
2024-02-23 16:54 ` Jamal Hadi Salim
1 sibling, 0 replies; 9+ messages in thread
From: Maciej Fijalkowski @ 2024-02-23 16:07 UTC (permalink / raw)
To: Jakub Kicinski
Cc: Jamal Hadi Salim, netdev, deb.chatterjee, anjali.singhai,
namrata.limaye, tom, mleitner, Mahesh.Shirshyad, Vipin.Jain,
tomasz.osinski, jiri, xiyou.wangcong, davem, edumazet, pabeni,
vladbu, horms, khalidm, toke, mattyk, daniel, bpf, dan.daly,
andy.fingerhut, chris.sommers, pctammela, victor
On Fri, Feb 23, 2024 at 07:38:02AM -0800, Jakub Kicinski wrote:
> On Fri, 23 Feb 2024 08:17:23 -0500 Jamal Hadi Salim wrote:
> > This is the first patchset of two. In this patch we are only submitting 5
> > patches which touch the general TC code given these are trivial. We will be
> > posting a second patchset which handles the P4 objects and associated infra
> > (which includes 10 patches that we have already been posting to hit the 15
> > limit).
>
> Don't use the limit as a justification for questionable tactics :|
> If there's still BPF in it, it's not getting merged without BPF
> maintainers's acks. So we're going to merge these 5 and then what?
>
> BTW the diffstat at the end of the commit message is from the full set.
...and it is followed by the current one, but that old scary diffstat
sould better go away ;)
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH net-next v11 0/5] Introducing P4TC (series 1)
2024-02-23 15:38 ` [PATCH net-next v11 0/5] Introducing P4TC (series 1) Jakub Kicinski
2024-02-23 16:07 ` Maciej Fijalkowski
@ 2024-02-23 16:54 ` Jamal Hadi Salim
1 sibling, 0 replies; 9+ messages in thread
From: Jamal Hadi Salim @ 2024-02-23 16:54 UTC (permalink / raw)
To: Jakub Kicinski
Cc: netdev, deb.chatterjee, anjali.singhai, namrata.limaye, tom,
mleitner, Mahesh.Shirshyad, Vipin.Jain, tomasz.osinski, jiri,
xiyou.wangcong, davem, edumazet, pabeni, vladbu, horms, khalidm,
toke, mattyk, daniel, bpf, dan.daly, andy.fingerhut,
chris.sommers, pctammela, victor
On Fri, Feb 23, 2024 at 10:38 AM Jakub Kicinski <kuba@kernel.org> wrote:
>
> On Fri, 23 Feb 2024 08:17:23 -0500 Jamal Hadi Salim wrote:
> > This is the first patchset of two. In this patch we are only submitting 5
> > patches which touch the general TC code given these are trivial. We will be
> > posting a second patchset which handles the P4 objects and associated infra
> > (which includes 10 patches that we have already been posting to hit the 15
> > limit).
>
> Don't use the limit as a justification for questionable tactics :|
The discussion with Daniel was on removing the XDP referencing in the
filter which in my last email exchange i offered to remove. I believe
that removing the XDP reference should resolve the issue. Instead of
waiting for Daniel to respond (the last response took a while), at the
last minute i decided to only do the first five which are trivial and
have been posted for over a year now and have been reviewd by multiple
people. I had no intention to make this a conspiracy of any sort.
> If there's still BPF in it, it's not getting merged without BPF
> maintainers's acks. So we're going to merge these 5 and then what?
>
Look, this is getting to be too much navigation (which is what scares
most newbies from participating and i have been here for 100 years
now). I dont have a problem removing the XDP reference - but now we
are treading into subsystem territories; this is about P4 abstraction
and the infra around it, it is really not about eBPF. We dont need
anything "new" from ebpf i.e none of these patches make any eBPF
changes. This is a tc classifier that happens to use ebpf, whose
domain is that? The exhausting part is some feedback is "you do it
our way or else" thing: I apologize i dont want to lump everyone in
that pool, and it is nothing to do specifically with ebpf people
rather a failure in reaching compromise within this community.
> BTW the diffstat at the end of the commit message is from the full set
Yeah, sorry - this was last minute "should i send all or just these
five to make space for the remainder 5 that we havent posted since
V8".
We have 5 more patches on top of what we posted on V10 - merging these
would open the door to post the rest with 15 limit.
I can repost all 15 if that works better.
cheers,
jamal
^ permalink raw reply [flat|nested] 9+ messages in thread