flow_offload: pass action cookie through offload structures
authorJiri Pirko <jiri@mellanox.com>
Tue, 25 Feb 2020 10:45:18 +0000 (11:45 +0100)
committerDavid S. Miller <davem@davemloft.net>
Tue, 25 Feb 2020 19:05:54 +0000 (11:05 -0800)
Extend struct flow_action_entry in order to hold TC action cookie
specified by user inserting the action.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Reviewed-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/flow_offload.h
net/core/flow_offload.c
net/sched/cls_api.c

index c6f7bd22db6092f344161aeaf454067dd5ec3bae..4e864c34a1b01b6b7261d20bb4a917c18b12da38 100644 (file)
@@ -156,6 +156,16 @@ enum flow_action_mangle_base {
 
 typedef void (*action_destr)(void *priv);
 
+struct flow_action_cookie {
+       u32 cookie_len;
+       u8 cookie[];
+};
+
+struct flow_action_cookie *flow_action_cookie_create(void *data,
+                                                    unsigned int len,
+                                                    gfp_t gfp);
+void flow_action_cookie_destroy(struct flow_action_cookie *cookie);
+
 struct flow_action_entry {
        enum flow_action_id             id;
        action_destr                    destructor;
@@ -214,6 +224,7 @@ struct flow_action_entry {
                        u8              ttl;
                } mpls_mangle;
        };
+       struct flow_action_cookie *cookie; /* user defined action cookie */
 };
 
 struct flow_action {
index 45b6a59ac1243fbaf93240a422f5429de95b34a9..d21348202ba619194ac00f0164f71f347b958f0c 100644 (file)
@@ -167,6 +167,27 @@ void flow_rule_match_enc_opts(const struct flow_rule *rule,
 }
 EXPORT_SYMBOL(flow_rule_match_enc_opts);
 
+struct flow_action_cookie *flow_action_cookie_create(void *data,
+                                                    unsigned int len,
+                                                    gfp_t gfp)
+{
+       struct flow_action_cookie *cookie;
+
+       cookie = kmalloc(sizeof(*cookie) + len, gfp);
+       if (!cookie)
+               return NULL;
+       cookie->cookie_len = len;
+       memcpy(cookie->cookie, data, len);
+       return cookie;
+}
+EXPORT_SYMBOL(flow_action_cookie_create);
+
+void flow_action_cookie_destroy(struct flow_action_cookie *cookie)
+{
+       kfree(cookie);
+}
+EXPORT_SYMBOL(flow_action_cookie_destroy);
+
 struct flow_block_cb *flow_block_cb_alloc(flow_setup_cb_t *cb,
                                          void *cb_ident, void *cb_priv,
                                          void (*release)(void *cb_priv))
index 13c33eaf1ca10c5adec839c7978da67222c2b5de..4e766c5ab77a1ec1875b18b7d86303cea607a4e3 100644 (file)
@@ -3382,14 +3382,40 @@ int tc_setup_cb_reoffload(struct tcf_block *block, struct tcf_proto *tp,
 }
 EXPORT_SYMBOL(tc_setup_cb_reoffload);
 
+static int tcf_act_get_cookie(struct flow_action_entry *entry,
+                             const struct tc_action *act)
+{
+       struct tc_cookie *cookie;
+       int err = 0;
+
+       rcu_read_lock();
+       cookie = rcu_dereference(act->act_cookie);
+       if (cookie) {
+               entry->cookie = flow_action_cookie_create(cookie->data,
+                                                         cookie->len,
+                                                         GFP_ATOMIC);
+               if (!entry->cookie)
+                       err = -ENOMEM;
+       }
+       rcu_read_unlock();
+       return err;
+}
+
+static void tcf_act_put_cookie(struct flow_action_entry *entry)
+{
+       flow_action_cookie_destroy(entry->cookie);
+}
+
 void tc_cleanup_flow_action(struct flow_action *flow_action)
 {
        struct flow_action_entry *entry;
        int i;
 
-       flow_action_for_each(i, entry, flow_action)
+       flow_action_for_each(i, entry, flow_action) {
+               tcf_act_put_cookie(entry);
                if (entry->destructor)
                        entry->destructor(entry->destructor_priv);
+       }
 }
 EXPORT_SYMBOL(tc_cleanup_flow_action);
 
@@ -3447,6 +3473,9 @@ int tc_setup_flow_action(struct flow_action *flow_action,
 
                entry = &flow_action->entries[j];
                spin_lock_bh(&act->tcfa_lock);
+               err = tcf_act_get_cookie(entry, act);
+               if (err)
+                       goto err_out_locked;
                if (is_tcf_gact_ok(act)) {
                        entry->id = FLOW_ACTION_ACCEPT;
                } else if (is_tcf_gact_shot(act)) {