]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
net: microchip: vcap api: Use src and dst chain id to chain VCAP lookups
authorSteen Hegelund <steen.hegelund@microchip.com>
Sat, 14 Jan 2023 13:42:39 +0000 (14:42 +0100)
committerDavid S. Miller <davem@davemloft.net>
Mon, 16 Jan 2023 13:45:17 +0000 (13:45 +0000)
This adds both the source and destination chain id to the information kept
for enabled port lookups.
This allows enabling and disabling a chain of lookups by walking the chain
information for a port.

This changes the way that VCAP lookups are enabled from userspace: instead
of one matchall rule that enables all the 4 Sparx5 IS2 lookups, you need a
matchall rule per lookup.

In practice that is done by adding one matchall rule in chain 0 to goto IS2
Lookup 0, and then for each lookup you add a rule per lookup (low priority)
that does a goto to the next lookup chain.

Examples:

If you want IS2 Lookup 0 to be enabled you add the same matchall filter as
before:

tc filter add dev eth12 ingress chain 0 prio 1000 handle 1000 matchall \
       skip_sw action goto chain 8000000

If you also want to enable lookup 1 to 3 in IS2 and chain them you need
to add the following matchall filters:

tc filter add dev eth12 ingress chain 8000000 prio 1000 handle 1000 \
    matchall skip_sw action goto chain 8100000

tc filter add dev eth12 ingress chain 8100000 prio 1000 handle 1000 \
    matchall skip_sw action goto chain 8200000

tc filter add dev eth12 ingress chain 8200000 prio 1000 handle 1000 \
    matchall skip_sw action goto chain 8300000

Signed-off-by: Horatiu Vultur <horatiu.vultur@microchip.com>
Signed-off-by: Steen Hegelund <steen.hegelund@microchip.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/microchip/lan966x/lan966x_goto.c
drivers/net/ethernet/microchip/lan966x/lan966x_main.h
drivers/net/ethernet/microchip/lan966x/lan966x_tc_matchall.c
drivers/net/ethernet/microchip/sparx5/sparx5_tc_matchall.c
drivers/net/ethernet/microchip/vcap/vcap_api.c
drivers/net/ethernet/microchip/vcap/vcap_api_client.h

index bf0cfe24a8fc085352e4528d153e54d03a5db368..9b18156eea1a4c242c08da7d0e95187611b90958 100644 (file)
@@ -4,7 +4,7 @@
 #include "vcap_api_client.h"
 
 int lan966x_goto_port_add(struct lan966x_port *port,
-                         struct flow_action_entry *act,
+                         int from_cid, int to_cid,
                          unsigned long goto_id,
                          struct netlink_ext_ack *extack)
 {
@@ -12,7 +12,7 @@ int lan966x_goto_port_add(struct lan966x_port *port,
        int err;
 
        err = vcap_enable_lookups(lan966x->vcap_ctrl, port->dev,
-                                 act->chain_index, goto_id,
+                                 from_cid, to_cid, goto_id,
                                  true);
        if (err == -EFAULT) {
                NL_SET_ERR_MSG_MOD(extack, "Unsupported goto chain");
@@ -29,8 +29,6 @@ int lan966x_goto_port_add(struct lan966x_port *port,
                return err;
        }
 
-       port->tc.goto_id = goto_id;
-
        return 0;
 }
 
@@ -41,14 +39,12 @@ int lan966x_goto_port_del(struct lan966x_port *port,
        struct lan966x *lan966x = port->lan966x;
        int err;
 
-       err = vcap_enable_lookups(lan966x->vcap_ctrl, port->dev, 0,
+       err = vcap_enable_lookups(lan966x->vcap_ctrl, port->dev, 0, 0,
                                  goto_id, false);
        if (err) {
                NL_SET_ERR_MSG_MOD(extack, "Could not disable VCAP lookups");
                return err;
        }
 
-       port->tc.goto_id = 0;
-
        return 0;
 }
index 3491f1961835815322543a28743c3fd8eac73326..0106f9487cbec86ac547f4c73856a25d1b7aa829 100644 (file)
@@ -332,7 +332,6 @@ struct lan966x_port_tc {
        unsigned long police_id;
        unsigned long ingress_mirror_id;
        unsigned long egress_mirror_id;
-       unsigned long goto_id;
        struct flow_stats police_stat;
        struct flow_stats mirror_stat;
 };
@@ -607,7 +606,7 @@ int lan966x_tc_flower(struct lan966x_port *port,
                      struct flow_cls_offload *f);
 
 int lan966x_goto_port_add(struct lan966x_port *port,
-                         struct flow_action_entry *act,
+                         int from_cid, int to_cid,
                          unsigned long goto_id,
                          struct netlink_ext_ack *extack);
 int lan966x_goto_port_del(struct lan966x_port *port,
index a539abaad9b674eeca9e2ced5be69372473abb8b..20627323d656f7cdf67ec072ee6a66c427d7c1f2 100644 (file)
@@ -24,7 +24,8 @@ static int lan966x_tc_matchall_add(struct lan966x_port *port,
                return lan966x_mirror_port_add(port, act, f->cookie,
                                               ingress, f->common.extack);
        case FLOW_ACTION_GOTO:
-               return lan966x_goto_port_add(port, act, f->cookie,
+               return lan966x_goto_port_add(port, f->common.chain_index,
+                                            act->chain_index, f->cookie,
                                             f->common.extack);
        default:
                NL_SET_ERR_MSG_MOD(f->common.extack,
@@ -46,13 +47,8 @@ static int lan966x_tc_matchall_del(struct lan966x_port *port,
                   f->cookie == port->tc.egress_mirror_id) {
                return lan966x_mirror_port_del(port, ingress,
                                               f->common.extack);
-       } else if (f->cookie == port->tc.goto_id) {
-               return lan966x_goto_port_del(port, f->cookie,
-                                            f->common.extack);
        } else {
-               NL_SET_ERR_MSG_MOD(f->common.extack,
-                                  "Unsupported action");
-               return -EOPNOTSUPP;
+               return lan966x_goto_port_del(port, f->cookie, f->common.extack);
        }
 
        return 0;
@@ -80,12 +76,6 @@ int lan966x_tc_matchall(struct lan966x_port *port,
                        struct tc_cls_matchall_offload *f,
                        bool ingress)
 {
-       if (!tc_cls_can_offload_and_chain0(port->dev, &f->common)) {
-               NL_SET_ERR_MSG_MOD(f->common.extack,
-                                  "Only chain zero is supported");
-               return -EOPNOTSUPP;
-       }
-
        switch (f->command) {
        case TC_CLSMATCHALL_REPLACE:
                return lan966x_tc_matchall_add(port, f, ingress);
index 30dd61e5d150fbb87a34c861288f694417f370fc..d88a93f226065834d22c36c050c094a93be2248d 100644 (file)
@@ -31,6 +31,7 @@ static int sparx5_tc_matchall_replace(struct net_device *ndev,
        switch (action->id) {
        case FLOW_ACTION_GOTO:
                err = vcap_enable_lookups(sparx5->vcap_ctrl, ndev,
+                                         tmo->common.chain_index,
                                          action->chain_index, tmo->cookie,
                                          true);
                if (err == -EFAULT) {
@@ -43,6 +44,11 @@ static int sparx5_tc_matchall_replace(struct net_device *ndev,
                                           "VCAP already enabled");
                        return -EOPNOTSUPP;
                }
+               if (err == -EADDRNOTAVAIL) {
+                       NL_SET_ERR_MSG_MOD(tmo->common.extack,
+                                          "Already matching this chain");
+                       return -EOPNOTSUPP;
+               }
                if (err) {
                        NL_SET_ERR_MSG_MOD(tmo->common.extack,
                                           "Could not enable VCAP lookups");
@@ -66,8 +72,8 @@ static int sparx5_tc_matchall_destroy(struct net_device *ndev,
 
        sparx5 = port->sparx5;
        if (!tmo->rule && tmo->cookie) {
-               err = vcap_enable_lookups(sparx5->vcap_ctrl, ndev, 0,
-                                         tmo->cookie, false);
+               err = vcap_enable_lookups(sparx5->vcap_ctrl, ndev,
+                                         0, 0, tmo->cookie, false);
                if (err)
                        return err;
                return 0;
@@ -80,12 +86,6 @@ int sparx5_tc_matchall(struct net_device *ndev,
                       struct tc_cls_matchall_offload *tmo,
                       bool ingress)
 {
-       if (!tc_cls_can_offload_and_chain0(ndev, &tmo->common)) {
-               NL_SET_ERR_MSG_MOD(tmo->common.extack,
-                                  "Only chain zero is supported");
-               return -EOPNOTSUPP;
-       }
-
        switch (tmo->command) {
        case TC_CLSMATCHALL_REPLACE:
                return sparx5_tc_matchall_replace(ndev, tmo, ingress);
index a0fddd8744d3fbb6068c6730182ec896232e20cc..a5572bcab8e68177a87b5ad4ef047d20ad4180fe 100644 (file)
@@ -37,11 +37,13 @@ struct vcap_rule_move {
        int count; /* blocksize of addresses to move */
 };
 
-/* Stores the filter cookie that enabled the port */
+/* Stores the filter cookie and chain id that enabled the port */
 struct vcap_enabled_port {
        struct list_head list; /* for insertion in enabled ports list */
        struct net_device *ndev;  /* the enabled port */
        unsigned long cookie; /* filter that enabled the port */
+       int src_cid; /* source chain id */
+       int dst_cid; /* destination chain id */
 };
 
 void vcap_iter_set(struct vcap_stream_iter *itr, int sw_width,
@@ -1930,6 +1932,21 @@ static void vcap_move_rules(struct vcap_rule_internal *ri,
                         move->offset, move->count);
 }
 
+/* Check if the chain is already used to enable a VCAP lookup for this port */
+static bool vcap_is_chain_used(struct vcap_control *vctrl,
+                              struct net_device *ndev, int src_cid)
+{
+       struct vcap_enabled_port *eport;
+       struct vcap_admin *admin;
+
+       list_for_each_entry(admin, &vctrl->list, list)
+               list_for_each_entry(eport, &admin->enabled, list)
+                       if (eport->src_cid == src_cid && eport->ndev == ndev)
+                               return true;
+
+       return false;
+}
+
 /* Encode and write a validated rule to the VCAP */
 int vcap_add_rule(struct vcap_rule *rule)
 {
@@ -2595,23 +2612,33 @@ void vcap_set_tc_exterr(struct flow_cls_offload *fco, struct vcap_rule *vrule)
 EXPORT_SYMBOL_GPL(vcap_set_tc_exterr);
 
 /* Check if this port is already enabled for this VCAP instance */
-static bool vcap_is_enabled(struct vcap_admin *admin, struct net_device *ndev,
-                           unsigned long cookie)
+static bool vcap_is_enabled(struct vcap_control *vctrl, struct net_device *ndev,
+                           int dst_cid)
 {
        struct vcap_enabled_port *eport;
+       struct vcap_admin *admin;
 
-       list_for_each_entry(eport, &admin->enabled, list)
-               if (eport->cookie == cookie || eport->ndev == ndev)
-                       return true;
+       list_for_each_entry(admin, &vctrl->list, list)
+               list_for_each_entry(eport, &admin->enabled, list)
+                       if (eport->dst_cid == dst_cid && eport->ndev == ndev)
+                               return true;
 
        return false;
 }
 
-/* Enable this port for this VCAP instance */
-static int vcap_enable(struct vcap_admin *admin, struct net_device *ndev,
-                      unsigned long cookie)
+/* Enable this port and chain id in a VCAP instance */
+static int vcap_enable(struct vcap_control *vctrl, struct net_device *ndev,
+                      unsigned long cookie, int src_cid, int dst_cid)
 {
        struct vcap_enabled_port *eport;
+       struct vcap_admin *admin;
+
+       if (src_cid >= dst_cid)
+               return -EFAULT;
+
+       admin = vcap_find_admin(vctrl, dst_cid);
+       if (!admin)
+               return -ENOENT;
 
        eport = kzalloc(sizeof(*eport), GFP_KERNEL);
        if (!eport)
@@ -2619,48 +2646,49 @@ static int vcap_enable(struct vcap_admin *admin, struct net_device *ndev,
 
        eport->ndev = ndev;
        eport->cookie = cookie;
+       eport->src_cid = src_cid;
+       eport->dst_cid = dst_cid;
+       mutex_lock(&admin->lock);
        list_add_tail(&eport->list, &admin->enabled);
+       mutex_unlock(&admin->lock);
 
        return 0;
 }
 
-/* Disable this port for this VCAP instance */
-static int vcap_disable(struct vcap_admin *admin, struct net_device *ndev,
+/* Disable this port and chain id for a VCAP instance */
+static int vcap_disable(struct vcap_control *vctrl, struct net_device *ndev,
                        unsigned long cookie)
 {
-       struct vcap_enabled_port *eport;
+       struct vcap_enabled_port *elem, *eport = NULL;
+       struct vcap_admin *found = NULL, *admin;
 
-       list_for_each_entry(eport, &admin->enabled, list) {
-               if (eport->cookie == cookie && eport->ndev == ndev) {
-                       list_del(&eport->list);
-                       kfree(eport);
-                       return 0;
+       list_for_each_entry(admin, &vctrl->list, list) {
+               list_for_each_entry(elem, &admin->enabled, list) {
+                       if (elem->cookie == cookie && elem->ndev == ndev) {
+                               eport = elem;
+                               found = admin;
+                               break;
+                       }
                }
+               if (eport)
+                       break;
        }
 
-       return -ENOENT;
-}
-
-/* Find the VCAP instance that enabled the port using a specific filter */
-static struct vcap_admin *vcap_find_admin_by_cookie(struct vcap_control *vctrl,
-                                                   unsigned long cookie)
-{
-       struct vcap_enabled_port *eport;
-       struct vcap_admin *admin;
-
-       list_for_each_entry(admin, &vctrl->list, list)
-               list_for_each_entry(eport, &admin->enabled, list)
-                       if (eport->cookie == cookie)
-                               return admin;
+       if (!eport)
+               return -ENOENT;
 
-       return NULL;
+       mutex_lock(&found->lock);
+       list_del(&eport->list);
+       mutex_unlock(&found->lock);
+       kfree(eport);
+       return 0;
 }
 
-/* Enable/Disable the VCAP instance lookups. Chain id 0 means disable */
+/* Enable/Disable the VCAP instance lookups */
 int vcap_enable_lookups(struct vcap_control *vctrl, struct net_device *ndev,
-                       int chain_id, unsigned long cookie, bool enable)
+                       int src_cid, int dst_cid, unsigned long cookie,
+                       bool enable)
 {
-       struct vcap_admin *admin;
        int err;
 
        err = vcap_api_check(vctrl);
@@ -2670,29 +2698,23 @@ int vcap_enable_lookups(struct vcap_control *vctrl, struct net_device *ndev,
        if (!ndev)
                return -ENODEV;
 
-       if (chain_id)
-               admin = vcap_find_admin(vctrl, chain_id);
-       else
-               admin = vcap_find_admin_by_cookie(vctrl, cookie);
-       if (!admin)
-               return -ENOENT;
-
-       /* first instance and first chain */
-       if (admin->vinst || chain_id > admin->first_cid)
+       /* Source and destination must be the first chain in a lookup */
+       if (src_cid % VCAP_CID_LOOKUP_SIZE)
+               return -EFAULT;
+       if (dst_cid % VCAP_CID_LOOKUP_SIZE)
                return -EFAULT;
 
-       if (chain_id) {
-               if (vcap_is_enabled(admin, ndev, cookie))
+       if (enable) {
+               if (vcap_is_enabled(vctrl, ndev, dst_cid))
                        return -EADDRINUSE;
-               mutex_lock(&admin->lock);
-               vcap_enable(admin, ndev, cookie);
+               if (vcap_is_chain_used(vctrl, ndev, src_cid))
+                       return -EADDRNOTAVAIL;
+               err = vcap_enable(vctrl, ndev, cookie, src_cid, dst_cid);
        } else {
-               mutex_lock(&admin->lock);
-               vcap_disable(admin, ndev, cookie);
+               err = vcap_disable(vctrl, ndev, cookie);
        }
-       mutex_unlock(&admin->lock);
 
-       return 0;
+       return err;
 }
 EXPORT_SYMBOL_GPL(vcap_enable_lookups);
 
index 0319866f9c94d0818e92edcb17620ce228247a19..e07dc8d3c639065a6ee8276aa3ea7f935bd554f7 100644 (file)
@@ -148,9 +148,10 @@ struct vcap_counter {
        bool sticky;
 };
 
-/* Enable/Disable the VCAP instance lookups. Chain id 0 means disable */
+/* Enable/Disable the VCAP instance lookups */
 int vcap_enable_lookups(struct vcap_control *vctrl, struct net_device *ndev,
-                       int chain_id, unsigned long cookie, bool enable);
+                       int from_cid, int to_cid, unsigned long cookie,
+                       bool enable);
 
 /* VCAP rule operations */
 /* Allocate a rule and fill in the basic information */