From: Ioana Ciornei <ioana.cior...@nxp.com>

Add support TC_SETUP_CLSMATCHALL by using the same ACL table entries
framework as for tc flower. Adding a matchall rule is done by installing
an entry which has a mask of all zeroes, thus matching on any packet.

This can be used as a catch-all type of rule if used correctly, ie the
priority of the matchall filter should be kept as the lowest one in the
entire filter block.

Signed-off-by: Ioana Ciornei <ioana.cior...@nxp.com>
---
 .../freescale/dpaa2/dpaa2-switch-flower.c     | 56 +++++++++++++++++++
 .../ethernet/freescale/dpaa2/dpaa2-switch.c   | 16 ++++++
 .../ethernet/freescale/dpaa2/dpaa2-switch.h   |  7 +++
 3 files changed, 79 insertions(+)

diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch-flower.c 
b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch-flower.c
index ee987fa02f0d..b4807ddc2011 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch-flower.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch-flower.c
@@ -434,3 +434,59 @@ int dpaa2_switch_cls_flower_destroy(struct 
dpaa2_switch_acl_tbl *acl_tbl,
 
        return dpaa2_switch_acl_tbl_remove_entry(acl_tbl, entry);
 }
+
+int dpaa2_switch_cls_matchall_replace(struct dpaa2_switch_acl_tbl *acl_tbl,
+                                     struct tc_cls_matchall_offload *cls)
+{
+       struct netlink_ext_ack *extack = cls->common.extack;
+       struct ethsw_core *ethsw = acl_tbl->ethsw;
+       struct dpaa2_switch_acl_entry *acl_entry;
+       struct flow_action_entry *act;
+       int err;
+
+       if (!flow_offload_has_one_action(&cls->rule->action)) {
+               NL_SET_ERR_MSG(extack, "Only singular actions are supported");
+               return -EOPNOTSUPP;
+       }
+
+       if (dpaa2_switch_acl_tbl_is_full(acl_tbl)) {
+               NL_SET_ERR_MSG(extack, "Maximum filter capacity reached");
+               return -ENOMEM;
+       }
+
+       acl_entry = kzalloc(sizeof(*acl_entry), GFP_KERNEL);
+       if (!acl_entry)
+               return -ENOMEM;
+
+       act = &cls->rule->action.entries[0];
+       err = dpaa2_switch_tc_parse_action(ethsw, act,
+                                          &acl_entry->cfg.result, extack);
+       if (err)
+               goto free_acl_entry;
+
+       acl_entry->prio = cls->common.prio;
+       acl_entry->cookie = cls->cookie;
+
+       err = dpaa2_switch_acl_tbl_add_entry(acl_tbl, acl_entry);
+       if (err)
+               goto free_acl_entry;
+
+       return 0;
+
+free_acl_entry:
+       kfree(acl_entry);
+
+       return err;
+}
+
+int dpaa2_switch_cls_matchall_destroy(struct dpaa2_switch_acl_tbl *acl_tbl,
+                                     struct tc_cls_matchall_offload *cls)
+{
+       struct dpaa2_switch_acl_entry *entry;
+
+       entry = dpaa2_switch_acl_tbl_find_entry_by_cookie(acl_tbl, cls->cookie);
+       if (!entry)
+               return 0;
+
+       return  dpaa2_switch_acl_tbl_remove_entry(acl_tbl, entry);
+}
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c 
b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
index 5080788c692b..adf9e5880d89 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
@@ -1140,6 +1140,20 @@ dpaa2_switch_setup_tc_cls_flower(struct 
dpaa2_switch_acl_tbl *acl_tbl,
        }
 }
 
+static int
+dpaa2_switch_setup_tc_cls_matchall(struct dpaa2_switch_acl_tbl *acl_tbl,
+                                  struct tc_cls_matchall_offload *f)
+{
+       switch (f->command) {
+       case TC_CLSMATCHALL_REPLACE:
+               return dpaa2_switch_cls_matchall_replace(acl_tbl, f);
+       case TC_CLSMATCHALL_DESTROY:
+               return dpaa2_switch_cls_matchall_destroy(acl_tbl, f);
+       default:
+               return -EOPNOTSUPP;
+       }
+}
+
 static int dpaa2_switch_port_setup_tc_block_cb_ig(enum tc_setup_type type,
                                                  void *type_data,
                                                  void *cb_priv)
@@ -1147,6 +1161,8 @@ static int dpaa2_switch_port_setup_tc_block_cb_ig(enum 
tc_setup_type type,
        switch (type) {
        case TC_SETUP_CLSFLOWER:
                return dpaa2_switch_setup_tc_cls_flower(cb_priv, type_data);
+       case TC_SETUP_CLSMATCHALL:
+               return dpaa2_switch_setup_tc_cls_matchall(cb_priv, type_data);
        default:
                return -EOPNOTSUPP;
        }
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.h 
b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.h
index 629186208b58..8575eed02d15 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.h
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.h
@@ -18,6 +18,7 @@
 #include <net/switchdev.h>
 #include <linux/if_bridge.h>
 #include <linux/fsl/mc.h>
+#include <net/pkt_cls.h>
 #include <soc/fsl/dpaa2-io.h>
 
 #include "dpsw.h"
@@ -233,4 +234,10 @@ int dpaa2_switch_cls_flower_replace(struct 
dpaa2_switch_acl_tbl *acl_tbl,
 
 int dpaa2_switch_cls_flower_destroy(struct dpaa2_switch_acl_tbl *acl_tbl,
                                    struct flow_cls_offload *cls);
+
+int dpaa2_switch_cls_matchall_replace(struct dpaa2_switch_acl_tbl *acl_tbl,
+                                     struct tc_cls_matchall_offload *cls);
+
+int dpaa2_switch_cls_matchall_destroy(struct dpaa2_switch_acl_tbl *acl_tbl,
+                                     struct tc_cls_matchall_offload *cls);
 #endif /* __ETHSW_H */
-- 
2.30.0

Reply via email to