summaryrefslogtreecommitdiffstats
path: root/drivers/net/dsa/sja1105/sja1105_flower.c
diff options
context:
space:
mode:
authorVladimir Oltean <vladimir.oltean@nxp.com>2020-05-05 21:20:55 +0200
committerDavid S. Miller <davem@davemloft.net>2020-05-08 02:31:57 +0200
commitdfacc5a23e227cabdff41b6202f510398e90d36b (patch)
tree97a90de67d292ec4e70f166b7771de7b8fac3800 /drivers/net/dsa/sja1105/sja1105_flower.c
parentnet: dsa: sja1105: make room for virtual link parsing in flower offload (diff)
downloadlinux-dfacc5a23e227cabdff41b6202f510398e90d36b.tar.xz
linux-dfacc5a23e227cabdff41b6202f510398e90d36b.zip
net: dsa: sja1105: support flow-based redirection via virtual links
Implement tc-flower offloads for redirect, trap and drop using non-critical virtual links. Commands which were tested to work are: # Send frames received on swp2 with a DA of 42:be:24:9b:76:20 to the # CPU and to swp3. This type of key (DA only) when the port's VLAN # awareness state is off. tc qdisc add dev swp2 clsact tc filter add dev swp2 ingress flower skip_sw dst_mac 42:be:24:9b:76:20 \ action mirred egress redirect dev swp3 \ action trap # Drop frames received on swp2 with a DA of 42:be:24:9b:76:20, a VID # of 100 and a PCP of 0. tc filter add dev swp2 ingress protocol 802.1Q flower skip_sw \ dst_mac 42:be:24:9b:76:20 vlan_id 100 vlan_prio 0 action drop Under the hood, all rules match on DMAC, VID and PCP, but when VLAN filtering is disabled, those are set internally by the driver to the port-based defaults. Because we would be put in an awkward situation if the user were to change the VLAN filtering state while there are active rules (packets would no longer match on the specified keys), we simply deny changing vlan_filtering unless the list of flows offloaded via virtual links is empty. Then the user can re-add new rules. Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/dsa/sja1105/sja1105_flower.c')
-rw-r--r--drivers/net/dsa/sja1105/sja1105_flower.c57
1 files changed, 52 insertions, 5 deletions
diff --git a/drivers/net/dsa/sja1105/sja1105_flower.c b/drivers/net/dsa/sja1105/sja1105_flower.c
index 3246d5a49436..5f08eed0b1fc 100644
--- a/drivers/net/dsa/sja1105/sja1105_flower.c
+++ b/drivers/net/dsa/sja1105/sja1105_flower.c
@@ -2,9 +2,10 @@
/* Copyright 2020, NXP Semiconductors
*/
#include "sja1105.h"
+#include "sja1105_vl.h"
-static struct sja1105_rule *sja1105_rule_find(struct sja1105_private *priv,
- unsigned long cookie)
+struct sja1105_rule *sja1105_rule_find(struct sja1105_private *priv,
+ unsigned long cookie)
{
struct sja1105_rule *rule;
@@ -173,7 +174,8 @@ out:
static int sja1105_flower_policer(struct sja1105_private *priv, int port,
struct netlink_ext_ack *extack,
- unsigned long cookie, struct sja1105_key *key,
+ unsigned long cookie,
+ struct sja1105_key *key,
u64 rate_bytes_per_sec,
s64 burst)
{
@@ -308,6 +310,7 @@ int sja1105_cls_flower_add(struct dsa_switch *ds, int port,
const struct flow_action_entry *act;
unsigned long cookie = cls->cookie;
struct sja1105_key key;
+ bool vl_rule = false;
int rc, i;
rc = sja1105_flower_parse_key(priv, extack, cls, &key);
@@ -319,13 +322,50 @@ int sja1105_cls_flower_add(struct dsa_switch *ds, int port,
flow_action_for_each(i, act, &rule->action) {
switch (act->id) {
case FLOW_ACTION_POLICE:
- rc = sja1105_flower_policer(priv, port,
- extack, cookie, &key,
+ rc = sja1105_flower_policer(priv, port, extack, cookie,
+ &key,
act->police.rate_bytes_ps,
act->police.burst);
if (rc)
goto out;
break;
+ case FLOW_ACTION_TRAP: {
+ int cpu = dsa_upstream_port(ds, port);
+
+ vl_rule = true;
+
+ rc = sja1105_vl_redirect(priv, port, extack, cookie,
+ &key, BIT(cpu), true);
+ if (rc)
+ goto out;
+ break;
+ }
+ case FLOW_ACTION_REDIRECT: {
+ struct dsa_port *to_dp;
+
+ to_dp = dsa_port_from_netdev(act->dev);
+ if (IS_ERR(to_dp)) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "Destination not a switch port");
+ return -EOPNOTSUPP;
+ }
+
+ vl_rule = true;
+
+ rc = sja1105_vl_redirect(priv, port, extack, cookie,
+ &key, BIT(to_dp->index), true);
+ if (rc)
+ goto out;
+ break;
+ }
+ case FLOW_ACTION_DROP:
+ vl_rule = true;
+
+ rc = sja1105_vl_redirect(priv, port, extack, cookie,
+ &key, 0, false);
+ if (rc)
+ goto out;
+ break;
default:
NL_SET_ERR_MSG_MOD(extack,
"Action not supported");
@@ -333,6 +373,10 @@ int sja1105_cls_flower_add(struct dsa_switch *ds, int port,
goto out;
}
}
+
+ if (vl_rule && !rc)
+ rc = sja1105_static_config_reload(priv, SJA1105_VIRTUAL_LINKS);
+
out:
return rc;
}
@@ -348,6 +392,9 @@ int sja1105_cls_flower_del(struct dsa_switch *ds, int port,
if (!rule)
return 0;
+ if (rule->type == SJA1105_RULE_VL)
+ return sja1105_vl_delete(priv, port, rule, cls->common.extack);
+
policing = priv->static_config.tables[BLK_IDX_L2_POLICING].entries;
if (rule->type == SJA1105_RULE_BCAST_POLICER) {