All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next mlxsw v2 0/2] bridge: FDB: Notify about removal of non-user-added entries
@ 2018-05-03 12:43 ` Petr Machata
  0 siblings, 0 replies; 18+ messages in thread
From: Petr Machata @ 2018-05-03 12:43 UTC (permalink / raw)
  To: netdev, bridge
  Cc: ivecera, f.fainelli, andrew, vivien.didelot, idosch, jiri, davem

Device drivers may generally need to keep in sync with bridge's FDB. In
particular, for its offload of tc mirror action where the mirrored-to
device is a gretap device, mlxsw needs to listen to a number of events,
FDB events among the others. SWITCHDEV_FDB_{ADD,DEL}_TO_DEVICE would be
a natural notification in that case.

However, for removal of FDB entries added due to device activity (as
opposed to explicit addition through "bridge fdb add" or similar), there
are no notifications.

Thus in patch #1, add the "added_by_user" field to switchdev
notifications sent for FDB activity. Adapt drivers to ignore activity on
non-user-added entries, to maintain the current behavior. Specifically
in case of mlxsw, allow mlxsw_sp_span_respin() call for any and all FDB
updates.

In patch #2, change the bridge driver to actually emit notifications for
these FDB entries. Take care not to send notification for bridge
updates that itself originate in SWITCHDEV_FDB_*_TO_BRIDGE events.

Changes from v1 to v2:
- Instead of introducing a new variant of fdb_delete(), add a new
  parameter to the existing function.
- Name the parameter swdev_notify, not notify.

Petr Machata (2):
  switchdev: Add fdb.added_by_user to switchdev notifications
  net: bridge: Notify about !added_by_user FDB entries

 .../ethernet/mellanox/mlxsw/spectrum_switchdev.c   |  4 ++
 drivers/net/ethernet/rocker/rocker_main.c          |  2 +
 include/net/switchdev.h                            |  1 +
 net/bridge/br.c                                    |  4 +-
 net/bridge/br_fdb.c                                | 47 ++++++++++++----------
 net/bridge/br_private.h                            |  6 ++-
 net/bridge/br_switchdev.c                          | 12 ++++--
 net/dsa/slave.c                                    |  5 ++-
 8 files changed, 51 insertions(+), 30 deletions(-)

-- 
2.4.11

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

* [Bridge] [PATCH net-next mlxsw v2 0/2] bridge: FDB: Notify about removal of non-user-added entries
@ 2018-05-03 12:43 ` Petr Machata
  0 siblings, 0 replies; 18+ messages in thread
From: Petr Machata @ 2018-05-03 12:43 UTC (permalink / raw)
  To: netdev, bridge
  Cc: ivecera, f.fainelli, andrew, vivien.didelot, idosch, jiri, davem

Device drivers may generally need to keep in sync with bridge's FDB. In
particular, for its offload of tc mirror action where the mirrored-to
device is a gretap device, mlxsw needs to listen to a number of events,
FDB events among the others. SWITCHDEV_FDB_{ADD,DEL}_TO_DEVICE would be
a natural notification in that case.

However, for removal of FDB entries added due to device activity (as
opposed to explicit addition through "bridge fdb add" or similar), there
are no notifications.

Thus in patch #1, add the "added_by_user" field to switchdev
notifications sent for FDB activity. Adapt drivers to ignore activity on
non-user-added entries, to maintain the current behavior. Specifically
in case of mlxsw, allow mlxsw_sp_span_respin() call for any and all FDB
updates.

In patch #2, change the bridge driver to actually emit notifications for
these FDB entries. Take care not to send notification for bridge
updates that itself originate in SWITCHDEV_FDB_*_TO_BRIDGE events.

Changes from v1 to v2:
- Instead of introducing a new variant of fdb_delete(), add a new
  parameter to the existing function.
- Name the parameter swdev_notify, not notify.

Petr Machata (2):
  switchdev: Add fdb.added_by_user to switchdev notifications
  net: bridge: Notify about !added_by_user FDB entries

 .../ethernet/mellanox/mlxsw/spectrum_switchdev.c   |  4 ++
 drivers/net/ethernet/rocker/rocker_main.c          |  2 +
 include/net/switchdev.h                            |  1 +
 net/bridge/br.c                                    |  4 +-
 net/bridge/br_fdb.c                                | 47 ++++++++++++----------
 net/bridge/br_private.h                            |  6 ++-
 net/bridge/br_switchdev.c                          | 12 ++++--
 net/dsa/slave.c                                    |  5 ++-
 8 files changed, 51 insertions(+), 30 deletions(-)

-- 
2.4.11


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

* [PATCH net-next mlxsw v2 1/2] switchdev: Add fdb.added_by_user to switchdev notifications
  2018-05-03 12:43 ` [Bridge] " Petr Machata
@ 2018-05-03 12:43   ` Petr Machata
  -1 siblings, 0 replies; 18+ messages in thread
From: Petr Machata @ 2018-05-03 12:43 UTC (permalink / raw)
  To: netdev, bridge
  Cc: ivecera, f.fainelli, andrew, vivien.didelot, idosch, jiri, davem

The following patch enables sending notifications also for events on FDB
entries that weren't added by the user. Give the drivers the information
necessary to distinguish between the two origins of FDB entries.

To maintain the current behavior, have switchdev-implementing drivers
bail out on notifications about non-user-added FDB entries. In case of
mlxsw driver, allow a call to mlxsw_sp_span_respin() so that SPAN over
bridge catches up with the changed FDB.

Signed-off-by: Petr Machata <petrm@mellanox.com>
Reviewed-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c |  4 ++++
 drivers/net/ethernet/rocker/rocker_main.c                |  2 ++
 include/net/switchdev.h                                  |  1 +
 net/bridge/br_switchdev.c                                | 10 +++++++---
 net/dsa/slave.c                                          |  5 ++++-
 5 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 1af99fe..3973d90 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -2270,6 +2270,8 @@ static void mlxsw_sp_switchdev_event_work(struct work_struct *work)
 	switch (switchdev_work->event) {
 	case SWITCHDEV_FDB_ADD_TO_DEVICE:
 		fdb_info = &switchdev_work->fdb_info;
+		if (!fdb_info->added_by_user)
+			break;
 		err = mlxsw_sp_port_fdb_set(mlxsw_sp_port, fdb_info, true);
 		if (err)
 			break;
@@ -2279,6 +2281,8 @@ static void mlxsw_sp_switchdev_event_work(struct work_struct *work)
 		break;
 	case SWITCHDEV_FDB_DEL_TO_DEVICE:
 		fdb_info = &switchdev_work->fdb_info;
+		if (!fdb_info->added_by_user)
+			break;
 		mlxsw_sp_port_fdb_set(mlxsw_sp_port, fdb_info, false);
 		break;
 	case SWITCHDEV_FDB_ADD_TO_BRIDGE: /* fall through */
diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c
index 056cb60..152d694 100644
--- a/drivers/net/ethernet/rocker/rocker_main.c
+++ b/drivers/net/ethernet/rocker/rocker_main.c
@@ -2783,6 +2783,8 @@ static int rocker_switchdev_event(struct notifier_block *unused,
 	switch (event) {
 	case SWITCHDEV_FDB_ADD_TO_DEVICE: /* fall through */
 	case SWITCHDEV_FDB_DEL_TO_DEVICE:
+		if (!fdb_info->added_by_user)
+			break;
 		memcpy(&switchdev_work->fdb_info, ptr,
 		       sizeof(switchdev_work->fdb_info));
 		switchdev_work->fdb_info.addr = kzalloc(ETH_ALEN, GFP_ATOMIC);
diff --git a/include/net/switchdev.h b/include/net/switchdev.h
index 39bc855..d574ce6 100644
--- a/include/net/switchdev.h
+++ b/include/net/switchdev.h
@@ -155,6 +155,7 @@ struct switchdev_notifier_fdb_info {
 	struct switchdev_notifier_info info; /* must be first */
 	const unsigned char *addr;
 	u16 vid;
+	bool added_by_user;
 };
 
 static inline struct net_device *
diff --git a/net/bridge/br_switchdev.c b/net/bridge/br_switchdev.c
index ee775f4..71a03c4 100644
--- a/net/bridge/br_switchdev.c
+++ b/net/bridge/br_switchdev.c
@@ -102,13 +102,15 @@ int br_switchdev_set_port_flag(struct net_bridge_port *p,
 
 static void
 br_switchdev_fdb_call_notifiers(bool adding, const unsigned char *mac,
-				u16 vid, struct net_device *dev)
+				u16 vid, struct net_device *dev,
+				bool added_by_user)
 {
 	struct switchdev_notifier_fdb_info info;
 	unsigned long notifier_type;
 
 	info.addr = mac;
 	info.vid = vid;
+	info.added_by_user = added_by_user;
 	notifier_type = adding ? SWITCHDEV_FDB_ADD_TO_DEVICE : SWITCHDEV_FDB_DEL_TO_DEVICE;
 	call_switchdev_notifiers(notifier_type, dev, &info.info);
 }
@@ -123,12 +125,14 @@ br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb, int type)
 	case RTM_DELNEIGH:
 		br_switchdev_fdb_call_notifiers(false, fdb->key.addr.addr,
 						fdb->key.vlan_id,
-						fdb->dst->dev);
+						fdb->dst->dev,
+						fdb->added_by_user);
 		break;
 	case RTM_NEWNEIGH:
 		br_switchdev_fdb_call_notifiers(true, fdb->key.addr.addr,
 						fdb->key.vlan_id,
-						fdb->dst->dev);
+						fdb->dst->dev,
+						fdb->added_by_user);
 		break;
 	}
 }
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index f3fb3a0..c287f1e 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -1441,6 +1441,7 @@ static int dsa_slave_switchdev_event(struct notifier_block *unused,
 				     unsigned long event, void *ptr)
 {
 	struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
+	struct switchdev_notifier_fdb_info *fdb_info = ptr;
 	struct dsa_switchdev_event_work *switchdev_work;
 
 	if (!dsa_slave_dev_check(dev))
@@ -1458,8 +1459,10 @@ static int dsa_slave_switchdev_event(struct notifier_block *unused,
 	switch (event) {
 	case SWITCHDEV_FDB_ADD_TO_DEVICE: /* fall through */
 	case SWITCHDEV_FDB_DEL_TO_DEVICE:
+		if (!fdb_info->added_by_user)
+			break;
 		if (dsa_slave_switchdev_fdb_work_init(switchdev_work,
-						      ptr))
+						      fdb_info))
 			goto err_fdb_work_init;
 		dev_hold(dev);
 		break;
-- 
2.4.11

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

* [Bridge] [PATCH net-next mlxsw v2 1/2] switchdev: Add fdb.added_by_user to switchdev notifications
@ 2018-05-03 12:43   ` Petr Machata
  0 siblings, 0 replies; 18+ messages in thread
From: Petr Machata @ 2018-05-03 12:43 UTC (permalink / raw)
  To: netdev, bridge
  Cc: ivecera, f.fainelli, andrew, vivien.didelot, idosch, jiri, davem

The following patch enables sending notifications also for events on FDB
entries that weren't added by the user. Give the drivers the information
necessary to distinguish between the two origins of FDB entries.

To maintain the current behavior, have switchdev-implementing drivers
bail out on notifications about non-user-added FDB entries. In case of
mlxsw driver, allow a call to mlxsw_sp_span_respin() so that SPAN over
bridge catches up with the changed FDB.

Signed-off-by: Petr Machata <petrm@mellanox.com>
Reviewed-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c |  4 ++++
 drivers/net/ethernet/rocker/rocker_main.c                |  2 ++
 include/net/switchdev.h                                  |  1 +
 net/bridge/br_switchdev.c                                | 10 +++++++---
 net/dsa/slave.c                                          |  5 ++++-
 5 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 1af99fe..3973d90 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -2270,6 +2270,8 @@ static void mlxsw_sp_switchdev_event_work(struct work_struct *work)
 	switch (switchdev_work->event) {
 	case SWITCHDEV_FDB_ADD_TO_DEVICE:
 		fdb_info = &switchdev_work->fdb_info;
+		if (!fdb_info->added_by_user)
+			break;
 		err = mlxsw_sp_port_fdb_set(mlxsw_sp_port, fdb_info, true);
 		if (err)
 			break;
@@ -2279,6 +2281,8 @@ static void mlxsw_sp_switchdev_event_work(struct work_struct *work)
 		break;
 	case SWITCHDEV_FDB_DEL_TO_DEVICE:
 		fdb_info = &switchdev_work->fdb_info;
+		if (!fdb_info->added_by_user)
+			break;
 		mlxsw_sp_port_fdb_set(mlxsw_sp_port, fdb_info, false);
 		break;
 	case SWITCHDEV_FDB_ADD_TO_BRIDGE: /* fall through */
diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c
index 056cb60..152d694 100644
--- a/drivers/net/ethernet/rocker/rocker_main.c
+++ b/drivers/net/ethernet/rocker/rocker_main.c
@@ -2783,6 +2783,8 @@ static int rocker_switchdev_event(struct notifier_block *unused,
 	switch (event) {
 	case SWITCHDEV_FDB_ADD_TO_DEVICE: /* fall through */
 	case SWITCHDEV_FDB_DEL_TO_DEVICE:
+		if (!fdb_info->added_by_user)
+			break;
 		memcpy(&switchdev_work->fdb_info, ptr,
 		       sizeof(switchdev_work->fdb_info));
 		switchdev_work->fdb_info.addr = kzalloc(ETH_ALEN, GFP_ATOMIC);
diff --git a/include/net/switchdev.h b/include/net/switchdev.h
index 39bc855..d574ce6 100644
--- a/include/net/switchdev.h
+++ b/include/net/switchdev.h
@@ -155,6 +155,7 @@ struct switchdev_notifier_fdb_info {
 	struct switchdev_notifier_info info; /* must be first */
 	const unsigned char *addr;
 	u16 vid;
+	bool added_by_user;
 };
 
 static inline struct net_device *
diff --git a/net/bridge/br_switchdev.c b/net/bridge/br_switchdev.c
index ee775f4..71a03c4 100644
--- a/net/bridge/br_switchdev.c
+++ b/net/bridge/br_switchdev.c
@@ -102,13 +102,15 @@ int br_switchdev_set_port_flag(struct net_bridge_port *p,
 
 static void
 br_switchdev_fdb_call_notifiers(bool adding, const unsigned char *mac,
-				u16 vid, struct net_device *dev)
+				u16 vid, struct net_device *dev,
+				bool added_by_user)
 {
 	struct switchdev_notifier_fdb_info info;
 	unsigned long notifier_type;
 
 	info.addr = mac;
 	info.vid = vid;
+	info.added_by_user = added_by_user;
 	notifier_type = adding ? SWITCHDEV_FDB_ADD_TO_DEVICE : SWITCHDEV_FDB_DEL_TO_DEVICE;
 	call_switchdev_notifiers(notifier_type, dev, &info.info);
 }
@@ -123,12 +125,14 @@ br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb, int type)
 	case RTM_DELNEIGH:
 		br_switchdev_fdb_call_notifiers(false, fdb->key.addr.addr,
 						fdb->key.vlan_id,
-						fdb->dst->dev);
+						fdb->dst->dev,
+						fdb->added_by_user);
 		break;
 	case RTM_NEWNEIGH:
 		br_switchdev_fdb_call_notifiers(true, fdb->key.addr.addr,
 						fdb->key.vlan_id,
-						fdb->dst->dev);
+						fdb->dst->dev,
+						fdb->added_by_user);
 		break;
 	}
 }
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index f3fb3a0..c287f1e 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -1441,6 +1441,7 @@ static int dsa_slave_switchdev_event(struct notifier_block *unused,
 				     unsigned long event, void *ptr)
 {
 	struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
+	struct switchdev_notifier_fdb_info *fdb_info = ptr;
 	struct dsa_switchdev_event_work *switchdev_work;
 
 	if (!dsa_slave_dev_check(dev))
@@ -1458,8 +1459,10 @@ static int dsa_slave_switchdev_event(struct notifier_block *unused,
 	switch (event) {
 	case SWITCHDEV_FDB_ADD_TO_DEVICE: /* fall through */
 	case SWITCHDEV_FDB_DEL_TO_DEVICE:
+		if (!fdb_info->added_by_user)
+			break;
 		if (dsa_slave_switchdev_fdb_work_init(switchdev_work,
-						      ptr))
+						      fdb_info))
 			goto err_fdb_work_init;
 		dev_hold(dev);
 		break;
-- 
2.4.11


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

* [PATCH net-next mlxsw v2 2/2] net: bridge: Notify about !added_by_user FDB entries
  2018-05-03 12:43 ` [Bridge] " Petr Machata
@ 2018-05-03 12:43   ` Petr Machata
  -1 siblings, 0 replies; 18+ messages in thread
From: Petr Machata @ 2018-05-03 12:43 UTC (permalink / raw)
  To: netdev, bridge
  Cc: jiri, idosch, ivecera, davem, stephen, andrew, vivien.didelot,
	f.fainelli

Do not automatically bail out on sending notifications about activity on
non-user-added FDB entries. Instead, notify about this activity except
for cases where the activity itself originates in a notification, to
avoid sending duplicate notifications.

Signed-off-by: Petr Machata <petrm@mellanox.com>
---
 net/bridge/br.c           |  4 ++--
 net/bridge/br_fdb.c       | 47 ++++++++++++++++++++++++++---------------------
 net/bridge/br_private.h   |  6 ++++--
 net/bridge/br_switchdev.c |  2 +-
 4 files changed, 33 insertions(+), 26 deletions(-)

diff --git a/net/bridge/br.c b/net/bridge/br.c
index 671d13c..c6b033e 100644
--- a/net/bridge/br.c
+++ b/net/bridge/br.c
@@ -141,7 +141,7 @@ static int br_switchdev_event(struct notifier_block *unused,
 	case SWITCHDEV_FDB_ADD_TO_BRIDGE:
 		fdb_info = ptr;
 		err = br_fdb_external_learn_add(br, p, fdb_info->addr,
-						fdb_info->vid);
+						fdb_info->vid, false);
 		if (err) {
 			err = notifier_from_errno(err);
 			break;
@@ -152,7 +152,7 @@ static int br_switchdev_event(struct notifier_block *unused,
 	case SWITCHDEV_FDB_DEL_TO_BRIDGE:
 		fdb_info = ptr;
 		err = br_fdb_external_learn_del(br, p, fdb_info->addr,
-						fdb_info->vid);
+						fdb_info->vid, false);
 		if (err)
 			err = notifier_from_errno(err);
 		break;
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index a1c409c..b19e310 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -40,7 +40,7 @@ static struct kmem_cache *br_fdb_cache __read_mostly;
 static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
 		      const unsigned char *addr, u16 vid);
 static void fdb_notify(struct net_bridge *br,
-		       const struct net_bridge_fdb_entry *, int);
+		       const struct net_bridge_fdb_entry *, int, bool);
 
 int __init br_fdb_init(void)
 {
@@ -195,7 +195,8 @@ static void fdb_del_hw_addr(struct net_bridge *br, const unsigned char *addr)
 	}
 }
 
-static void fdb_delete(struct net_bridge *br, struct net_bridge_fdb_entry *f)
+static void fdb_delete(struct net_bridge *br, struct net_bridge_fdb_entry *f,
+		       bool swdev_notify)
 {
 	trace_fdb_delete(br, f);
 
@@ -205,7 +206,7 @@ static void fdb_delete(struct net_bridge *br, struct net_bridge_fdb_entry *f)
 	hlist_del_init_rcu(&f->fdb_node);
 	rhashtable_remove_fast(&br->fdb_hash_tbl, &f->rhnode,
 			       br_fdb_rht_params);
-	fdb_notify(br, f, RTM_DELNEIGH);
+	fdb_notify(br, f, RTM_DELNEIGH, swdev_notify);
 	call_rcu(&f->rcu, fdb_rcu_free);
 }
 
@@ -241,7 +242,7 @@ static void fdb_delete_local(struct net_bridge *br,
 		return;
 	}
 
-	fdb_delete(br, f);
+	fdb_delete(br, f, true);
 }
 
 void br_fdb_find_delete_local(struct net_bridge *br,
@@ -356,7 +357,7 @@ void br_fdb_cleanup(struct work_struct *work)
 		} else {
 			spin_lock_bh(&br->hash_lock);
 			if (!hlist_unhashed(&f->fdb_node))
-				fdb_delete(br, f);
+				fdb_delete(br, f, true);
 			spin_unlock_bh(&br->hash_lock);
 		}
 	}
@@ -376,7 +377,7 @@ void br_fdb_flush(struct net_bridge *br)
 	spin_lock_bh(&br->hash_lock);
 	hlist_for_each_entry_safe(f, tmp, &br->fdb_list, fdb_node) {
 		if (!f->is_static)
-			fdb_delete(br, f);
+			fdb_delete(br, f, true);
 	}
 	spin_unlock_bh(&br->hash_lock);
 }
@@ -405,7 +406,7 @@ void br_fdb_delete_by_port(struct net_bridge *br,
 		if (f->is_local)
 			fdb_delete_local(br, p, f);
 		else
-			fdb_delete(br, f);
+			fdb_delete(br, f, true);
 	}
 	spin_unlock_bh(&br->hash_lock);
 }
@@ -531,7 +532,7 @@ static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
 			return 0;
 		br_warn(br, "adding interface %s with same address as a received packet (addr:%pM, vlan:%u)\n",
 		       source ? source->dev->name : br->dev->name, addr, vid);
-		fdb_delete(br, fdb);
+		fdb_delete(br, fdb, true);
 	}
 
 	fdb = fdb_create(br, source, addr, vid, 1, 1);
@@ -539,7 +540,7 @@ static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
 		return -ENOMEM;
 
 	fdb_add_hw_addr(br, addr);
-	fdb_notify(br, fdb, RTM_NEWNEIGH);
+	fdb_notify(br, fdb, RTM_NEWNEIGH, true);
 	return 0;
 }
 
@@ -594,7 +595,7 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
 				fdb->added_by_user = 1;
 			if (unlikely(fdb_modified)) {
 				trace_br_fdb_update(br, source, addr, vid, added_by_user);
-				fdb_notify(br, fdb, RTM_NEWNEIGH);
+				fdb_notify(br, fdb, RTM_NEWNEIGH, true);
 			}
 		}
 	} else {
@@ -605,7 +606,7 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
 				fdb->added_by_user = 1;
 			trace_br_fdb_update(br, source, addr, vid,
 					    added_by_user);
-			fdb_notify(br, fdb, RTM_NEWNEIGH);
+			fdb_notify(br, fdb, RTM_NEWNEIGH, true);
 		}
 		/* else  we lose race and someone else inserts
 		 * it first, don't bother updating
@@ -687,13 +688,15 @@ static inline size_t fdb_nlmsg_size(void)
 }
 
 static void fdb_notify(struct net_bridge *br,
-		       const struct net_bridge_fdb_entry *fdb, int type)
+		       const struct net_bridge_fdb_entry *fdb, int type,
+		       bool swdev_notify)
 {
 	struct net *net = dev_net(br->dev);
 	struct sk_buff *skb;
 	int err = -ENOBUFS;
 
-	br_switchdev_fdb_notify(fdb, type);
+	if (swdev_notify)
+		br_switchdev_fdb_notify(fdb, type);
 
 	skb = nlmsg_new(fdb_nlmsg_size(), GFP_ATOMIC);
 	if (skb == NULL)
@@ -832,7 +835,7 @@ static int fdb_add_entry(struct net_bridge *br, struct net_bridge_port *source,
 	fdb->used = jiffies;
 	if (modified) {
 		fdb->updated = jiffies;
-		fdb_notify(br, fdb, RTM_NEWNEIGH);
+		fdb_notify(br, fdb, RTM_NEWNEIGH, true);
 	}
 
 	return 0;
@@ -856,7 +859,7 @@ static int __br_fdb_add(struct ndmsg *ndm, struct net_bridge *br,
 		rcu_read_unlock();
 		local_bh_enable();
 	} else if (ndm->ndm_flags & NTF_EXT_LEARNED) {
-		err = br_fdb_external_learn_add(br, p, addr, vid);
+		err = br_fdb_external_learn_add(br, p, addr, vid, true);
 	} else {
 		spin_lock_bh(&br->hash_lock);
 		err = fdb_add_entry(br, p, addr, ndm->ndm_state,
@@ -945,7 +948,7 @@ static int fdb_delete_by_addr_and_port(struct net_bridge *br,
 	if (!fdb || fdb->dst != p)
 		return -ENOENT;
 
-	fdb_delete(br, fdb);
+	fdb_delete(br, fdb, true);
 
 	return 0;
 }
@@ -1065,7 +1068,8 @@ void br_fdb_unsync_static(struct net_bridge *br, struct net_bridge_port *p)
 }
 
 int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
-			      const unsigned char *addr, u16 vid)
+			      const unsigned char *addr, u16 vid,
+			      bool swdev_notify)
 {
 	struct net_bridge_fdb_entry *fdb;
 	bool modified = false;
@@ -1083,7 +1087,7 @@ int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
 			goto err_unlock;
 		}
 		fdb->added_by_external_learn = 1;
-		fdb_notify(br, fdb, RTM_NEWNEIGH);
+		fdb_notify(br, fdb, RTM_NEWNEIGH, swdev_notify);
 	} else {
 		fdb->updated = jiffies;
 
@@ -1102,7 +1106,7 @@ int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
 		}
 
 		if (modified)
-			fdb_notify(br, fdb, RTM_NEWNEIGH);
+			fdb_notify(br, fdb, RTM_NEWNEIGH, swdev_notify);
 	}
 
 err_unlock:
@@ -1112,7 +1116,8 @@ int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
 }
 
 int br_fdb_external_learn_del(struct net_bridge *br, struct net_bridge_port *p,
-			      const unsigned char *addr, u16 vid)
+			      const unsigned char *addr, u16 vid,
+			      bool swdev_notify)
 {
 	struct net_bridge_fdb_entry *fdb;
 	int err = 0;
@@ -1121,7 +1126,7 @@ int br_fdb_external_learn_del(struct net_bridge *br, struct net_bridge_port *p,
 
 	fdb = br_fdb_find(br, addr, vid);
 	if (fdb && fdb->added_by_external_learn)
-		fdb_delete(br, fdb);
+		fdb_delete(br, fdb, swdev_notify);
 	else
 		err = -ENOENT;
 
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 1a50931..80a69b8 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -553,9 +553,11 @@ int br_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
 int br_fdb_sync_static(struct net_bridge *br, struct net_bridge_port *p);
 void br_fdb_unsync_static(struct net_bridge *br, struct net_bridge_port *p);
 int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
-			      const unsigned char *addr, u16 vid);
+			      const unsigned char *addr, u16 vid,
+			      bool swdev_notify);
 int br_fdb_external_learn_del(struct net_bridge *br, struct net_bridge_port *p,
-			      const unsigned char *addr, u16 vid);
+			      const unsigned char *addr, u16 vid,
+			      bool swdev_notify);
 void br_fdb_offloaded_set(struct net_bridge *br, struct net_bridge_port *p,
 			  const unsigned char *addr, u16 vid);
 
diff --git a/net/bridge/br_switchdev.c b/net/bridge/br_switchdev.c
index 71a03c4..35474d4 100644
--- a/net/bridge/br_switchdev.c
+++ b/net/bridge/br_switchdev.c
@@ -118,7 +118,7 @@ br_switchdev_fdb_call_notifiers(bool adding, const unsigned char *mac,
 void
 br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb, int type)
 {
-	if (!fdb->added_by_user || !fdb->dst)
+	if (!fdb->dst)
 		return;
 
 	switch (type) {
-- 
2.4.11

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

* [Bridge] [PATCH net-next mlxsw v2 2/2] net: bridge: Notify about !added_by_user FDB entries
@ 2018-05-03 12:43   ` Petr Machata
  0 siblings, 0 replies; 18+ messages in thread
From: Petr Machata @ 2018-05-03 12:43 UTC (permalink / raw)
  To: netdev, bridge
  Cc: ivecera, f.fainelli, andrew, vivien.didelot, idosch, jiri, davem

Do not automatically bail out on sending notifications about activity on
non-user-added FDB entries. Instead, notify about this activity except
for cases where the activity itself originates in a notification, to
avoid sending duplicate notifications.

Signed-off-by: Petr Machata <petrm@mellanox.com>
---
 net/bridge/br.c           |  4 ++--
 net/bridge/br_fdb.c       | 47 ++++++++++++++++++++++++++---------------------
 net/bridge/br_private.h   |  6 ++++--
 net/bridge/br_switchdev.c |  2 +-
 4 files changed, 33 insertions(+), 26 deletions(-)

diff --git a/net/bridge/br.c b/net/bridge/br.c
index 671d13c..c6b033e 100644
--- a/net/bridge/br.c
+++ b/net/bridge/br.c
@@ -141,7 +141,7 @@ static int br_switchdev_event(struct notifier_block *unused,
 	case SWITCHDEV_FDB_ADD_TO_BRIDGE:
 		fdb_info = ptr;
 		err = br_fdb_external_learn_add(br, p, fdb_info->addr,
-						fdb_info->vid);
+						fdb_info->vid, false);
 		if (err) {
 			err = notifier_from_errno(err);
 			break;
@@ -152,7 +152,7 @@ static int br_switchdev_event(struct notifier_block *unused,
 	case SWITCHDEV_FDB_DEL_TO_BRIDGE:
 		fdb_info = ptr;
 		err = br_fdb_external_learn_del(br, p, fdb_info->addr,
-						fdb_info->vid);
+						fdb_info->vid, false);
 		if (err)
 			err = notifier_from_errno(err);
 		break;
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index a1c409c..b19e310 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -40,7 +40,7 @@ static struct kmem_cache *br_fdb_cache __read_mostly;
 static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
 		      const unsigned char *addr, u16 vid);
 static void fdb_notify(struct net_bridge *br,
-		       const struct net_bridge_fdb_entry *, int);
+		       const struct net_bridge_fdb_entry *, int, bool);
 
 int __init br_fdb_init(void)
 {
@@ -195,7 +195,8 @@ static void fdb_del_hw_addr(struct net_bridge *br, const unsigned char *addr)
 	}
 }
 
-static void fdb_delete(struct net_bridge *br, struct net_bridge_fdb_entry *f)
+static void fdb_delete(struct net_bridge *br, struct net_bridge_fdb_entry *f,
+		       bool swdev_notify)
 {
 	trace_fdb_delete(br, f);
 
@@ -205,7 +206,7 @@ static void fdb_delete(struct net_bridge *br, struct net_bridge_fdb_entry *f)
 	hlist_del_init_rcu(&f->fdb_node);
 	rhashtable_remove_fast(&br->fdb_hash_tbl, &f->rhnode,
 			       br_fdb_rht_params);
-	fdb_notify(br, f, RTM_DELNEIGH);
+	fdb_notify(br, f, RTM_DELNEIGH, swdev_notify);
 	call_rcu(&f->rcu, fdb_rcu_free);
 }
 
@@ -241,7 +242,7 @@ static void fdb_delete_local(struct net_bridge *br,
 		return;
 	}
 
-	fdb_delete(br, f);
+	fdb_delete(br, f, true);
 }
 
 void br_fdb_find_delete_local(struct net_bridge *br,
@@ -356,7 +357,7 @@ void br_fdb_cleanup(struct work_struct *work)
 		} else {
 			spin_lock_bh(&br->hash_lock);
 			if (!hlist_unhashed(&f->fdb_node))
-				fdb_delete(br, f);
+				fdb_delete(br, f, true);
 			spin_unlock_bh(&br->hash_lock);
 		}
 	}
@@ -376,7 +377,7 @@ void br_fdb_flush(struct net_bridge *br)
 	spin_lock_bh(&br->hash_lock);
 	hlist_for_each_entry_safe(f, tmp, &br->fdb_list, fdb_node) {
 		if (!f->is_static)
-			fdb_delete(br, f);
+			fdb_delete(br, f, true);
 	}
 	spin_unlock_bh(&br->hash_lock);
 }
@@ -405,7 +406,7 @@ void br_fdb_delete_by_port(struct net_bridge *br,
 		if (f->is_local)
 			fdb_delete_local(br, p, f);
 		else
-			fdb_delete(br, f);
+			fdb_delete(br, f, true);
 	}
 	spin_unlock_bh(&br->hash_lock);
 }
@@ -531,7 +532,7 @@ static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
 			return 0;
 		br_warn(br, "adding interface %s with same address as a received packet (addr:%pM, vlan:%u)\n",
 		       source ? source->dev->name : br->dev->name, addr, vid);
-		fdb_delete(br, fdb);
+		fdb_delete(br, fdb, true);
 	}
 
 	fdb = fdb_create(br, source, addr, vid, 1, 1);
@@ -539,7 +540,7 @@ static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
 		return -ENOMEM;
 
 	fdb_add_hw_addr(br, addr);
-	fdb_notify(br, fdb, RTM_NEWNEIGH);
+	fdb_notify(br, fdb, RTM_NEWNEIGH, true);
 	return 0;
 }
 
@@ -594,7 +595,7 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
 				fdb->added_by_user = 1;
 			if (unlikely(fdb_modified)) {
 				trace_br_fdb_update(br, source, addr, vid, added_by_user);
-				fdb_notify(br, fdb, RTM_NEWNEIGH);
+				fdb_notify(br, fdb, RTM_NEWNEIGH, true);
 			}
 		}
 	} else {
@@ -605,7 +606,7 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
 				fdb->added_by_user = 1;
 			trace_br_fdb_update(br, source, addr, vid,
 					    added_by_user);
-			fdb_notify(br, fdb, RTM_NEWNEIGH);
+			fdb_notify(br, fdb, RTM_NEWNEIGH, true);
 		}
 		/* else  we lose race and someone else inserts
 		 * it first, don't bother updating
@@ -687,13 +688,15 @@ static inline size_t fdb_nlmsg_size(void)
 }
 
 static void fdb_notify(struct net_bridge *br,
-		       const struct net_bridge_fdb_entry *fdb, int type)
+		       const struct net_bridge_fdb_entry *fdb, int type,
+		       bool swdev_notify)
 {
 	struct net *net = dev_net(br->dev);
 	struct sk_buff *skb;
 	int err = -ENOBUFS;
 
-	br_switchdev_fdb_notify(fdb, type);
+	if (swdev_notify)
+		br_switchdev_fdb_notify(fdb, type);
 
 	skb = nlmsg_new(fdb_nlmsg_size(), GFP_ATOMIC);
 	if (skb == NULL)
@@ -832,7 +835,7 @@ static int fdb_add_entry(struct net_bridge *br, struct net_bridge_port *source,
 	fdb->used = jiffies;
 	if (modified) {
 		fdb->updated = jiffies;
-		fdb_notify(br, fdb, RTM_NEWNEIGH);
+		fdb_notify(br, fdb, RTM_NEWNEIGH, true);
 	}
 
 	return 0;
@@ -856,7 +859,7 @@ static int __br_fdb_add(struct ndmsg *ndm, struct net_bridge *br,
 		rcu_read_unlock();
 		local_bh_enable();
 	} else if (ndm->ndm_flags & NTF_EXT_LEARNED) {
-		err = br_fdb_external_learn_add(br, p, addr, vid);
+		err = br_fdb_external_learn_add(br, p, addr, vid, true);
 	} else {
 		spin_lock_bh(&br->hash_lock);
 		err = fdb_add_entry(br, p, addr, ndm->ndm_state,
@@ -945,7 +948,7 @@ static int fdb_delete_by_addr_and_port(struct net_bridge *br,
 	if (!fdb || fdb->dst != p)
 		return -ENOENT;
 
-	fdb_delete(br, fdb);
+	fdb_delete(br, fdb, true);
 
 	return 0;
 }
@@ -1065,7 +1068,8 @@ void br_fdb_unsync_static(struct net_bridge *br, struct net_bridge_port *p)
 }
 
 int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
-			      const unsigned char *addr, u16 vid)
+			      const unsigned char *addr, u16 vid,
+			      bool swdev_notify)
 {
 	struct net_bridge_fdb_entry *fdb;
 	bool modified = false;
@@ -1083,7 +1087,7 @@ int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
 			goto err_unlock;
 		}
 		fdb->added_by_external_learn = 1;
-		fdb_notify(br, fdb, RTM_NEWNEIGH);
+		fdb_notify(br, fdb, RTM_NEWNEIGH, swdev_notify);
 	} else {
 		fdb->updated = jiffies;
 
@@ -1102,7 +1106,7 @@ int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
 		}
 
 		if (modified)
-			fdb_notify(br, fdb, RTM_NEWNEIGH);
+			fdb_notify(br, fdb, RTM_NEWNEIGH, swdev_notify);
 	}
 
 err_unlock:
@@ -1112,7 +1116,8 @@ int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
 }
 
 int br_fdb_external_learn_del(struct net_bridge *br, struct net_bridge_port *p,
-			      const unsigned char *addr, u16 vid)
+			      const unsigned char *addr, u16 vid,
+			      bool swdev_notify)
 {
 	struct net_bridge_fdb_entry *fdb;
 	int err = 0;
@@ -1121,7 +1126,7 @@ int br_fdb_external_learn_del(struct net_bridge *br, struct net_bridge_port *p,
 
 	fdb = br_fdb_find(br, addr, vid);
 	if (fdb && fdb->added_by_external_learn)
-		fdb_delete(br, fdb);
+		fdb_delete(br, fdb, swdev_notify);
 	else
 		err = -ENOENT;
 
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 1a50931..80a69b8 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -553,9 +553,11 @@ int br_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
 int br_fdb_sync_static(struct net_bridge *br, struct net_bridge_port *p);
 void br_fdb_unsync_static(struct net_bridge *br, struct net_bridge_port *p);
 int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
-			      const unsigned char *addr, u16 vid);
+			      const unsigned char *addr, u16 vid,
+			      bool swdev_notify);
 int br_fdb_external_learn_del(struct net_bridge *br, struct net_bridge_port *p,
-			      const unsigned char *addr, u16 vid);
+			      const unsigned char *addr, u16 vid,
+			      bool swdev_notify);
 void br_fdb_offloaded_set(struct net_bridge *br, struct net_bridge_port *p,
 			  const unsigned char *addr, u16 vid);
 
diff --git a/net/bridge/br_switchdev.c b/net/bridge/br_switchdev.c
index 71a03c4..35474d4 100644
--- a/net/bridge/br_switchdev.c
+++ b/net/bridge/br_switchdev.c
@@ -118,7 +118,7 @@ br_switchdev_fdb_call_notifiers(bool adding, const unsigned char *mac,
 void
 br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb, int type)
 {
-	if (!fdb->added_by_user || !fdb->dst)
+	if (!fdb->dst)
 		return;
 
 	switch (type) {
-- 
2.4.11


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

* Re: [PATCH net-next mlxsw v2 0/2] bridge: FDB: Notify about removal of non-user-added entries
  2018-05-03 12:43 ` [Bridge] " Petr Machata
@ 2018-05-03 12:48   ` Petr Machata
  -1 siblings, 0 replies; 18+ messages in thread
From: Petr Machata @ 2018-05-03 12:48 UTC (permalink / raw)
  To: netdev
  Cc: bridge, jiri, idosch, ivecera, davem, stephen, andrew,
	vivien.didelot, f.fainelli

This is of course not meant for "mlxsw" :-/

Petr

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

* Re: [Bridge] [PATCH net-next mlxsw v2 0/2] bridge: FDB: Notify about removal of non-user-added entries
@ 2018-05-03 12:48   ` Petr Machata
  0 siblings, 0 replies; 18+ messages in thread
From: Petr Machata @ 2018-05-03 12:48 UTC (permalink / raw)
  To: netdev
  Cc: ivecera, f.fainelli, andrew, bridge, idosch, jiri, vivien.didelot, davem

This is of course not meant for "mlxsw" :-/

Petr

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

* Re: [PATCH net-next mlxsw v2 2/2] net: bridge: Notify about !added_by_user FDB entries
  2018-05-03 12:43   ` [Bridge] " Petr Machata
@ 2018-05-03 12:56     ` Nikolay Aleksandrov
  -1 siblings, 0 replies; 18+ messages in thread
From: Nikolay Aleksandrov @ 2018-05-03 12:56 UTC (permalink / raw)
  To: Petr Machata, netdev, bridge
  Cc: jiri, idosch, ivecera, davem, stephen, andrew, vivien.didelot,
	f.fainelli

On 03/05/18 15:43, Petr Machata wrote:
> Do not automatically bail out on sending notifications about activity on
> non-user-added FDB entries. Instead, notify about this activity except
> for cases where the activity itself originates in a notification, to
> avoid sending duplicate notifications.
> 
> Signed-off-by: Petr Machata <petrm@mellanox.com>
> ---
>   net/bridge/br.c           |  4 ++--
>   net/bridge/br_fdb.c       | 47 ++++++++++++++++++++++++++---------------------
>   net/bridge/br_private.h   |  6 ++++--
>   net/bridge/br_switchdev.c |  2 +-
>   4 files changed, 33 insertions(+), 26 deletions(-)
> 

Thanks, looks good to me! In the future please add the reviewers to the CC list
when sending a v2, I actually missed the v2 set and saw your reply to the cover
letter patch later.

Acked-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>

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

* Re: [Bridge] [PATCH net-next mlxsw v2 2/2] net: bridge: Notify about !added_by_user FDB entries
@ 2018-05-03 12:56     ` Nikolay Aleksandrov
  0 siblings, 0 replies; 18+ messages in thread
From: Nikolay Aleksandrov @ 2018-05-03 12:56 UTC (permalink / raw)
  To: Petr Machata, netdev, bridge
  Cc: ivecera, f.fainelli, andrew, vivien.didelot, idosch, jiri, davem

On 03/05/18 15:43, Petr Machata wrote:
> Do not automatically bail out on sending notifications about activity on
> non-user-added FDB entries. Instead, notify about this activity except
> for cases where the activity itself originates in a notification, to
> avoid sending duplicate notifications.
> 
> Signed-off-by: Petr Machata <petrm@mellanox.com>
> ---
>   net/bridge/br.c           |  4 ++--
>   net/bridge/br_fdb.c       | 47 ++++++++++++++++++++++++++---------------------
>   net/bridge/br_private.h   |  6 ++++--
>   net/bridge/br_switchdev.c |  2 +-
>   4 files changed, 33 insertions(+), 26 deletions(-)
> 

Thanks, looks good to me! In the future please add the reviewers to the CC list
when sending a v2, I actually missed the v2 set and saw your reply to the cover
letter patch later.

Acked-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>


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

* Re: [PATCH net-next mlxsw v2 1/2] switchdev: Add fdb.added_by_user to switchdev notifications
  2018-05-03 12:43   ` [Bridge] " Petr Machata
@ 2018-05-03 12:59     ` Ivan Vecera
  -1 siblings, 0 replies; 18+ messages in thread
From: Ivan Vecera @ 2018-05-03 12:59 UTC (permalink / raw)
  To: Petr Machata, netdev, bridge
  Cc: jiri, idosch, davem, stephen, andrew, vivien.didelot, f.fainelli

On 3.5.2018 14:43, Petr Machata wrote:
> The following patch enables sending notifications also for events on FDB
> entries that weren't added by the user. Give the drivers the information
> necessary to distinguish between the two origins of FDB entries.
> 
> To maintain the current behavior, have switchdev-implementing drivers
> bail out on notifications about non-user-added FDB entries. In case of
> mlxsw driver, allow a call to mlxsw_sp_span_respin() so that SPAN over
> bridge catches up with the changed FDB.
> 
> Signed-off-by: Petr Machata <petrm@mellanox.com>
> Reviewed-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
> ---
>  drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c |  4 ++++
>  drivers/net/ethernet/rocker/rocker_main.c                |  2 ++
>  include/net/switchdev.h                                  |  1 +
>  net/bridge/br_switchdev.c                                | 10 +++++++---
>  net/dsa/slave.c                                          |  5 ++++-
>  5 files changed, 18 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
> index 1af99fe..3973d90 100644
> --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
> +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
> @@ -2270,6 +2270,8 @@ static void mlxsw_sp_switchdev_event_work(struct work_struct *work)
>  	switch (switchdev_work->event) {
>  	case SWITCHDEV_FDB_ADD_TO_DEVICE:
>  		fdb_info = &switchdev_work->fdb_info;
> +		if (!fdb_info->added_by_user)
> +			break;
>  		err = mlxsw_sp_port_fdb_set(mlxsw_sp_port, fdb_info, true);
>  		if (err)
>  			break;
> @@ -2279,6 +2281,8 @@ static void mlxsw_sp_switchdev_event_work(struct work_struct *work)
>  		break;
>  	case SWITCHDEV_FDB_DEL_TO_DEVICE:
>  		fdb_info = &switchdev_work->fdb_info;
> +		if (!fdb_info->added_by_user)
> +			break;
>  		mlxsw_sp_port_fdb_set(mlxsw_sp_port, fdb_info, false);
>  		break;
>  	case SWITCHDEV_FDB_ADD_TO_BRIDGE: /* fall through */
> diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c
> index 056cb60..152d694 100644
> --- a/drivers/net/ethernet/rocker/rocker_main.c
> +++ b/drivers/net/ethernet/rocker/rocker_main.c
> @@ -2783,6 +2783,8 @@ static int rocker_switchdev_event(struct notifier_block *unused,
>  	switch (event) {
>  	case SWITCHDEV_FDB_ADD_TO_DEVICE: /* fall through */
>  	case SWITCHDEV_FDB_DEL_TO_DEVICE:
> +		if (!fdb_info->added_by_user)
> +			break;
>  		memcpy(&switchdev_work->fdb_info, ptr,
>  		       sizeof(switchdev_work->fdb_info));
>  		switchdev_work->fdb_info.addr = kzalloc(ETH_ALEN, GFP_ATOMIC);
> diff --git a/include/net/switchdev.h b/include/net/switchdev.h
> index 39bc855..d574ce6 100644
> --- a/include/net/switchdev.h
> +++ b/include/net/switchdev.h
> @@ -155,6 +155,7 @@ struct switchdev_notifier_fdb_info {
>  	struct switchdev_notifier_info info; /* must be first */
>  	const unsigned char *addr;
>  	u16 vid;
> +	bool added_by_user;
>  };
>  
>  static inline struct net_device *
> diff --git a/net/bridge/br_switchdev.c b/net/bridge/br_switchdev.c
> index ee775f4..71a03c4 100644
> --- a/net/bridge/br_switchdev.c
> +++ b/net/bridge/br_switchdev.c
> @@ -102,13 +102,15 @@ int br_switchdev_set_port_flag(struct net_bridge_port *p,
>  
>  static void
>  br_switchdev_fdb_call_notifiers(bool adding, const unsigned char *mac,
> -				u16 vid, struct net_device *dev)
> +				u16 vid, struct net_device *dev,
> +				bool added_by_user)
>  {
>  	struct switchdev_notifier_fdb_info info;
>  	unsigned long notifier_type;
>  
>  	info.addr = mac;
>  	info.vid = vid;
> +	info.added_by_user = added_by_user;
>  	notifier_type = adding ? SWITCHDEV_FDB_ADD_TO_DEVICE : SWITCHDEV_FDB_DEL_TO_DEVICE;
>  	call_switchdev_notifiers(notifier_type, dev, &info.info);
>  }
> @@ -123,12 +125,14 @@ br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb, int type)
>  	case RTM_DELNEIGH:
>  		br_switchdev_fdb_call_notifiers(false, fdb->key.addr.addr,
>  						fdb->key.vlan_id,
> -						fdb->dst->dev);
> +						fdb->dst->dev,
> +						fdb->added_by_user);
>  		break;
>  	case RTM_NEWNEIGH:
>  		br_switchdev_fdb_call_notifiers(true, fdb->key.addr.addr,
>  						fdb->key.vlan_id,
> -						fdb->dst->dev);
> +						fdb->dst->dev,
> +						fdb->added_by_user);
>  		break;
>  	}
>  }
> diff --git a/net/dsa/slave.c b/net/dsa/slave.c
> index f3fb3a0..c287f1e 100644
> --- a/net/dsa/slave.c
> +++ b/net/dsa/slave.c
> @@ -1441,6 +1441,7 @@ static int dsa_slave_switchdev_event(struct notifier_block *unused,
>  				     unsigned long event, void *ptr)
>  {
>  	struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
> +	struct switchdev_notifier_fdb_info *fdb_info = ptr;
>  	struct dsa_switchdev_event_work *switchdev_work;
>  
>  	if (!dsa_slave_dev_check(dev))
> @@ -1458,8 +1459,10 @@ static int dsa_slave_switchdev_event(struct notifier_block *unused,
>  	switch (event) {
>  	case SWITCHDEV_FDB_ADD_TO_DEVICE: /* fall through */
>  	case SWITCHDEV_FDB_DEL_TO_DEVICE:
> +		if (!fdb_info->added_by_user)
> +			break;
>  		if (dsa_slave_switchdev_fdb_work_init(switchdev_work,
> -						      ptr))
> +						      fdb_info))
>  			goto err_fdb_work_init;
>  		dev_hold(dev);
>  		break;
> 
LGTM

Acked-by: Ivan Vecera <ivecera@redhat.com>

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

* Re: [Bridge] [PATCH net-next mlxsw v2 1/2] switchdev: Add fdb.added_by_user to switchdev notifications
@ 2018-05-03 12:59     ` Ivan Vecera
  0 siblings, 0 replies; 18+ messages in thread
From: Ivan Vecera @ 2018-05-03 12:59 UTC (permalink / raw)
  To: Petr Machata, netdev, bridge
  Cc: f.fainelli, vivien.didelot, idosch, jiri, andrew, davem

On 3.5.2018 14:43, Petr Machata wrote:
> The following patch enables sending notifications also for events on FDB
> entries that weren't added by the user. Give the drivers the information
> necessary to distinguish between the two origins of FDB entries.
> 
> To maintain the current behavior, have switchdev-implementing drivers
> bail out on notifications about non-user-added FDB entries. In case of
> mlxsw driver, allow a call to mlxsw_sp_span_respin() so that SPAN over
> bridge catches up with the changed FDB.
> 
> Signed-off-by: Petr Machata <petrm@mellanox.com>
> Reviewed-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
> ---
>  drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c |  4 ++++
>  drivers/net/ethernet/rocker/rocker_main.c                |  2 ++
>  include/net/switchdev.h                                  |  1 +
>  net/bridge/br_switchdev.c                                | 10 +++++++---
>  net/dsa/slave.c                                          |  5 ++++-
>  5 files changed, 18 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
> index 1af99fe..3973d90 100644
> --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
> +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
> @@ -2270,6 +2270,8 @@ static void mlxsw_sp_switchdev_event_work(struct work_struct *work)
>  	switch (switchdev_work->event) {
>  	case SWITCHDEV_FDB_ADD_TO_DEVICE:
>  		fdb_info = &switchdev_work->fdb_info;
> +		if (!fdb_info->added_by_user)
> +			break;
>  		err = mlxsw_sp_port_fdb_set(mlxsw_sp_port, fdb_info, true);
>  		if (err)
>  			break;
> @@ -2279,6 +2281,8 @@ static void mlxsw_sp_switchdev_event_work(struct work_struct *work)
>  		break;
>  	case SWITCHDEV_FDB_DEL_TO_DEVICE:
>  		fdb_info = &switchdev_work->fdb_info;
> +		if (!fdb_info->added_by_user)
> +			break;
>  		mlxsw_sp_port_fdb_set(mlxsw_sp_port, fdb_info, false);
>  		break;
>  	case SWITCHDEV_FDB_ADD_TO_BRIDGE: /* fall through */
> diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c
> index 056cb60..152d694 100644
> --- a/drivers/net/ethernet/rocker/rocker_main.c
> +++ b/drivers/net/ethernet/rocker/rocker_main.c
> @@ -2783,6 +2783,8 @@ static int rocker_switchdev_event(struct notifier_block *unused,
>  	switch (event) {
>  	case SWITCHDEV_FDB_ADD_TO_DEVICE: /* fall through */
>  	case SWITCHDEV_FDB_DEL_TO_DEVICE:
> +		if (!fdb_info->added_by_user)
> +			break;
>  		memcpy(&switchdev_work->fdb_info, ptr,
>  		       sizeof(switchdev_work->fdb_info));
>  		switchdev_work->fdb_info.addr = kzalloc(ETH_ALEN, GFP_ATOMIC);
> diff --git a/include/net/switchdev.h b/include/net/switchdev.h
> index 39bc855..d574ce6 100644
> --- a/include/net/switchdev.h
> +++ b/include/net/switchdev.h
> @@ -155,6 +155,7 @@ struct switchdev_notifier_fdb_info {
>  	struct switchdev_notifier_info info; /* must be first */
>  	const unsigned char *addr;
>  	u16 vid;
> +	bool added_by_user;
>  };
>  
>  static inline struct net_device *
> diff --git a/net/bridge/br_switchdev.c b/net/bridge/br_switchdev.c
> index ee775f4..71a03c4 100644
> --- a/net/bridge/br_switchdev.c
> +++ b/net/bridge/br_switchdev.c
> @@ -102,13 +102,15 @@ int br_switchdev_set_port_flag(struct net_bridge_port *p,
>  
>  static void
>  br_switchdev_fdb_call_notifiers(bool adding, const unsigned char *mac,
> -				u16 vid, struct net_device *dev)
> +				u16 vid, struct net_device *dev,
> +				bool added_by_user)
>  {
>  	struct switchdev_notifier_fdb_info info;
>  	unsigned long notifier_type;
>  
>  	info.addr = mac;
>  	info.vid = vid;
> +	info.added_by_user = added_by_user;
>  	notifier_type = adding ? SWITCHDEV_FDB_ADD_TO_DEVICE : SWITCHDEV_FDB_DEL_TO_DEVICE;
>  	call_switchdev_notifiers(notifier_type, dev, &info.info);
>  }
> @@ -123,12 +125,14 @@ br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb, int type)
>  	case RTM_DELNEIGH:
>  		br_switchdev_fdb_call_notifiers(false, fdb->key.addr.addr,
>  						fdb->key.vlan_id,
> -						fdb->dst->dev);
> +						fdb->dst->dev,
> +						fdb->added_by_user);
>  		break;
>  	case RTM_NEWNEIGH:
>  		br_switchdev_fdb_call_notifiers(true, fdb->key.addr.addr,
>  						fdb->key.vlan_id,
> -						fdb->dst->dev);
> +						fdb->dst->dev,
> +						fdb->added_by_user);
>  		break;
>  	}
>  }
> diff --git a/net/dsa/slave.c b/net/dsa/slave.c
> index f3fb3a0..c287f1e 100644
> --- a/net/dsa/slave.c
> +++ b/net/dsa/slave.c
> @@ -1441,6 +1441,7 @@ static int dsa_slave_switchdev_event(struct notifier_block *unused,
>  				     unsigned long event, void *ptr)
>  {
>  	struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
> +	struct switchdev_notifier_fdb_info *fdb_info = ptr;
>  	struct dsa_switchdev_event_work *switchdev_work;
>  
>  	if (!dsa_slave_dev_check(dev))
> @@ -1458,8 +1459,10 @@ static int dsa_slave_switchdev_event(struct notifier_block *unused,
>  	switch (event) {
>  	case SWITCHDEV_FDB_ADD_TO_DEVICE: /* fall through */
>  	case SWITCHDEV_FDB_DEL_TO_DEVICE:
> +		if (!fdb_info->added_by_user)
> +			break;
>  		if (dsa_slave_switchdev_fdb_work_init(switchdev_work,
> -						      ptr))
> +						      fdb_info))
>  			goto err_fdb_work_init;
>  		dev_hold(dev);
>  		break;
> 
LGTM

Acked-by: Ivan Vecera <ivecera@redhat.com>

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

* Re: [PATCH net-next mlxsw v2 2/2] net: bridge: Notify about !added_by_user FDB entries
  2018-05-03 12:43   ` [Bridge] " Petr Machata
@ 2018-05-03 13:00     ` Ivan Vecera
  -1 siblings, 0 replies; 18+ messages in thread
From: Ivan Vecera @ 2018-05-03 13:00 UTC (permalink / raw)
  To: Petr Machata, netdev, bridge
  Cc: jiri, idosch, davem, stephen, andrew, vivien.didelot, f.fainelli

On 3.5.2018 14:43, Petr Machata wrote:
> Do not automatically bail out on sending notifications about activity on
> non-user-added FDB entries. Instead, notify about this activity except
> for cases where the activity itself originates in a notification, to
> avoid sending duplicate notifications.
> 
> Signed-off-by: Petr Machata <petrm@mellanox.com>
> ---
>  net/bridge/br.c           |  4 ++--
>  net/bridge/br_fdb.c       | 47 ++++++++++++++++++++++++++---------------------
>  net/bridge/br_private.h   |  6 ++++--
>  net/bridge/br_switchdev.c |  2 +-
>  4 files changed, 33 insertions(+), 26 deletions(-)
> 
> diff --git a/net/bridge/br.c b/net/bridge/br.c
> index 671d13c..c6b033e 100644
> --- a/net/bridge/br.c
> +++ b/net/bridge/br.c
> @@ -141,7 +141,7 @@ static int br_switchdev_event(struct notifier_block *unused,
>  	case SWITCHDEV_FDB_ADD_TO_BRIDGE:
>  		fdb_info = ptr;
>  		err = br_fdb_external_learn_add(br, p, fdb_info->addr,
> -						fdb_info->vid);
> +						fdb_info->vid, false);
>  		if (err) {
>  			err = notifier_from_errno(err);
>  			break;
> @@ -152,7 +152,7 @@ static int br_switchdev_event(struct notifier_block *unused,
>  	case SWITCHDEV_FDB_DEL_TO_BRIDGE:
>  		fdb_info = ptr;
>  		err = br_fdb_external_learn_del(br, p, fdb_info->addr,
> -						fdb_info->vid);
> +						fdb_info->vid, false);
>  		if (err)
>  			err = notifier_from_errno(err);
>  		break;
> diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
> index a1c409c..b19e310 100644
> --- a/net/bridge/br_fdb.c
> +++ b/net/bridge/br_fdb.c
> @@ -40,7 +40,7 @@ static struct kmem_cache *br_fdb_cache __read_mostly;
>  static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
>  		      const unsigned char *addr, u16 vid);
>  static void fdb_notify(struct net_bridge *br,
> -		       const struct net_bridge_fdb_entry *, int);
> +		       const struct net_bridge_fdb_entry *, int, bool);
>  
>  int __init br_fdb_init(void)
>  {
> @@ -195,7 +195,8 @@ static void fdb_del_hw_addr(struct net_bridge *br, const unsigned char *addr)
>  	}
>  }
>  
> -static void fdb_delete(struct net_bridge *br, struct net_bridge_fdb_entry *f)
> +static void fdb_delete(struct net_bridge *br, struct net_bridge_fdb_entry *f,
> +		       bool swdev_notify)
>  {
>  	trace_fdb_delete(br, f);
>  
> @@ -205,7 +206,7 @@ static void fdb_delete(struct net_bridge *br, struct net_bridge_fdb_entry *f)
>  	hlist_del_init_rcu(&f->fdb_node);
>  	rhashtable_remove_fast(&br->fdb_hash_tbl, &f->rhnode,
>  			       br_fdb_rht_params);
> -	fdb_notify(br, f, RTM_DELNEIGH);
> +	fdb_notify(br, f, RTM_DELNEIGH, swdev_notify);
>  	call_rcu(&f->rcu, fdb_rcu_free);
>  }
>  
> @@ -241,7 +242,7 @@ static void fdb_delete_local(struct net_bridge *br,
>  		return;
>  	}
>  
> -	fdb_delete(br, f);
> +	fdb_delete(br, f, true);
>  }
>  
>  void br_fdb_find_delete_local(struct net_bridge *br,
> @@ -356,7 +357,7 @@ void br_fdb_cleanup(struct work_struct *work)
>  		} else {
>  			spin_lock_bh(&br->hash_lock);
>  			if (!hlist_unhashed(&f->fdb_node))
> -				fdb_delete(br, f);
> +				fdb_delete(br, f, true);
>  			spin_unlock_bh(&br->hash_lock);
>  		}
>  	}
> @@ -376,7 +377,7 @@ void br_fdb_flush(struct net_bridge *br)
>  	spin_lock_bh(&br->hash_lock);
>  	hlist_for_each_entry_safe(f, tmp, &br->fdb_list, fdb_node) {
>  		if (!f->is_static)
> -			fdb_delete(br, f);
> +			fdb_delete(br, f, true);
>  	}
>  	spin_unlock_bh(&br->hash_lock);
>  }
> @@ -405,7 +406,7 @@ void br_fdb_delete_by_port(struct net_bridge *br,
>  		if (f->is_local)
>  			fdb_delete_local(br, p, f);
>  		else
> -			fdb_delete(br, f);
> +			fdb_delete(br, f, true);
>  	}
>  	spin_unlock_bh(&br->hash_lock);
>  }
> @@ -531,7 +532,7 @@ static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
>  			return 0;
>  		br_warn(br, "adding interface %s with same address as a received packet (addr:%pM, vlan:%u)\n",
>  		       source ? source->dev->name : br->dev->name, addr, vid);
> -		fdb_delete(br, fdb);
> +		fdb_delete(br, fdb, true);
>  	}
>  
>  	fdb = fdb_create(br, source, addr, vid, 1, 1);
> @@ -539,7 +540,7 @@ static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
>  		return -ENOMEM;
>  
>  	fdb_add_hw_addr(br, addr);
> -	fdb_notify(br, fdb, RTM_NEWNEIGH);
> +	fdb_notify(br, fdb, RTM_NEWNEIGH, true);
>  	return 0;
>  }
>  
> @@ -594,7 +595,7 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
>  				fdb->added_by_user = 1;
>  			if (unlikely(fdb_modified)) {
>  				trace_br_fdb_update(br, source, addr, vid, added_by_user);
> -				fdb_notify(br, fdb, RTM_NEWNEIGH);
> +				fdb_notify(br, fdb, RTM_NEWNEIGH, true);
>  			}
>  		}
>  	} else {
> @@ -605,7 +606,7 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
>  				fdb->added_by_user = 1;
>  			trace_br_fdb_update(br, source, addr, vid,
>  					    added_by_user);
> -			fdb_notify(br, fdb, RTM_NEWNEIGH);
> +			fdb_notify(br, fdb, RTM_NEWNEIGH, true);
>  		}
>  		/* else  we lose race and someone else inserts
>  		 * it first, don't bother updating
> @@ -687,13 +688,15 @@ static inline size_t fdb_nlmsg_size(void)
>  }
>  
>  static void fdb_notify(struct net_bridge *br,
> -		       const struct net_bridge_fdb_entry *fdb, int type)
> +		       const struct net_bridge_fdb_entry *fdb, int type,
> +		       bool swdev_notify)
>  {
>  	struct net *net = dev_net(br->dev);
>  	struct sk_buff *skb;
>  	int err = -ENOBUFS;
>  
> -	br_switchdev_fdb_notify(fdb, type);
> +	if (swdev_notify)
> +		br_switchdev_fdb_notify(fdb, type);
>  
>  	skb = nlmsg_new(fdb_nlmsg_size(), GFP_ATOMIC);
>  	if (skb == NULL)
> @@ -832,7 +835,7 @@ static int fdb_add_entry(struct net_bridge *br, struct net_bridge_port *source,
>  	fdb->used = jiffies;
>  	if (modified) {
>  		fdb->updated = jiffies;
> -		fdb_notify(br, fdb, RTM_NEWNEIGH);
> +		fdb_notify(br, fdb, RTM_NEWNEIGH, true);
>  	}
>  
>  	return 0;
> @@ -856,7 +859,7 @@ static int __br_fdb_add(struct ndmsg *ndm, struct net_bridge *br,
>  		rcu_read_unlock();
>  		local_bh_enable();
>  	} else if (ndm->ndm_flags & NTF_EXT_LEARNED) {
> -		err = br_fdb_external_learn_add(br, p, addr, vid);
> +		err = br_fdb_external_learn_add(br, p, addr, vid, true);
>  	} else {
>  		spin_lock_bh(&br->hash_lock);
>  		err = fdb_add_entry(br, p, addr, ndm->ndm_state,
> @@ -945,7 +948,7 @@ static int fdb_delete_by_addr_and_port(struct net_bridge *br,
>  	if (!fdb || fdb->dst != p)
>  		return -ENOENT;
>  
> -	fdb_delete(br, fdb);
> +	fdb_delete(br, fdb, true);
>  
>  	return 0;
>  }
> @@ -1065,7 +1068,8 @@ void br_fdb_unsync_static(struct net_bridge *br, struct net_bridge_port *p)
>  }
>  
>  int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
> -			      const unsigned char *addr, u16 vid)
> +			      const unsigned char *addr, u16 vid,
> +			      bool swdev_notify)
>  {
>  	struct net_bridge_fdb_entry *fdb;
>  	bool modified = false;
> @@ -1083,7 +1087,7 @@ int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
>  			goto err_unlock;
>  		}
>  		fdb->added_by_external_learn = 1;
> -		fdb_notify(br, fdb, RTM_NEWNEIGH);
> +		fdb_notify(br, fdb, RTM_NEWNEIGH, swdev_notify);
>  	} else {
>  		fdb->updated = jiffies;
>  
> @@ -1102,7 +1106,7 @@ int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
>  		}
>  
>  		if (modified)
> -			fdb_notify(br, fdb, RTM_NEWNEIGH);
> +			fdb_notify(br, fdb, RTM_NEWNEIGH, swdev_notify);
>  	}
>  
>  err_unlock:
> @@ -1112,7 +1116,8 @@ int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
>  }
>  
>  int br_fdb_external_learn_del(struct net_bridge *br, struct net_bridge_port *p,
> -			      const unsigned char *addr, u16 vid)
> +			      const unsigned char *addr, u16 vid,
> +			      bool swdev_notify)
>  {
>  	struct net_bridge_fdb_entry *fdb;
>  	int err = 0;
> @@ -1121,7 +1126,7 @@ int br_fdb_external_learn_del(struct net_bridge *br, struct net_bridge_port *p,
>  
>  	fdb = br_fdb_find(br, addr, vid);
>  	if (fdb && fdb->added_by_external_learn)
> -		fdb_delete(br, fdb);
> +		fdb_delete(br, fdb, swdev_notify);
>  	else
>  		err = -ENOENT;
>  
> diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
> index 1a50931..80a69b8 100644
> --- a/net/bridge/br_private.h
> +++ b/net/bridge/br_private.h
> @@ -553,9 +553,11 @@ int br_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
>  int br_fdb_sync_static(struct net_bridge *br, struct net_bridge_port *p);
>  void br_fdb_unsync_static(struct net_bridge *br, struct net_bridge_port *p);
>  int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
> -			      const unsigned char *addr, u16 vid);
> +			      const unsigned char *addr, u16 vid,
> +			      bool swdev_notify);
>  int br_fdb_external_learn_del(struct net_bridge *br, struct net_bridge_port *p,
> -			      const unsigned char *addr, u16 vid);
> +			      const unsigned char *addr, u16 vid,
> +			      bool swdev_notify);
>  void br_fdb_offloaded_set(struct net_bridge *br, struct net_bridge_port *p,
>  			  const unsigned char *addr, u16 vid);
>  
> diff --git a/net/bridge/br_switchdev.c b/net/bridge/br_switchdev.c
> index 71a03c4..35474d4 100644
> --- a/net/bridge/br_switchdev.c
> +++ b/net/bridge/br_switchdev.c
> @@ -118,7 +118,7 @@ br_switchdev_fdb_call_notifiers(bool adding, const unsigned char *mac,
>  void
>  br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb, int type)
>  {
> -	if (!fdb->added_by_user || !fdb->dst)
> +	if (!fdb->dst)
>  		return;
>  
>  	switch (type) {
> 

Acked-by: Ivan Vecera <ivecera@redhat.com>

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

* Re: [Bridge] [PATCH net-next mlxsw v2 2/2] net: bridge: Notify about !added_by_user FDB entries
@ 2018-05-03 13:00     ` Ivan Vecera
  0 siblings, 0 replies; 18+ messages in thread
From: Ivan Vecera @ 2018-05-03 13:00 UTC (permalink / raw)
  To: Petr Machata, netdev, bridge
  Cc: f.fainelli, vivien.didelot, idosch, jiri, andrew, davem

On 3.5.2018 14:43, Petr Machata wrote:
> Do not automatically bail out on sending notifications about activity on
> non-user-added FDB entries. Instead, notify about this activity except
> for cases where the activity itself originates in a notification, to
> avoid sending duplicate notifications.
> 
> Signed-off-by: Petr Machata <petrm@mellanox.com>
> ---
>  net/bridge/br.c           |  4 ++--
>  net/bridge/br_fdb.c       | 47 ++++++++++++++++++++++++++---------------------
>  net/bridge/br_private.h   |  6 ++++--
>  net/bridge/br_switchdev.c |  2 +-
>  4 files changed, 33 insertions(+), 26 deletions(-)
> 
> diff --git a/net/bridge/br.c b/net/bridge/br.c
> index 671d13c..c6b033e 100644
> --- a/net/bridge/br.c
> +++ b/net/bridge/br.c
> @@ -141,7 +141,7 @@ static int br_switchdev_event(struct notifier_block *unused,
>  	case SWITCHDEV_FDB_ADD_TO_BRIDGE:
>  		fdb_info = ptr;
>  		err = br_fdb_external_learn_add(br, p, fdb_info->addr,
> -						fdb_info->vid);
> +						fdb_info->vid, false);
>  		if (err) {
>  			err = notifier_from_errno(err);
>  			break;
> @@ -152,7 +152,7 @@ static int br_switchdev_event(struct notifier_block *unused,
>  	case SWITCHDEV_FDB_DEL_TO_BRIDGE:
>  		fdb_info = ptr;
>  		err = br_fdb_external_learn_del(br, p, fdb_info->addr,
> -						fdb_info->vid);
> +						fdb_info->vid, false);
>  		if (err)
>  			err = notifier_from_errno(err);
>  		break;
> diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
> index a1c409c..b19e310 100644
> --- a/net/bridge/br_fdb.c
> +++ b/net/bridge/br_fdb.c
> @@ -40,7 +40,7 @@ static struct kmem_cache *br_fdb_cache __read_mostly;
>  static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
>  		      const unsigned char *addr, u16 vid);
>  static void fdb_notify(struct net_bridge *br,
> -		       const struct net_bridge_fdb_entry *, int);
> +		       const struct net_bridge_fdb_entry *, int, bool);
>  
>  int __init br_fdb_init(void)
>  {
> @@ -195,7 +195,8 @@ static void fdb_del_hw_addr(struct net_bridge *br, const unsigned char *addr)
>  	}
>  }
>  
> -static void fdb_delete(struct net_bridge *br, struct net_bridge_fdb_entry *f)
> +static void fdb_delete(struct net_bridge *br, struct net_bridge_fdb_entry *f,
> +		       bool swdev_notify)
>  {
>  	trace_fdb_delete(br, f);
>  
> @@ -205,7 +206,7 @@ static void fdb_delete(struct net_bridge *br, struct net_bridge_fdb_entry *f)
>  	hlist_del_init_rcu(&f->fdb_node);
>  	rhashtable_remove_fast(&br->fdb_hash_tbl, &f->rhnode,
>  			       br_fdb_rht_params);
> -	fdb_notify(br, f, RTM_DELNEIGH);
> +	fdb_notify(br, f, RTM_DELNEIGH, swdev_notify);
>  	call_rcu(&f->rcu, fdb_rcu_free);
>  }
>  
> @@ -241,7 +242,7 @@ static void fdb_delete_local(struct net_bridge *br,
>  		return;
>  	}
>  
> -	fdb_delete(br, f);
> +	fdb_delete(br, f, true);
>  }
>  
>  void br_fdb_find_delete_local(struct net_bridge *br,
> @@ -356,7 +357,7 @@ void br_fdb_cleanup(struct work_struct *work)
>  		} else {
>  			spin_lock_bh(&br->hash_lock);
>  			if (!hlist_unhashed(&f->fdb_node))
> -				fdb_delete(br, f);
> +				fdb_delete(br, f, true);
>  			spin_unlock_bh(&br->hash_lock);
>  		}
>  	}
> @@ -376,7 +377,7 @@ void br_fdb_flush(struct net_bridge *br)
>  	spin_lock_bh(&br->hash_lock);
>  	hlist_for_each_entry_safe(f, tmp, &br->fdb_list, fdb_node) {
>  		if (!f->is_static)
> -			fdb_delete(br, f);
> +			fdb_delete(br, f, true);
>  	}
>  	spin_unlock_bh(&br->hash_lock);
>  }
> @@ -405,7 +406,7 @@ void br_fdb_delete_by_port(struct net_bridge *br,
>  		if (f->is_local)
>  			fdb_delete_local(br, p, f);
>  		else
> -			fdb_delete(br, f);
> +			fdb_delete(br, f, true);
>  	}
>  	spin_unlock_bh(&br->hash_lock);
>  }
> @@ -531,7 +532,7 @@ static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
>  			return 0;
>  		br_warn(br, "adding interface %s with same address as a received packet (addr:%pM, vlan:%u)\n",
>  		       source ? source->dev->name : br->dev->name, addr, vid);
> -		fdb_delete(br, fdb);
> +		fdb_delete(br, fdb, true);
>  	}
>  
>  	fdb = fdb_create(br, source, addr, vid, 1, 1);
> @@ -539,7 +540,7 @@ static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
>  		return -ENOMEM;
>  
>  	fdb_add_hw_addr(br, addr);
> -	fdb_notify(br, fdb, RTM_NEWNEIGH);
> +	fdb_notify(br, fdb, RTM_NEWNEIGH, true);
>  	return 0;
>  }
>  
> @@ -594,7 +595,7 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
>  				fdb->added_by_user = 1;
>  			if (unlikely(fdb_modified)) {
>  				trace_br_fdb_update(br, source, addr, vid, added_by_user);
> -				fdb_notify(br, fdb, RTM_NEWNEIGH);
> +				fdb_notify(br, fdb, RTM_NEWNEIGH, true);
>  			}
>  		}
>  	} else {
> @@ -605,7 +606,7 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
>  				fdb->added_by_user = 1;
>  			trace_br_fdb_update(br, source, addr, vid,
>  					    added_by_user);
> -			fdb_notify(br, fdb, RTM_NEWNEIGH);
> +			fdb_notify(br, fdb, RTM_NEWNEIGH, true);
>  		}
>  		/* else  we lose race and someone else inserts
>  		 * it first, don't bother updating
> @@ -687,13 +688,15 @@ static inline size_t fdb_nlmsg_size(void)
>  }
>  
>  static void fdb_notify(struct net_bridge *br,
> -		       const struct net_bridge_fdb_entry *fdb, int type)
> +		       const struct net_bridge_fdb_entry *fdb, int type,
> +		       bool swdev_notify)
>  {
>  	struct net *net = dev_net(br->dev);
>  	struct sk_buff *skb;
>  	int err = -ENOBUFS;
>  
> -	br_switchdev_fdb_notify(fdb, type);
> +	if (swdev_notify)
> +		br_switchdev_fdb_notify(fdb, type);
>  
>  	skb = nlmsg_new(fdb_nlmsg_size(), GFP_ATOMIC);
>  	if (skb == NULL)
> @@ -832,7 +835,7 @@ static int fdb_add_entry(struct net_bridge *br, struct net_bridge_port *source,
>  	fdb->used = jiffies;
>  	if (modified) {
>  		fdb->updated = jiffies;
> -		fdb_notify(br, fdb, RTM_NEWNEIGH);
> +		fdb_notify(br, fdb, RTM_NEWNEIGH, true);
>  	}
>  
>  	return 0;
> @@ -856,7 +859,7 @@ static int __br_fdb_add(struct ndmsg *ndm, struct net_bridge *br,
>  		rcu_read_unlock();
>  		local_bh_enable();
>  	} else if (ndm->ndm_flags & NTF_EXT_LEARNED) {
> -		err = br_fdb_external_learn_add(br, p, addr, vid);
> +		err = br_fdb_external_learn_add(br, p, addr, vid, true);
>  	} else {
>  		spin_lock_bh(&br->hash_lock);
>  		err = fdb_add_entry(br, p, addr, ndm->ndm_state,
> @@ -945,7 +948,7 @@ static int fdb_delete_by_addr_and_port(struct net_bridge *br,
>  	if (!fdb || fdb->dst != p)
>  		return -ENOENT;
>  
> -	fdb_delete(br, fdb);
> +	fdb_delete(br, fdb, true);
>  
>  	return 0;
>  }
> @@ -1065,7 +1068,8 @@ void br_fdb_unsync_static(struct net_bridge *br, struct net_bridge_port *p)
>  }
>  
>  int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
> -			      const unsigned char *addr, u16 vid)
> +			      const unsigned char *addr, u16 vid,
> +			      bool swdev_notify)
>  {
>  	struct net_bridge_fdb_entry *fdb;
>  	bool modified = false;
> @@ -1083,7 +1087,7 @@ int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
>  			goto err_unlock;
>  		}
>  		fdb->added_by_external_learn = 1;
> -		fdb_notify(br, fdb, RTM_NEWNEIGH);
> +		fdb_notify(br, fdb, RTM_NEWNEIGH, swdev_notify);
>  	} else {
>  		fdb->updated = jiffies;
>  
> @@ -1102,7 +1106,7 @@ int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
>  		}
>  
>  		if (modified)
> -			fdb_notify(br, fdb, RTM_NEWNEIGH);
> +			fdb_notify(br, fdb, RTM_NEWNEIGH, swdev_notify);
>  	}
>  
>  err_unlock:
> @@ -1112,7 +1116,8 @@ int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
>  }
>  
>  int br_fdb_external_learn_del(struct net_bridge *br, struct net_bridge_port *p,
> -			      const unsigned char *addr, u16 vid)
> +			      const unsigned char *addr, u16 vid,
> +			      bool swdev_notify)
>  {
>  	struct net_bridge_fdb_entry *fdb;
>  	int err = 0;
> @@ -1121,7 +1126,7 @@ int br_fdb_external_learn_del(struct net_bridge *br, struct net_bridge_port *p,
>  
>  	fdb = br_fdb_find(br, addr, vid);
>  	if (fdb && fdb->added_by_external_learn)
> -		fdb_delete(br, fdb);
> +		fdb_delete(br, fdb, swdev_notify);
>  	else
>  		err = -ENOENT;
>  
> diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
> index 1a50931..80a69b8 100644
> --- a/net/bridge/br_private.h
> +++ b/net/bridge/br_private.h
> @@ -553,9 +553,11 @@ int br_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
>  int br_fdb_sync_static(struct net_bridge *br, struct net_bridge_port *p);
>  void br_fdb_unsync_static(struct net_bridge *br, struct net_bridge_port *p);
>  int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
> -			      const unsigned char *addr, u16 vid);
> +			      const unsigned char *addr, u16 vid,
> +			      bool swdev_notify);
>  int br_fdb_external_learn_del(struct net_bridge *br, struct net_bridge_port *p,
> -			      const unsigned char *addr, u16 vid);
> +			      const unsigned char *addr, u16 vid,
> +			      bool swdev_notify);
>  void br_fdb_offloaded_set(struct net_bridge *br, struct net_bridge_port *p,
>  			  const unsigned char *addr, u16 vid);
>  
> diff --git a/net/bridge/br_switchdev.c b/net/bridge/br_switchdev.c
> index 71a03c4..35474d4 100644
> --- a/net/bridge/br_switchdev.c
> +++ b/net/bridge/br_switchdev.c
> @@ -118,7 +118,7 @@ br_switchdev_fdb_call_notifiers(bool adding, const unsigned char *mac,
>  void
>  br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb, int type)
>  {
> -	if (!fdb->added_by_user || !fdb->dst)
> +	if (!fdb->dst)
>  		return;
>  
>  	switch (type) {
> 

Acked-by: Ivan Vecera <ivecera@redhat.com>


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

* Re: [PATCH net-next mlxsw v2 2/2] net: bridge: Notify about !added_by_user FDB entries
  2018-05-03 12:56     ` [Bridge] " Nikolay Aleksandrov
@ 2018-05-03 13:07       ` Petr Machata
  -1 siblings, 0 replies; 18+ messages in thread
From: Petr Machata @ 2018-05-03 13:07 UTC (permalink / raw)
  To: Nikolay Aleksandrov
  Cc: netdev, bridge, jiri, idosch, ivecera, davem, stephen, andrew,
	vivien.didelot, f.fainelli

Nikolay Aleksandrov <nikolay@cumulusnetworks.com> writes:

> On 03/05/18 15:43, Petr Machata wrote:
>> Do not automatically bail out on sending notifications about activity on
>> non-user-added FDB entries. Instead, notify about this activity except
>> for cases where the activity itself originates in a notification, to
>> avoid sending duplicate notifications.
>>
>> Signed-off-by: Petr Machata <petrm@mellanox.com>
>> ---
>>   net/bridge/br.c           |  4 ++--
>>   net/bridge/br_fdb.c       | 47 ++++++++++++++++++++++++++---------------------
>>   net/bridge/br_private.h   |  6 ++++--
>>   net/bridge/br_switchdev.c |  2 +-
>>   4 files changed, 33 insertions(+), 26 deletions(-)
>>
>
> Thanks, looks good to me! In the future please add the reviewers to the CC list
> when sending a v2, I actually missed the v2 set and saw your reply to the cover
> letter patch later.

Sorry, I'm still tweaking my process for direct submission after going
almost exclusively through mlxsw for so long!

> Acked-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>

Thanks,
Petr

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

* Re: [Bridge] [PATCH net-next mlxsw v2 2/2] net: bridge: Notify about !added_by_user FDB entries
@ 2018-05-03 13:07       ` Petr Machata
  0 siblings, 0 replies; 18+ messages in thread
From: Petr Machata @ 2018-05-03 13:07 UTC (permalink / raw)
  To: Nikolay Aleksandrov
  Cc: ivecera, f.fainelli, andrew, netdev, bridge, idosch, jiri,
	vivien.didelot, davem

Nikolay Aleksandrov <nikolay@cumulusnetworks.com> writes:

> On 03/05/18 15:43, Petr Machata wrote:
>> Do not automatically bail out on sending notifications about activity on
>> non-user-added FDB entries. Instead, notify about this activity except
>> for cases where the activity itself originates in a notification, to
>> avoid sending duplicate notifications.
>>
>> Signed-off-by: Petr Machata <petrm@mellanox.com>
>> ---
>>   net/bridge/br.c           |  4 ++--
>>   net/bridge/br_fdb.c       | 47 ++++++++++++++++++++++++++---------------------
>>   net/bridge/br_private.h   |  6 ++++--
>>   net/bridge/br_switchdev.c |  2 +-
>>   4 files changed, 33 insertions(+), 26 deletions(-)
>>
>
> Thanks, looks good to me! In the future please add the reviewers to the CC list
> when sending a v2, I actually missed the v2 set and saw your reply to the cover
> letter patch later.

Sorry, I'm still tweaking my process for direct submission after going
almost exclusively through mlxsw for so long!

> Acked-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>

Thanks,
Petr

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

* Re: [PATCH net-next mlxsw v2 0/2] bridge: FDB: Notify about removal of non-user-added entries
  2018-05-03 12:43 ` [Bridge] " Petr Machata
@ 2018-05-03 17:47   ` David Miller
  -1 siblings, 0 replies; 18+ messages in thread
From: David Miller @ 2018-05-03 17:47 UTC (permalink / raw)
  To: petrm
  Cc: netdev, bridge, jiri, idosch, ivecera, stephen, andrew,
	vivien.didelot, f.fainelli

From: Petr Machata <petrm@mellanox.com>
Date: Thu, 03 May 2018 14:43:40 +0200

> Device drivers may generally need to keep in sync with bridge's FDB. In
> particular, for its offload of tc mirror action where the mirrored-to
> device is a gretap device, mlxsw needs to listen to a number of events,
> FDB events among the others. SWITCHDEV_FDB_{ADD,DEL}_TO_DEVICE would be
> a natural notification in that case.
> 
> However, for removal of FDB entries added due to device activity (as
> opposed to explicit addition through "bridge fdb add" or similar), there
> are no notifications.
> 
> Thus in patch #1, add the "added_by_user" field to switchdev
> notifications sent for FDB activity. Adapt drivers to ignore activity on
> non-user-added entries, to maintain the current behavior. Specifically
> in case of mlxsw, allow mlxsw_sp_span_respin() call for any and all FDB
> updates.
> 
> In patch #2, change the bridge driver to actually emit notifications for
> these FDB entries. Take care not to send notification for bridge
> updates that itself originate in SWITCHDEV_FDB_*_TO_BRIDGE events.
> 
> Changes from v1 to v2:
> - Instead of introducing a new variant of fdb_delete(), add a new
>   parameter to the existing function.
> - Name the parameter swdev_notify, not notify.

Series applied, thank you.

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

* Re: [Bridge] [PATCH net-next mlxsw v2 0/2] bridge: FDB: Notify about removal of non-user-added entries
@ 2018-05-03 17:47   ` David Miller
  0 siblings, 0 replies; 18+ messages in thread
From: David Miller @ 2018-05-03 17:47 UTC (permalink / raw)
  To: petrm
  Cc: ivecera, f.fainelli, andrew, netdev, bridge, idosch, jiri,
	vivien.didelot

From: Petr Machata <petrm@mellanox.com>
Date: Thu, 03 May 2018 14:43:40 +0200

> Device drivers may generally need to keep in sync with bridge's FDB. In
> particular, for its offload of tc mirror action where the mirrored-to
> device is a gretap device, mlxsw needs to listen to a number of events,
> FDB events among the others. SWITCHDEV_FDB_{ADD,DEL}_TO_DEVICE would be
> a natural notification in that case.
> 
> However, for removal of FDB entries added due to device activity (as
> opposed to explicit addition through "bridge fdb add" or similar), there
> are no notifications.
> 
> Thus in patch #1, add the "added_by_user" field to switchdev
> notifications sent for FDB activity. Adapt drivers to ignore activity on
> non-user-added entries, to maintain the current behavior. Specifically
> in case of mlxsw, allow mlxsw_sp_span_respin() call for any and all FDB
> updates.
> 
> In patch #2, change the bridge driver to actually emit notifications for
> these FDB entries. Take care not to send notification for bridge
> updates that itself originate in SWITCHDEV_FDB_*_TO_BRIDGE events.
> 
> Changes from v1 to v2:
> - Instead of introducing a new variant of fdb_delete(), add a new
>   parameter to the existing function.
> - Name the parameter swdev_notify, not notify.

Series applied, thank you.

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

end of thread, other threads:[~2018-05-03 17:47 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-05-03 12:43 [PATCH net-next mlxsw v2 0/2] bridge: FDB: Notify about removal of non-user-added entries Petr Machata
2018-05-03 12:43 ` [Bridge] " Petr Machata
2018-05-03 12:43 ` [PATCH net-next mlxsw v2 1/2] switchdev: Add fdb.added_by_user to switchdev notifications Petr Machata
2018-05-03 12:43   ` [Bridge] " Petr Machata
2018-05-03 12:59   ` Ivan Vecera
2018-05-03 12:59     ` [Bridge] " Ivan Vecera
2018-05-03 12:43 ` [PATCH net-next mlxsw v2 2/2] net: bridge: Notify about !added_by_user FDB entries Petr Machata
2018-05-03 12:43   ` [Bridge] " Petr Machata
2018-05-03 12:56   ` Nikolay Aleksandrov
2018-05-03 12:56     ` [Bridge] " Nikolay Aleksandrov
2018-05-03 13:07     ` Petr Machata
2018-05-03 13:07       ` [Bridge] " Petr Machata
2018-05-03 13:00   ` Ivan Vecera
2018-05-03 13:00     ` [Bridge] " Ivan Vecera
2018-05-03 12:48 ` [PATCH net-next mlxsw v2 0/2] bridge: FDB: Notify about removal of non-user-added entries Petr Machata
2018-05-03 12:48   ` [Bridge] " Petr Machata
2018-05-03 17:47 ` David Miller
2018-05-03 17:47   ` [Bridge] " 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.