net: schedule: add action gate offloading
authorPo Liu <Po.Liu@nxp.com>
Fri, 1 May 2020 00:53:16 +0000 (08:53 +0800)
committerDavid S. Miller <davem@davemloft.net>
Fri, 1 May 2020 23:08:19 +0000 (16:08 -0700)
Add the gate action to the flow action entry. Add the gate parameters to
the tc_setup_flow_action() queueing to the entries of flow_action_entry
array provide to the driver.

Signed-off-by: Po Liu <Po.Liu@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/flow_offload.h
include/net/tc_act/tc_gate.h
net/sched/cls_api.c

index 3619c6acf60fa563f7915f6a03647b975eaa1ac8..94a30fe02e6d5a757931e93529f927a2335b6b9a 100644 (file)
@@ -147,6 +147,7 @@ enum flow_action_id {
        FLOW_ACTION_MPLS_PUSH,
        FLOW_ACTION_MPLS_POP,
        FLOW_ACTION_MPLS_MANGLE,
+       FLOW_ACTION_GATE,
        NUM_FLOW_ACTIONS,
 };
 
@@ -255,6 +256,15 @@ struct flow_action_entry {
                        u8              bos;
                        u8              ttl;
                } mpls_mangle;
+               struct {
+                       u32             index;
+                       s32             prio;
+                       u64             basetime;
+                       u64             cycletime;
+                       u64             cycletimeext;
+                       u32             num_entries;
+                       struct action_gate_entry *entries;
+               } gate;
        };
        struct flow_action_cookie *cookie; /* user defined action cookie */
 };
index 330ad8b02495e15bbd1437d2dce83b1e06769034..8bc6be81a7adfaea76abaf33bc379632c1c22e93 100644 (file)
@@ -7,6 +7,13 @@
 #include <net/act_api.h>
 #include <linux/tc_act/tc_gate.h>
 
+struct action_gate_entry {
+       u8                      gate_state;
+       u32                     interval;
+       s32                     ipv;
+       s32                     maxoctets;
+};
+
 struct tcfg_gate_entry {
        int                     index;
        u8                      gate_state;
@@ -44,4 +51,96 @@ struct tcf_gate {
 
 #define to_gate(a) ((struct tcf_gate *)a)
 
+static inline bool is_tcf_gate(const struct tc_action *a)
+{
+#ifdef CONFIG_NET_CLS_ACT
+       if (a->ops && a->ops->id == TCA_ID_GATE)
+               return true;
+#endif
+       return false;
+}
+
+static inline u32 tcf_gate_index(const struct tc_action *a)
+{
+       return a->tcfa_index;
+}
+
+static inline s32 tcf_gate_prio(const struct tc_action *a)
+{
+       s32 tcfg_prio;
+
+       tcfg_prio = to_gate(a)->param.tcfg_priority;
+
+       return tcfg_prio;
+}
+
+static inline u64 tcf_gate_basetime(const struct tc_action *a)
+{
+       u64 tcfg_basetime;
+
+       tcfg_basetime = to_gate(a)->param.tcfg_basetime;
+
+       return tcfg_basetime;
+}
+
+static inline u64 tcf_gate_cycletime(const struct tc_action *a)
+{
+       u64 tcfg_cycletime;
+
+       tcfg_cycletime = to_gate(a)->param.tcfg_cycletime;
+
+       return tcfg_cycletime;
+}
+
+static inline u64 tcf_gate_cycletimeext(const struct tc_action *a)
+{
+       u64 tcfg_cycletimeext;
+
+       tcfg_cycletimeext = to_gate(a)->param.tcfg_cycletime_ext;
+
+       return tcfg_cycletimeext;
+}
+
+static inline u32 tcf_gate_num_entries(const struct tc_action *a)
+{
+       u32 num_entries;
+
+       num_entries = to_gate(a)->param.num_entries;
+
+       return num_entries;
+}
+
+static inline struct action_gate_entry
+                       *tcf_gate_get_list(const struct tc_action *a)
+{
+       struct action_gate_entry *oe;
+       struct tcf_gate_params *p;
+       struct tcfg_gate_entry *entry;
+       u32 num_entries;
+       int i = 0;
+
+       p = &to_gate(a)->param;
+       num_entries = p->num_entries;
+
+       list_for_each_entry(entry, &p->entries, list)
+               i++;
+
+       if (i != num_entries)
+               return NULL;
+
+       oe = kcalloc(num_entries, sizeof(*oe), GFP_ATOMIC);
+       if (!oe)
+               return NULL;
+
+       i = 0;
+       list_for_each_entry(entry, &p->entries, list) {
+               oe[i].gate_state = entry->gate_state;
+               oe[i].interval = entry->interval;
+               oe[i].ipv = entry->ipv;
+               oe[i].maxoctets = entry->maxoctets;
+               i++;
+       }
+
+       return oe;
+}
 #endif
index 11b683c45c2897cf52e3d0d599cbd4dcf9f2bf22..7e85c91d07526e0eca42f67fa629a70b6d8da6b9 100644 (file)
@@ -39,6 +39,7 @@
 #include <net/tc_act/tc_skbedit.h>
 #include <net/tc_act/tc_ct.h>
 #include <net/tc_act/tc_mpls.h>
+#include <net/tc_act/tc_gate.h>
 #include <net/flow_offload.h>
 
 extern const struct nla_policy rtm_tca_policy[TCA_MAX + 1];
@@ -3526,6 +3527,27 @@ static void tcf_sample_get_group(struct flow_action_entry *entry,
 #endif
 }
 
+static void tcf_gate_entry_destructor(void *priv)
+{
+       struct action_gate_entry *oe = priv;
+
+       kfree(oe);
+}
+
+static int tcf_gate_get_entries(struct flow_action_entry *entry,
+                               const struct tc_action *act)
+{
+       entry->gate.entries = tcf_gate_get_list(act);
+
+       if (!entry->gate.entries)
+               return -EINVAL;
+
+       entry->destructor = tcf_gate_entry_destructor;
+       entry->destructor_priv = entry->gate.entries;
+
+       return 0;
+}
+
 int tc_setup_flow_action(struct flow_action *flow_action,
                         const struct tcf_exts *exts)
 {
@@ -3672,6 +3694,17 @@ int tc_setup_flow_action(struct flow_action *flow_action,
                } else if (is_tcf_skbedit_priority(act)) {
                        entry->id = FLOW_ACTION_PRIORITY;
                        entry->priority = tcf_skbedit_priority(act);
+               } else if (is_tcf_gate(act)) {
+                       entry->id = FLOW_ACTION_GATE;
+                       entry->gate.index = tcf_gate_index(act);
+                       entry->gate.prio = tcf_gate_prio(act);
+                       entry->gate.basetime = tcf_gate_basetime(act);
+                       entry->gate.cycletime = tcf_gate_cycletime(act);
+                       entry->gate.cycletimeext = tcf_gate_cycletimeext(act);
+                       entry->gate.num_entries = tcf_gate_num_entries(act);
+                       err = tcf_gate_get_entries(entry, act);
+                       if (err)
+                               goto err_out;
                } else {
                        err = -EOPNOTSUPP;
                        goto err_out_locked;