forked from Openwrt/openwrt
6407ef8d2b
Reorder and update existing patches Signed-off-by: Felix Fietkau <nbd@nbd.name>
143 lines
3.8 KiB
Diff
143 lines
3.8 KiB
Diff
From ba8f870dfa635113ce6e8095a5eb1835ecde2e9e Mon Sep 17 00:00:00 2001
|
|
From: Ansuel Smith <ansuelsmth@gmail.com>
|
|
Date: Mon, 22 Nov 2021 16:23:48 +0100
|
|
Subject: net: dsa: qca8k: add support for mdb_add/del
|
|
|
|
Add support for mdb add/del function. The ARL table is used to insert
|
|
the rule. The rule will be searched, deleted and reinserted with the
|
|
port mask updated. The function will check if the rule has to be updated
|
|
or insert directly with no deletion of the old rule.
|
|
If every port is removed from the port mask, the rule is removed.
|
|
The rule is set STATIC in the ARL table (aka it doesn't age) to not be
|
|
flushed by fast age function.
|
|
|
|
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
|
|
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
|
|
Signed-off-by: David S. Miller <davem@davemloft.net>
|
|
---
|
|
drivers/net/dsa/qca8k.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++
|
|
1 file changed, 99 insertions(+)
|
|
|
|
--- a/drivers/net/dsa/qca8k.c
|
|
+++ b/drivers/net/dsa/qca8k.c
|
|
@@ -436,6 +436,81 @@ qca8k_fdb_flush(struct qca8k_priv *priv)
|
|
}
|
|
|
|
static int
|
|
+qca8k_fdb_search_and_insert(struct qca8k_priv *priv, u8 port_mask,
|
|
+ const u8 *mac, u16 vid)
|
|
+{
|
|
+ struct qca8k_fdb fdb = { 0 };
|
|
+ int ret;
|
|
+
|
|
+ mutex_lock(&priv->reg_mutex);
|
|
+
|
|
+ qca8k_fdb_write(priv, vid, 0, mac, 0);
|
|
+ ret = qca8k_fdb_access(priv, QCA8K_FDB_SEARCH, -1);
|
|
+ if (ret < 0)
|
|
+ goto exit;
|
|
+
|
|
+ ret = qca8k_fdb_read(priv, &fdb);
|
|
+ if (ret < 0)
|
|
+ goto exit;
|
|
+
|
|
+ /* Rule exist. Delete first */
|
|
+ if (!fdb.aging) {
|
|
+ ret = qca8k_fdb_access(priv, QCA8K_FDB_PURGE, -1);
|
|
+ if (ret)
|
|
+ goto exit;
|
|
+ }
|
|
+
|
|
+ /* Add port to fdb portmask */
|
|
+ fdb.port_mask |= port_mask;
|
|
+
|
|
+ qca8k_fdb_write(priv, vid, fdb.port_mask, mac, fdb.aging);
|
|
+ ret = qca8k_fdb_access(priv, QCA8K_FDB_LOAD, -1);
|
|
+
|
|
+exit:
|
|
+ mutex_unlock(&priv->reg_mutex);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static int
|
|
+qca8k_fdb_search_and_del(struct qca8k_priv *priv, u8 port_mask,
|
|
+ const u8 *mac, u16 vid)
|
|
+{
|
|
+ struct qca8k_fdb fdb = { 0 };
|
|
+ int ret;
|
|
+
|
|
+ mutex_lock(&priv->reg_mutex);
|
|
+
|
|
+ qca8k_fdb_write(priv, vid, 0, mac, 0);
|
|
+ ret = qca8k_fdb_access(priv, QCA8K_FDB_SEARCH, -1);
|
|
+ if (ret < 0)
|
|
+ goto exit;
|
|
+
|
|
+ /* Rule doesn't exist. Why delete? */
|
|
+ if (!fdb.aging) {
|
|
+ ret = -EINVAL;
|
|
+ goto exit;
|
|
+ }
|
|
+
|
|
+ ret = qca8k_fdb_access(priv, QCA8K_FDB_PURGE, -1);
|
|
+ if (ret)
|
|
+ goto exit;
|
|
+
|
|
+ /* Only port in the rule is this port. Don't re insert */
|
|
+ if (fdb.port_mask == port_mask)
|
|
+ goto exit;
|
|
+
|
|
+ /* Remove port from port mask */
|
|
+ fdb.port_mask &= ~port_mask;
|
|
+
|
|
+ qca8k_fdb_write(priv, vid, fdb.port_mask, mac, fdb.aging);
|
|
+ ret = qca8k_fdb_access(priv, QCA8K_FDB_LOAD, -1);
|
|
+
|
|
+exit:
|
|
+ mutex_unlock(&priv->reg_mutex);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static int
|
|
qca8k_vlan_access(struct qca8k_priv *priv, enum qca8k_vlan_cmd cmd, u16 vid)
|
|
{
|
|
u32 reg;
|
|
@@ -1949,6 +2024,28 @@ qca8k_port_fdb_dump(struct dsa_switch *d
|
|
}
|
|
|
|
static int
|
|
+qca8k_port_mdb_add(struct dsa_switch *ds, int port,
|
|
+ const struct switchdev_obj_port_mdb *mdb)
|
|
+{
|
|
+ struct qca8k_priv *priv = ds->priv;
|
|
+ const u8 *addr = mdb->addr;
|
|
+ u16 vid = mdb->vid;
|
|
+
|
|
+ return qca8k_fdb_search_and_insert(priv, BIT(port), addr, vid);
|
|
+}
|
|
+
|
|
+static int
|
|
+qca8k_port_mdb_del(struct dsa_switch *ds, int port,
|
|
+ const struct switchdev_obj_port_mdb *mdb)
|
|
+{
|
|
+ struct qca8k_priv *priv = ds->priv;
|
|
+ const u8 *addr = mdb->addr;
|
|
+ u16 vid = mdb->vid;
|
|
+
|
|
+ return qca8k_fdb_search_and_del(priv, BIT(port), addr, vid);
|
|
+}
|
|
+
|
|
+static int
|
|
qca8k_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering,
|
|
struct netlink_ext_ack *extack)
|
|
{
|
|
@@ -2056,6 +2153,8 @@ static const struct dsa_switch_ops qca8k
|
|
.port_fdb_add = qca8k_port_fdb_add,
|
|
.port_fdb_del = qca8k_port_fdb_del,
|
|
.port_fdb_dump = qca8k_port_fdb_dump,
|
|
+ .port_mdb_add = qca8k_port_mdb_add,
|
|
+ .port_mdb_del = qca8k_port_mdb_del,
|
|
.port_vlan_filtering = qca8k_port_vlan_filtering,
|
|
.port_vlan_add = qca8k_port_vlan_add,
|
|
.port_vlan_del = qca8k_port_vlan_del,
|