All of lore.kernel.org
 help / color / mirror / Atom feed
* [patch net-next 00/16] mlxsw: Multicast flood update
@ 2017-09-20 14:15 Jiri Pirko
  2017-09-20 14:15 ` [patch net-next 01/16] mlxsw: spectrum_switchdev: Change mc_router to mrouter Jiri Pirko
                   ` (16 more replies)
  0 siblings, 17 replies; 18+ messages in thread
From: Jiri Pirko @ 2017-09-20 14:15 UTC (permalink / raw)
  To: netdev; +Cc: davem, nogahf, idosch, mlxsw

From: Jiri Pirko <jiri@mellanox.com>

Nogah says:

Currently, there are four erroneous flows in MC flood:
1. When MC is disabled it affects only the flood table for unregistered
   MC packets, but packets that match an entry in the MDB are unaffected.
2. When MC is disabled, MC packets are being sent to all the ports in the
   bridge (like BC and link-local MC packets) regardless of the designated
   flag (BR_MCAST_FLAG).
3. When a port is being deleted from a bridge it might remain in the MDB.
4. When MC is enabled packets are flooded to the mrouter ports only if
   they don't match any entry in the MDB, when they should always be
   flooded to them.

What these problems have in common is the discrepancy between how the
hardware handles MDB and mcast flood, and how the driver does it. Each
of these problems needs fixing either in the MDB code, or in mcast flood
code, and some in both.

Patches 1-6 change the way the MDB is handled in the driver to make the
following changes easier.
Patches 7-8 fix problem number 1 by removing the MDB from the HW when MC
is being disabled and restoring it when it is being enabled.
Patches 9-10 fix problem number 2 by offloading the flood table by the
appropriate flag.
Patch 11 fixes problem number 3 by adding MDB flush to the port removal.
Patches 12-14 fix problem number 4 by adding the mrouter ports to every
MDB entry in the HW to mimic the wanted behaviour.

Nogah Frankel (16):
  mlxsw: spectrum_switchdev: Change mc_router to mrouter
  mlxsw: spectrum_switchdev: Add a ports bitmap to the mid db
  mlxsw: spectrum_switchdev: Remove reference count from mid
  mlxsw: spectrum_switchdev: Save mids list per bridge device
  mlxsw: spectrum_switchdev: Break smid write function
  mlxsw: spectrum_switchdev: Attach mid id allocation to HW write
  mlxsw: spectrum_switchdev: Break mid deletion into two function
  mlxsw: spectrum_switchdev: Don't write mids to the HW when mc is
    disabled
  mlxsw: spectrum_switchdev: Disable mdb when mc is disabled
  mlxsw: spectrum_switchdev: Use generic mc flood function
  mlxsw: spectrum_switchdev: Flood mc when mc is disabled by user flag
  mlxsw: spectrum_switchdev: Flush the mdb when a port is being removed
  mlxsw: spectrum_switchdev: Flood all mc packets to mrouter ports
  mlxsw: spectrum_switchdev: Update the mdb of mrouter port change
  mlxsw: spectrum_switchdev: Remove mrouter flood in mdb flush
  mlxsw: spectrum_switchdev: Consider mrouter status for mdb changes

 drivers/net/ethernet/mellanox/mlxsw/spectrum.h     |   3 +-
 .../ethernet/mellanox/mlxsw/spectrum_switchdev.c   | 417 ++++++++++++++++-----
 2 files changed, 323 insertions(+), 97 deletions(-)

-- 
2.9.5

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [patch net-next 01/16] mlxsw: spectrum_switchdev: Change mc_router to mrouter
  2017-09-20 14:15 [patch net-next 00/16] mlxsw: Multicast flood update Jiri Pirko
@ 2017-09-20 14:15 ` Jiri Pirko
  2017-09-20 14:15 ` [patch net-next 02/16] mlxsw: spectrum_switchdev: Add a ports bitmap to the mid db Jiri Pirko
                   ` (15 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Jiri Pirko @ 2017-09-20 14:15 UTC (permalink / raw)
  To: netdev; +Cc: davem, nogahf, idosch, mlxsw

From: Nogah Frankel <nogahf@mellanox.com>

Change the naming of mc_router to mrouter to keep consistency.

Signed-off-by: Nogah Frankel <nogahf@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 .../net/ethernet/mellanox/mlxsw/spectrum_switchdev.c   | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index d39ffbf..22f8d74 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -699,10 +699,10 @@ static int mlxsw_sp_port_attr_br_vlan_set(struct mlxsw_sp_port *mlxsw_sp_port,
 	return -EINVAL;
 }
 
-static int mlxsw_sp_port_attr_mc_router_set(struct mlxsw_sp_port *mlxsw_sp_port,
-					    struct switchdev_trans *trans,
-					    struct net_device *orig_dev,
-					    bool is_port_mc_router)
+static int mlxsw_sp_port_attr_mrouter_set(struct mlxsw_sp_port *mlxsw_sp_port,
+					  struct switchdev_trans *trans,
+					  struct net_device *orig_dev,
+					  bool is_port_mrouter)
 {
 	struct mlxsw_sp_bridge_port *bridge_port;
 	int err;
@@ -720,12 +720,12 @@ static int mlxsw_sp_port_attr_mc_router_set(struct mlxsw_sp_port *mlxsw_sp_port,
 
 	err = mlxsw_sp_bridge_port_flood_table_set(mlxsw_sp_port, bridge_port,
 						   MLXSW_SP_FLOOD_TYPE_MC,
-						   is_port_mc_router);
+						   is_port_mrouter);
 	if (err)
 		return err;
 
 out:
-	bridge_port->mrouter = is_port_mc_router;
+	bridge_port->mrouter = is_port_mrouter;
 	return 0;
 }
 
@@ -793,9 +793,9 @@ static int mlxsw_sp_port_attr_set(struct net_device *dev,
 						     attr->u.vlan_filtering);
 		break;
 	case SWITCHDEV_ATTR_ID_PORT_MROUTER:
-		err = mlxsw_sp_port_attr_mc_router_set(mlxsw_sp_port, trans,
-						       attr->orig_dev,
-						       attr->u.mrouter);
+		err = mlxsw_sp_port_attr_mrouter_set(mlxsw_sp_port, trans,
+						     attr->orig_dev,
+						     attr->u.mrouter);
 		break;
 	case SWITCHDEV_ATTR_ID_BRIDGE_MC_DISABLED:
 		err = mlxsw_sp_port_mc_disabled_set(mlxsw_sp_port, trans,
-- 
2.9.5

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [patch net-next 02/16] mlxsw: spectrum_switchdev: Add a ports bitmap to the mid db
  2017-09-20 14:15 [patch net-next 00/16] mlxsw: Multicast flood update Jiri Pirko
  2017-09-20 14:15 ` [patch net-next 01/16] mlxsw: spectrum_switchdev: Change mc_router to mrouter Jiri Pirko
@ 2017-09-20 14:15 ` Jiri Pirko
  2017-09-20 14:15 ` [patch net-next 03/16] mlxsw: spectrum_switchdev: Remove reference count from mid Jiri Pirko
                   ` (14 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Jiri Pirko @ 2017-09-20 14:15 UTC (permalink / raw)
  To: netdev; +Cc: davem, nogahf, idosch, mlxsw

From: Nogah Frankel <nogahf@mellanox.com>

Add a bitmap of ports to the mid struct to hold the ports that are
registered to this mid.

Signed-off-by: Nogah Frankel <nogahf@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.h       |  1 +
 .../net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 20 +++++++++++++++++---
 2 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index 7180d8f..0424bee 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -95,6 +95,7 @@ struct mlxsw_sp_mid {
 	u16 fid;
 	u16 mid;
 	unsigned int ref_count;
+	unsigned long *ports_in_mid; /* bits array */
 };
 
 enum mlxsw_sp_span_type {
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 22f8d74..0fde16a 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -1239,6 +1239,7 @@ static struct mlxsw_sp_mid *__mlxsw_sp_mc_alloc(struct mlxsw_sp *mlxsw_sp,
 						u16 fid)
 {
 	struct mlxsw_sp_mid *mid;
+	size_t alloc_size;
 	u16 mid_idx;
 
 	mid_idx = find_first_zero_bit(mlxsw_sp->bridge->mids_bitmap,
@@ -1250,6 +1251,14 @@ static struct mlxsw_sp_mid *__mlxsw_sp_mc_alloc(struct mlxsw_sp *mlxsw_sp,
 	if (!mid)
 		return NULL;
 
+	alloc_size = sizeof(unsigned long) *
+		     BITS_TO_LONGS(mlxsw_core_max_ports(mlxsw_sp->core));
+	mid->ports_in_mid = kzalloc(alloc_size, GFP_KERNEL);
+	if (!mid->ports_in_mid) {
+		kfree(mid);
+		return NULL;
+	}
+
 	set_bit(mid_idx, mlxsw_sp->bridge->mids_bitmap);
 	ether_addr_copy(mid->addr, addr);
 	mid->fid = fid;
@@ -1260,12 +1269,16 @@ static struct mlxsw_sp_mid *__mlxsw_sp_mc_alloc(struct mlxsw_sp *mlxsw_sp,
 	return mid;
 }
 
-static int __mlxsw_sp_mc_dec_ref(struct mlxsw_sp *mlxsw_sp,
+static int __mlxsw_sp_mc_dec_ref(struct mlxsw_sp_port *mlxsw_sp_port,
 				 struct mlxsw_sp_mid *mid)
 {
+	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+
+	clear_bit(mlxsw_sp_port->local_port, mid->ports_in_mid);
 	if (--mid->ref_count == 0) {
 		list_del(&mid->list);
 		clear_bit(mid->mid, mlxsw_sp->bridge->mids_bitmap);
+		kfree(mid->ports_in_mid);
 		kfree(mid);
 		return 1;
 	}
@@ -1311,6 +1324,7 @@ static int mlxsw_sp_port_mdb_add(struct mlxsw_sp_port *mlxsw_sp_port,
 		}
 	}
 	mid->ref_count++;
+	set_bit(mlxsw_sp_port->local_port, mid->ports_in_mid);
 
 	err = mlxsw_sp_port_smid_set(mlxsw_sp_port, mid->mid, true,
 				     mid->ref_count == 1);
@@ -1331,7 +1345,7 @@ static int mlxsw_sp_port_mdb_add(struct mlxsw_sp_port *mlxsw_sp_port,
 	return 0;
 
 err_out:
-	__mlxsw_sp_mc_dec_ref(mlxsw_sp, mid);
+	__mlxsw_sp_mc_dec_ref(mlxsw_sp_port, mid);
 	return err;
 }
 
@@ -1437,7 +1451,7 @@ static int mlxsw_sp_port_mdb_del(struct mlxsw_sp_port *mlxsw_sp_port,
 		netdev_err(dev, "Unable to remove port from SMID\n");
 
 	mid_idx = mid->mid;
-	if (__mlxsw_sp_mc_dec_ref(mlxsw_sp, mid)) {
+	if (__mlxsw_sp_mc_dec_ref(mlxsw_sp_port, mid)) {
 		err = mlxsw_sp_port_mdb_op(mlxsw_sp, mdb->addr, fid_index,
 					   mid_idx, false);
 		if (err)
-- 
2.9.5

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [patch net-next 03/16] mlxsw: spectrum_switchdev: Remove reference count from mid
  2017-09-20 14:15 [patch net-next 00/16] mlxsw: Multicast flood update Jiri Pirko
  2017-09-20 14:15 ` [patch net-next 01/16] mlxsw: spectrum_switchdev: Change mc_router to mrouter Jiri Pirko
  2017-09-20 14:15 ` [patch net-next 02/16] mlxsw: spectrum_switchdev: Add a ports bitmap to the mid db Jiri Pirko
@ 2017-09-20 14:15 ` Jiri Pirko
  2017-09-20 14:15 ` [patch net-next 04/16] mlxsw: spectrum_switchdev: Save mids list per bridge device Jiri Pirko
                   ` (13 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Jiri Pirko @ 2017-09-20 14:15 UTC (permalink / raw)
  To: netdev; +Cc: davem, nogahf, idosch, mlxsw

From: Nogah Frankel <nogahf@mellanox.com>

Since there is a bitmap for the ports registered to each mid, there is no
need for a ref count, since it will always be the number of set bits in
this bitmap. Any check of the ref count was replaced with checking if the
bitmap is empty.

Signed-off-by: Nogah Frankel <nogahf@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.h       |  1 -
 .../net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 20 ++++++++++----------
 2 files changed, 10 insertions(+), 11 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index 0424bee..6fd0afe 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -94,7 +94,6 @@ struct mlxsw_sp_mid {
 	unsigned char addr[ETH_ALEN];
 	u16 fid;
 	u16 mid;
-	unsigned int ref_count;
 	unsigned long *ports_in_mid; /* bits array */
 };
 
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 0fde16a..cb2275ed 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -1263,19 +1263,19 @@ static struct mlxsw_sp_mid *__mlxsw_sp_mc_alloc(struct mlxsw_sp *mlxsw_sp,
 	ether_addr_copy(mid->addr, addr);
 	mid->fid = fid;
 	mid->mid = mid_idx;
-	mid->ref_count = 0;
 	list_add_tail(&mid->list, &mlxsw_sp->bridge->mids_list);
 
 	return mid;
 }
 
-static int __mlxsw_sp_mc_dec_ref(struct mlxsw_sp_port *mlxsw_sp_port,
-				 struct mlxsw_sp_mid *mid)
+static int mlxsw_sp_port_remove_from_mid(struct mlxsw_sp_port *mlxsw_sp_port,
+					 struct mlxsw_sp_mid *mid)
 {
 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
 
 	clear_bit(mlxsw_sp_port->local_port, mid->ports_in_mid);
-	if (--mid->ref_count == 0) {
+	if (bitmap_empty(mid->ports_in_mid,
+			 mlxsw_core_max_ports(mlxsw_sp->core))) {
 		list_del(&mid->list);
 		clear_bit(mid->mid, mlxsw_sp->bridge->mids_bitmap);
 		kfree(mid->ports_in_mid);
@@ -1296,6 +1296,7 @@ static int mlxsw_sp_port_mdb_add(struct mlxsw_sp_port *mlxsw_sp_port,
 	struct mlxsw_sp_bridge_device *bridge_device;
 	struct mlxsw_sp_bridge_port *bridge_port;
 	struct mlxsw_sp_mid *mid;
+	bool is_new_mid = false;
 	u16 fid_index;
 	int err = 0;
 
@@ -1322,18 +1323,17 @@ static int mlxsw_sp_port_mdb_add(struct mlxsw_sp_port *mlxsw_sp_port,
 			netdev_err(dev, "Unable to allocate MC group\n");
 			return -ENOMEM;
 		}
+		is_new_mid = true;
 	}
-	mid->ref_count++;
 	set_bit(mlxsw_sp_port->local_port, mid->ports_in_mid);
 
-	err = mlxsw_sp_port_smid_set(mlxsw_sp_port, mid->mid, true,
-				     mid->ref_count == 1);
+	err = mlxsw_sp_port_smid_set(mlxsw_sp_port, mid->mid, true, is_new_mid);
 	if (err) {
 		netdev_err(dev, "Unable to set SMID\n");
 		goto err_out;
 	}
 
-	if (mid->ref_count == 1) {
+	if (is_new_mid) {
 		err = mlxsw_sp_port_mdb_op(mlxsw_sp, mdb->addr, fid_index,
 					   mid->mid, true);
 		if (err) {
@@ -1345,7 +1345,7 @@ static int mlxsw_sp_port_mdb_add(struct mlxsw_sp_port *mlxsw_sp_port,
 	return 0;
 
 err_out:
-	__mlxsw_sp_mc_dec_ref(mlxsw_sp_port, mid);
+	mlxsw_sp_port_remove_from_mid(mlxsw_sp_port, mid);
 	return err;
 }
 
@@ -1451,7 +1451,7 @@ static int mlxsw_sp_port_mdb_del(struct mlxsw_sp_port *mlxsw_sp_port,
 		netdev_err(dev, "Unable to remove port from SMID\n");
 
 	mid_idx = mid->mid;
-	if (__mlxsw_sp_mc_dec_ref(mlxsw_sp_port, mid)) {
+	if (mlxsw_sp_port_remove_from_mid(mlxsw_sp_port, mid)) {
 		err = mlxsw_sp_port_mdb_op(mlxsw_sp, mdb->addr, fid_index,
 					   mid_idx, false);
 		if (err)
-- 
2.9.5

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [patch net-next 04/16] mlxsw: spectrum_switchdev: Save mids list per bridge device
  2017-09-20 14:15 [patch net-next 00/16] mlxsw: Multicast flood update Jiri Pirko
                   ` (2 preceding siblings ...)
  2017-09-20 14:15 ` [patch net-next 03/16] mlxsw: spectrum_switchdev: Remove reference count from mid Jiri Pirko
@ 2017-09-20 14:15 ` Jiri Pirko
  2017-09-20 14:15 ` [patch net-next 05/16] mlxsw: spectrum_switchdev: Break smid write function Jiri Pirko
                   ` (12 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Jiri Pirko @ 2017-09-20 14:15 UTC (permalink / raw)
  To: netdev; +Cc: davem, nogahf, idosch, mlxsw

From: Nogah Frankel <nogahf@mellanox.com>

Instead of saving all the mids in the same list, save them per vlan
device. This change allows a more efficient mid find.
Also, in the next patches, there will be added a lot of loops over all the
mids in bridge device for multicast disable, mrouter change and ndb flush.

Signed-off-by: Nogah Frankel <nogahf@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 .../ethernet/mellanox/mlxsw/spectrum_switchdev.c   | 49 +++++++++++-----------
 1 file changed, 24 insertions(+), 25 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index cb2275ed..2ba8a44 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -67,7 +67,6 @@ struct mlxsw_sp_bridge {
 	u32 ageing_time;
 	bool vlan_enabled_exists;
 	struct list_head bridges_list;
-	struct list_head mids_list;
 	DECLARE_BITMAP(mids_bitmap, MLXSW_SP_MID_MAX);
 	const struct mlxsw_sp_bridge_ops *bridge_8021q_ops;
 	const struct mlxsw_sp_bridge_ops *bridge_8021d_ops;
@@ -77,6 +76,7 @@ struct mlxsw_sp_bridge_device {
 	struct net_device *dev;
 	struct list_head list;
 	struct list_head ports_list;
+	struct list_head mids_list;
 	u8 vlan_enabled:1,
 	   multicast_enabled:1;
 	const struct mlxsw_sp_bridge_ops *ops;
@@ -161,6 +161,7 @@ mlxsw_sp_bridge_device_create(struct mlxsw_sp_bridge *bridge,
 	} else {
 		bridge_device->ops = bridge->bridge_8021d_ops;
 	}
+	INIT_LIST_HEAD(&bridge_device->mids_list);
 	list_add(&bridge_device->list, &bridge->bridges_list);
 
 	return bridge_device;
@@ -170,10 +171,17 @@ static void
 mlxsw_sp_bridge_device_destroy(struct mlxsw_sp_bridge *bridge,
 			       struct mlxsw_sp_bridge_device *bridge_device)
 {
+	struct mlxsw_sp_mid *mid, *tmp;
+
 	list_del(&bridge_device->list);
 	if (bridge_device->vlan_enabled)
 		bridge->vlan_enabled_exists = false;
 	WARN_ON(!list_empty(&bridge_device->ports_list));
+	list_for_each_entry_safe(mid, tmp, &bridge_device->mids_list, list) {
+		list_del(&mid->list);
+		clear_bit(mid->mid, bridge->mids_bitmap);
+		kfree(mid);
+	}
 	kfree(bridge_device);
 }
 
@@ -1221,22 +1229,25 @@ static int mlxsw_sp_port_smid_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 mid,
 	return err;
 }
 
-static struct mlxsw_sp_mid *__mlxsw_sp_mc_get(struct mlxsw_sp *mlxsw_sp,
-					      const unsigned char *addr,
-					      u16 fid)
+static struct
+mlxsw_sp_mid *__mlxsw_sp_mc_get(struct mlxsw_sp_bridge_device *bridge_device,
+				const unsigned char *addr,
+				u16 fid)
 {
 	struct mlxsw_sp_mid *mid;
 
-	list_for_each_entry(mid, &mlxsw_sp->bridge->mids_list, list) {
+	list_for_each_entry(mid, &bridge_device->mids_list, list) {
 		if (ether_addr_equal(mid->addr, addr) && mid->fid == fid)
 			return mid;
 	}
 	return NULL;
 }
 
-static struct mlxsw_sp_mid *__mlxsw_sp_mc_alloc(struct mlxsw_sp *mlxsw_sp,
-						const unsigned char *addr,
-						u16 fid)
+static struct
+mlxsw_sp_mid *__mlxsw_sp_mc_alloc(struct mlxsw_sp *mlxsw_sp,
+				  struct mlxsw_sp_bridge_device *bridge_device,
+				  const unsigned char *addr,
+				  u16 fid)
 {
 	struct mlxsw_sp_mid *mid;
 	size_t alloc_size;
@@ -1263,7 +1274,7 @@ static struct mlxsw_sp_mid *__mlxsw_sp_mc_alloc(struct mlxsw_sp *mlxsw_sp,
 	ether_addr_copy(mid->addr, addr);
 	mid->fid = fid;
 	mid->mid = mid_idx;
-	list_add_tail(&mid->list, &mlxsw_sp->bridge->mids_list);
+	list_add_tail(&mid->list, &bridge_device->mids_list);
 
 	return mid;
 }
@@ -1316,9 +1327,10 @@ static int mlxsw_sp_port_mdb_add(struct mlxsw_sp_port *mlxsw_sp_port,
 
 	fid_index = mlxsw_sp_fid_index(mlxsw_sp_port_vlan->fid);
 
-	mid = __mlxsw_sp_mc_get(mlxsw_sp, mdb->addr, fid_index);
+	mid = __mlxsw_sp_mc_get(bridge_device, mdb->addr, fid_index);
 	if (!mid) {
-		mid = __mlxsw_sp_mc_alloc(mlxsw_sp, mdb->addr, fid_index);
+		mid = __mlxsw_sp_mc_alloc(mlxsw_sp, bridge_device, mdb->addr,
+					  fid_index);
 		if (!mid) {
 			netdev_err(dev, "Unable to allocate MC group\n");
 			return -ENOMEM;
@@ -1440,7 +1452,7 @@ static int mlxsw_sp_port_mdb_del(struct mlxsw_sp_port *mlxsw_sp_port,
 
 	fid_index = mlxsw_sp_fid_index(mlxsw_sp_port_vlan->fid);
 
-	mid = __mlxsw_sp_mc_get(mlxsw_sp, mdb->addr, fid_index);
+	mid = __mlxsw_sp_mc_get(bridge_device, mdb->addr, fid_index);
 	if (!mid) {
 		netdev_err(dev, "Unable to remove port from MC DB\n");
 		return -EINVAL;
@@ -1995,17 +2007,6 @@ static void mlxsw_sp_fdb_fini(struct mlxsw_sp *mlxsw_sp)
 
 }
 
-static void mlxsw_sp_mids_fini(struct mlxsw_sp *mlxsw_sp)
-{
-	struct mlxsw_sp_mid *mid, *tmp;
-
-	list_for_each_entry_safe(mid, tmp, &mlxsw_sp->bridge->mids_list, list) {
-		list_del(&mid->list);
-		clear_bit(mid->mid, mlxsw_sp->bridge->mids_bitmap);
-		kfree(mid);
-	}
-}
-
 int mlxsw_sp_switchdev_init(struct mlxsw_sp *mlxsw_sp)
 {
 	struct mlxsw_sp_bridge *bridge;
@@ -2017,7 +2018,6 @@ int mlxsw_sp_switchdev_init(struct mlxsw_sp *mlxsw_sp)
 	bridge->mlxsw_sp = mlxsw_sp;
 
 	INIT_LIST_HEAD(&mlxsw_sp->bridge->bridges_list);
-	INIT_LIST_HEAD(&mlxsw_sp->bridge->mids_list);
 
 	bridge->bridge_8021q_ops = &mlxsw_sp_bridge_8021q_ops;
 	bridge->bridge_8021d_ops = &mlxsw_sp_bridge_8021d_ops;
@@ -2028,7 +2028,6 @@ int mlxsw_sp_switchdev_init(struct mlxsw_sp *mlxsw_sp)
 void mlxsw_sp_switchdev_fini(struct mlxsw_sp *mlxsw_sp)
 {
 	mlxsw_sp_fdb_fini(mlxsw_sp);
-	mlxsw_sp_mids_fini(mlxsw_sp);
 	WARN_ON(!list_empty(&mlxsw_sp->bridge->bridges_list));
 	kfree(mlxsw_sp->bridge);
 }
-- 
2.9.5

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [patch net-next 05/16] mlxsw: spectrum_switchdev: Break smid write function
  2017-09-20 14:15 [patch net-next 00/16] mlxsw: Multicast flood update Jiri Pirko
                   ` (3 preceding siblings ...)
  2017-09-20 14:15 ` [patch net-next 04/16] mlxsw: spectrum_switchdev: Save mids list per bridge device Jiri Pirko
@ 2017-09-20 14:15 ` Jiri Pirko
  2017-09-20 14:15 ` [patch net-next 06/16] mlxsw: spectrum_switchdev: Attach mid id allocation to HW write Jiri Pirko
                   ` (11 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Jiri Pirko @ 2017-09-20 14:15 UTC (permalink / raw)
  To: netdev; +Cc: davem, nogahf, idosch, mlxsw

From: Nogah Frankel <nogahf@mellanox.com>

Break the smid write function into two, one that cleans the ports that
might be still written there and one that changes an exiting mid entry.

Signed-off-by: Nogah Frankel <nogahf@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 .../ethernet/mellanox/mlxsw/spectrum_switchdev.c   | 42 +++++++++++++++-------
 1 file changed, 30 insertions(+), 12 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 2ba8a44..09ead97 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -1190,7 +1190,7 @@ mlxsw_sp_port_fdb_set(struct mlxsw_sp_port *mlxsw_sp_port,
 }
 
 static int mlxsw_sp_port_mdb_op(struct mlxsw_sp *mlxsw_sp, const char *addr,
-				u16 fid, u16 mid, bool adding)
+				u16 fid, u16 mid_idx, bool adding)
 {
 	char *sfd_pl;
 	int err;
@@ -1201,16 +1201,16 @@ static int mlxsw_sp_port_mdb_op(struct mlxsw_sp *mlxsw_sp, const char *addr,
 
 	mlxsw_reg_sfd_pack(sfd_pl, mlxsw_sp_sfd_op(adding), 0);
 	mlxsw_reg_sfd_mc_pack(sfd_pl, 0, addr, fid,
-			      MLXSW_REG_SFD_REC_ACTION_NOP, mid);
+			      MLXSW_REG_SFD_REC_ACTION_NOP, mid_idx);
 	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfd), sfd_pl);
 	kfree(sfd_pl);
 	return err;
 }
 
-static int mlxsw_sp_port_smid_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 mid,
-				  bool add, bool clear_all_ports)
+/* clean the an entry from the HW and write there a full new entry */
+static int mlxsw_sp_port_smid_full_entry(struct mlxsw_sp *mlxsw_sp,
+					 u16 mid_idx)
 {
-	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
 	char *smid_pl;
 	int err, i;
 
@@ -1218,12 +1218,29 @@ static int mlxsw_sp_port_smid_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 mid,
 	if (!smid_pl)
 		return -ENOMEM;
 
-	mlxsw_reg_smid_pack(smid_pl, mid, mlxsw_sp_port->local_port, add);
-	if (clear_all_ports) {
-		for (i = 1; i < mlxsw_core_max_ports(mlxsw_sp->core); i++)
-			if (mlxsw_sp->ports[i])
-				mlxsw_reg_smid_port_mask_set(smid_pl, i, 1);
+	mlxsw_reg_smid_pack(smid_pl, mid_idx, 0, false);
+	for (i = 1; i < mlxsw_core_max_ports(mlxsw_sp->core); i++) {
+		if (mlxsw_sp->ports[i])
+			mlxsw_reg_smid_port_mask_set(smid_pl, i, 1);
 	}
+
+	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(smid), smid_pl);
+	kfree(smid_pl);
+	return err;
+}
+
+static int mlxsw_sp_port_smid_set(struct mlxsw_sp_port *mlxsw_sp_port,
+				  u16 mid_idx, bool add)
+{
+	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+	char *smid_pl;
+	int err;
+
+	smid_pl = kmalloc(MLXSW_REG_SMID_LEN, GFP_KERNEL);
+	if (!smid_pl)
+		return -ENOMEM;
+
+	mlxsw_reg_smid_pack(smid_pl, mid_idx, mlxsw_sp_port->local_port, add);
 	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(smid), smid_pl);
 	kfree(smid_pl);
 	return err;
@@ -1336,10 +1353,11 @@ static int mlxsw_sp_port_mdb_add(struct mlxsw_sp_port *mlxsw_sp_port,
 			return -ENOMEM;
 		}
 		is_new_mid = true;
+		mlxsw_sp_port_smid_full_entry(mlxsw_sp, mid->mid);
 	}
 	set_bit(mlxsw_sp_port->local_port, mid->ports_in_mid);
 
-	err = mlxsw_sp_port_smid_set(mlxsw_sp_port, mid->mid, true, is_new_mid);
+	err = mlxsw_sp_port_smid_set(mlxsw_sp_port, mid->mid, true);
 	if (err) {
 		netdev_err(dev, "Unable to set SMID\n");
 		goto err_out;
@@ -1458,7 +1476,7 @@ static int mlxsw_sp_port_mdb_del(struct mlxsw_sp_port *mlxsw_sp_port,
 		return -EINVAL;
 	}
 
-	err = mlxsw_sp_port_smid_set(mlxsw_sp_port, mid->mid, false, false);
+	err = mlxsw_sp_port_smid_set(mlxsw_sp_port, mid->mid, false);
 	if (err)
 		netdev_err(dev, "Unable to remove port from SMID\n");
 
-- 
2.9.5

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [patch net-next 06/16] mlxsw: spectrum_switchdev: Attach mid id allocation to HW write
  2017-09-20 14:15 [patch net-next 00/16] mlxsw: Multicast flood update Jiri Pirko
                   ` (4 preceding siblings ...)
  2017-09-20 14:15 ` [patch net-next 05/16] mlxsw: spectrum_switchdev: Break smid write function Jiri Pirko
@ 2017-09-20 14:15 ` Jiri Pirko
  2017-09-20 14:15 ` [patch net-next 07/16] mlxsw: spectrum_switchdev: Break mid deletion into two function Jiri Pirko
                   ` (10 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Jiri Pirko @ 2017-09-20 14:15 UTC (permalink / raw)
  To: netdev; +Cc: davem, nogahf, idosch, mlxsw

From: Nogah Frankel <nogahf@mellanox.com>

Attach mid getting and releasing mid id to the HW write / remove, and add
a flag to indicate whether the mid is in the HW. It is done because mid id
is also HW index to this mid.
This change allows adding in the following patches the ability to have a
mid in the mdb cache but not in the HW. It will be useful for being able
to disable the multicast.
It means that the mdb is being written / delete to the HW in the mid
allocation / removing function, not after them.

Signed-off-by: Nogah Frankel <nogahf@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.h     |  1 +
 .../ethernet/mellanox/mlxsw/spectrum_switchdev.c   | 88 ++++++++++++++--------
 2 files changed, 56 insertions(+), 33 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index 6fd0afe..e907ec4 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -94,6 +94,7 @@ struct mlxsw_sp_mid {
 	unsigned char addr[ETH_ALEN];
 	u16 fid;
 	u16 mid;
+	bool in_hw;
 	unsigned long *ports_in_mid; /* bits array */
 };
 
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 09ead97..9dd05d8 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -1260,6 +1260,42 @@ mlxsw_sp_mid *__mlxsw_sp_mc_get(struct mlxsw_sp_bridge_device *bridge_device,
 	return NULL;
 }
 
+static bool
+mlxsw_sp_mc_write_mdb_entry(struct mlxsw_sp *mlxsw_sp,
+			    struct mlxsw_sp_mid *mid)
+{
+	u16 mid_idx;
+	int err;
+
+	mid_idx = find_first_zero_bit(mlxsw_sp->bridge->mids_bitmap,
+				      MLXSW_SP_MID_MAX);
+	if (mid_idx == MLXSW_SP_MID_MAX)
+		return false;
+
+	mid->mid = mid_idx;
+	err = mlxsw_sp_port_smid_full_entry(mlxsw_sp, mid_idx);
+	if (err)
+		return false;
+
+	err = mlxsw_sp_port_mdb_op(mlxsw_sp, mid->addr, mid->fid, mid_idx,
+				   true);
+	if (err)
+		return false;
+
+	set_bit(mid_idx, mlxsw_sp->bridge->mids_bitmap);
+	mid->in_hw = true;
+	return true;
+}
+
+static int mlxsw_sp_mc_remove_mdb_entry(struct mlxsw_sp *mlxsw_sp,
+					struct mlxsw_sp_mid *mid)
+{
+	clear_bit(mid->mid, mlxsw_sp->bridge->mids_bitmap);
+	mid->in_hw = false;
+	return mlxsw_sp_port_mdb_op(mlxsw_sp, mid->addr, mid->fid, mid->mid,
+				    false);
+}
+
 static struct
 mlxsw_sp_mid *__mlxsw_sp_mc_alloc(struct mlxsw_sp *mlxsw_sp,
 				  struct mlxsw_sp_bridge_device *bridge_device,
@@ -1268,12 +1304,6 @@ mlxsw_sp_mid *__mlxsw_sp_mc_alloc(struct mlxsw_sp *mlxsw_sp,
 {
 	struct mlxsw_sp_mid *mid;
 	size_t alloc_size;
-	u16 mid_idx;
-
-	mid_idx = find_first_zero_bit(mlxsw_sp->bridge->mids_bitmap,
-				      MLXSW_SP_MID_MAX);
-	if (mid_idx == MLXSW_SP_MID_MAX)
-		return NULL;
 
 	mid = kzalloc(sizeof(*mid), GFP_KERNEL);
 	if (!mid)
@@ -1281,36 +1311,43 @@ mlxsw_sp_mid *__mlxsw_sp_mc_alloc(struct mlxsw_sp *mlxsw_sp,
 
 	alloc_size = sizeof(unsigned long) *
 		     BITS_TO_LONGS(mlxsw_core_max_ports(mlxsw_sp->core));
+
 	mid->ports_in_mid = kzalloc(alloc_size, GFP_KERNEL);
-	if (!mid->ports_in_mid) {
-		kfree(mid);
-		return NULL;
-	}
+	if (!mid->ports_in_mid)
+		goto err_ports_in_mid_alloc;
 
-	set_bit(mid_idx, mlxsw_sp->bridge->mids_bitmap);
 	ether_addr_copy(mid->addr, addr);
 	mid->fid = fid;
-	mid->mid = mid_idx;
+	mid->in_hw = false;
+	if (!mlxsw_sp_mc_write_mdb_entry(mlxsw_sp, mid))
+		goto err_write_mdb_entry;
+
 	list_add_tail(&mid->list, &bridge_device->mids_list);
 
 	return mid;
+
+err_write_mdb_entry:
+	kfree(mid->ports_in_mid);
+err_ports_in_mid_alloc:
+	kfree(mid);
+	return NULL;
 }
 
 static int mlxsw_sp_port_remove_from_mid(struct mlxsw_sp_port *mlxsw_sp_port,
 					 struct mlxsw_sp_mid *mid)
 {
 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+	int err = 0;
 
 	clear_bit(mlxsw_sp_port->local_port, mid->ports_in_mid);
 	if (bitmap_empty(mid->ports_in_mid,
 			 mlxsw_core_max_ports(mlxsw_sp->core))) {
+		err = mlxsw_sp_mc_remove_mdb_entry(mlxsw_sp, mid);
 		list_del(&mid->list);
-		clear_bit(mid->mid, mlxsw_sp->bridge->mids_bitmap);
 		kfree(mid->ports_in_mid);
 		kfree(mid);
-		return 1;
 	}
-	return 0;
+	return err;
 }
 
 static int mlxsw_sp_port_mdb_add(struct mlxsw_sp_port *mlxsw_sp_port,
@@ -1324,7 +1361,6 @@ static int mlxsw_sp_port_mdb_add(struct mlxsw_sp_port *mlxsw_sp_port,
 	struct mlxsw_sp_bridge_device *bridge_device;
 	struct mlxsw_sp_bridge_port *bridge_port;
 	struct mlxsw_sp_mid *mid;
-	bool is_new_mid = false;
 	u16 fid_index;
 	int err = 0;
 
@@ -1352,8 +1388,6 @@ static int mlxsw_sp_port_mdb_add(struct mlxsw_sp_port *mlxsw_sp_port,
 			netdev_err(dev, "Unable to allocate MC group\n");
 			return -ENOMEM;
 		}
-		is_new_mid = true;
-		mlxsw_sp_port_smid_full_entry(mlxsw_sp, mid->mid);
 	}
 	set_bit(mlxsw_sp_port->local_port, mid->ports_in_mid);
 
@@ -1363,15 +1397,6 @@ static int mlxsw_sp_port_mdb_add(struct mlxsw_sp_port *mlxsw_sp_port,
 		goto err_out;
 	}
 
-	if (is_new_mid) {
-		err = mlxsw_sp_port_mdb_op(mlxsw_sp, mdb->addr, fid_index,
-					   mid->mid, true);
-		if (err) {
-			netdev_err(dev, "Unable to set MC SFD\n");
-			goto err_out;
-		}
-	}
-
 	return 0;
 
 err_out:
@@ -1481,12 +1506,9 @@ static int mlxsw_sp_port_mdb_del(struct mlxsw_sp_port *mlxsw_sp_port,
 		netdev_err(dev, "Unable to remove port from SMID\n");
 
 	mid_idx = mid->mid;
-	if (mlxsw_sp_port_remove_from_mid(mlxsw_sp_port, mid)) {
-		err = mlxsw_sp_port_mdb_op(mlxsw_sp, mdb->addr, fid_index,
-					   mid_idx, false);
-		if (err)
-			netdev_err(dev, "Unable to remove MC SFD\n");
-	}
+	err = mlxsw_sp_port_remove_from_mid(mlxsw_sp_port, mid);
+	if (err)
+		netdev_err(dev, "Unable to remove MC SFD\n");
 
 	return err;
 }
-- 
2.9.5

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [patch net-next 07/16] mlxsw: spectrum_switchdev: Break mid deletion into two function
  2017-09-20 14:15 [patch net-next 00/16] mlxsw: Multicast flood update Jiri Pirko
                   ` (5 preceding siblings ...)
  2017-09-20 14:15 ` [patch net-next 06/16] mlxsw: spectrum_switchdev: Attach mid id allocation to HW write Jiri Pirko
@ 2017-09-20 14:15 ` Jiri Pirko
  2017-09-20 14:15 ` [patch net-next 08/16] mlxsw: spectrum_switchdev: Don't write mids to the HW when mc is disabled Jiri Pirko
                   ` (9 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Jiri Pirko @ 2017-09-20 14:15 UTC (permalink / raw)
  To: netdev; +Cc: davem, nogahf, idosch, mlxsw

From: Nogah Frankel <nogahf@mellanox.com>

Break mid deletion into two function, so it will be possible in the future
to delete a mid entry for other reasons then switchdev command (like port
deletion).

Signed-off-by: Nogah Frankel <nogahf@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 .../ethernet/mellanox/mlxsw/spectrum_switchdev.c   | 32 ++++++++++++++--------
 1 file changed, 20 insertions(+), 12 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 9dd05d8..7f622de 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -1468,6 +1468,25 @@ static int mlxsw_sp_port_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port,
 	return 0;
 }
 
+static int
+__mlxsw_sp_port_mdb_del(struct mlxsw_sp_port *mlxsw_sp_port,
+			struct mlxsw_sp_bridge_port *bridge_port,
+			struct mlxsw_sp_mid *mid)
+{
+	struct net_device *dev = mlxsw_sp_port->dev;
+	int err;
+
+	err = mlxsw_sp_port_smid_set(mlxsw_sp_port, mid->mid, false);
+	if (err)
+		netdev_err(dev, "Unable to remove port from SMID\n");
+
+	err = mlxsw_sp_port_remove_from_mid(mlxsw_sp_port, mid);
+	if (err)
+		netdev_err(dev, "Unable to remove MC SFD\n");
+
+	return err;
+}
+
 static int mlxsw_sp_port_mdb_del(struct mlxsw_sp_port *mlxsw_sp_port,
 				 const struct switchdev_obj_port_mdb *mdb)
 {
@@ -1479,8 +1498,6 @@ static int mlxsw_sp_port_mdb_del(struct mlxsw_sp_port *mlxsw_sp_port,
 	struct mlxsw_sp_bridge_port *bridge_port;
 	struct mlxsw_sp_mid *mid;
 	u16 fid_index;
-	u16 mid_idx;
-	int err = 0;
 
 	bridge_port = mlxsw_sp_bridge_port_find(mlxsw_sp->bridge, orig_dev);
 	if (!bridge_port)
@@ -1501,16 +1518,7 @@ static int mlxsw_sp_port_mdb_del(struct mlxsw_sp_port *mlxsw_sp_port,
 		return -EINVAL;
 	}
 
-	err = mlxsw_sp_port_smid_set(mlxsw_sp_port, mid->mid, false);
-	if (err)
-		netdev_err(dev, "Unable to remove port from SMID\n");
-
-	mid_idx = mid->mid;
-	err = mlxsw_sp_port_remove_from_mid(mlxsw_sp_port, mid);
-	if (err)
-		netdev_err(dev, "Unable to remove MC SFD\n");
-
-	return err;
+	return __mlxsw_sp_port_mdb_del(mlxsw_sp_port, bridge_port, mid);
 }
 
 static int mlxsw_sp_port_obj_del(struct net_device *dev,
-- 
2.9.5

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [patch net-next 08/16] mlxsw: spectrum_switchdev: Don't write mids to the HW when mc is disabled
  2017-09-20 14:15 [patch net-next 00/16] mlxsw: Multicast flood update Jiri Pirko
                   ` (6 preceding siblings ...)
  2017-09-20 14:15 ` [patch net-next 07/16] mlxsw: spectrum_switchdev: Break mid deletion into two function Jiri Pirko
@ 2017-09-20 14:15 ` Jiri Pirko
  2017-09-20 14:15 ` [patch net-next 09/16] mlxsw: spectrum_switchdev: Disable mdb " Jiri Pirko
                   ` (8 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Jiri Pirko @ 2017-09-20 14:15 UTC (permalink / raw)
  To: netdev; +Cc: davem, nogahf, idosch, mlxsw

From: Nogah Frankel <nogahf@mellanox.com>

Don't write multicast related data to the HW when mc is disabled.
Also, don't allocate mid id to new mids (so the remove function could know
that they weren't wrote to the HW)

Signed-off-by: Nogah Frankel <nogahf@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 .../ethernet/mellanox/mlxsw/spectrum_switchdev.c    | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 7f622de..cea257a 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -1290,6 +1290,9 @@ mlxsw_sp_mc_write_mdb_entry(struct mlxsw_sp *mlxsw_sp,
 static int mlxsw_sp_mc_remove_mdb_entry(struct mlxsw_sp *mlxsw_sp,
 					struct mlxsw_sp_mid *mid)
 {
+	if (!mid->in_hw)
+		return 0;
+
 	clear_bit(mid->mid, mlxsw_sp->bridge->mids_bitmap);
 	mid->in_hw = false;
 	return mlxsw_sp_port_mdb_op(mlxsw_sp, mid->addr, mid->fid, mid->mid,
@@ -1319,11 +1322,15 @@ mlxsw_sp_mid *__mlxsw_sp_mc_alloc(struct mlxsw_sp *mlxsw_sp,
 	ether_addr_copy(mid->addr, addr);
 	mid->fid = fid;
 	mid->in_hw = false;
+
+	if (!bridge_device->multicast_enabled)
+		goto out;
+
 	if (!mlxsw_sp_mc_write_mdb_entry(mlxsw_sp, mid))
 		goto err_write_mdb_entry;
 
+out:
 	list_add_tail(&mid->list, &bridge_device->mids_list);
-
 	return mid;
 
 err_write_mdb_entry:
@@ -1391,6 +1398,9 @@ static int mlxsw_sp_port_mdb_add(struct mlxsw_sp_port *mlxsw_sp_port,
 	}
 	set_bit(mlxsw_sp_port->local_port, mid->ports_in_mid);
 
+	if (!bridge_device->multicast_enabled)
+		return 0;
+
 	err = mlxsw_sp_port_smid_set(mlxsw_sp_port, mid->mid, true);
 	if (err) {
 		netdev_err(dev, "Unable to set SMID\n");
@@ -1476,9 +1486,12 @@ __mlxsw_sp_port_mdb_del(struct mlxsw_sp_port *mlxsw_sp_port,
 	struct net_device *dev = mlxsw_sp_port->dev;
 	int err;
 
-	err = mlxsw_sp_port_smid_set(mlxsw_sp_port, mid->mid, false);
-	if (err)
-		netdev_err(dev, "Unable to remove port from SMID\n");
+	if (bridge_port->bridge_device->multicast_enabled) {
+		err = mlxsw_sp_port_smid_set(mlxsw_sp_port, mid->mid, false);
+
+		if (err)
+			netdev_err(dev, "Unable to remove port from SMID\n");
+	}
 
 	err = mlxsw_sp_port_remove_from_mid(mlxsw_sp_port, mid);
 	if (err)
-- 
2.9.5

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [patch net-next 09/16] mlxsw: spectrum_switchdev: Disable mdb when mc is disabled
  2017-09-20 14:15 [patch net-next 00/16] mlxsw: Multicast flood update Jiri Pirko
                   ` (7 preceding siblings ...)
  2017-09-20 14:15 ` [patch net-next 08/16] mlxsw: spectrum_switchdev: Don't write mids to the HW when mc is disabled Jiri Pirko
@ 2017-09-20 14:15 ` Jiri Pirko
  2017-09-20 14:15 ` [patch net-next 10/16] mlxsw: spectrum_switchdev: Use generic mc flood function Jiri Pirko
                   ` (7 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Jiri Pirko @ 2017-09-20 14:15 UTC (permalink / raw)
  To: netdev; +Cc: davem, nogahf, idosch, mlxsw

From: Nogah Frankel <nogahf@mellanox.com>

Remove all the mdb entries from the HW when mc is being disabled and
re-write them when it is being enabled.

Signed-off-by: Nogah Frankel <nogahf@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 .../ethernet/mellanox/mlxsw/spectrum_switchdev.c   | 41 +++++++++++++++++++---
 1 file changed, 37 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index cea257a..79806af 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -121,6 +121,11 @@ mlxsw_sp_bridge_port_fdb_flush(struct mlxsw_sp *mlxsw_sp,
 			       struct mlxsw_sp_bridge_port *bridge_port,
 			       u16 fid_index);
 
+static void
+mlxsw_sp_bridge_mdb_mc_enable_sync(struct mlxsw_sp_port *mlxsw_sp_port,
+				   struct mlxsw_sp_bridge_device
+				   *bridge_device);
+
 static struct mlxsw_sp_bridge_device *
 mlxsw_sp_bridge_device_find(const struct mlxsw_sp_bridge *bridge,
 			    const struct net_device *br_dev)
@@ -757,6 +762,12 @@ static int mlxsw_sp_port_mc_disabled_set(struct mlxsw_sp_port *mlxsw_sp_port,
 	if (!bridge_device)
 		return 0;
 
+	if (bridge_device->multicast_enabled != !mc_disabled) {
+		bridge_device->multicast_enabled = !mc_disabled;
+		mlxsw_sp_bridge_mdb_mc_enable_sync(mlxsw_sp_port,
+						   bridge_device);
+	}
+
 	list_for_each_entry(bridge_port, &bridge_device->ports_list, list) {
 		enum mlxsw_sp_flood_type packet_type = MLXSW_SP_FLOOD_TYPE_MC;
 		bool member = mc_disabled ? true : bridge_port->mrouter;
@@ -1207,9 +1218,8 @@ static int mlxsw_sp_port_mdb_op(struct mlxsw_sp *mlxsw_sp, const char *addr,
 	return err;
 }
 
-/* clean the an entry from the HW and write there a full new entry */
-static int mlxsw_sp_port_smid_full_entry(struct mlxsw_sp *mlxsw_sp,
-					 u16 mid_idx)
+static int mlxsw_sp_port_smid_full_entry(struct mlxsw_sp *mlxsw_sp, u16 mid_idx,
+					 long *ports_bitmap)
 {
 	char *smid_pl;
 	int err, i;
@@ -1224,6 +1234,9 @@ static int mlxsw_sp_port_smid_full_entry(struct mlxsw_sp *mlxsw_sp,
 			mlxsw_reg_smid_port_mask_set(smid_pl, i, 1);
 	}
 
+	for_each_set_bit(i, ports_bitmap, mlxsw_core_max_ports(mlxsw_sp->core))
+		mlxsw_reg_smid_port_set(smid_pl, i, 1);
+
 	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(smid), smid_pl);
 	kfree(smid_pl);
 	return err;
@@ -1273,7 +1286,8 @@ mlxsw_sp_mc_write_mdb_entry(struct mlxsw_sp *mlxsw_sp,
 		return false;
 
 	mid->mid = mid_idx;
-	err = mlxsw_sp_port_smid_full_entry(mlxsw_sp, mid_idx);
+	err = mlxsw_sp_port_smid_full_entry(mlxsw_sp, mid_idx,
+					    mid->ports_in_mid);
 	if (err)
 		return false;
 
@@ -1414,6 +1428,25 @@ static int mlxsw_sp_port_mdb_add(struct mlxsw_sp_port *mlxsw_sp_port,
 	return err;
 }
 
+static void
+mlxsw_sp_bridge_mdb_mc_enable_sync(struct mlxsw_sp_port *mlxsw_sp_port,
+				   struct mlxsw_sp_bridge_device
+				   *bridge_device)
+{
+	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+	struct mlxsw_sp_mid *mid;
+	bool mc_enabled;
+
+	mc_enabled = bridge_device->multicast_enabled;
+
+	list_for_each_entry(mid, &bridge_device->mids_list, list) {
+		if (mc_enabled)
+			mlxsw_sp_mc_write_mdb_entry(mlxsw_sp, mid);
+		else
+			mlxsw_sp_mc_remove_mdb_entry(mlxsw_sp, mid);
+	}
+}
+
 static int mlxsw_sp_port_obj_add(struct net_device *dev,
 				 const struct switchdev_obj *obj,
 				 struct switchdev_trans *trans)
-- 
2.9.5

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [patch net-next 10/16] mlxsw: spectrum_switchdev: Use generic mc flood function
  2017-09-20 14:15 [patch net-next 00/16] mlxsw: Multicast flood update Jiri Pirko
                   ` (8 preceding siblings ...)
  2017-09-20 14:15 ` [patch net-next 09/16] mlxsw: spectrum_switchdev: Disable mdb " Jiri Pirko
@ 2017-09-20 14:15 ` Jiri Pirko
  2017-09-20 14:15 ` [patch net-next 11/16] mlxsw: spectrum_switchdev: Flood mc when mc is disabled by user flag Jiri Pirko
                   ` (6 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Jiri Pirko @ 2017-09-20 14:15 UTC (permalink / raw)
  To: netdev; +Cc: davem, nogahf, idosch, mlxsw

From: Nogah Frankel <nogahf@mellanox.com>

Use the generic mc flood function to decide whether to flood mc to a port
when mc is being enabled / disabled.
Move this function in the file to avoid forward declaration.

Signed-off-by: Nogah Frankel <nogahf@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 .../net/ethernet/mellanox/mlxsw/spectrum_switchdev.c   | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 79806af..19ac206 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -742,6 +742,14 @@ static int mlxsw_sp_port_attr_mrouter_set(struct mlxsw_sp_port *mlxsw_sp_port,
 	return 0;
 }
 
+static bool mlxsw_sp_mc_flood(const struct mlxsw_sp_bridge_port *bridge_port)
+{
+	const struct mlxsw_sp_bridge_device *bridge_device;
+
+	bridge_device = bridge_port->bridge_device;
+	return !bridge_device->multicast_enabled ? true : bridge_port->mrouter;
+}
+
 static int mlxsw_sp_port_mc_disabled_set(struct mlxsw_sp_port *mlxsw_sp_port,
 					 struct switchdev_trans *trans,
 					 struct net_device *orig_dev,
@@ -770,7 +778,7 @@ static int mlxsw_sp_port_mc_disabled_set(struct mlxsw_sp_port *mlxsw_sp_port,
 
 	list_for_each_entry(bridge_port, &bridge_device->ports_list, list) {
 		enum mlxsw_sp_flood_type packet_type = MLXSW_SP_FLOOD_TYPE_MC;
-		bool member = mc_disabled ? true : bridge_port->mrouter;
+		bool member = mlxsw_sp_mc_flood(bridge_port);
 
 		err = mlxsw_sp_bridge_port_flood_table_set(mlxsw_sp_port,
 							   bridge_port,
@@ -829,14 +837,6 @@ static int mlxsw_sp_port_attr_set(struct net_device *dev,
 	return err;
 }
 
-static bool mlxsw_sp_mc_flood(const struct mlxsw_sp_bridge_port *bridge_port)
-{
-	const struct mlxsw_sp_bridge_device *bridge_device;
-
-	bridge_device = bridge_port->bridge_device;
-	return !bridge_device->multicast_enabled ? true : bridge_port->mrouter;
-}
-
 static int
 mlxsw_sp_port_vlan_fid_join(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan,
 			    struct mlxsw_sp_bridge_port *bridge_port)
-- 
2.9.5

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [patch net-next 11/16] mlxsw: spectrum_switchdev: Flood mc when mc is disabled by user flag
  2017-09-20 14:15 [patch net-next 00/16] mlxsw: Multicast flood update Jiri Pirko
                   ` (9 preceding siblings ...)
  2017-09-20 14:15 ` [patch net-next 10/16] mlxsw: spectrum_switchdev: Use generic mc flood function Jiri Pirko
@ 2017-09-20 14:15 ` Jiri Pirko
  2017-09-20 14:15 ` [patch net-next 12/16] mlxsw: spectrum_switchdev: Flush the mdb when a port is being removed Jiri Pirko
                   ` (5 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Jiri Pirko @ 2017-09-20 14:15 UTC (permalink / raw)
  To: netdev; +Cc: davem, nogahf, idosch, mlxsw

From: Nogah Frankel <nogahf@mellanox.com>

When multicast is disabled, flood mc packets only to port that are marked
BR_MCAST_FLOOD (instead to all).

Signed-off-by: Nogah Frankel <nogahf@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 .../ethernet/mellanox/mlxsw/spectrum_switchdev.c    | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 19ac206..50c4d7c 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -262,7 +262,8 @@ mlxsw_sp_bridge_port_create(struct mlxsw_sp_bridge_device *bridge_device,
 	bridge_port->dev = brport_dev;
 	bridge_port->bridge_device = bridge_device;
 	bridge_port->stp_state = BR_STATE_DISABLED;
-	bridge_port->flags = BR_LEARNING | BR_FLOOD | BR_LEARNING_SYNC;
+	bridge_port->flags = BR_LEARNING | BR_FLOOD | BR_LEARNING_SYNC |
+			     BR_MCAST_FLOOD;
 	INIT_LIST_HEAD(&bridge_port->vlans_list);
 	list_add(&bridge_port->list, &bridge_device->ports_list);
 	bridge_port->ref_count = 1;
@@ -468,7 +469,8 @@ static int mlxsw_sp_port_attr_get(struct net_device *dev,
 					       &attr->u.brport_flags);
 		break;
 	case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT:
-		attr->u.brport_flags_support = BR_LEARNING | BR_FLOOD;
+		attr->u.brport_flags_support = BR_LEARNING | BR_FLOOD |
+					       BR_MCAST_FLOOD;
 		break;
 	default:
 		return -EOPNOTSUPP;
@@ -653,8 +655,18 @@ static int mlxsw_sp_port_attr_br_flags_set(struct mlxsw_sp_port *mlxsw_sp_port,
 	if (err)
 		return err;
 
-	memcpy(&bridge_port->flags, &brport_flags, sizeof(brport_flags));
+	if (bridge_port->bridge_device->multicast_enabled)
+		goto out;
 
+	err = mlxsw_sp_bridge_port_flood_table_set(mlxsw_sp_port, bridge_port,
+						   MLXSW_SP_FLOOD_TYPE_MC,
+						   brport_flags &
+						   BR_MCAST_FLOOD);
+	if (err)
+		return err;
+
+out:
+	memcpy(&bridge_port->flags, &brport_flags, sizeof(brport_flags));
 	return 0;
 }
 
@@ -747,7 +759,8 @@ static bool mlxsw_sp_mc_flood(const struct mlxsw_sp_bridge_port *bridge_port)
 	const struct mlxsw_sp_bridge_device *bridge_device;
 
 	bridge_device = bridge_port->bridge_device;
-	return !bridge_device->multicast_enabled ? true : bridge_port->mrouter;
+	return bridge_device->multicast_enabled ? bridge_port->mrouter :
+					bridge_port->flags & BR_MCAST_FLOOD;
 }
 
 static int mlxsw_sp_port_mc_disabled_set(struct mlxsw_sp_port *mlxsw_sp_port,
-- 
2.9.5

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [patch net-next 12/16] mlxsw: spectrum_switchdev: Flush the mdb when a port is being removed
  2017-09-20 14:15 [patch net-next 00/16] mlxsw: Multicast flood update Jiri Pirko
                   ` (10 preceding siblings ...)
  2017-09-20 14:15 ` [patch net-next 11/16] mlxsw: spectrum_switchdev: Flood mc when mc is disabled by user flag Jiri Pirko
@ 2017-09-20 14:15 ` Jiri Pirko
  2017-09-20 14:15 ` [patch net-next 13/16] mlxsw: spectrum_switchdev: Flood all mc packets to mrouter ports Jiri Pirko
                   ` (4 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Jiri Pirko @ 2017-09-20 14:15 UTC (permalink / raw)
  To: netdev; +Cc: davem, nogahf, idosch, mlxsw

From: Nogah Frankel <nogahf@mellanox.com>

When a port is being removed from a bridge, flush the bridge mdb to remove
the mids of that port.

Signed-off-by: Nogah Frankel <nogahf@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 .../ethernet/mellanox/mlxsw/spectrum_switchdev.c   | 39 ++++++++++++++++------
 1 file changed, 29 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 50c4d7c..bc07873 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -122,6 +122,10 @@ mlxsw_sp_bridge_port_fdb_flush(struct mlxsw_sp *mlxsw_sp,
 			       u16 fid_index);
 
 static void
+mlxsw_sp_bridge_port_mdb_flush(struct mlxsw_sp_port *mlxsw_sp_port,
+			       struct mlxsw_sp_bridge_port *bridge_port);
+
+static void
 mlxsw_sp_bridge_mdb_mc_enable_sync(struct mlxsw_sp_port *mlxsw_sp_port,
 				   struct mlxsw_sp_bridge_device
 				   *bridge_device);
@@ -176,17 +180,11 @@ static void
 mlxsw_sp_bridge_device_destroy(struct mlxsw_sp_bridge *bridge,
 			       struct mlxsw_sp_bridge_device *bridge_device)
 {
-	struct mlxsw_sp_mid *mid, *tmp;
-
 	list_del(&bridge_device->list);
 	if (bridge_device->vlan_enabled)
 		bridge->vlan_enabled_exists = false;
 	WARN_ON(!list_empty(&bridge_device->ports_list));
-	list_for_each_entry_safe(mid, tmp, &bridge_device->mids_list, list) {
-		list_del(&mid->list);
-		clear_bit(mid->mid, bridge->mids_bitmap);
-		kfree(mid);
-	}
+	WARN_ON(!list_empty(&bridge_device->mids_list));
 	kfree(bridge_device);
 }
 
@@ -987,24 +985,28 @@ mlxsw_sp_port_vlan_bridge_leave(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan)
 	struct mlxsw_sp_bridge_vlan *bridge_vlan;
 	struct mlxsw_sp_bridge_port *bridge_port;
 	u16 vid = mlxsw_sp_port_vlan->vid;
-	bool last;
+	bool last_port, last_vlan;
 
 	if (WARN_ON(mlxsw_sp_fid_type(fid) != MLXSW_SP_FID_TYPE_8021Q &&
 		    mlxsw_sp_fid_type(fid) != MLXSW_SP_FID_TYPE_8021D))
 		return;
 
 	bridge_port = mlxsw_sp_port_vlan->bridge_port;
+	last_vlan = list_is_singular(&bridge_port->vlans_list);
 	bridge_vlan = mlxsw_sp_bridge_vlan_find(bridge_port, vid);
-	last = list_is_singular(&bridge_vlan->port_vlan_list);
+	last_port = list_is_singular(&bridge_vlan->port_vlan_list);
 
 	list_del(&mlxsw_sp_port_vlan->bridge_vlan_node);
 	mlxsw_sp_bridge_vlan_put(bridge_vlan);
 	mlxsw_sp_port_vid_stp_set(mlxsw_sp_port, vid, BR_STATE_DISABLED);
 	mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid, false);
-	if (last)
+	if (last_port)
 		mlxsw_sp_bridge_port_fdb_flush(mlxsw_sp_port->mlxsw_sp,
 					       bridge_port,
 					       mlxsw_sp_fid_index(fid));
+	if (last_vlan)
+		mlxsw_sp_bridge_port_mdb_flush(mlxsw_sp_port, bridge_port);
+
 	mlxsw_sp_port_vlan_fid_leave(mlxsw_sp_port_vlan);
 
 	mlxsw_sp_bridge_port_put(mlxsw_sp_port->mlxsw_sp->bridge, bridge_port);
@@ -1580,6 +1582,23 @@ static int mlxsw_sp_port_mdb_del(struct mlxsw_sp_port *mlxsw_sp_port,
 	return __mlxsw_sp_port_mdb_del(mlxsw_sp_port, bridge_port, mid);
 }
 
+static void
+mlxsw_sp_bridge_port_mdb_flush(struct mlxsw_sp_port *mlxsw_sp_port,
+			       struct mlxsw_sp_bridge_port *bridge_port)
+{
+	struct mlxsw_sp_bridge_device *bridge_device;
+	struct mlxsw_sp_mid *mid, *tmp;
+
+	bridge_device = bridge_port->bridge_device;
+
+	list_for_each_entry_safe(mid, tmp, &bridge_device->mids_list, list) {
+		if (test_bit(mlxsw_sp_port->local_port, mid->ports_in_mid)) {
+			__mlxsw_sp_port_mdb_del(mlxsw_sp_port, bridge_port,
+						mid);
+		}
+	}
+}
+
 static int mlxsw_sp_port_obj_del(struct net_device *dev,
 				 const struct switchdev_obj *obj)
 {
-- 
2.9.5

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [patch net-next 13/16] mlxsw: spectrum_switchdev: Flood all mc packets to mrouter ports
  2017-09-20 14:15 [patch net-next 00/16] mlxsw: Multicast flood update Jiri Pirko
                   ` (11 preceding siblings ...)
  2017-09-20 14:15 ` [patch net-next 12/16] mlxsw: spectrum_switchdev: Flush the mdb when a port is being removed Jiri Pirko
@ 2017-09-20 14:15 ` Jiri Pirko
  2017-09-20 14:15 ` [patch net-next 14/16] mlxsw: spectrum_switchdev: Update the mdb of mrouter port change Jiri Pirko
                   ` (3 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Jiri Pirko @ 2017-09-20 14:15 UTC (permalink / raw)
  To: netdev; +Cc: davem, nogahf, idosch, mlxsw

From: Nogah Frankel <nogahf@mellanox.com>

When mc is enabled, whenever a mc packet doesn't hit any mdb entry it is
being flood to the ports marked as mrouters. However, all mc packets should
be flooded to them even if they match an entry in the mdb.
This patch adds the mrouter ports to every mdb entry that is being written
to the HW.

Signed-off-by: Nogah Frankel <nogahf@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 .../ethernet/mellanox/mlxsw/spectrum_switchdev.c   | 65 ++++++++++++++++++++--
 1 file changed, 60 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index bc07873..146beaa 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -1288,10 +1288,55 @@ mlxsw_sp_mid *__mlxsw_sp_mc_get(struct mlxsw_sp_bridge_device *bridge_device,
 	return NULL;
 }
 
+static void
+mlxsw_sp_bridge_port_get_ports_bitmap(struct mlxsw_sp *mlxsw_sp,
+				      struct mlxsw_sp_bridge_port *bridge_port,
+				      unsigned long *ports_bitmap)
+{
+	struct mlxsw_sp_port *mlxsw_sp_port;
+	u64 max_lag_members, i;
+	int lag_id;
+
+	if (!bridge_port->lagged) {
+		set_bit(bridge_port->system_port, ports_bitmap);
+	} else {
+		max_lag_members = MLXSW_CORE_RES_GET(mlxsw_sp->core,
+						     MAX_LAG_MEMBERS);
+		lag_id = bridge_port->lag_id;
+		for (i = 0; i < max_lag_members; i++) {
+			mlxsw_sp_port = mlxsw_sp_port_lagged_get(mlxsw_sp,
+								 lag_id, i);
+			if (mlxsw_sp_port)
+				set_bit(mlxsw_sp_port->local_port,
+					ports_bitmap);
+		}
+	}
+}
+
+static void
+mlxsw_sp_mc_get_mrouters_bitmap(unsigned long *flood_bitmap,
+				struct mlxsw_sp_bridge_device *bridge_device,
+				struct mlxsw_sp *mlxsw_sp)
+{
+	struct mlxsw_sp_bridge_port *bridge_port;
+
+	list_for_each_entry(bridge_port, &bridge_device->ports_list, list) {
+		if (bridge_port->mrouter) {
+			mlxsw_sp_bridge_port_get_ports_bitmap(mlxsw_sp,
+							      bridge_port,
+							      flood_bitmap);
+		}
+	}
+}
+
 static bool
 mlxsw_sp_mc_write_mdb_entry(struct mlxsw_sp *mlxsw_sp,
-			    struct mlxsw_sp_mid *mid)
+			    struct mlxsw_sp_mid *mid,
+			    struct mlxsw_sp_bridge_device *bridge_device)
 {
+	long *flood_bitmap;
+	int num_of_ports;
+	int alloc_size;
 	u16 mid_idx;
 	int err;
 
@@ -1300,9 +1345,18 @@ mlxsw_sp_mc_write_mdb_entry(struct mlxsw_sp *mlxsw_sp,
 	if (mid_idx == MLXSW_SP_MID_MAX)
 		return false;
 
+	num_of_ports = mlxsw_core_max_ports(mlxsw_sp->core);
+	alloc_size = sizeof(long) * BITS_TO_LONGS(num_of_ports);
+	flood_bitmap = kzalloc(alloc_size, GFP_KERNEL);
+	if (!flood_bitmap)
+		return false;
+
+	bitmap_copy(flood_bitmap,  mid->ports_in_mid, num_of_ports);
+	mlxsw_sp_mc_get_mrouters_bitmap(flood_bitmap, bridge_device, mlxsw_sp);
+
 	mid->mid = mid_idx;
-	err = mlxsw_sp_port_smid_full_entry(mlxsw_sp, mid_idx,
-					    mid->ports_in_mid);
+	err = mlxsw_sp_port_smid_full_entry(mlxsw_sp, mid_idx, flood_bitmap);
+	kfree(flood_bitmap);
 	if (err)
 		return false;
 
@@ -1355,7 +1409,7 @@ mlxsw_sp_mid *__mlxsw_sp_mc_alloc(struct mlxsw_sp *mlxsw_sp,
 	if (!bridge_device->multicast_enabled)
 		goto out;
 
-	if (!mlxsw_sp_mc_write_mdb_entry(mlxsw_sp, mid))
+	if (!mlxsw_sp_mc_write_mdb_entry(mlxsw_sp, mid, bridge_device))
 		goto err_write_mdb_entry;
 
 out:
@@ -1456,7 +1510,8 @@ mlxsw_sp_bridge_mdb_mc_enable_sync(struct mlxsw_sp_port *mlxsw_sp_port,
 
 	list_for_each_entry(mid, &bridge_device->mids_list, list) {
 		if (mc_enabled)
-			mlxsw_sp_mc_write_mdb_entry(mlxsw_sp, mid);
+			mlxsw_sp_mc_write_mdb_entry(mlxsw_sp, mid,
+						    bridge_device);
 		else
 			mlxsw_sp_mc_remove_mdb_entry(mlxsw_sp, mid);
 	}
-- 
2.9.5

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [patch net-next 14/16] mlxsw: spectrum_switchdev: Update the mdb of mrouter port change
  2017-09-20 14:15 [patch net-next 00/16] mlxsw: Multicast flood update Jiri Pirko
                   ` (12 preceding siblings ...)
  2017-09-20 14:15 ` [patch net-next 13/16] mlxsw: spectrum_switchdev: Flood all mc packets to mrouter ports Jiri Pirko
@ 2017-09-20 14:15 ` Jiri Pirko
  2017-09-20 14:15 ` [patch net-next 15/16] mlxsw: spectrum_switchdev: Remove mrouter flood in mdb flush Jiri Pirko
                   ` (2 subsequent siblings)
  16 siblings, 0 replies; 18+ messages in thread
From: Jiri Pirko @ 2017-09-20 14:15 UTC (permalink / raw)
  To: netdev; +Cc: davem, nogahf, idosch, mlxsw

From: Nogah Frankel <nogahf@mellanox.com>

Whenever a port starts / stops being mrouter, update all the mdb entries
in the HW to flood / stop flooding mc packets there.
The change should happen only if the port is not in the mid. (If it is,
the mid should flood mc packets to this port anyway)

Signed-off-by: Nogah Frankel <nogahf@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 .../ethernet/mellanox/mlxsw/spectrum_switchdev.c   | 23 ++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 146beaa..bf1a175 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -130,6 +130,11 @@ mlxsw_sp_bridge_mdb_mc_enable_sync(struct mlxsw_sp_port *mlxsw_sp_port,
 				   struct mlxsw_sp_bridge_device
 				   *bridge_device);
 
+static void
+mlxsw_sp_port_mrouter_update_mdb(struct mlxsw_sp_port *mlxsw_sp_port,
+				 struct mlxsw_sp_bridge_port *bridge_port,
+				 bool add);
+
 static struct mlxsw_sp_bridge_device *
 mlxsw_sp_bridge_device_find(const struct mlxsw_sp_bridge *bridge,
 			    const struct net_device *br_dev)
@@ -747,6 +752,8 @@ static int mlxsw_sp_port_attr_mrouter_set(struct mlxsw_sp_port *mlxsw_sp_port,
 	if (err)
 		return err;
 
+	mlxsw_sp_port_mrouter_update_mdb(mlxsw_sp_port, bridge_port,
+					 is_port_mrouter);
 out:
 	bridge_port->mrouter = is_port_mrouter;
 	return 0;
@@ -1517,6 +1524,22 @@ mlxsw_sp_bridge_mdb_mc_enable_sync(struct mlxsw_sp_port *mlxsw_sp_port,
 	}
 }
 
+static void
+mlxsw_sp_port_mrouter_update_mdb(struct mlxsw_sp_port *mlxsw_sp_port,
+				 struct mlxsw_sp_bridge_port *bridge_port,
+				 bool add)
+{
+	struct mlxsw_sp_bridge_device *bridge_device;
+	struct mlxsw_sp_mid *mid;
+
+	bridge_device = bridge_port->bridge_device;
+
+	list_for_each_entry(mid, &bridge_device->mids_list, list) {
+		if (!test_bit(mlxsw_sp_port->local_port, mid->ports_in_mid))
+			mlxsw_sp_port_smid_set(mlxsw_sp_port, mid->mid, add);
+	}
+}
+
 static int mlxsw_sp_port_obj_add(struct net_device *dev,
 				 const struct switchdev_obj *obj,
 				 struct switchdev_trans *trans)
-- 
2.9.5

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [patch net-next 15/16] mlxsw: spectrum_switchdev: Remove mrouter flood in mdb flush
  2017-09-20 14:15 [patch net-next 00/16] mlxsw: Multicast flood update Jiri Pirko
                   ` (13 preceding siblings ...)
  2017-09-20 14:15 ` [patch net-next 14/16] mlxsw: spectrum_switchdev: Update the mdb of mrouter port change Jiri Pirko
@ 2017-09-20 14:15 ` Jiri Pirko
  2017-09-20 14:15 ` [patch net-next 16/16] mlxsw: spectrum_switchdev: Consider mrouter status for mdb changes Jiri Pirko
  2017-09-21  1:05 ` [patch net-next 00/16] mlxsw: Multicast flood update David Miller
  16 siblings, 0 replies; 18+ messages in thread
From: Jiri Pirko @ 2017-09-20 14:15 UTC (permalink / raw)
  To: netdev; +Cc: davem, nogahf, idosch, mlxsw

From: Nogah Frankel <nogahf@mellanox.com>

In mdb flush the port is being removed from all the mids it is registered
to. But if the port is mrouter, all the mids floods to it.
This patch remove mrouter ports from mids it is not registered to in the
mdb flush.

Signed-off-by: Nogah Frankel <nogahf@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index bf1a175..459cedc 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -1673,6 +1673,9 @@ mlxsw_sp_bridge_port_mdb_flush(struct mlxsw_sp_port *mlxsw_sp_port,
 		if (test_bit(mlxsw_sp_port->local_port, mid->ports_in_mid)) {
 			__mlxsw_sp_port_mdb_del(mlxsw_sp_port, bridge_port,
 						mid);
+		} else if (bridge_device->multicast_enabled &&
+			   bridge_port->mrouter) {
+			mlxsw_sp_port_smid_set(mlxsw_sp_port, mid->mid, false);
 		}
 	}
 }
-- 
2.9.5

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [patch net-next 16/16] mlxsw: spectrum_switchdev: Consider mrouter status for mdb changes
  2017-09-20 14:15 [patch net-next 00/16] mlxsw: Multicast flood update Jiri Pirko
                   ` (14 preceding siblings ...)
  2017-09-20 14:15 ` [patch net-next 15/16] mlxsw: spectrum_switchdev: Remove mrouter flood in mdb flush Jiri Pirko
@ 2017-09-20 14:15 ` Jiri Pirko
  2017-09-21  1:05 ` [patch net-next 00/16] mlxsw: Multicast flood update David Miller
  16 siblings, 0 replies; 18+ messages in thread
From: Jiri Pirko @ 2017-09-20 14:15 UTC (permalink / raw)
  To: netdev; +Cc: davem, nogahf, idosch, mlxsw

From: Nogah Frankel <nogahf@mellanox.com>

When a mrouter is registered or leaves a mid, don't update the HW.

Signed-off-by: Nogah Frankel <nogahf@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 459cedc..0f9eac5 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -1491,6 +1491,9 @@ static int mlxsw_sp_port_mdb_add(struct mlxsw_sp_port *mlxsw_sp_port,
 	if (!bridge_device->multicast_enabled)
 		return 0;
 
+	if (bridge_port->mrouter)
+		return 0;
+
 	err = mlxsw_sp_port_smid_set(mlxsw_sp_port, mid->mid, true);
 	if (err) {
 		netdev_err(dev, "Unable to set SMID\n");
@@ -1613,10 +1616,12 @@ __mlxsw_sp_port_mdb_del(struct mlxsw_sp_port *mlxsw_sp_port,
 	int err;
 
 	if (bridge_port->bridge_device->multicast_enabled) {
-		err = mlxsw_sp_port_smid_set(mlxsw_sp_port, mid->mid, false);
-
-		if (err)
-			netdev_err(dev, "Unable to remove port from SMID\n");
+		if (bridge_port->bridge_device->multicast_enabled) {
+			err = mlxsw_sp_port_smid_set(mlxsw_sp_port, mid->mid,
+						     false);
+			if (err)
+				netdev_err(dev, "Unable to remove port from SMID\n");
+		}
 	}
 
 	err = mlxsw_sp_port_remove_from_mid(mlxsw_sp_port, mid);
-- 
2.9.5

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [patch net-next 00/16] mlxsw: Multicast flood update
  2017-09-20 14:15 [patch net-next 00/16] mlxsw: Multicast flood update Jiri Pirko
                   ` (15 preceding siblings ...)
  2017-09-20 14:15 ` [patch net-next 16/16] mlxsw: spectrum_switchdev: Consider mrouter status for mdb changes Jiri Pirko
@ 2017-09-21  1:05 ` David Miller
  16 siblings, 0 replies; 18+ messages in thread
From: David Miller @ 2017-09-21  1:05 UTC (permalink / raw)
  To: jiri; +Cc: netdev, nogahf, idosch, mlxsw

From: Jiri Pirko <jiri@resnulli.us>
Date: Wed, 20 Sep 2017 16:15:00 +0200

> From: Jiri Pirko <jiri@mellanox.com>
> 
> Nogah says:
> 
> Currently, there are four erroneous flows in MC flood:
> 1. When MC is disabled it affects only the flood table for unregistered
>    MC packets, but packets that match an entry in the MDB are unaffected.
> 2. When MC is disabled, MC packets are being sent to all the ports in the
>    bridge (like BC and link-local MC packets) regardless of the designated
>    flag (BR_MCAST_FLAG).
> 3. When a port is being deleted from a bridge it might remain in the MDB.
> 4. When MC is enabled packets are flooded to the mrouter ports only if
>    they don't match any entry in the MDB, when they should always be
>    flooded to them.
> 
> What these problems have in common is the discrepancy between how the
> hardware handles MDB and mcast flood, and how the driver does it. Each
> of these problems needs fixing either in the MDB code, or in mcast flood
> code, and some in both.
> 
> Patches 1-6 change the way the MDB is handled in the driver to make the
> following changes easier.
> Patches 7-8 fix problem number 1 by removing the MDB from the HW when MC
> is being disabled and restoring it when it is being enabled.
> Patches 9-10 fix problem number 2 by offloading the flood table by the
> appropriate flag.
> Patch 11 fixes problem number 3 by adding MDB flush to the port removal.
> Patches 12-14 fix problem number 4 by adding the mrouter ports to every
> MDB entry in the HW to mimic the wanted behaviour.

Looks good, series applied, thanks!

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2017-09-21  1:05 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-09-20 14:15 [patch net-next 00/16] mlxsw: Multicast flood update Jiri Pirko
2017-09-20 14:15 ` [patch net-next 01/16] mlxsw: spectrum_switchdev: Change mc_router to mrouter Jiri Pirko
2017-09-20 14:15 ` [patch net-next 02/16] mlxsw: spectrum_switchdev: Add a ports bitmap to the mid db Jiri Pirko
2017-09-20 14:15 ` [patch net-next 03/16] mlxsw: spectrum_switchdev: Remove reference count from mid Jiri Pirko
2017-09-20 14:15 ` [patch net-next 04/16] mlxsw: spectrum_switchdev: Save mids list per bridge device Jiri Pirko
2017-09-20 14:15 ` [patch net-next 05/16] mlxsw: spectrum_switchdev: Break smid write function Jiri Pirko
2017-09-20 14:15 ` [patch net-next 06/16] mlxsw: spectrum_switchdev: Attach mid id allocation to HW write Jiri Pirko
2017-09-20 14:15 ` [patch net-next 07/16] mlxsw: spectrum_switchdev: Break mid deletion into two function Jiri Pirko
2017-09-20 14:15 ` [patch net-next 08/16] mlxsw: spectrum_switchdev: Don't write mids to the HW when mc is disabled Jiri Pirko
2017-09-20 14:15 ` [patch net-next 09/16] mlxsw: spectrum_switchdev: Disable mdb " Jiri Pirko
2017-09-20 14:15 ` [patch net-next 10/16] mlxsw: spectrum_switchdev: Use generic mc flood function Jiri Pirko
2017-09-20 14:15 ` [patch net-next 11/16] mlxsw: spectrum_switchdev: Flood mc when mc is disabled by user flag Jiri Pirko
2017-09-20 14:15 ` [patch net-next 12/16] mlxsw: spectrum_switchdev: Flush the mdb when a port is being removed Jiri Pirko
2017-09-20 14:15 ` [patch net-next 13/16] mlxsw: spectrum_switchdev: Flood all mc packets to mrouter ports Jiri Pirko
2017-09-20 14:15 ` [patch net-next 14/16] mlxsw: spectrum_switchdev: Update the mdb of mrouter port change Jiri Pirko
2017-09-20 14:15 ` [patch net-next 15/16] mlxsw: spectrum_switchdev: Remove mrouter flood in mdb flush Jiri Pirko
2017-09-20 14:15 ` [patch net-next 16/16] mlxsw: spectrum_switchdev: Consider mrouter status for mdb changes Jiri Pirko
2017-09-21  1:05 ` [patch net-next 00/16] mlxsw: Multicast flood update David Miller

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.