From c467011d7ea11c7c3f728dc73b433cc3c0b67b80 Mon Sep 17 00:00:00 2001
From: Tobias Waldekranz <tobias@waldekranz.com>
Date: Tue, 16 Jan 2024 16:00:55 +0100
Subject: [PATCH 20/33] net: dsa: Support MDB memberships whose L2 addresses
 overlap
Organization: Wires

Multiple IP multicast groups (32 for v4, 2^80 for v6) map to the same
L2 address. This means that switchdev drivers may receive multiple MDB
additions for a particular L2 group on the same port. Since these were
not reference counted before this change, removing a group membership
after two overlapping memberships had been added would result in the
membership being removed from hardware, even though one reference to
the address still remained.

Steps to reproduce:

    root@infix:~# mvls atu | grep 01:02:03
    root@infix:~# bridge mdb add dev br0 port e8 grp 238.1.2.3 permanent
    root@infix:~# bridge mdb add dev br0 port e8 grp 239.1.2.3 permanent
    root@infix:~# mvls atu | grep 01:02:03
    01:00:5e:01:02:03     1  static     -  -  .  .  .  .  .  .  .  .  8  .  .
    root@infix:~# bridge mdb del dev br0 port e8 grp 239.1.2.3
    root@infix:~# mvls atu | grep 01:02:03
    root@infix:~#

Therefore, reference count MDB memberships and keep them in hardware
as long as the count is positive. Fortunately, all the infrastructure
needed to do this is already in place, since it is also needed on CPU
and DSA ports. Thus, "implement" this by simply removing the guards
which previously skipped reference countung on user ports.
---
 net/dsa/switch.c | 16 ----------------
 1 file changed, 16 deletions(-)

diff --git a/net/dsa/switch.c b/net/dsa/switch.c
index 3d2feeea897b..628e8a884dde 100644
--- a/net/dsa/switch.c
+++ b/net/dsa/switch.c
@@ -164,14 +164,6 @@ static int dsa_port_do_mdb_add(struct dsa_port *dp,
 	int port = dp->index;
 	int err = 0;
 
-	/* No need to bother with refcounting for user ports */
-	if (!(dsa_port_is_cpu(dp) || dsa_port_is_dsa(dp))) {
-		err = ds->ops->port_mdb_add(ds, port, mdb, db);
-		trace_dsa_mdb_add_hw(dp, mdb->addr, mdb->vid, &db, err);
-
-		return err;
-	}
-
 	mutex_lock(&dp->addr_lists_lock);
 
 	a = dsa_mac_addr_find(&dp->mdbs, mdb->addr, mdb->vid, db);
@@ -216,14 +208,6 @@ static int dsa_port_do_mdb_del(struct dsa_port *dp,
 	int port = dp->index;
 	int err = 0;
 
-	/* No need to bother with refcounting for user ports */
-	if (!(dsa_port_is_cpu(dp) || dsa_port_is_dsa(dp))) {
-		err = ds->ops->port_mdb_del(ds, port, mdb, db);
-		trace_dsa_mdb_del_hw(dp, mdb->addr, mdb->vid, &db, err);
-
-		return err;
-	}
-
 	mutex_lock(&dp->addr_lists_lock);
 
 	a = dsa_mac_addr_find(&dp->mdbs, mdb->addr, mdb->vid, db);
