diff mbox

[net-next,mlxsw,v2,6/7] mlxsw: Respin SPAN on switchdev events

Message ID 948a334a17b35e6ec03de5513fc8bd9dc27a9bb2.1524610426.git.petrm@mellanox.com (mailing list archive)
State Changes Requested
Delegated to: Ido Schimmel
Headers show

Commit Message

Petr Machata April 24, 2018, 11:08 p.m. UTC
Changes to switchdev artifact can make a SPAN entry offloadable or
unoffloadable. To that end:

- Listen to SWITCHDEV_FDB_*_TO_BRIDGE notifications in addition to
  the *_TO_DEVICE ones, to catch whatever activity is sent to the
  bridge (likely by mlxsw itself).

  On each FDB notification, respin SPAN to reconcile it with the FDB
  changes.

- Also respin on switchdev port attribute changes (which currently
  covers changes to STP state of ports) and port object additions and
  removals.

Signed-off-by: Petr Machata <petrm@mellanox.com>
---

Notes:
    Changes from v1 to v2:
    
    - In mlxsw_sp_switchdev_event_work(), add SWITCHDEV_FDB_*_TO_BRIDGE with
      a do-nothing handler to make it clear that these events expected.
    - Don't respin unless the switchdev event in question is a commit (as
      opposed to prepare).
    - Respin in mlxsw_sp_port_obj_add() and mlxsw_sp_port_obj_del().

 .../ethernet/mellanox/mlxsw/spectrum_switchdev.c   | 23 ++++++++++++++++++----
 1 file changed, 19 insertions(+), 4 deletions(-)

Comments

Ido Schimmel April 25, 2018, 7:19 a.m. UTC | #1
On Wed, Apr 25, 2018 at 01:08:17AM +0200, Petr Machata wrote:
> @@ -2236,8 +2244,13 @@ static void mlxsw_sp_switchdev_event_work(struct work_struct *work)
>  		fdb_info = &switchdev_work->fdb_info;
>  		mlxsw_sp_port_fdb_set(mlxsw_sp_port, fdb_info, false);
>  		break;
> +	case SWITCHDEV_FDB_ADD_TO_BRIDGE: /* fall through */
> +	case SWITCHDEV_FDB_DEL_TO_BRIDGE:

To make it even more explicit:
/* These events are only used to potentially update an existing SPAN mirror */

> +		break;
>  	}
Ido Schimmel April 25, 2018, 8:09 a.m. UTC | #2
On Wed, Apr 25, 2018 at 01:08:17AM +0200, Petr Machata wrote:
>  	switch (obj->id) {
>  	case SWITCHDEV_OBJ_ID_PORT_VLAN:
> -		err = mlxsw_sp_port_vlans_add(mlxsw_sp_port,
> -					      SWITCHDEV_OBJ_PORT_VLAN(obj),
> -					      trans);
> +		vlan = SWITCHDEV_OBJ_PORT_VLAN(obj);
> +		err = mlxsw_sp_port_vlans_add(mlxsw_sp_port, vlan, trans);
> +		if (switchdev_trans_ph_commit(trans))
> +			mlxsw_sp_span_respin(mlxsw_sp_port->mlxsw_sp, vlan);

I thought about it again. I think that instead of propagating the VLAN
everywhere, we can keep the code generic and simply schedule the respin
using a workqueue.
Petr Machata April 25, 2018, 8:57 a.m. UTC | #3
Ido Schimmel <idosch@mellanox.com> writes:

> On Wed, Apr 25, 2018 at 01:08:17AM +0200, Petr Machata wrote:
>>  	switch (obj->id) {
>>  	case SWITCHDEV_OBJ_ID_PORT_VLAN:
>> -		err = mlxsw_sp_port_vlans_add(mlxsw_sp_port,
>> -					      SWITCHDEV_OBJ_PORT_VLAN(obj),
>> -					      trans);
>> +		vlan = SWITCHDEV_OBJ_PORT_VLAN(obj);
>> +		err = mlxsw_sp_port_vlans_add(mlxsw_sp_port, vlan, trans);
>> +		if (switchdev_trans_ph_commit(trans))
>> +			mlxsw_sp_span_respin(mlxsw_sp_port->mlxsw_sp, vlan);
>
> I thought about it again. I think that instead of propagating the VLAN
> everywhere, we can keep the code generic and simply schedule the respin
> using a workqueue.

OK, I'll do it like that.
diff mbox

Patch

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index db4aea0..a6bfbfe 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -49,6 +49,7 @@ 
 #include <linux/netlink.h>
 #include <net/switchdev.h>
 
+#include "spectrum_span.h"
 #include "spectrum_router.h"
 #include "spectrum_switchdev.h"
 #include "spectrum.h"
@@ -923,6 +924,9 @@  static int mlxsw_sp_port_attr_set(struct net_device *dev,
 		break;
 	}
 
+	if (switchdev_trans_ph_commit(trans))
+		mlxsw_sp_span_respin(mlxsw_sp_port->mlxsw_sp, NULL);
+
 	return err;
 }
 
@@ -1652,13 +1656,15 @@  static int mlxsw_sp_port_obj_add(struct net_device *dev,
 				 struct switchdev_trans *trans)
 {
 	struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
+	const struct switchdev_obj_port_vlan *vlan;
 	int err = 0;
 
 	switch (obj->id) {
 	case SWITCHDEV_OBJ_ID_PORT_VLAN:
-		err = mlxsw_sp_port_vlans_add(mlxsw_sp_port,
-					      SWITCHDEV_OBJ_PORT_VLAN(obj),
-					      trans);
+		vlan = SWITCHDEV_OBJ_PORT_VLAN(obj);
+		err = mlxsw_sp_port_vlans_add(mlxsw_sp_port, vlan, trans);
+		if (switchdev_trans_ph_commit(trans))
+			mlxsw_sp_span_respin(mlxsw_sp_port->mlxsw_sp, vlan);
 		break;
 	case SWITCHDEV_OBJ_ID_PORT_MDB:
 		err = mlxsw_sp_port_mdb_add(mlxsw_sp_port,
@@ -1809,6 +1815,8 @@  static int mlxsw_sp_port_obj_del(struct net_device *dev,
 		break;
 	}
 
+	mlxsw_sp_span_respin(mlxsw_sp_port->mlxsw_sp, NULL);
+
 	return err;
 }
 
@@ -2236,8 +2244,13 @@  static void mlxsw_sp_switchdev_event_work(struct work_struct *work)
 		fdb_info = &switchdev_work->fdb_info;
 		mlxsw_sp_port_fdb_set(mlxsw_sp_port, fdb_info, false);
 		break;
+	case SWITCHDEV_FDB_ADD_TO_BRIDGE: /* fall through */
+	case SWITCHDEV_FDB_DEL_TO_BRIDGE:
+		break;
 	}
 
+	mlxsw_sp_span_respin(mlxsw_sp_port->mlxsw_sp, NULL);
+
 out:
 	rtnl_unlock();
 	kfree(switchdev_work->fdb_info.addr);
@@ -2266,7 +2279,9 @@  static int mlxsw_sp_switchdev_event(struct notifier_block *unused,
 
 	switch (event) {
 	case SWITCHDEV_FDB_ADD_TO_DEVICE: /* fall through */
-	case SWITCHDEV_FDB_DEL_TO_DEVICE:
+	case SWITCHDEV_FDB_DEL_TO_DEVICE: /* fall through */
+	case SWITCHDEV_FDB_ADD_TO_BRIDGE: /* fall through */
+	case SWITCHDEV_FDB_DEL_TO_BRIDGE:
 		memcpy(&switchdev_work->fdb_info, ptr,
 		       sizeof(switchdev_work->fdb_info));
 		switchdev_work->fdb_info.addr = kzalloc(ETH_ALEN, GFP_ATOMIC);