All of lore.kernel.org
 help / color / mirror / Atom feed
* [patch net-next 00/19] Remove support from bridge bypass for mlxsw/rocker drivers
@ 2017-06-05  9:20 Jiri Pirko
  2017-06-05  9:20 ` [patch net-next 01/19] net: switchdev: Add support for querying supported bridge flags by hardware Jiri Pirko
                   ` (19 more replies)
  0 siblings, 20 replies; 30+ messages in thread
From: Jiri Pirko @ 2017-06-05  9:20 UTC (permalink / raw)
  To: netdev; +Cc: davem, idosch, arkadis, mlxsw, roopa, stephen, ivecera

From: Jiri Pirko <jiri@mellanox.com>

Currently setting bridge port attributes and adding FDBs are done via
setting the SELF flag which implies unconsistent offloading model. This
patch-set fixes this behavior by making the bridge and drivers which are
using it to be totally in sync.

This implies several changes:
- Offloading bridge flags from the bridge code.
- Sending notification about FDB add/del to the software bridge in a
  similiar way it is done for the hardware externally learned FDBs.

By making the offloading model more consistent a cleanup is done in
the drivers supporting it. This is done in order to remove un-needed
logic related to dump operation which is redundant.

First add missing functionality to bridge, then clean up the mlxsw/rocker
drivers.

Arkadi Sharshevsky (19):
  net: switchdev: Add support for querying supported bridge flags by
    hardware
  net: bridge: Add support for offloading port attributes
  net: bridge: Add support for calling FDB external learning under rcu
  net: switchdev: Change notifier chain to be atomic
  net: bridge: Add support for notifying devices about FDB add/del
  net: bridge: Receive notification about successful FDB offload
  mlxsw: spectrum: Remove support for bridge FDB learning sync
  mlxsw: spectrum_switchdev: Add support for querying supported bridge
    flags
  mlxsw: spectrum: Remove support for bypass bridge port attributes/vlan
    set
  mlxsw: spectrum_switchdev: Change switchdev notifier API
  mlxsw: spectrum_switchdev: Add support for learning FDB through
    notification
  mlxsw: spectrum: Remove support for bridge bypass FDB add/del
  net: Remove support for bridge bypass ndos from stacked devices
  rocker: Remove support for bridge FDB learning sync
  rocker: Add support for querying supported bridge flags
  rocker: Change world_ops API and implementation to be switchdev
    independant
  rocker: Add support for learning FDB through notification
  rocker: Remove support for bypass bridge port attributes/vlan set
  rocker: Remove support bridge bypass FDB

 drivers/net/bonding/bond_main.c                    |   6 -
 drivers/net/ethernet/mellanox/mlxsw/spectrum.c     |   8 +-
 drivers/net/ethernet/mellanox/mlxsw/spectrum.h     |   1 +
 .../ethernet/mellanox/mlxsw/spectrum_switchdev.c   | 360 +++++-------
 drivers/net/ethernet/rocker/rocker.h               |  21 +-
 drivers/net/ethernet/rocker/rocker_main.c          | 235 +++++---
 drivers/net/ethernet/rocker/rocker_ofdpa.c         | 610 ++++++++-------------
 drivers/net/team/team.c                            |   6 -
 include/net/switchdev.h                            |   9 +-
 include/uapi/linux/neighbour.h                     |   1 +
 net/8021q/vlan_dev.c                               |   6 -
 net/bridge/br.c                                    |  19 +-
 net/bridge/br_fdb.c                                |  46 +-
 net/bridge/br_netlink.c                            | 112 +++-
 net/bridge/br_private.h                            |  23 +-
 net/bridge/br_switchdev.c                          |  13 +
 net/switchdev/switchdev.c                          |  30 +-
 17 files changed, 714 insertions(+), 792 deletions(-)

-- 
2.9.3

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

* [patch net-next 01/19] net: switchdev: Add support for querying supported bridge flags by hardware
  2017-06-05  9:20 [patch net-next 00/19] Remove support from bridge bypass for mlxsw/rocker drivers Jiri Pirko
@ 2017-06-05  9:20 ` Jiri Pirko
  2017-06-05 14:00   ` Ivan Vecera
  2017-06-05  9:20 ` [patch net-next 02/19] net: bridge: Add support for offloading port attributes Jiri Pirko
                   ` (18 subsequent siblings)
  19 siblings, 1 reply; 30+ messages in thread
From: Jiri Pirko @ 2017-06-05  9:20 UTC (permalink / raw)
  To: netdev; +Cc: davem, idosch, arkadis, mlxsw, roopa, stephen, ivecera

From: Arkadi Sharshevsky <arkadis@mellanox.com>

This is done as a preparation stage before setting the bridge port flags
from the bridge code. Currently the device can be queried for the bridge
flags state, but the querier cannot distinguish if the flag is disabled
or if it is not supported at all. Thus, add new attr and a bit-mask which
include information regarding the support on a per-flag basis.

Drivers that support bridge offload but not support bridge flags should
return zeroed bitmask.

Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com>
Reviewed-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 include/net/switchdev.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/net/switchdev.h b/include/net/switchdev.h
index 929d6af..63a754d 100644
--- a/include/net/switchdev.h
+++ b/include/net/switchdev.h
@@ -46,6 +46,7 @@ enum switchdev_attr_id {
 	SWITCHDEV_ATTR_ID_PORT_PARENT_ID,
 	SWITCHDEV_ATTR_ID_PORT_STP_STATE,
 	SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS,
+	SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT,
 	SWITCHDEV_ATTR_ID_PORT_MROUTER,
 	SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME,
 	SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING,
@@ -62,6 +63,7 @@ struct switchdev_attr {
 		struct netdev_phys_item_id ppid;	/* PORT_PARENT_ID */
 		u8 stp_state;				/* PORT_STP_STATE */
 		unsigned long brport_flags;		/* PORT_BRIDGE_FLAGS */
+		unsigned long brport_flags_support;	/* PORT_BRIDGE_FLAGS_SUPPORT */
 		bool mrouter;				/* PORT_MROUTER */
 		clock_t ageing_time;			/* BRIDGE_AGEING_TIME */
 		bool vlan_filtering;			/* BRIDGE_VLAN_FILTERING */
-- 
2.9.3

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

* [patch net-next 02/19] net: bridge: Add support for offloading port attributes
  2017-06-05  9:20 [patch net-next 00/19] Remove support from bridge bypass for mlxsw/rocker drivers Jiri Pirko
  2017-06-05  9:20 ` [patch net-next 01/19] net: switchdev: Add support for querying supported bridge flags by hardware Jiri Pirko
@ 2017-06-05  9:20 ` Jiri Pirko
  2017-06-05 13:29   ` Nikolay Aleksandrov
  2017-06-05  9:20 ` [patch net-next 03/19] net: bridge: Add support for calling FDB external learning under rcu Jiri Pirko
                   ` (17 subsequent siblings)
  19 siblings, 1 reply; 30+ messages in thread
From: Jiri Pirko @ 2017-06-05  9:20 UTC (permalink / raw)
  To: netdev; +Cc: davem, idosch, arkadis, mlxsw, roopa, stephen, ivecera

From: Arkadi Sharshevsky <arkadis@mellanox.com>

Currently the flood, learning and learning_sync port attributes are
offloaded by setting the SELF flag. Add support for offloading the
flood and learning attribute through the bridge code. In case of
setting an unsupported flag on a offloded port the operation will
fail.

The learning_sync attribute doesn't have any software representation
and cannot be offloaded through the bridge code.

Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com>
Reviewed-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 net/bridge/br_netlink.c | 112 +++++++++++++++++++++++++++++++++++++++---------
 net/bridge/br_private.h |   4 ++
 2 files changed, 96 insertions(+), 20 deletions(-)

diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index 1e63ec4..1afafb7 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -17,6 +17,7 @@
 #include <net/net_namespace.h>
 #include <net/sock.h>
 #include <uapi/linux/if_bridge.h>
+#include <net/switchdev.h>
 
 #include "br_private.h"
 #include "br_private_stp.h"
@@ -662,16 +663,52 @@ static int br_set_port_state(struct net_bridge_port *p, u8 state)
 }
 
 /* Set/clear or port flags based on attribute */
-static void br_set_port_flag(struct net_bridge_port *p, struct nlattr *tb[],
-			   int attrtype, unsigned long mask)
+static int br_set_port_flag(struct net_bridge_port *p, struct nlattr *tb[],
+			    int attrtype, unsigned long mask)
 {
-	if (tb[attrtype]) {
-		u8 flag = nla_get_u8(tb[attrtype]);
-		if (flag)
-			p->flags |= mask;
-		else
-			p->flags &= ~mask;
+	struct switchdev_attr attr = {
+		.orig_dev = p->dev,
+		.id = SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT,
+	};
+	unsigned long flags;
+	int err;
+
+	if (!tb[attrtype])
+		return 0;
+
+	if (nla_get_u8(tb[attrtype]))
+		flags = p->flags | mask;
+	else
+		flags = p->flags & ~mask;
+
+	if (mask & ~BR_PORT_FLAGS_HW_OFFLOAD)
+		goto out;
+
+	err = switchdev_port_attr_get(p->dev, &attr);
+	if (err == -EOPNOTSUPP)
+		goto out;
+	if (err)
+		return err;
+
+	/* Check if specific bridge flag attribute offload is supported */
+	if (!(attr.u.brport_flags_support & mask)) {
+		br_warn(p->br, "bridge flag offload is not supported %u(%s)\n",
+			(unsigned int)p->port_no, p->dev->name);
+		return -EOPNOTSUPP;
+	}
+
+	attr.id = SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS;
+	attr.flags = SWITCHDEV_F_DEFER;
+	attr.u.brport_flags = flags;
+	err = switchdev_port_attr_set(p->dev, &attr);
+	if (err) {
+		br_warn(p->br, "error setting offload FLAG on port %u(%s)\n",
+			(unsigned int)p->port_no, p->dev->name);
+		return err;
 	}
+out:
+	p->flags = flags;
+	return 0;
 }
 
 /* Process bridge protocol info on port */
@@ -681,20 +718,55 @@ static int br_setport(struct net_bridge_port *p, struct nlattr *tb[])
 	bool br_vlan_tunnel_old = false;
 	int err;
 
-	br_set_port_flag(p, tb, IFLA_BRPORT_MODE, BR_HAIRPIN_MODE);
-	br_set_port_flag(p, tb, IFLA_BRPORT_GUARD, BR_BPDU_GUARD);
-	br_set_port_flag(p, tb, IFLA_BRPORT_FAST_LEAVE, BR_MULTICAST_FAST_LEAVE);
-	br_set_port_flag(p, tb, IFLA_BRPORT_PROTECT, BR_ROOT_BLOCK);
-	br_set_port_flag(p, tb, IFLA_BRPORT_LEARNING, BR_LEARNING);
-	br_set_port_flag(p, tb, IFLA_BRPORT_UNICAST_FLOOD, BR_FLOOD);
-	br_set_port_flag(p, tb, IFLA_BRPORT_MCAST_FLOOD, BR_MCAST_FLOOD);
-	br_set_port_flag(p, tb, IFLA_BRPORT_MCAST_TO_UCAST, BR_MULTICAST_TO_UNICAST);
-	br_set_port_flag(p, tb, IFLA_BRPORT_BCAST_FLOOD, BR_BCAST_FLOOD);
-	br_set_port_flag(p, tb, IFLA_BRPORT_PROXYARP, BR_PROXYARP);
-	br_set_port_flag(p, tb, IFLA_BRPORT_PROXYARP_WIFI, BR_PROXYARP_WIFI);
+	err = br_set_port_flag(p, tb, IFLA_BRPORT_MODE, BR_HAIRPIN_MODE);
+	if (err)
+		return err;
+
+	err = br_set_port_flag(p, tb, IFLA_BRPORT_GUARD, BR_BPDU_GUARD);
+	if (err)
+		return err;
+
+	err = br_set_port_flag(p, tb, IFLA_BRPORT_FAST_LEAVE, BR_MULTICAST_FAST_LEAVE);
+	if (err)
+		return err;
+
+	err = br_set_port_flag(p, tb, IFLA_BRPORT_PROTECT, BR_ROOT_BLOCK);
+	if (err)
+		return err;
+
+	err = br_set_port_flag(p, tb, IFLA_BRPORT_LEARNING, BR_LEARNING);
+	if (err)
+		return err;
+
+	err = br_set_port_flag(p, tb, IFLA_BRPORT_UNICAST_FLOOD, BR_FLOOD);
+	if (err)
+		return err;
+
+	err = br_set_port_flag(p, tb, IFLA_BRPORT_MCAST_FLOOD, BR_MCAST_FLOOD);
+	if (err)
+		return err;
+
+	err = br_set_port_flag(p, tb, IFLA_BRPORT_MCAST_TO_UCAST, BR_MULTICAST_TO_UNICAST);
+	if (err)
+		return err;
+
+	err = br_set_port_flag(p, tb, IFLA_BRPORT_BCAST_FLOOD, BR_BCAST_FLOOD);
+	if (err)
+		return err;
+
+	err = br_set_port_flag(p, tb, IFLA_BRPORT_PROXYARP, BR_PROXYARP);
+	if (err)
+		return err;
+
+	err = br_set_port_flag(p, tb, IFLA_BRPORT_PROXYARP_WIFI, BR_PROXYARP_WIFI);
+	if (err)
+		return err;
 
 	br_vlan_tunnel_old = (p->flags & BR_VLAN_TUNNEL) ? true : false;
-	br_set_port_flag(p, tb, IFLA_BRPORT_VLAN_TUNNEL, BR_VLAN_TUNNEL);
+	err = br_set_port_flag(p, tb, IFLA_BRPORT_VLAN_TUNNEL, BR_VLAN_TUNNEL);
+	if (err)
+		return err;
+
 	if (br_vlan_tunnel_old && !(p->flags & BR_VLAN_TUNNEL))
 		nbp_vlan_tunnel_info_flush(p);
 
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 2062692..5dc30ed 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -42,6 +42,10 @@
 /* Path to usermode spanning tree program */
 #define BR_STP_PROG	"/sbin/bridge-stp"
 
+/* Flags that can be offloaded to hardware */
+#define BR_PORT_FLAGS_HW_OFFLOAD (BR_LEARNING | BR_FLOOD | \
+				  BR_MCAST_FLOOD | BR_BCAST_FLOOD)
+
 typedef struct bridge_id bridge_id;
 typedef struct mac_addr mac_addr;
 typedef __u16 port_id;
-- 
2.9.3

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

* [patch net-next 03/19] net: bridge: Add support for calling FDB external learning under rcu
  2017-06-05  9:20 [patch net-next 00/19] Remove support from bridge bypass for mlxsw/rocker drivers Jiri Pirko
  2017-06-05  9:20 ` [patch net-next 01/19] net: switchdev: Add support for querying supported bridge flags by hardware Jiri Pirko
  2017-06-05  9:20 ` [patch net-next 02/19] net: bridge: Add support for offloading port attributes Jiri Pirko
@ 2017-06-05  9:20 ` Jiri Pirko
  2017-06-05 13:36   ` Nikolay Aleksandrov
  2017-06-05  9:20 ` [patch net-next 04/19] net: switchdev: Change notifier chain to be atomic Jiri Pirko
                   ` (16 subsequent siblings)
  19 siblings, 1 reply; 30+ messages in thread
From: Jiri Pirko @ 2017-06-05  9:20 UTC (permalink / raw)
  To: netdev; +Cc: davem, idosch, arkadis, mlxsw, roopa, stephen, ivecera

From: Arkadi Sharshevsky <arkadis@mellanox.com>

This is done as a preparation to moving the switchdev notifier chain
to be atomic. The FDB external learning should be called under rtnl
or rcu.

Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com>
Reviewed-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 net/bridge/br.c         | 4 ++--
 net/bridge/br_fdb.c     | 2 --
 net/bridge/br_private.h | 6 ++++++
 3 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/net/bridge/br.c b/net/bridge/br.c
index 889e564..e962fff 100644
--- a/net/bridge/br.c
+++ b/net/bridge/br.c
@@ -121,7 +121,7 @@ static struct notifier_block br_device_notifier = {
 	.notifier_call = br_device_event
 };
 
-/* called with RTNL */
+/* called with RTNL or RCU */
 static int br_switchdev_event(struct notifier_block *unused,
 			      unsigned long event, void *ptr)
 {
@@ -131,7 +131,7 @@ static int br_switchdev_event(struct notifier_block *unused,
 	struct switchdev_notifier_fdb_info *fdb_info;
 	int err = NOTIFY_DONE;
 
-	p = br_port_get_rtnl(dev);
+	p = br_port_get_rtnl_rcu(dev);
 	if (!p)
 		goto out;
 
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index ab0c7cc..5c780cd 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -1075,7 +1075,6 @@ int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
 	struct net_bridge_fdb_entry *fdb;
 	int err = 0;
 
-	ASSERT_RTNL();
 	spin_lock_bh(&br->hash_lock);
 
 	head = &br->hash[br_mac_hash(addr, vid)];
@@ -1110,7 +1109,6 @@ int br_fdb_external_learn_del(struct net_bridge *br, struct net_bridge_port *p,
 	struct net_bridge_fdb_entry *fdb;
 	int err = 0;
 
-	ASSERT_RTNL();
 	spin_lock_bh(&br->hash_lock);
 
 	fdb = br_fdb_find(br, addr, vid);
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 5dc30ed..69ba3ba 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -288,6 +288,12 @@ static inline struct net_bridge_port *br_port_get_rtnl(const struct net_device *
 		rtnl_dereference(dev->rx_handler_data) : NULL;
 }
 
+static inline struct net_bridge_port *br_port_get_rtnl_rcu(const struct net_device *dev)
+{
+	return br_port_exists(dev) ?
+		rcu_dereference_rtnl(dev->rx_handler_data) : NULL;
+}
+
 struct net_bridge {
 	spinlock_t			lock;
 	spinlock_t			hash_lock;
-- 
2.9.3

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

* [patch net-next 04/19] net: switchdev: Change notifier chain to be atomic
  2017-06-05  9:20 [patch net-next 00/19] Remove support from bridge bypass for mlxsw/rocker drivers Jiri Pirko
                   ` (2 preceding siblings ...)
  2017-06-05  9:20 ` [patch net-next 03/19] net: bridge: Add support for calling FDB external learning under rcu Jiri Pirko
@ 2017-06-05  9:20 ` Jiri Pirko
  2017-06-05 13:59   ` Ivan Vecera
  2017-06-05  9:20 ` [patch net-next 05/19] net: bridge: Add support for notifying devices about FDB add/del Jiri Pirko
                   ` (15 subsequent siblings)
  19 siblings, 1 reply; 30+ messages in thread
From: Jiri Pirko @ 2017-06-05  9:20 UTC (permalink / raw)
  To: netdev; +Cc: davem, idosch, arkadis, mlxsw, roopa, stephen, ivecera

From: Arkadi Sharshevsky <arkadis@mellanox.com>

In order to use the switchdev notifier chain for FDB sync with the
device it has to be changed to atomic. The is done because the bridge
can learn new FDBs in atomic context.

Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com>
Reviewed-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 net/switchdev/switchdev.c | 30 ++++++------------------------
 1 file changed, 6 insertions(+), 24 deletions(-)

diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c
index 8d40a7d..25dc67e 100644
--- a/net/switchdev/switchdev.c
+++ b/net/switchdev/switchdev.c
@@ -571,24 +571,17 @@ int switchdev_port_obj_dump(struct net_device *dev, struct switchdev_obj *obj,
 }
 EXPORT_SYMBOL_GPL(switchdev_port_obj_dump);
 
-static RAW_NOTIFIER_HEAD(switchdev_notif_chain);
+static ATOMIC_NOTIFIER_HEAD(switchdev_notif_chain);
 
 /**
  *	register_switchdev_notifier - Register notifier
  *	@nb: notifier_block
  *
- *	Register switch device notifier. This should be used by code
- *	which needs to monitor events happening in particular device.
- *	Return values are same as for atomic_notifier_chain_register().
+ *	Register switch device notifier.
  */
 int register_switchdev_notifier(struct notifier_block *nb)
 {
-	int err;
-
-	rtnl_lock();
-	err = raw_notifier_chain_register(&switchdev_notif_chain, nb);
-	rtnl_unlock();
-	return err;
+	return atomic_notifier_chain_register(&switchdev_notif_chain, nb);
 }
 EXPORT_SYMBOL_GPL(register_switchdev_notifier);
 
@@ -597,16 +590,10 @@ EXPORT_SYMBOL_GPL(register_switchdev_notifier);
  *	@nb: notifier_block
  *
  *	Unregister switch device notifier.
- *	Return values are same as for atomic_notifier_chain_unregister().
  */
 int unregister_switchdev_notifier(struct notifier_block *nb)
 {
-	int err;
-
-	rtnl_lock();
-	err = raw_notifier_chain_unregister(&switchdev_notif_chain, nb);
-	rtnl_unlock();
-	return err;
+	return atomic_notifier_chain_unregister(&switchdev_notif_chain, nb);
 }
 EXPORT_SYMBOL_GPL(unregister_switchdev_notifier);
 
@@ -616,18 +603,13 @@ EXPORT_SYMBOL_GPL(unregister_switchdev_notifier);
  *	@dev: port device
  *	@info: notifier information data
  *
- *	Call all network notifier blocks. This should be called by driver
- *	when it needs to propagate hardware event.
- *	Return values are same as for atomic_notifier_call_chain().
- *	rtnl_lock must be held.
+ *	Call all network notifier blocks.
  */
 int call_switchdev_notifiers(unsigned long val, struct net_device *dev,
 			     struct switchdev_notifier_info *info)
 {
-	ASSERT_RTNL();
-
 	info->dev = dev;
-	return raw_notifier_call_chain(&switchdev_notif_chain, val, info);
+	return atomic_notifier_call_chain(&switchdev_notif_chain, val, info);
 }
 EXPORT_SYMBOL_GPL(call_switchdev_notifiers);
 
-- 
2.9.3

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

* [patch net-next 05/19] net: bridge: Add support for notifying devices about FDB add/del
  2017-06-05  9:20 [patch net-next 00/19] Remove support from bridge bypass for mlxsw/rocker drivers Jiri Pirko
                   ` (3 preceding siblings ...)
  2017-06-05  9:20 ` [patch net-next 04/19] net: switchdev: Change notifier chain to be atomic Jiri Pirko
@ 2017-06-05  9:20 ` Jiri Pirko
  2017-06-05 13:35   ` Nikolay Aleksandrov
  2017-06-05  9:20 ` [patch net-next 06/19] net: bridge: Receive notification about successful FDB offload Jiri Pirko
                   ` (14 subsequent siblings)
  19 siblings, 1 reply; 30+ messages in thread
From: Jiri Pirko @ 2017-06-05  9:20 UTC (permalink / raw)
  To: netdev; +Cc: davem, idosch, arkadis, mlxsw, roopa, stephen, ivecera

From: Arkadi Sharshevsky <arkadis@mellanox.com>

Currently the bridge doesn't notify the underlying devices about new
FDBs learned. The FDB sync is placed on the switchdev notifier chain
because devices may potentially learn FDB that are not directly related
to their ports, for example:

1. Mixed SW/HW bridge - FDBs that point to the ASICs external devices
                        should be offloaded as CPU traps in order to
			perform forwarding in slow path.
2. EVPN - Externally learned FDBs for the vtep device.

Notification is sent only about static FDB add/del. This is done due
to fact that currently this is the only scenario supported by switch
drivers.

Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com>
Reviewed-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 .../ethernet/mellanox/mlxsw/spectrum_switchdev.c   |  2 +-
 drivers/net/ethernet/rocker/rocker_ofdpa.c         |  4 ++--
 include/net/switchdev.h                            |  6 ++++--
 net/bridge/br.c                                    |  4 ++--
 net/bridge/br_fdb.c                                | 22 ++++++++++++++++++++++
 net/bridge/br_private.h                            |  8 ++++++++
 net/bridge/br_switchdev.c                          | 13 +++++++++++++
 7 files changed, 52 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index edcc273..0111a77 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -1867,7 +1867,7 @@ static void mlxsw_sp_fdb_call_notifiers(bool learning_sync, bool adding,
 	if (learning_sync) {
 		info.addr = mac;
 		info.vid = vid;
-		notifier_type = adding ? SWITCHDEV_FDB_ADD : SWITCHDEV_FDB_DEL;
+		notifier_type = adding ? SWITCHDEV_FDB_ADD_TO_BRIDGE : SWITCHDEV_FDB_DEL_TO_BRIDGE;
 		call_switchdev_notifiers(notifier_type, dev, &info.info);
 	}
 }
diff --git a/drivers/net/ethernet/rocker/rocker_ofdpa.c b/drivers/net/ethernet/rocker/rocker_ofdpa.c
index 2ae8524..f659dad 100644
--- a/drivers/net/ethernet/rocker/rocker_ofdpa.c
+++ b/drivers/net/ethernet/rocker/rocker_ofdpa.c
@@ -1939,10 +1939,10 @@ static void ofdpa_port_fdb_learn_work(struct work_struct *work)
 
 	rtnl_lock();
 	if (learned && removing)
-		call_switchdev_notifiers(SWITCHDEV_FDB_DEL,
+		call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_BRIDGE,
 					 lw->ofdpa_port->dev, &info.info);
 	else if (learned && !removing)
-		call_switchdev_notifiers(SWITCHDEV_FDB_ADD,
+		call_switchdev_notifiers(SWITCHDEV_FDB_ADD_TO_BRIDGE,
 					 lw->ofdpa_port->dev, &info.info);
 	rtnl_unlock();
 
diff --git a/include/net/switchdev.h b/include/net/switchdev.h
index 63a754d..8165ed9 100644
--- a/include/net/switchdev.h
+++ b/include/net/switchdev.h
@@ -155,8 +155,10 @@ struct switchdev_ops {
 };
 
 enum switchdev_notifier_type {
-	SWITCHDEV_FDB_ADD = 1,
-	SWITCHDEV_FDB_DEL,
+	SWITCHDEV_FDB_ADD_TO_BRIDGE = 1,
+	SWITCHDEV_FDB_DEL_TO_BRIDGE,
+	SWITCHDEV_FDB_ADD_TO_DEVICE,
+	SWITCHDEV_FDB_DEL_TO_DEVICE,
 };
 
 struct switchdev_notifier_info {
diff --git a/net/bridge/br.c b/net/bridge/br.c
index e962fff..96d209c 100644
--- a/net/bridge/br.c
+++ b/net/bridge/br.c
@@ -138,14 +138,14 @@ static int br_switchdev_event(struct notifier_block *unused,
 	br = p->br;
 
 	switch (event) {
-	case SWITCHDEV_FDB_ADD:
+	case SWITCHDEV_FDB_ADD_TO_BRIDGE:
 		fdb_info = ptr;
 		err = br_fdb_external_learn_add(br, p, fdb_info->addr,
 						fdb_info->vid);
 		if (err)
 			err = notifier_from_errno(err);
 		break;
-	case SWITCHDEV_FDB_DEL:
+	case SWITCHDEV_FDB_DEL_TO_BRIDGE:
 		fdb_info = ptr;
 		err = br_fdb_external_learn_del(br, p, fdb_info->addr,
 						fdb_info->vid);
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index 5c780cd..21bf9d2 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -683,6 +683,26 @@ static inline size_t fdb_nlmsg_size(void)
 		+ nla_total_size(sizeof(struct nda_cacheinfo));
 }
 
+static void
+fdb_notify_switchdev(const struct net_bridge_fdb_entry *fdb, int type)
+{
+	if (!fdb->added_by_user)
+		return;
+
+	switch (type) {
+	case RTM_DELNEIGH:
+		br_switchdev_fdb_call_notifiers(false, fdb->addr.addr,
+						fdb->vlan_id,
+						fdb->dst->dev);
+		break;
+	case RTM_NEWNEIGH:
+		br_switchdev_fdb_call_notifiers(true, fdb->addr.addr,
+						fdb->vlan_id,
+						fdb->dst->dev);
+		break;
+	}
+}
+
 static void fdb_notify(struct net_bridge *br,
 		       const struct net_bridge_fdb_entry *fdb, int type)
 {
@@ -690,6 +710,8 @@ static void fdb_notify(struct net_bridge *br,
 	struct sk_buff *skb;
 	int err = -ENOBUFS;
 
+	fdb_notify_switchdev(fdb, type);
+
 	skb = nlmsg_new(fdb_nlmsg_size(), GFP_ATOMIC);
 	if (skb == NULL)
 		goto errout;
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 69ba3ba..5e944e9 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -1086,6 +1086,8 @@ void nbp_switchdev_frame_mark(const struct net_bridge_port *p,
 			      struct sk_buff *skb);
 bool nbp_switchdev_allowed_egress(const struct net_bridge_port *p,
 				  const struct sk_buff *skb);
+void br_switchdev_fdb_call_notifiers(bool adding, const unsigned char *mac,
+				     u16 vid, struct net_device *dev);
 #else
 static inline int nbp_switchdev_mark_set(struct net_bridge_port *p)
 {
@@ -1102,6 +1104,12 @@ static inline bool nbp_switchdev_allowed_egress(const struct net_bridge_port *p,
 {
 	return true;
 }
+
+static inline void
+br_switchdev_fdb_call_notifiers(bool adding, const unsigned char *mac,
+				u16 vid, struct net_device *dev)
+{
+}
 #endif /* CONFIG_NET_SWITCHDEV */
 
 #endif
diff --git a/net/bridge/br_switchdev.c b/net/bridge/br_switchdev.c
index f4097b9..c07dceb 100644
--- a/net/bridge/br_switchdev.c
+++ b/net/bridge/br_switchdev.c
@@ -55,3 +55,16 @@ bool nbp_switchdev_allowed_egress(const struct net_bridge_port *p,
 	return !skb->offload_fwd_mark ||
 	       BR_INPUT_SKB_CB(skb)->offload_fwd_mark != p->offload_fwd_mark;
 }
+
+void
+br_switchdev_fdb_call_notifiers(bool adding, const unsigned char *mac,
+				u16 vid, struct net_device *dev)
+{
+	struct switchdev_notifier_fdb_info info;
+	unsigned long notifier_type;
+
+	info.addr = mac;
+	info.vid = vid;
+	notifier_type = adding ? SWITCHDEV_FDB_ADD_TO_DEVICE : SWITCHDEV_FDB_DEL_TO_DEVICE;
+	call_switchdev_notifiers(notifier_type, dev, &info.info);
+}
-- 
2.9.3

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

* [patch net-next 06/19] net: bridge: Receive notification about successful FDB offload
  2017-06-05  9:20 [patch net-next 00/19] Remove support from bridge bypass for mlxsw/rocker drivers Jiri Pirko
                   ` (4 preceding siblings ...)
  2017-06-05  9:20 ` [patch net-next 05/19] net: bridge: Add support for notifying devices about FDB add/del Jiri Pirko
@ 2017-06-05  9:20 ` Jiri Pirko
  2017-06-05 13:44   ` Nikolay Aleksandrov
  2017-06-05  9:20 ` [patch net-next 07/19] mlxsw: spectrum: Remove support for bridge FDB learning sync Jiri Pirko
                   ` (13 subsequent siblings)
  19 siblings, 1 reply; 30+ messages in thread
From: Jiri Pirko @ 2017-06-05  9:20 UTC (permalink / raw)
  To: netdev; +Cc: davem, idosch, arkadis, mlxsw, roopa, stephen, ivecera

From: Arkadi Sharshevsky <arkadis@mellanox.com>

When a new static FDB is added to the bridge a notification is sent to
the driver for offload. In case of successful offload the driver should
notify the bridge back, which in turn should mark the FDB as offloaded.

Currently, externally learned is equivalent for being offloaded which is
not correct due to the fact that FDBs which are added from user-space are
also marked as externally learned. In order to specify if an FDB was
successfully offloaded a new flag is introduced.

Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com>
Reviewed-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 include/net/switchdev.h        |  1 +
 include/uapi/linux/neighbour.h |  1 +
 net/bridge/br.c                | 11 ++++++++++-
 net/bridge/br_fdb.c            | 22 +++++++++++++++++++++-
 net/bridge/br_private.h        |  5 ++++-
 5 files changed, 37 insertions(+), 3 deletions(-)

diff --git a/include/net/switchdev.h b/include/net/switchdev.h
index 8165ed9..c784a6a 100644
--- a/include/net/switchdev.h
+++ b/include/net/switchdev.h
@@ -159,6 +159,7 @@ enum switchdev_notifier_type {
 	SWITCHDEV_FDB_DEL_TO_BRIDGE,
 	SWITCHDEV_FDB_ADD_TO_DEVICE,
 	SWITCHDEV_FDB_DEL_TO_DEVICE,
+	SWITCHDEV_FDB_OFFLOADED,
 };
 
 struct switchdev_notifier_info {
diff --git a/include/uapi/linux/neighbour.h b/include/uapi/linux/neighbour.h
index f3d16db..3199d28 100644
--- a/include/uapi/linux/neighbour.h
+++ b/include/uapi/linux/neighbour.h
@@ -41,6 +41,7 @@ enum {
 #define NTF_MASTER	0x04
 #define NTF_PROXY	0x08	/* == ATF_PUBL */
 #define NTF_EXT_LEARNED	0x10
+#define NTF_OFFLOADED   0x20
 #define NTF_ROUTER	0x80
 
 /*
diff --git a/net/bridge/br.c b/net/bridge/br.c
index 96d209c..1407d1b 100644
--- a/net/bridge/br.c
+++ b/net/bridge/br.c
@@ -142,8 +142,12 @@ static int br_switchdev_event(struct notifier_block *unused,
 		fdb_info = ptr;
 		err = br_fdb_external_learn_add(br, p, fdb_info->addr,
 						fdb_info->vid);
-		if (err)
+		if (err) {
 			err = notifier_from_errno(err);
+			break;
+		}
+		br_fdb_offloaded_set(br, p, fdb_info->addr,
+				     fdb_info->vid);
 		break;
 	case SWITCHDEV_FDB_DEL_TO_BRIDGE:
 		fdb_info = ptr;
@@ -152,6 +156,11 @@ static int br_switchdev_event(struct notifier_block *unused,
 		if (err)
 			err = notifier_from_errno(err);
 		break;
+	case SWITCHDEV_FDB_OFFLOADED:
+		fdb_info = ptr;
+		br_fdb_offloaded_set(br, p, fdb_info->addr,
+				     fdb_info->vid);
+		break;
 	}
 
 out:
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index 21bf9d2..1bd3d84 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -511,6 +511,7 @@ static struct net_bridge_fdb_entry *fdb_create(struct hlist_head *head,
 		fdb->is_static = is_static;
 		fdb->added_by_user = 0;
 		fdb->added_by_external_learn = 0;
+		fdb->offloaded = 0;
 		fdb->updated = fdb->used = jiffies;
 		hlist_add_head_rcu(&fdb->hlist, head);
 	}
@@ -647,11 +648,16 @@ static int fdb_fill_info(struct sk_buff *skb, const struct net_bridge *br,
 	ndm->ndm_family	 = AF_BRIDGE;
 	ndm->ndm_pad1    = 0;
 	ndm->ndm_pad2    = 0;
-	ndm->ndm_flags	 = fdb->added_by_external_learn ? NTF_EXT_LEARNED : 0;
+	ndm->ndm_flags	 = 0;
 	ndm->ndm_type	 = 0;
 	ndm->ndm_ifindex = fdb->dst ? fdb->dst->dev->ifindex : br->dev->ifindex;
 	ndm->ndm_state   = fdb_to_nud(br, fdb);
 
+	if (fdb->offloaded)
+		ndm->ndm_flags |= NTF_OFFLOADED;
+	if (fdb->added_by_external_learn)
+		ndm->ndm_flags |= NTF_EXT_LEARNED;
+
 	if (nla_put(skb, NDA_LLADDR, ETH_ALEN, &fdb->addr))
 		goto nla_put_failure;
 	if (nla_put_u32(skb, NDA_MASTER, br->dev->ifindex))
@@ -1143,3 +1149,17 @@ int br_fdb_external_learn_del(struct net_bridge *br, struct net_bridge_port *p,
 
 	return err;
 }
+
+void br_fdb_offloaded_set(struct net_bridge *br, struct net_bridge_port *p,
+			  const unsigned char *addr, u16 vid)
+{
+	struct net_bridge_fdb_entry *fdb;
+
+	spin_lock_bh(&br->hash_lock);
+
+	fdb = br_fdb_find(br, addr, vid);
+	if (fdb)
+		fdb->offloaded = 1;
+
+	spin_unlock_bh(&br->hash_lock);
+}
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 5e944e9..a5db2e1 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -173,7 +173,8 @@ struct net_bridge_fdb_entry {
 	unsigned char			is_local:1,
 					is_static:1,
 					added_by_user:1,
-					added_by_external_learn:1;
+					added_by_external_learn:1,
+					offloaded:1;
 
 	/* write-heavy members should not affect lookups */
 	unsigned long			updated ____cacheline_aligned_in_smp;
@@ -540,6 +541,8 @@ int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
 			      const unsigned char *addr, u16 vid);
 int br_fdb_external_learn_del(struct net_bridge *br, struct net_bridge_port *p,
 			      const unsigned char *addr, u16 vid);
+void br_fdb_offloaded_set(struct net_bridge *br, struct net_bridge_port *p,
+			  const unsigned char *addr, u16 vid);
 
 /* br_forward.c */
 enum br_pkt_type {
-- 
2.9.3

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

* [patch net-next 07/19] mlxsw: spectrum: Remove support for bridge FDB learning sync
  2017-06-05  9:20 [patch net-next 00/19] Remove support from bridge bypass for mlxsw/rocker drivers Jiri Pirko
                   ` (5 preceding siblings ...)
  2017-06-05  9:20 ` [patch net-next 06/19] net: bridge: Receive notification about successful FDB offload Jiri Pirko
@ 2017-06-05  9:20 ` Jiri Pirko
  2017-06-05  9:20 ` [patch net-next 08/19] mlxsw: spectrum_switchdev: Add support for querying supported bridge flags Jiri Pirko
                   ` (12 subsequent siblings)
  19 siblings, 0 replies; 30+ messages in thread
From: Jiri Pirko @ 2017-06-05  9:20 UTC (permalink / raw)
  To: netdev; +Cc: davem, idosch, arkadis, mlxsw, roopa, stephen, ivecera

From: Arkadi Sharshevsky <arkadis@mellanox.com>

Currently the mlxsw driver supports an option for disabling syncing
the hardware learned FDBs with the software bridge. This behavior
breaks the bridge offload model and thus it is removed.

Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com>
Reviewed-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 .../net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 0111a77..eb88b72 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -1857,19 +1857,17 @@ void mlxsw_sp_port_bridge_leave(struct mlxsw_sp_port *mlxsw_sp_port,
 	mlxsw_sp_bridge_port_put(mlxsw_sp->bridge, bridge_port);
 }
 
-static void mlxsw_sp_fdb_call_notifiers(bool learning_sync, bool adding,
+static void mlxsw_sp_fdb_call_notifiers(bool adding,
 					char *mac, u16 vid,
 					struct net_device *dev)
 {
 	struct switchdev_notifier_fdb_info info;
 	unsigned long notifier_type;
 
-	if (learning_sync) {
-		info.addr = mac;
-		info.vid = vid;
-		notifier_type = adding ? SWITCHDEV_FDB_ADD_TO_BRIDGE : SWITCHDEV_FDB_DEL_TO_BRIDGE;
-		call_switchdev_notifiers(notifier_type, dev, &info.info);
-	}
+	info.addr = mac;
+	info.vid = vid;
+	notifier_type = adding ? SWITCHDEV_FDB_ADD_TO_BRIDGE : SWITCHDEV_FDB_DEL_TO_BRIDGE;
+	call_switchdev_notifiers(notifier_type, dev, &info.info);
 }
 
 static void mlxsw_sp_fdb_notify_mac_process(struct mlxsw_sp *mlxsw_sp,
@@ -1918,8 +1916,8 @@ static void mlxsw_sp_fdb_notify_mac_process(struct mlxsw_sp *mlxsw_sp,
 
 	if (!do_notification)
 		return;
-	mlxsw_sp_fdb_call_notifiers(bridge_port->flags & BR_LEARNING_SYNC,
-				    adding, mac, vid, bridge_port->dev);
+	mlxsw_sp_fdb_call_notifiers(adding, mac, vid, bridge_port->dev);
+
 	return;
 
 just_remove:
@@ -1976,8 +1974,8 @@ static void mlxsw_sp_fdb_notify_mac_lag_process(struct mlxsw_sp *mlxsw_sp,
 
 	if (!do_notification)
 		return;
-	mlxsw_sp_fdb_call_notifiers(bridge_port->flags & BR_LEARNING_SYNC,
-				    adding, mac, vid, bridge_port->dev);
+	mlxsw_sp_fdb_call_notifiers(adding, mac, vid, bridge_port->dev);
+
 	return;
 
 just_remove:
-- 
2.9.3

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

* [patch net-next 08/19] mlxsw: spectrum_switchdev: Add support for querying supported bridge flags
  2017-06-05  9:20 [patch net-next 00/19] Remove support from bridge bypass for mlxsw/rocker drivers Jiri Pirko
                   ` (6 preceding siblings ...)
  2017-06-05  9:20 ` [patch net-next 07/19] mlxsw: spectrum: Remove support for bridge FDB learning sync Jiri Pirko
@ 2017-06-05  9:20 ` Jiri Pirko
  2017-06-05  9:20 ` [patch net-next 09/19] mlxsw: spectrum: Remove support for bypass bridge port attributes/vlan set Jiri Pirko
                   ` (11 subsequent siblings)
  19 siblings, 0 replies; 30+ messages in thread
From: Jiri Pirko @ 2017-06-05  9:20 UTC (permalink / raw)
  To: netdev; +Cc: davem, idosch, arkadis, mlxsw, roopa, stephen, ivecera

From: Arkadi Sharshevsky <arkadis@mellanox.com>

Add support for querying supported bridge flags.

Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com>
Reviewed-by: Ido Schimmel <idosch@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 eb88b72..0333493 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -456,6 +456,9 @@ static int mlxsw_sp_port_attr_get(struct net_device *dev,
 		mlxsw_sp_port_bridge_flags_get(mlxsw_sp->bridge, attr->orig_dev,
 					       &attr->u.brport_flags);
 		break;
+	case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT:
+		attr->u.brport_flags_support = BR_LEARNING | BR_FLOOD;
+		break;
 	default:
 		return -EOPNOTSUPP;
 	}
-- 
2.9.3

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

* [patch net-next 09/19] mlxsw: spectrum: Remove support for bypass bridge port attributes/vlan set
  2017-06-05  9:20 [patch net-next 00/19] Remove support from bridge bypass for mlxsw/rocker drivers Jiri Pirko
                   ` (7 preceding siblings ...)
  2017-06-05  9:20 ` [patch net-next 08/19] mlxsw: spectrum_switchdev: Add support for querying supported bridge flags Jiri Pirko
@ 2017-06-05  9:20 ` Jiri Pirko
  2017-06-05  9:20 ` [patch net-next 10/19] mlxsw: spectrum_switchdev: Change switchdev notifier API Jiri Pirko
                   ` (10 subsequent siblings)
  19 siblings, 0 replies; 30+ messages in thread
From: Jiri Pirko @ 2017-06-05  9:20 UTC (permalink / raw)
  To: netdev; +Cc: davem, idosch, arkadis, mlxsw, roopa, stephen, ivecera

From: Arkadi Sharshevsky <arkadis@mellanox.com>

The bridge port attributes/vlan for mlxsw devices should be set only
from bridge code. The vlans are synced totally with the bridge so
there is no need to special dump support.

Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com>
Reviewed-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.c     |  3 --
 .../ethernet/mellanox/mlxsw/spectrum_switchdev.c   | 41 ----------------------
 2 files changed, 44 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 84b6f36..a2ec42e 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -1755,9 +1755,6 @@ static const struct net_device_ops mlxsw_sp_port_netdev_ops = {
 	.ndo_fdb_add		= switchdev_port_fdb_add,
 	.ndo_fdb_del		= switchdev_port_fdb_del,
 	.ndo_fdb_dump		= switchdev_port_fdb_dump,
-	.ndo_bridge_setlink	= switchdev_port_bridge_setlink,
-	.ndo_bridge_getlink	= switchdev_port_bridge_getlink,
-	.ndo_bridge_dellink	= switchdev_port_bridge_dellink,
 	.ndo_get_phys_port_name	= mlxsw_sp_port_get_phys_port_name,
 };
 
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 0333493..6257b0b 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -102,8 +102,6 @@ struct mlxsw_sp_bridge_vlan {
 	struct list_head list;
 	struct list_head port_vlan_list;
 	u16 vid;
-	u8 egress_untagged:1,
-	   pvid:1;
 };
 
 struct mlxsw_sp_bridge_ops {
@@ -1003,8 +1001,6 @@ mlxsw_sp_bridge_port_vlan_add(struct mlxsw_sp_port *mlxsw_sp_port,
 		goto err_port_vlan_bridge_join;
 
 	bridge_vlan = mlxsw_sp_bridge_vlan_find(bridge_port, vid);
-	bridge_vlan->egress_untagged = is_untagged;
-	bridge_vlan->pvid = is_pvid;
 
 	return 0;
 
@@ -1629,39 +1625,6 @@ static int mlxsw_sp_port_fdb_dump(struct mlxsw_sp_port *mlxsw_sp_port,
 	return stored_err ? stored_err : err;
 }
 
-static int mlxsw_sp_port_vlan_dump(struct mlxsw_sp_port *mlxsw_sp_port,
-				   struct switchdev_obj_port_vlan *vlan,
-				   switchdev_obj_dump_cb_t *cb)
-{
-	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
-	struct net_device *orig_dev = vlan->obj.orig_dev;
-	struct mlxsw_sp_bridge_port *bridge_port;
-	struct mlxsw_sp_bridge_vlan *bridge_vlan;
-	int err = 0;
-
-	bridge_port = mlxsw_sp_bridge_port_find(mlxsw_sp->bridge, orig_dev);
-	if (WARN_ON(!bridge_port))
-		return -EINVAL;
-
-	if (!bridge_port->bridge_device->vlan_enabled)
-		return 0;
-
-	list_for_each_entry(bridge_vlan, &bridge_port->vlans_list, list) {
-		vlan->flags = 0;
-		if (bridge_vlan->pvid)
-			vlan->flags |= BRIDGE_VLAN_INFO_PVID;
-		if (bridge_vlan->egress_untagged)
-			vlan->flags |= BRIDGE_VLAN_INFO_UNTAGGED;
-		vlan->vid_begin = bridge_vlan->vid;
-		vlan->vid_end = bridge_vlan->vid;
-		err = cb(&vlan->obj);
-		if (err)
-			break;
-	}
-
-	return err;
-}
-
 static int mlxsw_sp_port_obj_dump(struct net_device *dev,
 				  struct switchdev_obj *obj,
 				  switchdev_obj_dump_cb_t *cb)
@@ -1670,10 +1633,6 @@ static int mlxsw_sp_port_obj_dump(struct net_device *dev,
 	int err = 0;
 
 	switch (obj->id) {
-	case SWITCHDEV_OBJ_ID_PORT_VLAN:
-		err = mlxsw_sp_port_vlan_dump(mlxsw_sp_port,
-					      SWITCHDEV_OBJ_PORT_VLAN(obj), cb);
-		break;
 	case SWITCHDEV_OBJ_ID_PORT_FDB:
 		err = mlxsw_sp_port_fdb_dump(mlxsw_sp_port,
 					     SWITCHDEV_OBJ_PORT_FDB(obj), cb);
-- 
2.9.3

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

* [patch net-next 10/19] mlxsw: spectrum_switchdev: Change switchdev notifier API
  2017-06-05  9:20 [patch net-next 00/19] Remove support from bridge bypass for mlxsw/rocker drivers Jiri Pirko
                   ` (8 preceding siblings ...)
  2017-06-05  9:20 ` [patch net-next 09/19] mlxsw: spectrum: Remove support for bypass bridge port attributes/vlan set Jiri Pirko
@ 2017-06-05  9:20 ` Jiri Pirko
  2017-06-05  9:20 ` [patch net-next 11/19] mlxsw: spectrum_switchdev: Add support for learning FDB through notification Jiri Pirko
                   ` (9 subsequent siblings)
  19 siblings, 0 replies; 30+ messages in thread
From: Jiri Pirko @ 2017-06-05  9:20 UTC (permalink / raw)
  To: netdev; +Cc: davem, idosch, arkadis, mlxsw, roopa, stephen, ivecera

From: Arkadi Sharshevsky <arkadis@mellanox.com>

The current API for sending switchdev notifications implies only FDB
add/del. In order to support notification about successful FDB offload
the API is changed.

Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com>
Reviewed-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 .../net/ethernet/mellanox/mlxsw/spectrum_switchdev.c  | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 6257b0b..0b50d1d 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -1819,17 +1819,16 @@ void mlxsw_sp_port_bridge_leave(struct mlxsw_sp_port *mlxsw_sp_port,
 	mlxsw_sp_bridge_port_put(mlxsw_sp->bridge, bridge_port);
 }
 
-static void mlxsw_sp_fdb_call_notifiers(bool adding,
-					char *mac, u16 vid,
-					struct net_device *dev)
+static void
+mlxsw_sp_fdb_call_notifiers(enum switchdev_notifier_type type,
+			    const char *mac, u16 vid,
+			    struct net_device *dev)
 {
 	struct switchdev_notifier_fdb_info info;
-	unsigned long notifier_type;
 
 	info.addr = mac;
 	info.vid = vid;
-	notifier_type = adding ? SWITCHDEV_FDB_ADD_TO_BRIDGE : SWITCHDEV_FDB_DEL_TO_BRIDGE;
-	call_switchdev_notifiers(notifier_type, dev, &info.info);
+	call_switchdev_notifiers(type, dev, &info.info);
 }
 
 static void mlxsw_sp_fdb_notify_mac_process(struct mlxsw_sp *mlxsw_sp,
@@ -1840,6 +1839,7 @@ static void mlxsw_sp_fdb_notify_mac_process(struct mlxsw_sp *mlxsw_sp,
 	struct mlxsw_sp_bridge_device *bridge_device;
 	struct mlxsw_sp_bridge_port *bridge_port;
 	struct mlxsw_sp_port *mlxsw_sp_port;
+	enum switchdev_notifier_type type;
 	char mac[ETH_ALEN];
 	u8 local_port;
 	u16 vid, fid;
@@ -1878,7 +1878,8 @@ static void mlxsw_sp_fdb_notify_mac_process(struct mlxsw_sp *mlxsw_sp,
 
 	if (!do_notification)
 		return;
-	mlxsw_sp_fdb_call_notifiers(adding, mac, vid, bridge_port->dev);
+	type = adding ? SWITCHDEV_FDB_ADD_TO_BRIDGE : SWITCHDEV_FDB_DEL_TO_BRIDGE;
+	mlxsw_sp_fdb_call_notifiers(type, mac, vid, bridge_port->dev);
 
 	return;
 
@@ -1896,6 +1897,7 @@ static void mlxsw_sp_fdb_notify_mac_lag_process(struct mlxsw_sp *mlxsw_sp,
 	struct mlxsw_sp_bridge_device *bridge_device;
 	struct mlxsw_sp_bridge_port *bridge_port;
 	struct mlxsw_sp_port *mlxsw_sp_port;
+	enum switchdev_notifier_type type;
 	char mac[ETH_ALEN];
 	u16 lag_vid = 0;
 	u16 lag_id;
@@ -1936,7 +1938,8 @@ static void mlxsw_sp_fdb_notify_mac_lag_process(struct mlxsw_sp *mlxsw_sp,
 
 	if (!do_notification)
 		return;
-	mlxsw_sp_fdb_call_notifiers(adding, mac, vid, bridge_port->dev);
+	type = adding ? SWITCHDEV_FDB_ADD_TO_BRIDGE : SWITCHDEV_FDB_DEL_TO_BRIDGE;
+	mlxsw_sp_fdb_call_notifiers(type, mac, vid, bridge_port->dev);
 
 	return;
 
-- 
2.9.3

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

* [patch net-next 11/19] mlxsw: spectrum_switchdev: Add support for learning FDB through notification
  2017-06-05  9:20 [patch net-next 00/19] Remove support from bridge bypass for mlxsw/rocker drivers Jiri Pirko
                   ` (9 preceding siblings ...)
  2017-06-05  9:20 ` [patch net-next 10/19] mlxsw: spectrum_switchdev: Change switchdev notifier API Jiri Pirko
@ 2017-06-05  9:20 ` Jiri Pirko
  2017-06-05  9:20 ` [patch net-next 12/19] mlxsw: spectrum: Remove support for bridge bypass FDB add/del Jiri Pirko
                   ` (8 subsequent siblings)
  19 siblings, 0 replies; 30+ messages in thread
From: Jiri Pirko @ 2017-06-05  9:20 UTC (permalink / raw)
  To: netdev; +Cc: davem, idosch, arkadis, mlxsw, roopa, stephen, ivecera

From: Arkadi Sharshevsky <arkadis@mellanox.com>

Add support for learning FDB through notification. The driver defers
the hardware update via ordered work queue. Support for stacked devices
is also provided. In case of a successful FDB add a notification is
sent back to bridge.

Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com>
Reviewed-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.c     |   2 +-
 drivers/net/ethernet/mellanox/mlxsw/spectrum.h     |   1 +
 .../ethernet/mellanox/mlxsw/spectrum_switchdev.c   | 137 +++++++++++++++++++++
 3 files changed, 139 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index a2ec42e..1f6b396 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -3700,7 +3700,7 @@ struct mlxsw_sp *mlxsw_sp_lower_get(struct net_device *dev)
 	return mlxsw_sp_port ? mlxsw_sp_port->mlxsw_sp : NULL;
 }
 
-static struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find_rcu(struct net_device *dev)
+struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find_rcu(struct net_device *dev)
 {
 	struct mlxsw_sp_port *mlxsw_sp_port;
 
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index 99760fd..f4e9dbd 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -361,6 +361,7 @@ struct mlxsw_sp *mlxsw_sp_lower_get(struct net_device *dev);
 struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find(struct net_device *dev);
 struct mlxsw_sp_port *mlxsw_sp_port_lower_dev_hold(struct net_device *dev);
 void mlxsw_sp_port_dev_put(struct mlxsw_sp_port *mlxsw_sp_port);
+struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find_rcu(struct net_device *dev);
 
 /* spectrum_dcb.c */
 #ifdef CONFIG_MLXSW_SPECTRUM_DCB
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 0b50d1d..0297c13 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -1181,6 +1181,43 @@ mlxsw_sp_port_fdb_static_add(struct mlxsw_sp_port *mlxsw_sp_port,
 						   true, false);
 }
 
+static int
+mlxsw_sp_port_fdb_set(struct mlxsw_sp_port *mlxsw_sp_port,
+		      struct switchdev_notifier_fdb_info *fdb_info, bool adding)
+{
+	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+	struct net_device *orig_dev = fdb_info->info.dev;
+	struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
+	struct mlxsw_sp_bridge_device *bridge_device;
+	struct mlxsw_sp_bridge_port *bridge_port;
+	u16 fid_index, vid;
+
+	bridge_port = mlxsw_sp_bridge_port_find(mlxsw_sp->bridge, orig_dev);
+	if (!bridge_port)
+		return -EINVAL;
+
+	bridge_device = bridge_port->bridge_device;
+	mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_bridge(mlxsw_sp_port,
+							       bridge_device,
+							       fdb_info->vid);
+	if (!mlxsw_sp_port_vlan)
+		return 0;
+
+	fid_index = mlxsw_sp_fid_index(mlxsw_sp_port_vlan->fid);
+	vid = mlxsw_sp_port_vlan->vid;
+
+	if (!bridge_port->lagged)
+		return mlxsw_sp_port_fdb_uc_op(mlxsw_sp,
+					       bridge_port->system_port,
+					       fdb_info->addr, fid_index,
+					       adding, false);
+	else
+		return mlxsw_sp_port_fdb_uc_lag_op(mlxsw_sp,
+						   bridge_port->lag_id,
+						   fdb_info->addr, fid_index,
+						   vid, adding, false);
+}
+
 static int mlxsw_sp_port_mdb_op(struct mlxsw_sp *mlxsw_sp, const char *addr,
 				u16 fid, u16 mid, bool adding)
 {
@@ -2013,6 +2050,97 @@ static void mlxsw_sp_fdb_notify_work(struct work_struct *work)
 	mlxsw_sp_fdb_notify_work_schedule(mlxsw_sp);
 }
 
+struct mlxsw_sp_switchdev_event_work {
+	struct work_struct work;
+	struct switchdev_notifier_fdb_info fdb_info;
+	struct net_device *dev;
+	unsigned long event;
+};
+
+static void mlxsw_sp_switchdev_event_work(struct work_struct *work)
+{
+	struct mlxsw_sp_switchdev_event_work *switchdev_work =
+		container_of(work, struct mlxsw_sp_switchdev_event_work, work);
+	struct net_device *dev = switchdev_work->dev;
+	struct switchdev_notifier_fdb_info *fdb_info;
+	struct mlxsw_sp_port *mlxsw_sp_port;
+	int err;
+
+	rtnl_lock();
+	mlxsw_sp_port = mlxsw_sp_port_dev_lower_find(dev);
+	if (!mlxsw_sp_port)
+		goto out;
+
+	switch (switchdev_work->event) {
+	case SWITCHDEV_FDB_ADD_TO_DEVICE:
+		fdb_info = &switchdev_work->fdb_info;
+		err = mlxsw_sp_port_fdb_set(mlxsw_sp_port, fdb_info, true);
+		if (err)
+			break;
+		mlxsw_sp_fdb_call_notifiers(SWITCHDEV_FDB_OFFLOADED,
+					    fdb_info->addr,
+					    fdb_info->vid, dev);
+		break;
+	case SWITCHDEV_FDB_DEL_TO_DEVICE:
+		fdb_info = &switchdev_work->fdb_info;
+		mlxsw_sp_port_fdb_set(mlxsw_sp_port, fdb_info, false);
+		break;
+	}
+
+out:
+	rtnl_unlock();
+	kfree(switchdev_work->fdb_info.addr);
+	kfree(switchdev_work);
+	dev_put(dev);
+}
+
+/* Called under rcu_read_lock() */
+static int mlxsw_sp_switchdev_event(struct notifier_block *unused,
+				    unsigned long event, void *ptr)
+{
+	struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
+	struct mlxsw_sp_switchdev_event_work *switchdev_work;
+	struct switchdev_notifier_fdb_info *fdb_info = ptr;
+
+	if (!mlxsw_sp_port_dev_lower_find_rcu(dev))
+		return NOTIFY_DONE;
+
+	switchdev_work = kzalloc(sizeof(*switchdev_work), GFP_ATOMIC);
+	if (!switchdev_work)
+		return NOTIFY_BAD;
+
+	INIT_WORK(&switchdev_work->work, mlxsw_sp_switchdev_event_work);
+	switchdev_work->dev = dev;
+	switchdev_work->event = event;
+
+	switch (event) {
+	case SWITCHDEV_FDB_ADD_TO_DEVICE: /* fall through */
+	case SWITCHDEV_FDB_DEL_TO_DEVICE:
+		memcpy(&switchdev_work->fdb_info, ptr,
+		       sizeof(switchdev_work->fdb_info));
+		switchdev_work->fdb_info.addr = kzalloc(ETH_ALEN, GFP_ATOMIC);
+		ether_addr_copy((u8 *)switchdev_work->fdb_info.addr,
+				fdb_info->addr);
+		/* Take a reference on the device. This can be either
+		 * upper device containig mlxsw_sp_port or just a
+		 * mlxsw_sp_port
+		 */
+		dev_hold(dev);
+		break;
+	default:
+		kfree(switchdev_work);
+		return NOTIFY_DONE;
+	}
+
+	mlxsw_core_schedule_work(&switchdev_work->work);
+
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block mlxsw_sp_switchdev_notifier = {
+	.notifier_call = mlxsw_sp_switchdev_event,
+};
+
 static int mlxsw_sp_fdb_init(struct mlxsw_sp *mlxsw_sp)
 {
 	struct mlxsw_sp_bridge *bridge = mlxsw_sp->bridge;
@@ -2023,6 +2151,13 @@ static int mlxsw_sp_fdb_init(struct mlxsw_sp *mlxsw_sp)
 		dev_err(mlxsw_sp->bus_info->dev, "Failed to set default ageing time\n");
 		return err;
 	}
+
+	err = register_switchdev_notifier(&mlxsw_sp_switchdev_notifier);
+	if (err) {
+		dev_err(mlxsw_sp->bus_info->dev, "Failed to register switchdev notifier\n");
+		return err;
+	}
+
 	INIT_DELAYED_WORK(&bridge->fdb_notify.dw, mlxsw_sp_fdb_notify_work);
 	bridge->fdb_notify.interval = MLXSW_SP_DEFAULT_LEARNING_INTERVAL;
 	mlxsw_sp_fdb_notify_work_schedule(mlxsw_sp);
@@ -2032,6 +2167,8 @@ static int mlxsw_sp_fdb_init(struct mlxsw_sp *mlxsw_sp)
 static void mlxsw_sp_fdb_fini(struct mlxsw_sp *mlxsw_sp)
 {
 	cancel_delayed_work_sync(&mlxsw_sp->bridge->fdb_notify.dw);
+	unregister_switchdev_notifier(&mlxsw_sp_switchdev_notifier);
+
 }
 
 int mlxsw_sp_switchdev_init(struct mlxsw_sp *mlxsw_sp)
-- 
2.9.3

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

* [patch net-next 12/19] mlxsw: spectrum: Remove support for bridge bypass FDB add/del
  2017-06-05  9:20 [patch net-next 00/19] Remove support from bridge bypass for mlxsw/rocker drivers Jiri Pirko
                   ` (10 preceding siblings ...)
  2017-06-05  9:20 ` [patch net-next 11/19] mlxsw: spectrum_switchdev: Add support for learning FDB through notification Jiri Pirko
@ 2017-06-05  9:20 ` Jiri Pirko
  2017-06-05  9:20 ` [patch net-next 13/19] net: Remove support for bridge bypass ndos from stacked devices Jiri Pirko
                   ` (7 subsequent siblings)
  19 siblings, 0 replies; 30+ messages in thread
From: Jiri Pirko @ 2017-06-05  9:20 UTC (permalink / raw)
  To: netdev; +Cc: davem, idosch, arkadis, mlxsw, roopa, stephen, ivecera

From: Arkadi Sharshevsky <arkadis@mellanox.com>

The FDB add/del are now done through the notification chain. The FDBs
are synced with the bridge and there is no need for extra dumping.

Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com>
Reviewed-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.c     |   3 -
 .../ethernet/mellanox/mlxsw/spectrum_switchdev.c   | 200 ---------------------
 2 files changed, 203 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 1f6b396..67507c5 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -1752,9 +1752,6 @@ static const struct net_device_ops mlxsw_sp_port_netdev_ops = {
 	.ndo_get_offload_stats	= mlxsw_sp_port_get_offload_stats,
 	.ndo_vlan_rx_add_vid	= mlxsw_sp_port_add_vid,
 	.ndo_vlan_rx_kill_vid	= mlxsw_sp_port_kill_vid,
-	.ndo_fdb_add		= switchdev_port_fdb_add,
-	.ndo_fdb_del		= switchdev_port_fdb_del,
-	.ndo_fdb_dump		= switchdev_port_fdb_dump,
 	.ndo_get_phys_port_name	= mlxsw_sp_port_get_phys_port_name,
 };
 
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 0297c13..cd89a3e 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -1141,47 +1141,6 @@ static int mlxsw_sp_port_fdb_uc_lag_op(struct mlxsw_sp *mlxsw_sp, u16 lag_id,
 }
 
 static int
-mlxsw_sp_port_fdb_static_add(struct mlxsw_sp_port *mlxsw_sp_port,
-			     const struct switchdev_obj_port_fdb *fdb,
-			     struct switchdev_trans *trans)
-{
-	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
-	struct net_device *orig_dev = fdb->obj.orig_dev;
-	struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
-	struct mlxsw_sp_bridge_device *bridge_device;
-	struct mlxsw_sp_bridge_port *bridge_port;
-	u16 fid_index, vid;
-
-	if (switchdev_trans_ph_prepare(trans))
-		return 0;
-
-	bridge_port = mlxsw_sp_bridge_port_find(mlxsw_sp->bridge, orig_dev);
-	if (WARN_ON(!bridge_port))
-		return -EINVAL;
-
-	bridge_device = bridge_port->bridge_device;
-	mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_bridge(mlxsw_sp_port,
-							       bridge_device,
-							       fdb->vid);
-	if (!mlxsw_sp_port_vlan)
-		return 0;
-
-	fid_index = mlxsw_sp_fid_index(mlxsw_sp_port_vlan->fid);
-	vid = mlxsw_sp_port_vlan->vid;
-
-	if (!mlxsw_sp_port->lagged)
-		return mlxsw_sp_port_fdb_uc_op(mlxsw_sp,
-					       mlxsw_sp_port->local_port,
-					       fdb->addr, fid_index, true,
-					       false);
-	else
-		return mlxsw_sp_port_fdb_uc_lag_op(mlxsw_sp,
-						   mlxsw_sp_port->lag_id,
-						   fdb->addr, fid_index, vid,
-						   true, false);
-}
-
-static int
 mlxsw_sp_port_fdb_set(struct mlxsw_sp_port *mlxsw_sp_port,
 		      struct switchdev_notifier_fdb_info *fdb_info, bool adding)
 {
@@ -1385,11 +1344,6 @@ static int mlxsw_sp_port_obj_add(struct net_device *dev,
 					      SWITCHDEV_OBJ_PORT_VLAN(obj),
 					      trans);
 		break;
-	case SWITCHDEV_OBJ_ID_PORT_FDB:
-		err = mlxsw_sp_port_fdb_static_add(mlxsw_sp_port,
-						   SWITCHDEV_OBJ_PORT_FDB(obj),
-						   trans);
-		break;
 	case SWITCHDEV_OBJ_ID_PORT_MDB:
 		err = mlxsw_sp_port_mdb_add(mlxsw_sp_port,
 					    SWITCHDEV_OBJ_PORT_MDB(obj),
@@ -1441,43 +1395,6 @@ static int mlxsw_sp_port_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port,
 	return 0;
 }
 
-static int
-mlxsw_sp_port_fdb_static_del(struct mlxsw_sp_port *mlxsw_sp_port,
-			     const struct switchdev_obj_port_fdb *fdb)
-{
-	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
-	struct net_device *orig_dev = fdb->obj.orig_dev;
-	struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
-	struct mlxsw_sp_bridge_device *bridge_device;
-	struct mlxsw_sp_bridge_port *bridge_port;
-	u16 fid_index, vid;
-
-	bridge_port = mlxsw_sp_bridge_port_find(mlxsw_sp->bridge, orig_dev);
-	if (WARN_ON(!bridge_port))
-		return -EINVAL;
-
-	bridge_device = bridge_port->bridge_device;
-	mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_bridge(mlxsw_sp_port,
-							       bridge_device,
-							       fdb->vid);
-	if (!mlxsw_sp_port_vlan)
-		return 0;
-
-	fid_index = mlxsw_sp_fid_index(mlxsw_sp_port_vlan->fid);
-	vid = mlxsw_sp_port_vlan->vid;
-
-	if (!mlxsw_sp_port->lagged)
-		return mlxsw_sp_port_fdb_uc_op(mlxsw_sp,
-					       mlxsw_sp_port->local_port,
-					       fdb->addr, fid_index, false,
-					       false);
-	else
-		return mlxsw_sp_port_fdb_uc_lag_op(mlxsw_sp,
-						   mlxsw_sp_port->lag_id,
-						   fdb->addr, fid_index, vid,
-						   false, false);
-}
-
 static int mlxsw_sp_port_mdb_del(struct mlxsw_sp_port *mlxsw_sp_port,
 				 const struct switchdev_obj_port_mdb *mdb)
 {
@@ -1537,10 +1454,6 @@ static int mlxsw_sp_port_obj_del(struct net_device *dev,
 		err = mlxsw_sp_port_vlans_del(mlxsw_sp_port,
 					      SWITCHDEV_OBJ_PORT_VLAN(obj));
 		break;
-	case SWITCHDEV_OBJ_ID_PORT_FDB:
-		err = mlxsw_sp_port_fdb_static_del(mlxsw_sp_port,
-						   SWITCHDEV_OBJ_PORT_FDB(obj));
-		break;
 	case SWITCHDEV_OBJ_ID_PORT_MDB:
 		err = mlxsw_sp_port_mdb_del(mlxsw_sp_port,
 					    SWITCHDEV_OBJ_PORT_MDB(obj));
@@ -1570,124 +1483,11 @@ static struct mlxsw_sp_port *mlxsw_sp_lag_rep_port(struct mlxsw_sp *mlxsw_sp,
 	return NULL;
 }
 
-static int mlxsw_sp_port_fdb_dump(struct mlxsw_sp_port *mlxsw_sp_port,
-				  struct switchdev_obj_port_fdb *fdb,
-				  switchdev_obj_dump_cb_t *cb)
-{
-	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
-	struct net_device *orig_dev = fdb->obj.orig_dev;
-	struct mlxsw_sp_bridge_port *bridge_port;
-	u16 lag_id, fid_index;
-	char mac[ETH_ALEN];
-	int stored_err = 0;
-	char *sfd_pl;
-	u8 num_rec;
-	int err;
-
-	bridge_port = mlxsw_sp_bridge_port_find(mlxsw_sp->bridge, orig_dev);
-	if (!bridge_port)
-		return 0;
-
-	sfd_pl = kmalloc(MLXSW_REG_SFD_LEN, GFP_KERNEL);
-	if (!sfd_pl)
-		return -ENOMEM;
-
-	mlxsw_reg_sfd_pack(sfd_pl, MLXSW_REG_SFD_OP_QUERY_DUMP, 0);
-	do {
-		struct mlxsw_sp_port *tmp;
-		u8 local_port;
-		int i;
-
-		mlxsw_reg_sfd_num_rec_set(sfd_pl, MLXSW_REG_SFD_REC_MAX_COUNT);
-		err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(sfd), sfd_pl);
-		if (err)
-			goto out;
-
-		num_rec = mlxsw_reg_sfd_num_rec_get(sfd_pl);
-
-		/* Even in case of error, we have to run the dump to the end
-		 * so the session in firmware is finished.
-		 */
-		if (stored_err)
-			continue;
-
-		for (i = 0; i < num_rec; i++) {
-			switch (mlxsw_reg_sfd_rec_type_get(sfd_pl, i)) {
-			case MLXSW_REG_SFD_REC_TYPE_UNICAST:
-				mlxsw_reg_sfd_uc_unpack(sfd_pl, i, mac,
-							&fid_index,
-							&local_port);
-				if (bridge_port->lagged)
-					continue;
-				if (bridge_port->system_port != local_port)
-					continue;
-				if (bridge_port->bridge_device->vlan_enabled)
-					fdb->vid = fid_index;
-				else
-					fdb->vid = 0;
-				ether_addr_copy(fdb->addr, mac);
-				fdb->ndm_state = NUD_REACHABLE;
-				err = cb(&fdb->obj);
-				if (err)
-					stored_err = err;
-				break;
-			case MLXSW_REG_SFD_REC_TYPE_UNICAST_LAG:
-				mlxsw_reg_sfd_uc_lag_unpack(sfd_pl, i,
-							    mac, &fid_index,
-							    &lag_id);
-				if (!bridge_port->lagged)
-					continue;
-				if (bridge_port->lag_id != lag_id)
-					continue;
-				tmp = mlxsw_sp_lag_rep_port(mlxsw_sp, lag_id);
-				if (tmp->local_port !=
-				    mlxsw_sp_port->local_port)
-					continue;
-				if (bridge_port->bridge_device->vlan_enabled)
-					fdb->vid = fid_index;
-				else
-					fdb->vid = 0;
-				ether_addr_copy(fdb->addr, mac);
-				fdb->ndm_state = NUD_REACHABLE;
-				err = cb(&fdb->obj);
-				if (err)
-					stored_err = err;
-				break;
-			}
-		}
-	} while (num_rec == MLXSW_REG_SFD_REC_MAX_COUNT);
-
-out:
-	kfree(sfd_pl);
-	return stored_err ? stored_err : err;
-}
-
-static int mlxsw_sp_port_obj_dump(struct net_device *dev,
-				  struct switchdev_obj *obj,
-				  switchdev_obj_dump_cb_t *cb)
-{
-	struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
-	int err = 0;
-
-	switch (obj->id) {
-	case SWITCHDEV_OBJ_ID_PORT_FDB:
-		err = mlxsw_sp_port_fdb_dump(mlxsw_sp_port,
-					     SWITCHDEV_OBJ_PORT_FDB(obj), cb);
-		break;
-	default:
-		err = -EOPNOTSUPP;
-		break;
-	}
-
-	return err;
-}
-
 static const struct switchdev_ops mlxsw_sp_port_switchdev_ops = {
 	.switchdev_port_attr_get	= mlxsw_sp_port_attr_get,
 	.switchdev_port_attr_set	= mlxsw_sp_port_attr_set,
 	.switchdev_port_obj_add		= mlxsw_sp_port_obj_add,
 	.switchdev_port_obj_del		= mlxsw_sp_port_obj_del,
-	.switchdev_port_obj_dump	= mlxsw_sp_port_obj_dump,
 };
 
 static int
-- 
2.9.3

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

* [patch net-next 13/19] net: Remove support for bridge bypass ndos from stacked devices
  2017-06-05  9:20 [patch net-next 00/19] Remove support from bridge bypass for mlxsw/rocker drivers Jiri Pirko
                   ` (11 preceding siblings ...)
  2017-06-05  9:20 ` [patch net-next 12/19] mlxsw: spectrum: Remove support for bridge bypass FDB add/del Jiri Pirko
@ 2017-06-05  9:20 ` Jiri Pirko
  2017-06-05  9:20 ` [patch net-next 14/19] rocker: Remove support for bridge FDB learning sync Jiri Pirko
                   ` (6 subsequent siblings)
  19 siblings, 0 replies; 30+ messages in thread
From: Jiri Pirko @ 2017-06-05  9:20 UTC (permalink / raw)
  To: netdev; +Cc: davem, idosch, arkadis, mlxsw, roopa, stephen, ivecera

From: Arkadi Sharshevsky <arkadis@mellanox.com>

Remove support for bridge bypass ndos from stacked devices. At this point
no driver which supports stack device behavior offload supports operation
with SELF flag. The case for upper device is already taken care of in both
of the following cases:

1. FDB add/del - driver should check at the notification cb if the
                 stacked device contains his ports.

2. Port attribute - calls switchdev code directly which checks
                    for case of stack device.

Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com>
Reviewed-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 drivers/net/bonding/bond_main.c | 6 ------
 drivers/net/team/team.c         | 6 ------
 net/8021q/vlan_dev.c            | 6 ------
 3 files changed, 18 deletions(-)

diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index d4484d1..7d94743 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -4175,12 +4175,6 @@ static const struct net_device_ops bond_netdev_ops = {
 	.ndo_add_slave		= bond_enslave,
 	.ndo_del_slave		= bond_release,
 	.ndo_fix_features	= bond_fix_features,
-	.ndo_bridge_setlink	= switchdev_port_bridge_setlink,
-	.ndo_bridge_getlink	= switchdev_port_bridge_getlink,
-	.ndo_bridge_dellink	= switchdev_port_bridge_dellink,
-	.ndo_fdb_add		= switchdev_port_fdb_add,
-	.ndo_fdb_del		= switchdev_port_fdb_del,
-	.ndo_fdb_dump		= switchdev_port_fdb_dump,
 	.ndo_features_check	= passthru_features_check,
 };
 
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index 6c5d5ef..a3ec189 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -2005,12 +2005,6 @@ static const struct net_device_ops team_netdev_ops = {
 	.ndo_del_slave		= team_del_slave,
 	.ndo_fix_features	= team_fix_features,
 	.ndo_change_carrier     = team_change_carrier,
-	.ndo_bridge_setlink	= switchdev_port_bridge_setlink,
-	.ndo_bridge_getlink	= switchdev_port_bridge_getlink,
-	.ndo_bridge_dellink	= switchdev_port_bridge_dellink,
-	.ndo_fdb_add		= switchdev_port_fdb_add,
-	.ndo_fdb_del		= switchdev_port_fdb_del,
-	.ndo_fdb_dump		= switchdev_port_fdb_dump,
 	.ndo_features_check	= passthru_features_check,
 };
 
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 953b672..56d4b69 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -797,12 +797,6 @@ static const struct net_device_ops vlan_netdev_ops = {
 	.ndo_netpoll_cleanup	= vlan_dev_netpoll_cleanup,
 #endif
 	.ndo_fix_features	= vlan_dev_fix_features,
-	.ndo_fdb_add		= switchdev_port_fdb_add,
-	.ndo_fdb_del		= switchdev_port_fdb_del,
-	.ndo_fdb_dump		= switchdev_port_fdb_dump,
-	.ndo_bridge_setlink	= switchdev_port_bridge_setlink,
-	.ndo_bridge_getlink	= switchdev_port_bridge_getlink,
-	.ndo_bridge_dellink	= switchdev_port_bridge_dellink,
 	.ndo_get_lock_subclass  = vlan_dev_get_lock_subclass,
 	.ndo_get_iflink		= vlan_dev_get_iflink,
 };
-- 
2.9.3

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

* [patch net-next 14/19] rocker: Remove support for bridge FDB learning sync
  2017-06-05  9:20 [patch net-next 00/19] Remove support from bridge bypass for mlxsw/rocker drivers Jiri Pirko
                   ` (12 preceding siblings ...)
  2017-06-05  9:20 ` [patch net-next 13/19] net: Remove support for bridge bypass ndos from stacked devices Jiri Pirko
@ 2017-06-05  9:20 ` Jiri Pirko
  2017-06-05  9:20 ` [patch net-next 15/19] rocker: Add support for querying supported bridge flags Jiri Pirko
                   ` (5 subsequent siblings)
  19 siblings, 0 replies; 30+ messages in thread
From: Jiri Pirko @ 2017-06-05  9:20 UTC (permalink / raw)
  To: netdev; +Cc: davem, idosch, arkadis, mlxsw, roopa, stephen, ivecera

From: Arkadi Sharshevsky <arkadis@mellanox.com>

Currently the rocker driver supports an option for disabling syncing
the hardware learned FDBs with the software bridge. This behavior
breaks the bridge offload model and thus it is removed.

Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 drivers/net/ethernet/rocker/rocker_ofdpa.c | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/rocker/rocker_ofdpa.c b/drivers/net/ethernet/rocker/rocker_ofdpa.c
index f659dad..0b5a58f 100644
--- a/drivers/net/ethernet/rocker/rocker_ofdpa.c
+++ b/drivers/net/ethernet/rocker/rocker_ofdpa.c
@@ -1959,7 +1959,6 @@ static int ofdpa_port_fdb_learn(struct ofdpa_port *ofdpa_port,
 	u32 out_pport = ofdpa_port->pport;
 	u32 tunnel_id = 0;
 	u32 group_id = ROCKER_GROUP_NONE;
-	bool syncing = !!(ofdpa_port->brport_flags & BR_LEARNING_SYNC);
 	bool copy_to_cpu = false;
 	int err;
 
@@ -1974,9 +1973,6 @@ static int ofdpa_port_fdb_learn(struct ofdpa_port *ofdpa_port,
 			return err;
 	}
 
-	if (!syncing)
-		return 0;
-
 	if (!ofdpa_port_is_bridged(ofdpa_port))
 		return 0;
 
@@ -2550,7 +2546,7 @@ static int ofdpa_port_pre_init(struct rocker_port *rocker_port)
 	ofdpa_port->rocker_port = rocker_port;
 	ofdpa_port->dev = rocker_port->dev;
 	ofdpa_port->pport = rocker_port->pport;
-	ofdpa_port->brport_flags = BR_LEARNING | BR_LEARNING_SYNC;
+	ofdpa_port->brport_flags = BR_LEARNING;
 	ofdpa_port->ageing_time = BR_DEFAULT_AGEING_TIME;
 	return 0;
 }
-- 
2.9.3

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

* [patch net-next 15/19] rocker: Add support for querying supported bridge flags
  2017-06-05  9:20 [patch net-next 00/19] Remove support from bridge bypass for mlxsw/rocker drivers Jiri Pirko
                   ` (13 preceding siblings ...)
  2017-06-05  9:20 ` [patch net-next 14/19] rocker: Remove support for bridge FDB learning sync Jiri Pirko
@ 2017-06-05  9:20 ` Jiri Pirko
  2017-06-05  9:20 ` [patch net-next 16/19] rocker: Change world_ops API and implementation to be switchdev independant Jiri Pirko
                   ` (4 subsequent siblings)
  19 siblings, 0 replies; 30+ messages in thread
From: Jiri Pirko @ 2017-06-05  9:20 UTC (permalink / raw)
  To: netdev; +Cc: davem, idosch, arkadis, mlxsw, roopa, stephen, ivecera

From: Arkadi Sharshevsky <arkadis@mellanox.com>

Add support for querying supported bridge flags.

Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 drivers/net/ethernet/rocker/rocker.h       |  4 ++++
 drivers/net/ethernet/rocker/rocker_main.c  | 18 ++++++++++++++++++
 drivers/net/ethernet/rocker/rocker_ofdpa.c | 11 +++++++++++
 3 files changed, 33 insertions(+)

diff --git a/drivers/net/ethernet/rocker/rocker.h b/drivers/net/ethernet/rocker/rocker.h
index ee9675d..c25e331 100644
--- a/drivers/net/ethernet/rocker/rocker.h
+++ b/drivers/net/ethernet/rocker/rocker.h
@@ -112,6 +112,10 @@ struct rocker_world_ops {
 					  struct switchdev_trans *trans);
 	int (*port_attr_bridge_flags_get)(const struct rocker_port *rocker_port,
 					  unsigned long *p_brport_flags);
+	int (*port_attr_bridge_flags_support_get)(const struct rocker_port *
+						  rocker_port,
+						  unsigned long *
+						  p_brport_flags);
 	int (*port_attr_bridge_ageing_time_set)(struct rocker_port *rocker_port,
 						u32 ageing_time,
 						struct switchdev_trans *trans);
diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c
index bab1361..a741e51 100644
--- a/drivers/net/ethernet/rocker/rocker_main.c
+++ b/drivers/net/ethernet/rocker/rocker_main.c
@@ -1585,6 +1585,20 @@ rocker_world_port_attr_bridge_flags_get(const struct rocker_port *rocker_port,
 }
 
 static int
+rocker_world_port_attr_bridge_flags_support_get(const struct rocker_port *
+						rocker_port,
+						unsigned long *
+						p_brport_flags_support)
+{
+	struct rocker_world_ops *wops = rocker_port->rocker->wops;
+
+	if (!wops->port_attr_bridge_flags_support_get)
+		return -EOPNOTSUPP;
+	return wops->port_attr_bridge_flags_support_get(rocker_port,
+							p_brport_flags_support);
+}
+
+static int
 rocker_world_port_attr_bridge_ageing_time_set(struct rocker_port *rocker_port,
 					      u32 ageing_time,
 					      struct switchdev_trans *trans)
@@ -2053,6 +2067,10 @@ static int rocker_port_attr_get(struct net_device *dev,
 		err = rocker_world_port_attr_bridge_flags_get(rocker_port,
 							      &attr->u.brport_flags);
 		break;
+	case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT:
+		err = rocker_world_port_attr_bridge_flags_support_get(rocker_port,
+								      &attr->u.brport_flags_support);
+		break;
 	default:
 		return -EOPNOTSUPP;
 	}
diff --git a/drivers/net/ethernet/rocker/rocker_ofdpa.c b/drivers/net/ethernet/rocker/rocker_ofdpa.c
index 0b5a58f..7528ee7 100644
--- a/drivers/net/ethernet/rocker/rocker_ofdpa.c
+++ b/drivers/net/ethernet/rocker/rocker_ofdpa.c
@@ -2643,6 +2643,16 @@ ofdpa_port_attr_bridge_flags_get(const struct rocker_port *rocker_port,
 }
 
 static int
+ofdpa_port_attr_bridge_flags_support_get(const struct rocker_port *
+					 rocker_port,
+					 unsigned long *
+					 p_brport_flags_support)
+{
+	*p_brport_flags_support = BR_LEARNING;
+	return 0;
+}
+
+static int
 ofdpa_port_attr_bridge_ageing_time_set(struct rocker_port *rocker_port,
 				       u32 ageing_time,
 				       struct switchdev_trans *trans)
@@ -2989,6 +2999,7 @@ struct rocker_world_ops rocker_ofdpa_ops = {
 	.port_attr_stp_state_set = ofdpa_port_attr_stp_state_set,
 	.port_attr_bridge_flags_set = ofdpa_port_attr_bridge_flags_set,
 	.port_attr_bridge_flags_get = ofdpa_port_attr_bridge_flags_get,
+	.port_attr_bridge_flags_support_get = ofdpa_port_attr_bridge_flags_support_get,
 	.port_attr_bridge_ageing_time_set = ofdpa_port_attr_bridge_ageing_time_set,
 	.port_obj_vlan_add = ofdpa_port_obj_vlan_add,
 	.port_obj_vlan_del = ofdpa_port_obj_vlan_del,
-- 
2.9.3

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

* [patch net-next 16/19] rocker: Change world_ops API and implementation to be switchdev independant
  2017-06-05  9:20 [patch net-next 00/19] Remove support from bridge bypass for mlxsw/rocker drivers Jiri Pirko
                   ` (14 preceding siblings ...)
  2017-06-05  9:20 ` [patch net-next 15/19] rocker: Add support for querying supported bridge flags Jiri Pirko
@ 2017-06-05  9:20 ` Jiri Pirko
  2017-06-05  9:20 ` [patch net-next 17/19] rocker: Add support for learning FDB through notification Jiri Pirko
                   ` (3 subsequent siblings)
  19 siblings, 0 replies; 30+ messages in thread
From: Jiri Pirko @ 2017-06-05  9:20 UTC (permalink / raw)
  To: netdev; +Cc: davem, idosch, arkadis, mlxsw, roopa, stephen, ivecera

From: Arkadi Sharshevsky <arkadis@mellanox.com>

Currently the switchdev_trans struct is embedded in the world_ops API.
In order to add support for adding FDB via a notfication chain the API should
be switchdev independent.

Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 drivers/net/ethernet/rocker/rocker.h       |  11 +-
 drivers/net/ethernet/rocker/rocker_main.c  |  28 +-
 drivers/net/ethernet/rocker/rocker_ofdpa.c | 535 +++++++++++------------------
 3 files changed, 235 insertions(+), 339 deletions(-)

diff --git a/drivers/net/ethernet/rocker/rocker.h b/drivers/net/ethernet/rocker/rocker.h
index c25e331..a0f7782 100644
--- a/drivers/net/ethernet/rocker/rocker.h
+++ b/drivers/net/ethernet/rocker/rocker.h
@@ -105,8 +105,7 @@ struct rocker_world_ops {
 	int (*port_open)(struct rocker_port *rocker_port);
 	void (*port_stop)(struct rocker_port *rocker_port);
 	int (*port_attr_stp_state_set)(struct rocker_port *rocker_port,
-				       u8 state,
-				       struct switchdev_trans *trans);
+				       u8 state);
 	int (*port_attr_bridge_flags_set)(struct rocker_port *rocker_port,
 					  unsigned long brport_flags,
 					  struct switchdev_trans *trans);
@@ -120,18 +119,16 @@ struct rocker_world_ops {
 						u32 ageing_time,
 						struct switchdev_trans *trans);
 	int (*port_obj_vlan_add)(struct rocker_port *rocker_port,
-				 const struct switchdev_obj_port_vlan *vlan,
-				 struct switchdev_trans *trans);
+				 const struct switchdev_obj_port_vlan *vlan);
 	int (*port_obj_vlan_del)(struct rocker_port *rocker_port,
 				 const struct switchdev_obj_port_vlan *vlan);
 	int (*port_obj_vlan_dump)(const struct rocker_port *rocker_port,
 				  struct switchdev_obj_port_vlan *vlan,
 				  switchdev_obj_dump_cb_t *cb);
 	int (*port_obj_fdb_add)(struct rocker_port *rocker_port,
-				const struct switchdev_obj_port_fdb *fdb,
-				struct switchdev_trans *trans);
+				u16 vid, const unsigned char *addr);
 	int (*port_obj_fdb_del)(struct rocker_port *rocker_port,
-				const struct switchdev_obj_port_fdb *fdb);
+				u16 vid, const unsigned char *addr);
 	int (*port_obj_fdb_dump)(const struct rocker_port *rocker_port,
 				 struct switchdev_obj_port_fdb *fdb,
 				 switchdev_obj_dump_cb_t *cb);
diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c
index a741e51..9f0154d 100644
--- a/drivers/net/ethernet/rocker/rocker_main.c
+++ b/drivers/net/ethernet/rocker/rocker_main.c
@@ -1557,7 +1557,11 @@ static int rocker_world_port_attr_stp_state_set(struct rocker_port *rocker_port,
 
 	if (!wops->port_attr_stp_state_set)
 		return -EOPNOTSUPP;
-	return wops->port_attr_stp_state_set(rocker_port, state, trans);
+
+	if (switchdev_trans_ph_prepare(trans))
+		return 0;
+
+	return wops->port_attr_stp_state_set(rocker_port, state);
 }
 
 static int
@@ -1569,6 +1573,10 @@ rocker_world_port_attr_bridge_flags_set(struct rocker_port *rocker_port,
 
 	if (!wops->port_attr_bridge_flags_set)
 		return -EOPNOTSUPP;
+
+	if (switchdev_trans_ph_prepare(trans))
+		return 0;
+
 	return wops->port_attr_bridge_flags_set(rocker_port, brport_flags,
 						trans);
 }
@@ -1608,6 +1616,10 @@ rocker_world_port_attr_bridge_ageing_time_set(struct rocker_port *rocker_port,
 
 	if (!wops->port_attr_bridge_ageing_time_set)
 		return -EOPNOTSUPP;
+
+	if (switchdev_trans_ph_prepare(trans))
+		return 0;
+
 	return wops->port_attr_bridge_ageing_time_set(rocker_port, ageing_time,
 						      trans);
 }
@@ -1621,7 +1633,11 @@ rocker_world_port_obj_vlan_add(struct rocker_port *rocker_port,
 
 	if (!wops->port_obj_vlan_add)
 		return -EOPNOTSUPP;
-	return wops->port_obj_vlan_add(rocker_port, vlan, trans);
+
+	if (switchdev_trans_ph_prepare(trans))
+		return 0;
+
+	return wops->port_obj_vlan_add(rocker_port, vlan);
 }
 
 static int
@@ -1656,7 +1672,11 @@ rocker_world_port_obj_fdb_add(struct rocker_port *rocker_port,
 
 	if (!wops->port_obj_fdb_add)
 		return -EOPNOTSUPP;
-	return wops->port_obj_fdb_add(rocker_port, fdb, trans);
+
+	if (switchdev_trans_ph_prepare(trans))
+		return 0;
+
+	return wops->port_obj_fdb_add(rocker_port, fdb->vid, fdb->addr);
 }
 
 static int
@@ -1667,7 +1687,7 @@ rocker_world_port_obj_fdb_del(struct rocker_port *rocker_port,
 
 	if (!wops->port_obj_fdb_del)
 		return -EOPNOTSUPP;
-	return wops->port_obj_fdb_del(rocker_port, fdb);
+	return wops->port_obj_fdb_del(rocker_port, fdb->vid, fdb->addr);
 }
 
 static int
diff --git a/drivers/net/ethernet/rocker/rocker_ofdpa.c b/drivers/net/ethernet/rocker/rocker_ofdpa.c
index 7528ee7..184a478 100644
--- a/drivers/net/ethernet/rocker/rocker_ofdpa.c
+++ b/drivers/net/ethernet/rocker/rocker_ofdpa.c
@@ -300,64 +300,6 @@ static bool ofdpa_flags_nowait(int flags)
 	return flags & OFDPA_OP_FLAG_NOWAIT;
 }
 
-static void *__ofdpa_mem_alloc(struct switchdev_trans *trans, int flags,
-			       size_t size)
-{
-	struct switchdev_trans_item *elem = NULL;
-	gfp_t gfp_flags = (flags & OFDPA_OP_FLAG_NOWAIT) ?
-			  GFP_ATOMIC : GFP_KERNEL;
-
-	/* If in transaction prepare phase, allocate the memory
-	 * and enqueue it on a transaction.  If in transaction
-	 * commit phase, dequeue the memory from the transaction
-	 * rather than re-allocating the memory.  The idea is the
-	 * driver code paths for prepare and commit are identical
-	 * so the memory allocated in the prepare phase is the
-	 * memory used in the commit phase.
-	 */
-
-	if (!trans) {
-		elem = kzalloc(size + sizeof(*elem), gfp_flags);
-	} else if (switchdev_trans_ph_prepare(trans)) {
-		elem = kzalloc(size + sizeof(*elem), gfp_flags);
-		if (!elem)
-			return NULL;
-		switchdev_trans_item_enqueue(trans, elem, kfree, elem);
-	} else {
-		elem = switchdev_trans_item_dequeue(trans);
-	}
-
-	return elem ? elem + 1 : NULL;
-}
-
-static void *ofdpa_kzalloc(struct switchdev_trans *trans, int flags,
-			   size_t size)
-{
-	return __ofdpa_mem_alloc(trans, flags, size);
-}
-
-static void *ofdpa_kcalloc(struct switchdev_trans *trans, int flags,
-			   size_t n, size_t size)
-{
-	return __ofdpa_mem_alloc(trans, flags, n * size);
-}
-
-static void ofdpa_kfree(struct switchdev_trans *trans, const void *mem)
-{
-	struct switchdev_trans_item *elem;
-
-	/* Frees are ignored if in transaction prepare phase.  The
-	 * memory remains on the per-port list until freed in the
-	 * commit phase.
-	 */
-
-	if (switchdev_trans_ph_prepare(trans))
-		return;
-
-	elem = (struct switchdev_trans_item *) mem - 1;
-	kfree(elem);
-}
-
 /*************************************************************
  * Flow, group, FDB, internal VLAN and neigh command prepares
  *************************************************************/
@@ -815,8 +757,7 @@ ofdpa_flow_tbl_find(const struct ofdpa *ofdpa,
 }
 
 static int ofdpa_flow_tbl_add(struct ofdpa_port *ofdpa_port,
-			      struct switchdev_trans *trans, int flags,
-			      struct ofdpa_flow_tbl_entry *match)
+			      int flags, struct ofdpa_flow_tbl_entry *match)
 {
 	struct ofdpa *ofdpa = ofdpa_port->ofdpa;
 	struct ofdpa_flow_tbl_entry *found;
@@ -831,9 +772,8 @@ static int ofdpa_flow_tbl_add(struct ofdpa_port *ofdpa_port,
 
 	if (found) {
 		match->cookie = found->cookie;
-		if (!switchdev_trans_ph_prepare(trans))
-			hash_del(&found->entry);
-		ofdpa_kfree(trans, found);
+		hash_del(&found->entry);
+		kfree(found);
 		found = match;
 		found->cmd = ROCKER_TLV_CMD_TYPE_OF_DPA_FLOW_MOD;
 	} else {
@@ -842,22 +782,18 @@ static int ofdpa_flow_tbl_add(struct ofdpa_port *ofdpa_port,
 		found->cmd = ROCKER_TLV_CMD_TYPE_OF_DPA_FLOW_ADD;
 	}
 
-	if (!switchdev_trans_ph_prepare(trans))
-		hash_add(ofdpa->flow_tbl, &found->entry, found->key_crc32);
-
+	hash_add(ofdpa->flow_tbl, &found->entry, found->key_crc32);
 	spin_unlock_irqrestore(&ofdpa->flow_tbl_lock, lock_flags);
 
-	if (!switchdev_trans_ph_prepare(trans))
-		return rocker_cmd_exec(ofdpa_port->rocker_port,
-				       ofdpa_flags_nowait(flags),
-				       ofdpa_cmd_flow_tbl_add,
-				       found, NULL, NULL);
+	return rocker_cmd_exec(ofdpa_port->rocker_port,
+			       ofdpa_flags_nowait(flags),
+			       ofdpa_cmd_flow_tbl_add,
+			       found, NULL, NULL);
 	return 0;
 }
 
 static int ofdpa_flow_tbl_del(struct ofdpa_port *ofdpa_port,
-			      struct switchdev_trans *trans, int flags,
-			      struct ofdpa_flow_tbl_entry *match)
+			      int flags, struct ofdpa_flow_tbl_entry *match)
 {
 	struct ofdpa *ofdpa = ofdpa_port->ofdpa;
 	struct ofdpa_flow_tbl_entry *found;
@@ -872,45 +808,41 @@ static int ofdpa_flow_tbl_del(struct ofdpa_port *ofdpa_port,
 	found = ofdpa_flow_tbl_find(ofdpa, match);
 
 	if (found) {
-		if (!switchdev_trans_ph_prepare(trans))
-			hash_del(&found->entry);
+		hash_del(&found->entry);
 		found->cmd = ROCKER_TLV_CMD_TYPE_OF_DPA_FLOW_DEL;
 	}
 
 	spin_unlock_irqrestore(&ofdpa->flow_tbl_lock, lock_flags);
 
-	ofdpa_kfree(trans, match);
+	kfree(match);
 
 	if (found) {
-		if (!switchdev_trans_ph_prepare(trans))
-			err = rocker_cmd_exec(ofdpa_port->rocker_port,
-					      ofdpa_flags_nowait(flags),
-					      ofdpa_cmd_flow_tbl_del,
-					      found, NULL, NULL);
-		ofdpa_kfree(trans, found);
+		err = rocker_cmd_exec(ofdpa_port->rocker_port,
+				      ofdpa_flags_nowait(flags),
+				      ofdpa_cmd_flow_tbl_del,
+				      found, NULL, NULL);
+		kfree(found);
 	}
 
 	return err;
 }
 
-static int ofdpa_flow_tbl_do(struct ofdpa_port *ofdpa_port,
-			     struct switchdev_trans *trans, int flags,
+static int ofdpa_flow_tbl_do(struct ofdpa_port *ofdpa_port, int flags,
 			     struct ofdpa_flow_tbl_entry *entry)
 {
 	if (flags & OFDPA_OP_FLAG_REMOVE)
-		return ofdpa_flow_tbl_del(ofdpa_port, trans, flags, entry);
+		return ofdpa_flow_tbl_del(ofdpa_port, flags, entry);
 	else
-		return ofdpa_flow_tbl_add(ofdpa_port, trans, flags, entry);
+		return ofdpa_flow_tbl_add(ofdpa_port, flags, entry);
 }
 
-static int ofdpa_flow_tbl_ig_port(struct ofdpa_port *ofdpa_port,
-				  struct switchdev_trans *trans, int flags,
+static int ofdpa_flow_tbl_ig_port(struct ofdpa_port *ofdpa_port, int flags,
 				  u32 in_pport, u32 in_pport_mask,
 				  enum rocker_of_dpa_table_id goto_tbl)
 {
 	struct ofdpa_flow_tbl_entry *entry;
 
-	entry = ofdpa_kzalloc(trans, flags, sizeof(*entry));
+	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
 	if (!entry)
 		return -ENOMEM;
 
@@ -920,11 +852,11 @@ static int ofdpa_flow_tbl_ig_port(struct ofdpa_port *ofdpa_port,
 	entry->key.ig_port.in_pport_mask = in_pport_mask;
 	entry->key.ig_port.goto_tbl = goto_tbl;
 
-	return ofdpa_flow_tbl_do(ofdpa_port, trans, flags, entry);
+	return ofdpa_flow_tbl_do(ofdpa_port, flags, entry);
 }
 
 static int ofdpa_flow_tbl_vlan(struct ofdpa_port *ofdpa_port,
-			       struct switchdev_trans *trans, int flags,
+			       int flags,
 			       u32 in_pport, __be16 vlan_id,
 			       __be16 vlan_id_mask,
 			       enum rocker_of_dpa_table_id goto_tbl,
@@ -932,7 +864,7 @@ static int ofdpa_flow_tbl_vlan(struct ofdpa_port *ofdpa_port,
 {
 	struct ofdpa_flow_tbl_entry *entry;
 
-	entry = ofdpa_kzalloc(trans, flags, sizeof(*entry));
+	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
 	if (!entry)
 		return -ENOMEM;
 
@@ -946,11 +878,10 @@ static int ofdpa_flow_tbl_vlan(struct ofdpa_port *ofdpa_port,
 	entry->key.vlan.untagged = untagged;
 	entry->key.vlan.new_vlan_id = new_vlan_id;
 
-	return ofdpa_flow_tbl_do(ofdpa_port, trans, flags, entry);
+	return ofdpa_flow_tbl_do(ofdpa_port, flags, entry);
 }
 
 static int ofdpa_flow_tbl_term_mac(struct ofdpa_port *ofdpa_port,
-				   struct switchdev_trans *trans,
 				   u32 in_pport, u32 in_pport_mask,
 				   __be16 eth_type, const u8 *eth_dst,
 				   const u8 *eth_dst_mask, __be16 vlan_id,
@@ -959,7 +890,7 @@ static int ofdpa_flow_tbl_term_mac(struct ofdpa_port *ofdpa_port,
 {
 	struct ofdpa_flow_tbl_entry *entry;
 
-	entry = ofdpa_kzalloc(trans, flags, sizeof(*entry));
+	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
 	if (!entry)
 		return -ENOMEM;
 
@@ -983,13 +914,13 @@ static int ofdpa_flow_tbl_term_mac(struct ofdpa_port *ofdpa_port,
 	entry->key.term_mac.vlan_id_mask = vlan_id_mask;
 	entry->key.term_mac.copy_to_cpu = copy_to_cpu;
 
-	return ofdpa_flow_tbl_do(ofdpa_port, trans, flags, entry);
+	return ofdpa_flow_tbl_do(ofdpa_port, flags, entry);
 }
 
 static int ofdpa_flow_tbl_bridge(struct ofdpa_port *ofdpa_port,
-				 struct switchdev_trans *trans, int flags,
-				 const u8 *eth_dst, const u8 *eth_dst_mask,
-				 __be16 vlan_id, u32 tunnel_id,
+				 int flags, const u8 *eth_dst,
+				 const u8 *eth_dst_mask,  __be16 vlan_id,
+				 u32 tunnel_id,
 				 enum rocker_of_dpa_table_id goto_tbl,
 				 u32 group_id, bool copy_to_cpu)
 {
@@ -999,7 +930,7 @@ static int ofdpa_flow_tbl_bridge(struct ofdpa_port *ofdpa_port,
 	bool dflt = !eth_dst || (eth_dst && eth_dst_mask);
 	bool wild = false;
 
-	entry = ofdpa_kzalloc(trans, flags, sizeof(*entry));
+	entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
 	if (!entry)
 		return -ENOMEM;
 
@@ -1037,11 +968,10 @@ static int ofdpa_flow_tbl_bridge(struct ofdpa_port *ofdpa_port,
 	entry->key.bridge.group_id = group_id;
 	entry->key.bridge.copy_to_cpu = copy_to_cpu;
 
-	return ofdpa_flow_tbl_do(ofdpa_port, trans, flags, entry);
+	return ofdpa_flow_tbl_do(ofdpa_port, flags, entry);
 }
 
 static int ofdpa_flow_tbl_ucast4_routing(struct ofdpa_port *ofdpa_port,
-					 struct switchdev_trans *trans,
 					 __be16 eth_type, __be32 dst,
 					 __be32 dst_mask, u32 priority,
 					 enum rocker_of_dpa_table_id goto_tbl,
@@ -1050,7 +980,7 @@ static int ofdpa_flow_tbl_ucast4_routing(struct ofdpa_port *ofdpa_port,
 {
 	struct ofdpa_flow_tbl_entry *entry;
 
-	entry = ofdpa_kzalloc(trans, flags, sizeof(*entry));
+	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
 	if (!entry)
 		return -ENOMEM;
 
@@ -1065,11 +995,10 @@ static int ofdpa_flow_tbl_ucast4_routing(struct ofdpa_port *ofdpa_port,
 				  ucast_routing.group_id);
 	entry->fi = fi;
 
-	return ofdpa_flow_tbl_do(ofdpa_port, trans, flags, entry);
+	return ofdpa_flow_tbl_do(ofdpa_port, flags, entry);
 }
 
-static int ofdpa_flow_tbl_acl(struct ofdpa_port *ofdpa_port,
-			      struct switchdev_trans *trans, int flags,
+static int ofdpa_flow_tbl_acl(struct ofdpa_port *ofdpa_port, int flags,
 			      u32 in_pport, u32 in_pport_mask,
 			      const u8 *eth_src, const u8 *eth_src_mask,
 			      const u8 *eth_dst, const u8 *eth_dst_mask,
@@ -1081,7 +1010,7 @@ static int ofdpa_flow_tbl_acl(struct ofdpa_port *ofdpa_port,
 	u32 priority;
 	struct ofdpa_flow_tbl_entry *entry;
 
-	entry = ofdpa_kzalloc(trans, flags, sizeof(*entry));
+	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
 	if (!entry)
 		return -ENOMEM;
 
@@ -1116,7 +1045,7 @@ static int ofdpa_flow_tbl_acl(struct ofdpa_port *ofdpa_port,
 	entry->key.acl.ip_tos_mask = ip_tos_mask;
 	entry->key.acl.group_id = group_id;
 
-	return ofdpa_flow_tbl_do(ofdpa_port, trans, flags, entry);
+	return ofdpa_flow_tbl_do(ofdpa_port, flags, entry);
 }
 
 static struct ofdpa_group_tbl_entry *
@@ -1134,22 +1063,20 @@ ofdpa_group_tbl_find(const struct ofdpa *ofdpa,
 	return NULL;
 }
 
-static void ofdpa_group_tbl_entry_free(struct switchdev_trans *trans,
-				       struct ofdpa_group_tbl_entry *entry)
+static void ofdpa_group_tbl_entry_free(struct ofdpa_group_tbl_entry *entry)
 {
 	switch (ROCKER_GROUP_TYPE_GET(entry->group_id)) {
 	case ROCKER_OF_DPA_GROUP_TYPE_L2_FLOOD:
 	case ROCKER_OF_DPA_GROUP_TYPE_L2_MCAST:
-		ofdpa_kfree(trans, entry->group_ids);
+		kfree(entry->group_ids);
 		break;
 	default:
 		break;
 	}
-	ofdpa_kfree(trans, entry);
+	kfree(entry);
 }
 
-static int ofdpa_group_tbl_add(struct ofdpa_port *ofdpa_port,
-			       struct switchdev_trans *trans, int flags,
+static int ofdpa_group_tbl_add(struct ofdpa_port *ofdpa_port, int flags,
 			       struct ofdpa_group_tbl_entry *match)
 {
 	struct ofdpa *ofdpa = ofdpa_port->ofdpa;
@@ -1161,9 +1088,8 @@ static int ofdpa_group_tbl_add(struct ofdpa_port *ofdpa_port,
 	found = ofdpa_group_tbl_find(ofdpa, match);
 
 	if (found) {
-		if (!switchdev_trans_ph_prepare(trans))
-			hash_del(&found->entry);
-		ofdpa_group_tbl_entry_free(trans, found);
+		hash_del(&found->entry);
+		ofdpa_group_tbl_entry_free(found);
 		found = match;
 		found->cmd = ROCKER_TLV_CMD_TYPE_OF_DPA_GROUP_MOD;
 	} else {
@@ -1171,21 +1097,17 @@ static int ofdpa_group_tbl_add(struct ofdpa_port *ofdpa_port,
 		found->cmd = ROCKER_TLV_CMD_TYPE_OF_DPA_GROUP_ADD;
 	}
 
-	if (!switchdev_trans_ph_prepare(trans))
-		hash_add(ofdpa->group_tbl, &found->entry, found->group_id);
+	hash_add(ofdpa->group_tbl, &found->entry, found->group_id);
 
 	spin_unlock_irqrestore(&ofdpa->group_tbl_lock, lock_flags);
 
-	if (!switchdev_trans_ph_prepare(trans))
-		return rocker_cmd_exec(ofdpa_port->rocker_port,
-				       ofdpa_flags_nowait(flags),
-				       ofdpa_cmd_group_tbl_add,
-				       found, NULL, NULL);
-	return 0;
+	return rocker_cmd_exec(ofdpa_port->rocker_port,
+			       ofdpa_flags_nowait(flags),
+			       ofdpa_cmd_group_tbl_add,
+			       found, NULL, NULL);
 }
 
-static int ofdpa_group_tbl_del(struct ofdpa_port *ofdpa_port,
-			       struct switchdev_trans *trans, int flags,
+static int ofdpa_group_tbl_del(struct ofdpa_port *ofdpa_port, int flags,
 			       struct ofdpa_group_tbl_entry *match)
 {
 	struct ofdpa *ofdpa = ofdpa_port->ofdpa;
@@ -1198,97 +1120,90 @@ static int ofdpa_group_tbl_del(struct ofdpa_port *ofdpa_port,
 	found = ofdpa_group_tbl_find(ofdpa, match);
 
 	if (found) {
-		if (!switchdev_trans_ph_prepare(trans))
-			hash_del(&found->entry);
+		hash_del(&found->entry);
 		found->cmd = ROCKER_TLV_CMD_TYPE_OF_DPA_GROUP_DEL;
 	}
 
 	spin_unlock_irqrestore(&ofdpa->group_tbl_lock, lock_flags);
 
-	ofdpa_group_tbl_entry_free(trans, match);
+	ofdpa_group_tbl_entry_free(match);
 
 	if (found) {
-		if (!switchdev_trans_ph_prepare(trans))
-			err = rocker_cmd_exec(ofdpa_port->rocker_port,
-					      ofdpa_flags_nowait(flags),
-					      ofdpa_cmd_group_tbl_del,
-					      found, NULL, NULL);
-		ofdpa_group_tbl_entry_free(trans, found);
+		err = rocker_cmd_exec(ofdpa_port->rocker_port,
+				      ofdpa_flags_nowait(flags),
+				      ofdpa_cmd_group_tbl_del,
+				      found, NULL, NULL);
+		ofdpa_group_tbl_entry_free(found);
 	}
 
 	return err;
 }
 
-static int ofdpa_group_tbl_do(struct ofdpa_port *ofdpa_port,
-			      struct switchdev_trans *trans, int flags,
+static int ofdpa_group_tbl_do(struct ofdpa_port *ofdpa_port, int flags,
 			      struct ofdpa_group_tbl_entry *entry)
 {
 	if (flags & OFDPA_OP_FLAG_REMOVE)
-		return ofdpa_group_tbl_del(ofdpa_port, trans, flags, entry);
+		return ofdpa_group_tbl_del(ofdpa_port, flags, entry);
 	else
-		return ofdpa_group_tbl_add(ofdpa_port, trans, flags, entry);
+		return ofdpa_group_tbl_add(ofdpa_port, flags, entry);
 }
 
 static int ofdpa_group_l2_interface(struct ofdpa_port *ofdpa_port,
-				    struct switchdev_trans *trans, int flags,
-				    __be16 vlan_id, u32 out_pport,
-				    int pop_vlan)
+				    int flags, __be16 vlan_id,
+				    u32 out_pport, int pop_vlan)
 {
 	struct ofdpa_group_tbl_entry *entry;
 
-	entry = ofdpa_kzalloc(trans, flags, sizeof(*entry));
+	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
 	if (!entry)
 		return -ENOMEM;
 
 	entry->group_id = ROCKER_GROUP_L2_INTERFACE(vlan_id, out_pport);
 	entry->l2_interface.pop_vlan = pop_vlan;
 
-	return ofdpa_group_tbl_do(ofdpa_port, trans, flags, entry);
+	return ofdpa_group_tbl_do(ofdpa_port, flags, entry);
 }
 
 static int ofdpa_group_l2_fan_out(struct ofdpa_port *ofdpa_port,
-				  struct switchdev_trans *trans,
 				  int flags, u8 group_count,
 				  const u32 *group_ids, u32 group_id)
 {
 	struct ofdpa_group_tbl_entry *entry;
 
-	entry = ofdpa_kzalloc(trans, flags, sizeof(*entry));
+	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
 	if (!entry)
 		return -ENOMEM;
 
 	entry->group_id = group_id;
 	entry->group_count = group_count;
 
-	entry->group_ids = ofdpa_kcalloc(trans, flags,
-					 group_count, sizeof(u32));
+	entry->group_ids = kcalloc(flags, group_count, sizeof(u32));
 	if (!entry->group_ids) {
-		ofdpa_kfree(trans, entry);
+		kfree(entry);
 		return -ENOMEM;
 	}
 	memcpy(entry->group_ids, group_ids, group_count * sizeof(u32));
 
-	return ofdpa_group_tbl_do(ofdpa_port, trans, flags, entry);
+	return ofdpa_group_tbl_do(ofdpa_port, flags, entry);
 }
 
 static int ofdpa_group_l2_flood(struct ofdpa_port *ofdpa_port,
-				struct switchdev_trans *trans, int flags,
-				__be16 vlan_id, u8 group_count,
-				const u32 *group_ids, u32 group_id)
+				int flags, __be16 vlan_id,
+				u8 group_count,	const u32 *group_ids,
+				u32 group_id)
 {
-	return ofdpa_group_l2_fan_out(ofdpa_port, trans, flags,
+	return ofdpa_group_l2_fan_out(ofdpa_port, flags,
 				      group_count, group_ids,
 				      group_id);
 }
 
-static int ofdpa_group_l3_unicast(struct ofdpa_port *ofdpa_port,
-				  struct switchdev_trans *trans, int flags,
+static int ofdpa_group_l3_unicast(struct ofdpa_port *ofdpa_port, int flags,
 				  u32 index, const u8 *src_mac, const u8 *dst_mac,
 				  __be16 vlan_id, bool ttl_check, u32 pport)
 {
 	struct ofdpa_group_tbl_entry *entry;
 
-	entry = ofdpa_kzalloc(trans, flags, sizeof(*entry));
+	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
 	if (!entry)
 		return -ENOMEM;
 
@@ -1301,7 +1216,7 @@ static int ofdpa_group_l3_unicast(struct ofdpa_port *ofdpa_port,
 	entry->l3_unicast.ttl_check = ttl_check;
 	entry->l3_unicast.group_id = ROCKER_GROUP_L2_INTERFACE(vlan_id, pport);
 
-	return ofdpa_group_tbl_do(ofdpa_port, trans, flags, entry);
+	return ofdpa_group_tbl_do(ofdpa_port, flags, entry);
 }
 
 static struct ofdpa_neigh_tbl_entry *
@@ -1318,43 +1233,34 @@ ofdpa_neigh_tbl_find(const struct ofdpa *ofdpa, __be32 ip_addr)
 }
 
 static void ofdpa_neigh_add(struct ofdpa *ofdpa,
-			    struct switchdev_trans *trans,
 			    struct ofdpa_neigh_tbl_entry *entry)
 {
-	if (!switchdev_trans_ph_commit(trans))
-		entry->index = ofdpa->neigh_tbl_next_index++;
-	if (switchdev_trans_ph_prepare(trans))
-		return;
+	entry->index = ofdpa->neigh_tbl_next_index++;
 	entry->ref_count++;
 	hash_add(ofdpa->neigh_tbl, &entry->entry,
 		 be32_to_cpu(entry->ip_addr));
 }
 
-static void ofdpa_neigh_del(struct switchdev_trans *trans,
-			    struct ofdpa_neigh_tbl_entry *entry)
+static void ofdpa_neigh_del(struct ofdpa_neigh_tbl_entry *entry)
 {
-	if (switchdev_trans_ph_prepare(trans))
-		return;
 	if (--entry->ref_count == 0) {
 		hash_del(&entry->entry);
-		ofdpa_kfree(trans, entry);
+		kfree(entry);
 	}
 }
 
 static void ofdpa_neigh_update(struct ofdpa_neigh_tbl_entry *entry,
-			       struct switchdev_trans *trans,
 			       const u8 *eth_dst, bool ttl_check)
 {
 	if (eth_dst) {
 		ether_addr_copy(entry->eth_dst, eth_dst);
 		entry->ttl_check = ttl_check;
-	} else if (!switchdev_trans_ph_prepare(trans)) {
+	} else {
 		entry->ref_count++;
 	}
 }
 
 static int ofdpa_port_ipv4_neigh(struct ofdpa_port *ofdpa_port,
-				 struct switchdev_trans *trans,
 				 int flags, __be32 ip_addr, const u8 *eth_dst)
 {
 	struct ofdpa *ofdpa = ofdpa_port->ofdpa;
@@ -1371,7 +1277,7 @@ static int ofdpa_port_ipv4_neigh(struct ofdpa_port *ofdpa_port,
 	bool removing;
 	int err = 0;
 
-	entry = ofdpa_kzalloc(trans, flags, sizeof(*entry));
+	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
 	if (!entry)
 		return -ENOMEM;
 
@@ -1388,12 +1294,12 @@ static int ofdpa_port_ipv4_neigh(struct ofdpa_port *ofdpa_port,
 		entry->dev = ofdpa_port->dev;
 		ether_addr_copy(entry->eth_dst, eth_dst);
 		entry->ttl_check = true;
-		ofdpa_neigh_add(ofdpa, trans, entry);
+		ofdpa_neigh_add(ofdpa, entry);
 	} else if (removing) {
 		memcpy(entry, found, sizeof(*entry));
-		ofdpa_neigh_del(trans, found);
+		ofdpa_neigh_del(found);
 	} else if (updating) {
-		ofdpa_neigh_update(found, trans, eth_dst, true);
+		ofdpa_neigh_update(found, eth_dst, true);
 		memcpy(entry, found, sizeof(*entry));
 	} else {
 		err = -ENOENT;
@@ -1410,7 +1316,7 @@ static int ofdpa_port_ipv4_neigh(struct ofdpa_port *ofdpa_port,
 	 * other routes' nexthops.
 	 */
 
-	err = ofdpa_group_l3_unicast(ofdpa_port, trans, flags,
+	err = ofdpa_group_l3_unicast(ofdpa_port, flags,
 				     entry->index,
 				     ofdpa_port->dev->dev_addr,
 				     entry->eth_dst,
@@ -1425,7 +1331,7 @@ static int ofdpa_port_ipv4_neigh(struct ofdpa_port *ofdpa_port,
 
 	if (adding || removing) {
 		group_id = ROCKER_GROUP_L3_UNICAST(entry->index);
-		err = ofdpa_flow_tbl_ucast4_routing(ofdpa_port, trans,
+		err = ofdpa_flow_tbl_ucast4_routing(ofdpa_port,
 						    eth_type, ip_addr,
 						    inet_make_mask(32),
 						    priority, goto_tbl,
@@ -1438,13 +1344,12 @@ static int ofdpa_port_ipv4_neigh(struct ofdpa_port *ofdpa_port,
 
 err_out:
 	if (!adding)
-		ofdpa_kfree(trans, entry);
+		kfree(entry);
 
 	return err;
 }
 
 static int ofdpa_port_ipv4_resolve(struct ofdpa_port *ofdpa_port,
-				   struct switchdev_trans *trans,
 				   __be32 ip_addr)
 {
 	struct net_device *dev = ofdpa_port->dev;
@@ -1463,7 +1368,7 @@ static int ofdpa_port_ipv4_resolve(struct ofdpa_port *ofdpa_port,
 	 */
 
 	if (n->nud_state & NUD_VALID)
-		err = ofdpa_port_ipv4_neigh(ofdpa_port, trans, 0,
+		err = ofdpa_port_ipv4_neigh(ofdpa_port, 0,
 					    ip_addr, n->ha);
 	else
 		neigh_event_send(n, NULL);
@@ -1473,8 +1378,7 @@ static int ofdpa_port_ipv4_resolve(struct ofdpa_port *ofdpa_port,
 }
 
 static int ofdpa_port_ipv4_nh(struct ofdpa_port *ofdpa_port,
-			      struct switchdev_trans *trans, int flags,
-			      __be32 ip_addr, u32 *index)
+			      int flags, __be32 ip_addr, u32 *index)
 {
 	struct ofdpa *ofdpa = ofdpa_port->ofdpa;
 	struct ofdpa_neigh_tbl_entry *entry;
@@ -1486,7 +1390,7 @@ static int ofdpa_port_ipv4_nh(struct ofdpa_port *ofdpa_port,
 	bool resolved = true;
 	int err = 0;
 
-	entry = ofdpa_kzalloc(trans, flags, sizeof(*entry));
+	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
 	if (!entry)
 		return -ENOMEM;
 
@@ -1501,14 +1405,14 @@ static int ofdpa_port_ipv4_nh(struct ofdpa_port *ofdpa_port,
 	if (adding) {
 		entry->ip_addr = ip_addr;
 		entry->dev = ofdpa_port->dev;
-		ofdpa_neigh_add(ofdpa, trans, entry);
+		ofdpa_neigh_add(ofdpa, entry);
 		*index = entry->index;
 		resolved = false;
 	} else if (removing) {
-		ofdpa_neigh_del(trans, found);
+		ofdpa_neigh_del(found);
 		*index = found->index;
 	} else if (updating) {
-		ofdpa_neigh_update(found, trans, NULL, false);
+		ofdpa_neigh_update(found, NULL, false);
 		resolved = !is_zero_ether_addr(found->eth_dst);
 		*index = found->index;
 	} else {
@@ -1518,7 +1422,7 @@ static int ofdpa_port_ipv4_nh(struct ofdpa_port *ofdpa_port,
 	spin_unlock_irqrestore(&ofdpa->neigh_tbl_lock, lock_flags);
 
 	if (!adding)
-		ofdpa_kfree(trans, entry);
+		kfree(entry);
 
 	if (err)
 		return err;
@@ -1526,7 +1430,7 @@ static int ofdpa_port_ipv4_nh(struct ofdpa_port *ofdpa_port,
 	/* Resolved means neigh ip_addr is resolved to neigh mac. */
 
 	if (!resolved)
-		err = ofdpa_port_ipv4_resolve(ofdpa_port, trans, ip_addr);
+		err = ofdpa_port_ipv4_resolve(ofdpa_port, ip_addr);
 
 	return err;
 }
@@ -1541,7 +1445,6 @@ static struct ofdpa_port *ofdpa_port_get(const struct ofdpa *ofdpa,
 }
 
 static int ofdpa_port_vlan_flood_group(struct ofdpa_port *ofdpa_port,
-				       struct switchdev_trans *trans,
 				       int flags, __be16 vlan_id)
 {
 	struct ofdpa_port *p;
@@ -1553,7 +1456,7 @@ static int ofdpa_port_vlan_flood_group(struct ofdpa_port *ofdpa_port,
 	int err = 0;
 	int i;
 
-	group_ids = ofdpa_kcalloc(trans, flags, port_count, sizeof(u32));
+	group_ids = kcalloc(flags, port_count, sizeof(u32));
 	if (!group_ids)
 		return -ENOMEM;
 
@@ -1578,18 +1481,17 @@ static int ofdpa_port_vlan_flood_group(struct ofdpa_port *ofdpa_port,
 	if (group_count == 0)
 		goto no_ports_in_vlan;
 
-	err = ofdpa_group_l2_flood(ofdpa_port, trans, flags, vlan_id,
+	err = ofdpa_group_l2_flood(ofdpa_port, flags, vlan_id,
 				   group_count, group_ids, group_id);
 	if (err)
 		netdev_err(ofdpa_port->dev, "Error (%d) port VLAN l2 flood group\n", err);
 
 no_ports_in_vlan:
-	ofdpa_kfree(trans, group_ids);
+	kfree(group_ids);
 	return err;
 }
 
-static int ofdpa_port_vlan_l2_groups(struct ofdpa_port *ofdpa_port,
-				     struct switchdev_trans *trans, int flags,
+static int ofdpa_port_vlan_l2_groups(struct ofdpa_port *ofdpa_port, int flags,
 				     __be16 vlan_id, bool pop_vlan)
 {
 	const struct ofdpa *ofdpa = ofdpa_port->ofdpa;
@@ -1608,7 +1510,7 @@ static int ofdpa_port_vlan_l2_groups(struct ofdpa_port *ofdpa_port,
 	if (ofdpa_port->stp_state == BR_STATE_LEARNING ||
 	    ofdpa_port->stp_state == BR_STATE_FORWARDING) {
 		out_pport = ofdpa_port->pport;
-		err = ofdpa_group_l2_interface(ofdpa_port, trans, flags,
+		err = ofdpa_group_l2_interface(ofdpa_port, flags,
 					       vlan_id, out_pport, pop_vlan);
 		if (err) {
 			netdev_err(ofdpa_port->dev, "Error (%d) port VLAN l2 group for pport %d\n",
@@ -1632,7 +1534,7 @@ static int ofdpa_port_vlan_l2_groups(struct ofdpa_port *ofdpa_port,
 		return 0;
 
 	out_pport = 0;
-	err = ofdpa_group_l2_interface(ofdpa_port, trans, flags,
+	err = ofdpa_group_l2_interface(ofdpa_port, flags,
 				       vlan_id, out_pport, pop_vlan);
 	if (err) {
 		netdev_err(ofdpa_port->dev, "Error (%d) port VLAN l2 group for CPU port\n", err);
@@ -1693,8 +1595,7 @@ static struct ofdpa_ctrl {
 	},
 };
 
-static int ofdpa_port_ctrl_vlan_acl(struct ofdpa_port *ofdpa_port,
-				    struct switchdev_trans *trans, int flags,
+static int ofdpa_port_ctrl_vlan_acl(struct ofdpa_port *ofdpa_port, int flags,
 				    const struct ofdpa_ctrl *ctrl, __be16 vlan_id)
 {
 	u32 in_pport = ofdpa_port->pport;
@@ -1710,7 +1611,7 @@ static int ofdpa_port_ctrl_vlan_acl(struct ofdpa_port *ofdpa_port,
 	u32 group_id = ROCKER_GROUP_L2_INTERFACE(vlan_id, out_pport);
 	int err;
 
-	err = ofdpa_flow_tbl_acl(ofdpa_port, trans, flags,
+	err = ofdpa_flow_tbl_acl(ofdpa_port, flags,
 				 in_pport, in_pport_mask,
 				 eth_src, eth_src_mask,
 				 ctrl->eth_dst, ctrl->eth_dst_mask,
@@ -1727,9 +1628,7 @@ static int ofdpa_port_ctrl_vlan_acl(struct ofdpa_port *ofdpa_port,
 }
 
 static int ofdpa_port_ctrl_vlan_bridge(struct ofdpa_port *ofdpa_port,
-				       struct switchdev_trans *trans,
-				       int flags,
-				       const struct ofdpa_ctrl *ctrl,
+				       int flags, const struct ofdpa_ctrl *ctrl,
 				       __be16 vlan_id)
 {
 	enum rocker_of_dpa_table_id goto_tbl =
@@ -1741,7 +1640,7 @@ static int ofdpa_port_ctrl_vlan_bridge(struct ofdpa_port *ofdpa_port,
 	if (!ofdpa_port_is_bridged(ofdpa_port))
 		return 0;
 
-	err = ofdpa_flow_tbl_bridge(ofdpa_port, trans, flags,
+	err = ofdpa_flow_tbl_bridge(ofdpa_port, flags,
 				    ctrl->eth_dst, ctrl->eth_dst_mask,
 				    vlan_id, tunnel_id,
 				    goto_tbl, group_id, ctrl->copy_to_cpu);
@@ -1752,8 +1651,7 @@ static int ofdpa_port_ctrl_vlan_bridge(struct ofdpa_port *ofdpa_port,
 	return err;
 }
 
-static int ofdpa_port_ctrl_vlan_term(struct ofdpa_port *ofdpa_port,
-				     struct switchdev_trans *trans, int flags,
+static int ofdpa_port_ctrl_vlan_term(struct ofdpa_port *ofdpa_port, int flags,
 				     const struct ofdpa_ctrl *ctrl, __be16 vlan_id)
 {
 	u32 in_pport_mask = 0xffffffff;
@@ -1763,8 +1661,7 @@ static int ofdpa_port_ctrl_vlan_term(struct ofdpa_port *ofdpa_port,
 	if (ntohs(vlan_id) == 0)
 		vlan_id = ofdpa_port->internal_vlan_id;
 
-	err = ofdpa_flow_tbl_term_mac(ofdpa_port, trans,
-				      ofdpa_port->pport, in_pport_mask,
+	err = ofdpa_flow_tbl_term_mac(ofdpa_port, ofdpa_port->pport, in_pport_mask,
 				      ctrl->eth_type, ctrl->eth_dst,
 				      ctrl->eth_dst_mask, vlan_id,
 				      vlan_id_mask, ctrl->copy_to_cpu,
@@ -1776,26 +1673,24 @@ static int ofdpa_port_ctrl_vlan_term(struct ofdpa_port *ofdpa_port,
 	return err;
 }
 
-static int ofdpa_port_ctrl_vlan(struct ofdpa_port *ofdpa_port,
-				struct switchdev_trans *trans, int flags,
+static int ofdpa_port_ctrl_vlan(struct ofdpa_port *ofdpa_port, int flags,
 				const struct ofdpa_ctrl *ctrl, __be16 vlan_id)
 {
 	if (ctrl->acl)
-		return ofdpa_port_ctrl_vlan_acl(ofdpa_port, trans, flags,
+		return ofdpa_port_ctrl_vlan_acl(ofdpa_port, flags,
 						ctrl, vlan_id);
 	if (ctrl->bridge)
-		return ofdpa_port_ctrl_vlan_bridge(ofdpa_port, trans, flags,
+		return ofdpa_port_ctrl_vlan_bridge(ofdpa_port, flags,
 						   ctrl, vlan_id);
 
 	if (ctrl->term)
-		return ofdpa_port_ctrl_vlan_term(ofdpa_port, trans, flags,
+		return ofdpa_port_ctrl_vlan_term(ofdpa_port, flags,
 						 ctrl, vlan_id);
 
 	return -EOPNOTSUPP;
 }
 
-static int ofdpa_port_ctrl_vlan_add(struct ofdpa_port *ofdpa_port,
-				    struct switchdev_trans *trans, int flags,
+static int ofdpa_port_ctrl_vlan_add(struct ofdpa_port *ofdpa_port, int flags,
 				    __be16 vlan_id)
 {
 	int err = 0;
@@ -1803,7 +1698,7 @@ static int ofdpa_port_ctrl_vlan_add(struct ofdpa_port *ofdpa_port,
 
 	for (i = 0; i < OFDPA_CTRL_MAX; i++) {
 		if (ofdpa_port->ctrls[i]) {
-			err = ofdpa_port_ctrl_vlan(ofdpa_port, trans, flags,
+			err = ofdpa_port_ctrl_vlan(ofdpa_port, flags,
 						   &ofdpa_ctrls[i], vlan_id);
 			if (err)
 				return err;
@@ -1813,8 +1708,7 @@ static int ofdpa_port_ctrl_vlan_add(struct ofdpa_port *ofdpa_port,
 	return err;
 }
 
-static int ofdpa_port_ctrl(struct ofdpa_port *ofdpa_port,
-			   struct switchdev_trans *trans, int flags,
+static int ofdpa_port_ctrl(struct ofdpa_port *ofdpa_port, int flags,
 			   const struct ofdpa_ctrl *ctrl)
 {
 	u16 vid;
@@ -1823,7 +1717,7 @@ static int ofdpa_port_ctrl(struct ofdpa_port *ofdpa_port,
 	for (vid = 1; vid < VLAN_N_VID; vid++) {
 		if (!test_bit(vid, ofdpa_port->vlan_bitmap))
 			continue;
-		err = ofdpa_port_ctrl_vlan(ofdpa_port, trans, flags,
+		err = ofdpa_port_ctrl_vlan(ofdpa_port, flags,
 					   ctrl, htons(vid));
 		if (err)
 			break;
@@ -1832,8 +1726,8 @@ static int ofdpa_port_ctrl(struct ofdpa_port *ofdpa_port,
 	return err;
 }
 
-static int ofdpa_port_vlan(struct ofdpa_port *ofdpa_port,
-			   struct switchdev_trans *trans, int flags, u16 vid)
+static int ofdpa_port_vlan(struct ofdpa_port *ofdpa_port, int flags,
+			   u16 vid)
 {
 	enum rocker_of_dpa_table_id goto_tbl =
 			ROCKER_OF_DPA_TABLE_ID_TERMINATION_MAC;
@@ -1857,43 +1751,44 @@ static int ofdpa_port_vlan(struct ofdpa_port *ofdpa_port,
 	change_bit(ntohs(internal_vlan_id), ofdpa_port->vlan_bitmap);
 
 	if (adding) {
-		err = ofdpa_port_ctrl_vlan_add(ofdpa_port, trans, flags,
+		err = ofdpa_port_ctrl_vlan_add(ofdpa_port, flags,
 					       internal_vlan_id);
 		if (err) {
 			netdev_err(ofdpa_port->dev, "Error (%d) port ctrl vlan add\n", err);
-			goto err_out;
+			goto err_vlan_add;
 		}
 	}
 
-	err = ofdpa_port_vlan_l2_groups(ofdpa_port, trans, flags,
+	err = ofdpa_port_vlan_l2_groups(ofdpa_port, flags,
 					internal_vlan_id, untagged);
 	if (err) {
 		netdev_err(ofdpa_port->dev, "Error (%d) port VLAN l2 groups\n", err);
-		goto err_out;
+		goto err_vlan_l2_groups;
 	}
 
-	err = ofdpa_port_vlan_flood_group(ofdpa_port, trans, flags,
+	err = ofdpa_port_vlan_flood_group(ofdpa_port, flags,
 					  internal_vlan_id);
 	if (err) {
 		netdev_err(ofdpa_port->dev, "Error (%d) port VLAN l2 flood group\n", err);
-		goto err_out;
+		goto err_flood_group;
 	}
 
-	err = ofdpa_flow_tbl_vlan(ofdpa_port, trans, flags,
+	err = ofdpa_flow_tbl_vlan(ofdpa_port, flags,
 				  in_pport, vlan_id, vlan_id_mask,
 				  goto_tbl, untagged, internal_vlan_id);
 	if (err)
 		netdev_err(ofdpa_port->dev, "Error (%d) port VLAN table\n", err);
 
-err_out:
-	if (switchdev_trans_ph_prepare(trans))
-		change_bit(ntohs(internal_vlan_id), ofdpa_port->vlan_bitmap);
+	return 0;
 
+err_vlan_add:
+err_vlan_l2_groups:
+err_flood_group:
+	change_bit(ntohs(internal_vlan_id), ofdpa_port->vlan_bitmap);
 	return err;
 }
 
-static int ofdpa_port_ig_tbl(struct ofdpa_port *ofdpa_port,
-			     struct switchdev_trans *trans, int flags)
+static int ofdpa_port_ig_tbl(struct ofdpa_port *ofdpa_port, int flags)
 {
 	enum rocker_of_dpa_table_id goto_tbl;
 	u32 in_pport;
@@ -1908,7 +1803,7 @@ static int ofdpa_port_ig_tbl(struct ofdpa_port *ofdpa_port,
 	in_pport_mask = 0xffff0000;
 	goto_tbl = ROCKER_OF_DPA_TABLE_ID_VLAN;
 
-	err = ofdpa_flow_tbl_ig_port(ofdpa_port, trans, flags,
+	err = ofdpa_flow_tbl_ig_port(ofdpa_port, flags,
 				     in_pport, in_pport_mask,
 				     goto_tbl);
 	if (err)
@@ -1920,7 +1815,6 @@ static int ofdpa_port_ig_tbl(struct ofdpa_port *ofdpa_port,
 struct ofdpa_fdb_learn_work {
 	struct work_struct work;
 	struct ofdpa_port *ofdpa_port;
-	struct switchdev_trans *trans;
 	int flags;
 	u8 addr[ETH_ALEN];
 	u16 vid;
@@ -1946,12 +1840,11 @@ static void ofdpa_port_fdb_learn_work(struct work_struct *work)
 					 lw->ofdpa_port->dev, &info.info);
 	rtnl_unlock();
 
-	ofdpa_kfree(lw->trans, work);
+	kfree(work);
 }
 
 static int ofdpa_port_fdb_learn(struct ofdpa_port *ofdpa_port,
-				struct switchdev_trans *trans, int flags,
-				const u8 *addr, __be16 vlan_id)
+				int flags, const u8 *addr, __be16 vlan_id)
 {
 	struct ofdpa_fdb_learn_work *lw;
 	enum rocker_of_dpa_table_id goto_tbl =
@@ -1966,7 +1859,7 @@ static int ofdpa_port_fdb_learn(struct ofdpa_port *ofdpa_port,
 		group_id = ROCKER_GROUP_L2_INTERFACE(vlan_id, out_pport);
 
 	if (!(flags & OFDPA_OP_FLAG_REFRESH)) {
-		err = ofdpa_flow_tbl_bridge(ofdpa_port, trans, flags, addr,
+		err = ofdpa_flow_tbl_bridge(ofdpa_port, flags, addr,
 					    NULL, vlan_id, tunnel_id, goto_tbl,
 					    group_id, copy_to_cpu);
 		if (err)
@@ -1976,23 +1869,18 @@ static int ofdpa_port_fdb_learn(struct ofdpa_port *ofdpa_port,
 	if (!ofdpa_port_is_bridged(ofdpa_port))
 		return 0;
 
-	lw = ofdpa_kzalloc(trans, flags, sizeof(*lw));
+	lw = kzalloc(sizeof(*lw), GFP_ATOMIC);
 	if (!lw)
 		return -ENOMEM;
 
 	INIT_WORK(&lw->work, ofdpa_port_fdb_learn_work);
 
 	lw->ofdpa_port = ofdpa_port;
-	lw->trans = trans;
 	lw->flags = flags;
 	ether_addr_copy(lw->addr, addr);
 	lw->vid = ofdpa_port_vlan_to_vid(ofdpa_port, vlan_id);
 
-	if (switchdev_trans_ph_prepare(trans))
-		ofdpa_kfree(trans, lw);
-	else
-		schedule_work(&lw->work);
-
+	schedule_work(&lw->work);
 	return 0;
 }
 
@@ -2010,7 +1898,6 @@ ofdpa_fdb_tbl_find(const struct ofdpa *ofdpa,
 }
 
 static int ofdpa_port_fdb(struct ofdpa_port *ofdpa_port,
-			  struct switchdev_trans *trans,
 			  const unsigned char *addr,
 			  __be16 vlan_id, int flags)
 {
@@ -2020,7 +1907,7 @@ static int ofdpa_port_fdb(struct ofdpa_port *ofdpa_port,
 	bool removing = (flags & OFDPA_OP_FLAG_REMOVE);
 	unsigned long lock_flags;
 
-	fdb = ofdpa_kzalloc(trans, flags, sizeof(*fdb));
+	fdb = kzalloc(sizeof(*fdb), GFP_KERNEL);
 	if (!fdb)
 		return -ENOMEM;
 
@@ -2038,32 +1925,29 @@ static int ofdpa_port_fdb(struct ofdpa_port *ofdpa_port,
 	if (found) {
 		found->touched = jiffies;
 		if (removing) {
-			ofdpa_kfree(trans, fdb);
-			if (!switchdev_trans_ph_prepare(trans))
-				hash_del(&found->entry);
+			kfree(fdb);
+			hash_del(&found->entry);
 		}
 	} else if (!removing) {
-		if (!switchdev_trans_ph_prepare(trans))
-			hash_add(ofdpa->fdb_tbl, &fdb->entry,
-				 fdb->key_crc32);
+		hash_add(ofdpa->fdb_tbl, &fdb->entry,
+			 fdb->key_crc32);
 	}
 
 	spin_unlock_irqrestore(&ofdpa->fdb_tbl_lock, lock_flags);
 
 	/* Check if adding and already exists, or removing and can't find */
 	if (!found != !removing) {
-		ofdpa_kfree(trans, fdb);
+		kfree(fdb);
 		if (!found && removing)
 			return 0;
 		/* Refreshing existing to update aging timers */
 		flags |= OFDPA_OP_FLAG_REFRESH;
 	}
 
-	return ofdpa_port_fdb_learn(ofdpa_port, trans, flags, addr, vlan_id);
+	return ofdpa_port_fdb_learn(ofdpa_port, flags, addr, vlan_id);
 }
 
-static int ofdpa_port_fdb_flush(struct ofdpa_port *ofdpa_port,
-				struct switchdev_trans *trans, int flags)
+static int ofdpa_port_fdb_flush(struct ofdpa_port *ofdpa_port, int flags)
 {
 	struct ofdpa *ofdpa = ofdpa_port->ofdpa;
 	struct ofdpa_fdb_tbl_entry *found;
@@ -2085,13 +1969,12 @@ static int ofdpa_port_fdb_flush(struct ofdpa_port *ofdpa_port,
 			continue;
 		if (!found->learned)
 			continue;
-		err = ofdpa_port_fdb_learn(ofdpa_port, trans, flags,
+		err = ofdpa_port_fdb_learn(ofdpa_port, flags,
 					   found->key.addr,
 					   found->key.vlan_id);
 		if (err)
 			goto err_out;
-		if (!switchdev_trans_ph_prepare(trans))
-			hash_del(&found->entry);
+		hash_del(&found->entry);
 	}
 
 err_out:
@@ -2121,8 +2004,8 @@ static void ofdpa_fdb_cleanup(unsigned long data)
 		ofdpa_port = entry->key.ofdpa_port;
 		expires = entry->touched + ofdpa_port->ageing_time;
 		if (time_before_eq(expires, jiffies)) {
-			ofdpa_port_fdb_learn(ofdpa_port, NULL,
-					     flags, entry->key.addr,
+			ofdpa_port_fdb_learn(ofdpa_port, flags,
+					     entry->key.addr,
 					     entry->key.vlan_id);
 			hash_del(&entry->entry);
 		} else if (time_before(expires, next_timer)) {
@@ -2136,8 +2019,7 @@ static void ofdpa_fdb_cleanup(unsigned long data)
 }
 
 static int ofdpa_port_router_mac(struct ofdpa_port *ofdpa_port,
-				 struct switchdev_trans *trans, int flags,
-				 __be16 vlan_id)
+				 int flags, __be16 vlan_id)
 {
 	u32 in_pport_mask = 0xffffffff;
 	__be16 eth_type;
@@ -2150,26 +2032,25 @@ static int ofdpa_port_router_mac(struct ofdpa_port *ofdpa_port,
 		vlan_id = ofdpa_port->internal_vlan_id;
 
 	eth_type = htons(ETH_P_IP);
-	err = ofdpa_flow_tbl_term_mac(ofdpa_port, trans,
-				      ofdpa_port->pport, in_pport_mask,
-				      eth_type, ofdpa_port->dev->dev_addr,
+	err = ofdpa_flow_tbl_term_mac(ofdpa_port, ofdpa_port->pport,
+				      in_pport_mask, eth_type,
+				      ofdpa_port->dev->dev_addr,
 				      dst_mac_mask, vlan_id, vlan_id_mask,
 				      copy_to_cpu, flags);
 	if (err)
 		return err;
 
 	eth_type = htons(ETH_P_IPV6);
-	err = ofdpa_flow_tbl_term_mac(ofdpa_port, trans,
-				      ofdpa_port->pport, in_pport_mask,
-				      eth_type, ofdpa_port->dev->dev_addr,
+	err = ofdpa_flow_tbl_term_mac(ofdpa_port, ofdpa_port->pport,
+				      in_pport_mask, eth_type,
+				      ofdpa_port->dev->dev_addr,
 				      dst_mac_mask, vlan_id, vlan_id_mask,
 				      copy_to_cpu, flags);
 
 	return err;
 }
 
-static int ofdpa_port_fwding(struct ofdpa_port *ofdpa_port,
-			     struct switchdev_trans *trans, int flags)
+static int ofdpa_port_fwding(struct ofdpa_port *ofdpa_port, int flags)
 {
 	bool pop_vlan;
 	u32 out_pport;
@@ -2194,7 +2075,7 @@ static int ofdpa_port_fwding(struct ofdpa_port *ofdpa_port,
 			continue;
 		vlan_id = htons(vid);
 		pop_vlan = ofdpa_vlan_id_is_internal(vlan_id);
-		err = ofdpa_group_l2_interface(ofdpa_port, trans, flags,
+		err = ofdpa_group_l2_interface(ofdpa_port, flags,
 					       vlan_id, out_pport, pop_vlan);
 		if (err) {
 			netdev_err(ofdpa_port->dev, "Error (%d) port VLAN l2 group for pport %d\n",
@@ -2207,7 +2088,6 @@ static int ofdpa_port_fwding(struct ofdpa_port *ofdpa_port,
 }
 
 static int ofdpa_port_stp_update(struct ofdpa_port *ofdpa_port,
-				 struct switchdev_trans *trans,
 				 int flags, u8 state)
 {
 	bool want[OFDPA_CTRL_MAX] = { 0, };
@@ -2216,11 +2096,12 @@ static int ofdpa_port_stp_update(struct ofdpa_port *ofdpa_port,
 	int err;
 	int i;
 
+	memcpy(prev_ctrls, ofdpa_port->ctrls, sizeof(prev_ctrls));
 	prev_state = ofdpa_port->stp_state;
-	if (prev_state == state)
+
+	if (ofdpa_port->stp_state == state)
 		return 0;
 
-	memcpy(prev_ctrls, ofdpa_port->ctrls, sizeof(prev_ctrls));
 	ofdpa_port->stp_state = state;
 
 	switch (state) {
@@ -2250,26 +2131,29 @@ static int ofdpa_port_stp_update(struct ofdpa_port *ofdpa_port,
 		if (want[i] != ofdpa_port->ctrls[i]) {
 			int ctrl_flags = flags |
 					 (want[i] ? 0 : OFDPA_OP_FLAG_REMOVE);
-			err = ofdpa_port_ctrl(ofdpa_port, trans, ctrl_flags,
+			err = ofdpa_port_ctrl(ofdpa_port, ctrl_flags,
 					      &ofdpa_ctrls[i]);
 			if (err)
-				goto err_out;
+				goto err_port_ctrl;
 			ofdpa_port->ctrls[i] = want[i];
 		}
 	}
 
-	err = ofdpa_port_fdb_flush(ofdpa_port, trans, flags);
+	err = ofdpa_port_fdb_flush(ofdpa_port, flags);
 	if (err)
-		goto err_out;
+		goto err_fdb_flush;
 
-	err = ofdpa_port_fwding(ofdpa_port, trans, flags);
+	err = ofdpa_port_fwding(ofdpa_port, flags);
+	if (err)
+		goto err_port_fwding;
 
-err_out:
-	if (switchdev_trans_ph_prepare(trans)) {
-		memcpy(ofdpa_port->ctrls, prev_ctrls, sizeof(prev_ctrls));
-		ofdpa_port->stp_state = prev_state;
-	}
+	return 0;
 
+err_port_ctrl:
+err_fdb_flush:
+err_port_fwding:
+	memcpy(ofdpa_port->ctrls, prev_ctrls, sizeof(prev_ctrls));
+	ofdpa_port->stp_state = prev_state;
 	return err;
 }
 
@@ -2280,7 +2164,7 @@ static int ofdpa_port_fwd_enable(struct ofdpa_port *ofdpa_port, int flags)
 		return 0;
 
 	/* port is not bridged, so simulate going to FORWARDING state */
-	return ofdpa_port_stp_update(ofdpa_port, NULL, flags,
+	return ofdpa_port_stp_update(ofdpa_port, flags,
 				     BR_STATE_FORWARDING);
 }
 
@@ -2291,25 +2175,24 @@ static int ofdpa_port_fwd_disable(struct ofdpa_port *ofdpa_port, int flags)
 		return 0;
 
 	/* port is not bridged, so simulate going to DISABLED state */
-	return ofdpa_port_stp_update(ofdpa_port, NULL, flags,
+	return ofdpa_port_stp_update(ofdpa_port, flags,
 				     BR_STATE_DISABLED);
 }
 
 static int ofdpa_port_vlan_add(struct ofdpa_port *ofdpa_port,
-			       struct switchdev_trans *trans,
 			       u16 vid, u16 flags)
 {
 	int err;
 
 	/* XXX deal with flags for PVID and untagged */
 
-	err = ofdpa_port_vlan(ofdpa_port, trans, 0, vid);
+	err = ofdpa_port_vlan(ofdpa_port, 0, vid);
 	if (err)
 		return err;
 
-	err = ofdpa_port_router_mac(ofdpa_port, trans, 0, htons(vid));
+	err = ofdpa_port_router_mac(ofdpa_port, 0, htons(vid));
 	if (err)
-		ofdpa_port_vlan(ofdpa_port, trans,
+		ofdpa_port_vlan(ofdpa_port,
 				OFDPA_OP_FLAG_REMOVE, vid);
 
 	return err;
@@ -2320,13 +2203,13 @@ static int ofdpa_port_vlan_del(struct ofdpa_port *ofdpa_port,
 {
 	int err;
 
-	err = ofdpa_port_router_mac(ofdpa_port, NULL,
-				    OFDPA_OP_FLAG_REMOVE, htons(vid));
+	err = ofdpa_port_router_mac(ofdpa_port, OFDPA_OP_FLAG_REMOVE,
+				    htons(vid));
 	if (err)
 		return err;
 
-	return ofdpa_port_vlan(ofdpa_port, NULL,
-			       OFDPA_OP_FLAG_REMOVE, vid);
+	return ofdpa_port_vlan(ofdpa_port, OFDPA_OP_FLAG_REMOVE,
+			       vid);
 }
 
 static struct ofdpa_internal_vlan_tbl_entry *
@@ -2385,10 +2268,9 @@ static __be16 ofdpa_port_internal_vlan_id_get(struct ofdpa_port *ofdpa_port,
 	return found->vlan_id;
 }
 
-static int ofdpa_port_fib_ipv4(struct ofdpa_port *ofdpa_port,
-			       struct switchdev_trans *trans, __be32 dst,
-			       int dst_len, struct fib_info *fi,
-			       u32 tb_id, int flags)
+static int ofdpa_port_fib_ipv4(struct ofdpa_port *ofdpa_port,  __be32 dst,
+			       int dst_len, struct fib_info *fi, u32 tb_id,
+			       int flags)
 {
 	const struct fib_nh *nh;
 	__be16 eth_type = htons(ETH_P_IP);
@@ -2410,7 +2292,7 @@ static int ofdpa_port_fib_ipv4(struct ofdpa_port *ofdpa_port,
 	has_gw = !!nh->nh_gw;
 
 	if (has_gw && nh_on_port) {
-		err = ofdpa_port_ipv4_nh(ofdpa_port, trans, flags,
+		err = ofdpa_port_ipv4_nh(ofdpa_port, flags,
 					 nh->nh_gw, &index);
 		if (err)
 			return err;
@@ -2421,7 +2303,7 @@ static int ofdpa_port_fib_ipv4(struct ofdpa_port *ofdpa_port,
 		group_id = ROCKER_GROUP_L2_INTERFACE(internal_vlan_id, 0);
 	}
 
-	err = ofdpa_flow_tbl_ucast4_routing(ofdpa_port, trans, eth_type, dst,
+	err = ofdpa_flow_tbl_ucast4_routing(ofdpa_port, eth_type, dst,
 					    dst_mask, priority, goto_tbl,
 					    group_id, fi, flags);
 	if (err)
@@ -2559,7 +2441,7 @@ static int ofdpa_port_init(struct rocker_port *rocker_port)
 	rocker_port_set_learning(rocker_port,
 				 !!(ofdpa_port->brport_flags & BR_LEARNING));
 
-	err = ofdpa_port_ig_tbl(ofdpa_port, NULL, 0);
+	err = ofdpa_port_ig_tbl(ofdpa_port, 0);
 	if (err) {
 		netdev_err(ofdpa_port->dev, "install ig port table failed\n");
 		return err;
@@ -2569,7 +2451,7 @@ static int ofdpa_port_init(struct rocker_port *rocker_port)
 		ofdpa_port_internal_vlan_id_get(ofdpa_port,
 						ofdpa_port->dev->ifindex);
 
-	err = ofdpa_port_vlan_add(ofdpa_port, NULL, OFDPA_UNTAGGED_VID, 0);
+	err = ofdpa_port_vlan_add(ofdpa_port, OFDPA_UNTAGGED_VID, 0);
 	if (err) {
 		netdev_err(ofdpa_port->dev, "install untagged VLAN failed\n");
 		goto err_untagged_vlan;
@@ -2577,7 +2459,7 @@ static int ofdpa_port_init(struct rocker_port *rocker_port)
 	return 0;
 
 err_untagged_vlan:
-	ofdpa_port_ig_tbl(ofdpa_port, NULL, OFDPA_OP_FLAG_REMOVE);
+	ofdpa_port_ig_tbl(ofdpa_port, OFDPA_OP_FLAG_REMOVE);
 	return err;
 }
 
@@ -2585,7 +2467,7 @@ static void ofdpa_port_fini(struct rocker_port *rocker_port)
 {
 	struct ofdpa_port *ofdpa_port = rocker_port->wpriv;
 
-	ofdpa_port_ig_tbl(ofdpa_port, NULL, OFDPA_OP_FLAG_REMOVE);
+	ofdpa_port_ig_tbl(ofdpa_port, OFDPA_OP_FLAG_REMOVE);
 }
 
 static int ofdpa_port_open(struct rocker_port *rocker_port)
@@ -2603,12 +2485,11 @@ static void ofdpa_port_stop(struct rocker_port *rocker_port)
 }
 
 static int ofdpa_port_attr_stp_state_set(struct rocker_port *rocker_port,
-					 u8 state,
-					 struct switchdev_trans *trans)
+					 u8 state)
 {
 	struct ofdpa_port *ofdpa_port = rocker_port->wpriv;
 
-	return ofdpa_port_stp_update(ofdpa_port, trans, 0, state);
+	return ofdpa_port_stp_update(ofdpa_port, 0, state);
 }
 
 static int ofdpa_port_attr_bridge_flags_set(struct rocker_port *rocker_port,
@@ -2671,15 +2552,14 @@ ofdpa_port_attr_bridge_ageing_time_set(struct rocker_port *rocker_port,
 }
 
 static int ofdpa_port_obj_vlan_add(struct rocker_port *rocker_port,
-				   const struct switchdev_obj_port_vlan *vlan,
-				   struct switchdev_trans *trans)
+				   const struct switchdev_obj_port_vlan *vlan)
 {
 	struct ofdpa_port *ofdpa_port = rocker_port->wpriv;
 	u16 vid;
 	int err;
 
 	for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) {
-		err = ofdpa_port_vlan_add(ofdpa_port, trans, vid, vlan->flags);
+		err = ofdpa_port_vlan_add(ofdpa_port, vid, vlan->flags);
 		if (err)
 			return err;
 	}
@@ -2727,29 +2607,28 @@ static int ofdpa_port_obj_vlan_dump(const struct rocker_port *rocker_port,
 }
 
 static int ofdpa_port_obj_fdb_add(struct rocker_port *rocker_port,
-				  const struct switchdev_obj_port_fdb *fdb,
-				  struct switchdev_trans *trans)
+				  u16 vid, const unsigned char *addr)
 {
 	struct ofdpa_port *ofdpa_port = rocker_port->wpriv;
-	__be16 vlan_id = ofdpa_port_vid_to_vlan(ofdpa_port, fdb->vid, NULL);
+	__be16 vlan_id = ofdpa_port_vid_to_vlan(ofdpa_port, vid, NULL);
 
 	if (!ofdpa_port_is_bridged(ofdpa_port))
 		return -EINVAL;
 
-	return ofdpa_port_fdb(ofdpa_port, trans, fdb->addr, vlan_id, 0);
+	return ofdpa_port_fdb(ofdpa_port, addr, vlan_id, 0);
 }
 
 static int ofdpa_port_obj_fdb_del(struct rocker_port *rocker_port,
-				  const struct switchdev_obj_port_fdb *fdb)
+				  u16 vid, const unsigned char *addr)
 {
 	struct ofdpa_port *ofdpa_port = rocker_port->wpriv;
-	__be16 vlan_id = ofdpa_port_vid_to_vlan(ofdpa_port, fdb->vid, NULL);
+	__be16 vlan_id = ofdpa_port_vid_to_vlan(ofdpa_port, vid, NULL);
 	int flags = OFDPA_OP_FLAG_REMOVE;
 
 	if (!ofdpa_port_is_bridged(ofdpa_port))
 		return -EINVAL;
 
-	return ofdpa_port_fdb(ofdpa_port, NULL, fdb->addr, vlan_id, flags);
+	return ofdpa_port_fdb(ofdpa_port, addr, vlan_id, flags);
 }
 
 static int ofdpa_port_obj_fdb_dump(const struct rocker_port *rocker_port,
@@ -2803,7 +2682,7 @@ static int ofdpa_port_bridge_join(struct ofdpa_port *ofdpa_port,
 
 	ofdpa_port->bridge_dev = bridge;
 
-	return ofdpa_port_vlan_add(ofdpa_port, NULL, OFDPA_UNTAGGED_VID, 0);
+	return ofdpa_port_vlan_add(ofdpa_port, OFDPA_UNTAGGED_VID, 0);
 }
 
 static int ofdpa_port_bridge_leave(struct ofdpa_port *ofdpa_port)
@@ -2822,7 +2701,7 @@ static int ofdpa_port_bridge_leave(struct ofdpa_port *ofdpa_port)
 
 	ofdpa_port->bridge_dev = NULL;
 
-	err = ofdpa_port_vlan_add(ofdpa_port, NULL, OFDPA_UNTAGGED_VID, 0);
+	err = ofdpa_port_vlan_add(ofdpa_port, OFDPA_UNTAGGED_VID, 0);
 	if (err)
 		return err;
 
@@ -2881,7 +2760,7 @@ static int ofdpa_port_neigh_update(struct rocker_port *rocker_port,
 						    OFDPA_OP_FLAG_NOWAIT;
 	__be32 ip_addr = *(__be32 *) n->primary_key;
 
-	return ofdpa_port_ipv4_neigh(ofdpa_port, NULL, flags, ip_addr, n->ha);
+	return ofdpa_port_ipv4_neigh(ofdpa_port, flags, ip_addr, n->ha);
 }
 
 static int ofdpa_port_neigh_destroy(struct rocker_port *rocker_port,
@@ -2891,7 +2770,7 @@ static int ofdpa_port_neigh_destroy(struct rocker_port *rocker_port,
 	int flags = OFDPA_OP_FLAG_REMOVE | OFDPA_OP_FLAG_NOWAIT;
 	__be32 ip_addr = *(__be32 *) n->primary_key;
 
-	return ofdpa_port_ipv4_neigh(ofdpa_port, NULL, flags, ip_addr, n->ha);
+	return ofdpa_port_ipv4_neigh(ofdpa_port, flags, ip_addr, n->ha);
 }
 
 static int ofdpa_port_ev_mac_vlan_seen(struct rocker_port *rocker_port,
@@ -2905,7 +2784,7 @@ static int ofdpa_port_ev_mac_vlan_seen(struct rocker_port *rocker_port,
 	    ofdpa_port->stp_state != BR_STATE_FORWARDING)
 		return 0;
 
-	return ofdpa_port_fdb(ofdpa_port, NULL, addr, vlan_id, flags);
+	return ofdpa_port_fdb(ofdpa_port, addr, vlan_id, flags);
 }
 
 static struct ofdpa_port *ofdpa_port_dev_lower_find(struct net_device *dev,
@@ -2929,7 +2808,7 @@ static int ofdpa_fib4_add(struct rocker *rocker,
 	ofdpa_port = ofdpa_port_dev_lower_find(fen_info->fi->fib_dev, rocker);
 	if (!ofdpa_port)
 		return 0;
-	err = ofdpa_port_fib_ipv4(ofdpa_port, NULL, htonl(fen_info->dst),
+	err = ofdpa_port_fib_ipv4(ofdpa_port, htonl(fen_info->dst),
 				  fen_info->dst_len, fen_info->fi,
 				  fen_info->tb_id, 0);
 	if (err)
@@ -2950,7 +2829,7 @@ static int ofdpa_fib4_del(struct rocker *rocker,
 	if (!ofdpa_port)
 		return 0;
 	fib_info_offload_dec(fen_info->fi);
-	return ofdpa_port_fib_ipv4(ofdpa_port, NULL, htonl(fen_info->dst),
+	return ofdpa_port_fib_ipv4(ofdpa_port, htonl(fen_info->dst),
 				   fen_info->dst_len, fen_info->fi,
 				   fen_info->tb_id, OFDPA_OP_FLAG_REMOVE);
 }
@@ -2977,7 +2856,7 @@ static void ofdpa_fib4_abort(struct rocker *rocker)
 		if (!ofdpa_port)
 			continue;
 		fib_info_offload_dec(flow_entry->fi);
-		ofdpa_flow_tbl_del(ofdpa_port, NULL, OFDPA_OP_FLAG_REMOVE,
+		ofdpa_flow_tbl_del(ofdpa_port, OFDPA_OP_FLAG_REMOVE,
 				   flow_entry);
 	}
 	spin_unlock_irqrestore(&ofdpa->flow_tbl_lock, flags);
-- 
2.9.3

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

* [patch net-next 17/19] rocker: Add support for learning FDB through notification
  2017-06-05  9:20 [patch net-next 00/19] Remove support from bridge bypass for mlxsw/rocker drivers Jiri Pirko
                   ` (15 preceding siblings ...)
  2017-06-05  9:20 ` [patch net-next 16/19] rocker: Change world_ops API and implementation to be switchdev independant Jiri Pirko
@ 2017-06-05  9:20 ` Jiri Pirko
  2017-06-05  9:20 ` [patch net-next 18/19] rocker: Remove support for bypass bridge port attributes/vlan set Jiri Pirko
                   ` (2 subsequent siblings)
  19 siblings, 0 replies; 30+ messages in thread
From: Jiri Pirko @ 2017-06-05  9:20 UTC (permalink / raw)
  To: netdev; +Cc: davem, idosch, arkadis, mlxsw, roopa, stephen, ivecera

From: Arkadi Sharshevsky <arkadis@mellanox.com>

Add support for learning FDB through notification. The driver defers
the hardware update via ordered work queue.

Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 drivers/net/ethernet/rocker/rocker_main.c | 140 ++++++++++++++++++++++++++++--
 1 file changed, 135 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c
index 9f0154d..72dab7c 100644
--- a/drivers/net/ethernet/rocker/rocker_main.c
+++ b/drivers/net/ethernet/rocker/rocker_main.c
@@ -1691,6 +1691,29 @@ rocker_world_port_obj_fdb_del(struct rocker_port *rocker_port,
 }
 
 static int
+rocker_world_port_fdb_add(struct rocker_port *rocker_port,
+			  struct switchdev_notifier_fdb_info *info)
+{
+	struct rocker_world_ops *wops = rocker_port->rocker->wops;
+
+	if (!wops->port_obj_fdb_add)
+		return -EOPNOTSUPP;
+
+	return wops->port_obj_fdb_add(rocker_port, info->vid, info->addr);
+}
+
+static int
+rocker_world_port_fdb_del(struct rocker_port *rocker_port,
+			  struct switchdev_notifier_fdb_info *info)
+{
+	struct rocker_world_ops *wops = rocker_port->rocker->wops;
+
+	if (!wops->port_obj_fdb_del)
+		return -EOPNOTSUPP;
+	return wops->port_obj_fdb_del(rocker_port, info->vid, info->addr);
+}
+
+static int
 rocker_world_port_obj_fdb_dump(const struct rocker_port *rocker_port,
 			       struct switchdev_obj_port_fdb *fdb,
 			       switchdev_obj_dump_cb_t *cb)
@@ -2767,6 +2790,109 @@ static void rocker_msix_fini(const struct rocker *rocker)
 	kfree(rocker->msix_entries);
 }
 
+static bool rocker_port_dev_check(const struct net_device *dev)
+{
+	return dev->netdev_ops == &rocker_port_netdev_ops;
+}
+
+struct rocker_switchdev_event_work {
+	struct work_struct work;
+	struct switchdev_notifier_fdb_info fdb_info;
+	struct rocker_port *rocker_port;
+	unsigned long event;
+};
+
+static void
+rocker_fdb_offload_notify(struct rocker_port *rocker_port,
+			  struct switchdev_notifier_fdb_info *recv_info)
+{
+	struct switchdev_notifier_fdb_info info;
+
+	info.addr = recv_info->addr;
+	info.vid = recv_info->vid;
+	call_switchdev_notifiers(SWITCHDEV_FDB_OFFLOADED,
+				 rocker_port->dev, &info.info);
+}
+
+static void rocker_switchdev_event_work(struct work_struct *work)
+{
+	struct rocker_switchdev_event_work *switchdev_work =
+		container_of(work, struct rocker_switchdev_event_work, work);
+	struct rocker_port *rocker_port = switchdev_work->rocker_port;
+	struct switchdev_notifier_fdb_info *fdb_info;
+	int err;
+
+	rtnl_lock();
+	switch (switchdev_work->event) {
+	case SWITCHDEV_FDB_ADD_TO_DEVICE:
+		fdb_info = &switchdev_work->fdb_info;
+		err = rocker_world_port_fdb_add(rocker_port, fdb_info);
+		if (err) {
+			netdev_dbg(rocker_port->dev, "fdb add failed err=%d\n", err);
+			break;
+		}
+		rocker_fdb_offload_notify(rocker_port, fdb_info);
+		break;
+	case SWITCHDEV_FDB_DEL_TO_DEVICE:
+		fdb_info = &switchdev_work->fdb_info;
+		err = rocker_world_port_fdb_del(rocker_port, fdb_info);
+		if (err)
+			netdev_dbg(rocker_port->dev, "fdb add failed err=%d\n", err);
+		break;
+	}
+	rtnl_unlock();
+
+	kfree(switchdev_work->fdb_info.addr);
+	kfree(switchdev_work);
+	dev_put(rocker_port->dev);
+}
+
+/* called under rcu_read_lock() */
+static int rocker_switchdev_event(struct notifier_block *unused,
+				  unsigned long event, void *ptr)
+{
+	struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
+	struct rocker_switchdev_event_work *switchdev_work;
+	struct switchdev_notifier_fdb_info *fdb_info = ptr;
+	struct rocker_port *rocker_port;
+
+	if (!rocker_port_dev_check(dev))
+		return NOTIFY_DONE;
+
+	rocker_port = netdev_priv(dev);
+	switchdev_work = kzalloc(sizeof(*switchdev_work), GFP_ATOMIC);
+	if (WARN_ON(!switchdev_work))
+		return NOTIFY_BAD;
+
+	INIT_WORK(&switchdev_work->work, rocker_switchdev_event_work);
+	switchdev_work->rocker_port = rocker_port;
+	switchdev_work->event = event;
+
+	switch (event) {
+	case SWITCHDEV_FDB_ADD_TO_DEVICE: /* fall through */
+	case SWITCHDEV_FDB_DEL_TO_DEVICE:
+		memcpy(&switchdev_work->fdb_info, ptr,
+		       sizeof(switchdev_work->fdb_info));
+		switchdev_work->fdb_info.addr = kzalloc(ETH_ALEN, GFP_ATOMIC);
+		ether_addr_copy((u8 *)switchdev_work->fdb_info.addr,
+				fdb_info->addr);
+		/* Take a reference on the rocker device */
+		dev_hold(dev);
+		break;
+	default:
+		kfree(switchdev_work);
+		return NOTIFY_DONE;
+	}
+
+	queue_work(rocker_port->rocker->rocker_owq,
+		   &switchdev_work->work);
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block rocker_switchdev_notifier = {
+	.notifier_call = rocker_switchdev_event,
+};
+
 static int rocker_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	struct rocker *rocker;
@@ -2872,6 +2998,12 @@ static int rocker_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	if (err)
 		goto err_register_fib_notifier;
 
+	err = register_switchdev_notifier(&rocker_switchdev_notifier);
+	if (err) {
+		dev_err(&pdev->dev, "Failed to register switchdev notifier\n");
+		goto err_register_switchdev_notifier;
+	}
+
 	rocker->hw.id = rocker_read64(rocker, SWITCH_ID);
 
 	err = rocker_probe_ports(rocker);
@@ -2886,6 +3018,8 @@ static int rocker_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	return 0;
 
 err_probe_ports:
+	unregister_switchdev_notifier(&rocker_switchdev_notifier);
+err_register_switchdev_notifier:
 	unregister_fib_notifier(&rocker->fib_nb);
 err_register_fib_notifier:
 	destroy_workqueue(rocker->rocker_owq);
@@ -2916,6 +3050,7 @@ static void rocker_remove(struct pci_dev *pdev)
 	struct rocker *rocker = pci_get_drvdata(pdev);
 
 	rocker_remove_ports(rocker);
+	unregister_switchdev_notifier(&rocker_switchdev_notifier);
 	unregister_fib_notifier(&rocker->fib_nb);
 	rocker_write32(rocker, CONTROL, ROCKER_CONTROL_RESET);
 	destroy_workqueue(rocker->rocker_owq);
@@ -2940,11 +3075,6 @@ static struct pci_driver rocker_pci_driver = {
  * Net device notifier event handler
  ************************************/
 
-static bool rocker_port_dev_check(const struct net_device *dev)
-{
-	return dev->netdev_ops == &rocker_port_netdev_ops;
-}
-
 static bool rocker_port_dev_check_under(const struct net_device *dev,
 					struct rocker *rocker)
 {
-- 
2.9.3

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

* [patch net-next 18/19] rocker: Remove support for bypass bridge port attributes/vlan set
  2017-06-05  9:20 [patch net-next 00/19] Remove support from bridge bypass for mlxsw/rocker drivers Jiri Pirko
                   ` (16 preceding siblings ...)
  2017-06-05  9:20 ` [patch net-next 17/19] rocker: Add support for learning FDB through notification Jiri Pirko
@ 2017-06-05  9:20 ` Jiri Pirko
  2017-06-05  9:20 ` [patch net-next 19/19] rocker: Remove support bridge bypass FDB Jiri Pirko
  2017-06-05 10:07 ` [patch iproute2] bridge: Distinguish between externally learned vs offloaded FDBs Jiri Pirko
  19 siblings, 0 replies; 30+ messages in thread
From: Jiri Pirko @ 2017-06-05  9:20 UTC (permalink / raw)
  To: netdev; +Cc: davem, idosch, arkadis, mlxsw, roopa, stephen, ivecera

From: Arkadi Sharshevsky <arkadis@mellanox.com>

The bridge port attributes/vlan for mlxsw devices should be set only
from bridge code. The vlans are synced totally with the bridge so
there is no need to special dump support.

Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 drivers/net/ethernet/rocker/rocker.h       |  3 ---
 drivers/net/ethernet/rocker/rocker_main.c  | 20 --------------------
 drivers/net/ethernet/rocker/rocker_ofdpa.c | 24 ------------------------
 3 files changed, 47 deletions(-)

diff --git a/drivers/net/ethernet/rocker/rocker.h b/drivers/net/ethernet/rocker/rocker.h
index a0f7782..a0fa3f8 100644
--- a/drivers/net/ethernet/rocker/rocker.h
+++ b/drivers/net/ethernet/rocker/rocker.h
@@ -122,9 +122,6 @@ struct rocker_world_ops {
 				 const struct switchdev_obj_port_vlan *vlan);
 	int (*port_obj_vlan_del)(struct rocker_port *rocker_port,
 				 const struct switchdev_obj_port_vlan *vlan);
-	int (*port_obj_vlan_dump)(const struct rocker_port *rocker_port,
-				  struct switchdev_obj_port_vlan *vlan,
-				  switchdev_obj_dump_cb_t *cb);
 	int (*port_obj_fdb_add)(struct rocker_port *rocker_port,
 				u16 vid, const unsigned char *addr);
 	int (*port_obj_fdb_del)(struct rocker_port *rocker_port,
diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c
index 72dab7c..3e78129 100644
--- a/drivers/net/ethernet/rocker/rocker_main.c
+++ b/drivers/net/ethernet/rocker/rocker_main.c
@@ -1652,18 +1652,6 @@ rocker_world_port_obj_vlan_del(struct rocker_port *rocker_port,
 }
 
 static int
-rocker_world_port_obj_vlan_dump(const struct rocker_port *rocker_port,
-				struct switchdev_obj_port_vlan *vlan,
-				switchdev_obj_dump_cb_t *cb)
-{
-	struct rocker_world_ops *wops = rocker_port->rocker->wops;
-
-	if (!wops->port_obj_vlan_dump)
-		return -EOPNOTSUPP;
-	return wops->port_obj_vlan_dump(rocker_port, vlan, cb);
-}
-
-static int
 rocker_world_port_obj_fdb_add(struct rocker_port *rocker_port,
 			      const struct switchdev_obj_port_fdb *fdb,
 			      struct switchdev_trans *trans)
@@ -2079,9 +2067,6 @@ static const struct net_device_ops rocker_port_netdev_ops = {
 	.ndo_start_xmit			= rocker_port_xmit,
 	.ndo_set_mac_address		= rocker_port_set_mac_address,
 	.ndo_change_mtu			= rocker_port_change_mtu,
-	.ndo_bridge_getlink		= switchdev_port_bridge_getlink,
-	.ndo_bridge_setlink		= switchdev_port_bridge_setlink,
-	.ndo_bridge_dellink		= switchdev_port_bridge_dellink,
 	.ndo_fdb_add			= switchdev_port_fdb_add,
 	.ndo_fdb_del			= switchdev_port_fdb_del,
 	.ndo_fdb_dump			= switchdev_port_fdb_dump,
@@ -2214,11 +2199,6 @@ static int rocker_port_obj_dump(struct net_device *dev,
 						     SWITCHDEV_OBJ_PORT_FDB(obj),
 						     cb);
 		break;
-	case SWITCHDEV_OBJ_ID_PORT_VLAN:
-		err = rocker_world_port_obj_vlan_dump(rocker_port,
-						      SWITCHDEV_OBJ_PORT_VLAN(obj),
-						      cb);
-		break;
 	default:
 		err = -EOPNOTSUPP;
 		break;
diff --git a/drivers/net/ethernet/rocker/rocker_ofdpa.c b/drivers/net/ethernet/rocker/rocker_ofdpa.c
index 184a478..5510ad0 100644
--- a/drivers/net/ethernet/rocker/rocker_ofdpa.c
+++ b/drivers/net/ethernet/rocker/rocker_ofdpa.c
@@ -2583,29 +2583,6 @@ static int ofdpa_port_obj_vlan_del(struct rocker_port *rocker_port,
 	return 0;
 }
 
-static int ofdpa_port_obj_vlan_dump(const struct rocker_port *rocker_port,
-				    struct switchdev_obj_port_vlan *vlan,
-				    switchdev_obj_dump_cb_t *cb)
-{
-	const struct ofdpa_port *ofdpa_port = rocker_port->wpriv;
-	u16 vid;
-	int err = 0;
-
-	for (vid = 1; vid < VLAN_N_VID; vid++) {
-		if (!test_bit(vid, ofdpa_port->vlan_bitmap))
-			continue;
-		vlan->flags = 0;
-		if (ofdpa_vlan_id_is_internal(htons(vid)))
-			vlan->flags |= BRIDGE_VLAN_INFO_PVID;
-		vlan->vid_begin = vlan->vid_end = vid;
-		err = cb(&vlan->obj);
-		if (err)
-			break;
-	}
-
-	return err;
-}
-
 static int ofdpa_port_obj_fdb_add(struct rocker_port *rocker_port,
 				  u16 vid, const unsigned char *addr)
 {
@@ -2882,7 +2859,6 @@ struct rocker_world_ops rocker_ofdpa_ops = {
 	.port_attr_bridge_ageing_time_set = ofdpa_port_attr_bridge_ageing_time_set,
 	.port_obj_vlan_add = ofdpa_port_obj_vlan_add,
 	.port_obj_vlan_del = ofdpa_port_obj_vlan_del,
-	.port_obj_vlan_dump = ofdpa_port_obj_vlan_dump,
 	.port_obj_fdb_add = ofdpa_port_obj_fdb_add,
 	.port_obj_fdb_del = ofdpa_port_obj_fdb_del,
 	.port_obj_fdb_dump = ofdpa_port_obj_fdb_dump,
-- 
2.9.3

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

* [patch net-next 19/19] rocker: Remove support bridge bypass FDB
  2017-06-05  9:20 [patch net-next 00/19] Remove support from bridge bypass for mlxsw/rocker drivers Jiri Pirko
                   ` (17 preceding siblings ...)
  2017-06-05  9:20 ` [patch net-next 18/19] rocker: Remove support for bypass bridge port attributes/vlan set Jiri Pirko
@ 2017-06-05  9:20 ` Jiri Pirko
  2017-06-05 10:07 ` [patch iproute2] bridge: Distinguish between externally learned vs offloaded FDBs Jiri Pirko
  19 siblings, 0 replies; 30+ messages in thread
From: Jiri Pirko @ 2017-06-05  9:20 UTC (permalink / raw)
  To: netdev; +Cc: davem, idosch, arkadis, mlxsw, roopa, stephen, ivecera

From: Arkadi Sharshevsky <arkadis@mellanox.com>

The FDB add/delete are now done through the notification chain. The FDBs
are synced with the bridge and there is no need for extra dumping.

Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 drivers/net/ethernet/rocker/rocker.h       |  3 --
 drivers/net/ethernet/rocker/rocker_main.c  | 73 ------------------------------
 drivers/net/ethernet/rocker/rocker_ofdpa.c | 30 ------------
 3 files changed, 106 deletions(-)

diff --git a/drivers/net/ethernet/rocker/rocker.h b/drivers/net/ethernet/rocker/rocker.h
index a0fa3f8..748fb12 100644
--- a/drivers/net/ethernet/rocker/rocker.h
+++ b/drivers/net/ethernet/rocker/rocker.h
@@ -126,9 +126,6 @@ struct rocker_world_ops {
 				u16 vid, const unsigned char *addr);
 	int (*port_obj_fdb_del)(struct rocker_port *rocker_port,
 				u16 vid, const unsigned char *addr);
-	int (*port_obj_fdb_dump)(const struct rocker_port *rocker_port,
-				 struct switchdev_obj_port_fdb *fdb,
-				 switchdev_obj_dump_cb_t *cb);
 	int (*port_master_linked)(struct rocker_port *rocker_port,
 				  struct net_device *master);
 	int (*port_master_unlinked)(struct rocker_port *rocker_port,
diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c
index 3e78129..b1e5c07 100644
--- a/drivers/net/ethernet/rocker/rocker_main.c
+++ b/drivers/net/ethernet/rocker/rocker_main.c
@@ -1652,33 +1652,6 @@ rocker_world_port_obj_vlan_del(struct rocker_port *rocker_port,
 }
 
 static int
-rocker_world_port_obj_fdb_add(struct rocker_port *rocker_port,
-			      const struct switchdev_obj_port_fdb *fdb,
-			      struct switchdev_trans *trans)
-{
-	struct rocker_world_ops *wops = rocker_port->rocker->wops;
-
-	if (!wops->port_obj_fdb_add)
-		return -EOPNOTSUPP;
-
-	if (switchdev_trans_ph_prepare(trans))
-		return 0;
-
-	return wops->port_obj_fdb_add(rocker_port, fdb->vid, fdb->addr);
-}
-
-static int
-rocker_world_port_obj_fdb_del(struct rocker_port *rocker_port,
-			      const struct switchdev_obj_port_fdb *fdb)
-{
-	struct rocker_world_ops *wops = rocker_port->rocker->wops;
-
-	if (!wops->port_obj_fdb_del)
-		return -EOPNOTSUPP;
-	return wops->port_obj_fdb_del(rocker_port, fdb->vid, fdb->addr);
-}
-
-static int
 rocker_world_port_fdb_add(struct rocker_port *rocker_port,
 			  struct switchdev_notifier_fdb_info *info)
 {
@@ -1701,18 +1674,6 @@ rocker_world_port_fdb_del(struct rocker_port *rocker_port,
 	return wops->port_obj_fdb_del(rocker_port, info->vid, info->addr);
 }
 
-static int
-rocker_world_port_obj_fdb_dump(const struct rocker_port *rocker_port,
-			       struct switchdev_obj_port_fdb *fdb,
-			       switchdev_obj_dump_cb_t *cb)
-{
-	struct rocker_world_ops *wops = rocker_port->rocker->wops;
-
-	if (!wops->port_obj_fdb_dump)
-		return -EOPNOTSUPP;
-	return wops->port_obj_fdb_dump(rocker_port, fdb, cb);
-}
-
 static int rocker_world_port_master_linked(struct rocker_port *rocker_port,
 					   struct net_device *master)
 {
@@ -2067,9 +2028,6 @@ static const struct net_device_ops rocker_port_netdev_ops = {
 	.ndo_start_xmit			= rocker_port_xmit,
 	.ndo_set_mac_address		= rocker_port_set_mac_address,
 	.ndo_change_mtu			= rocker_port_change_mtu,
-	.ndo_fdb_add			= switchdev_port_fdb_add,
-	.ndo_fdb_del			= switchdev_port_fdb_del,
-	.ndo_fdb_dump			= switchdev_port_fdb_dump,
 	.ndo_get_phys_port_name		= rocker_port_get_phys_port_name,
 	.ndo_change_proto_down		= rocker_port_change_proto_down,
 	.ndo_neigh_destroy		= rocker_port_neigh_destroy,
@@ -2150,11 +2108,6 @@ static int rocker_port_obj_add(struct net_device *dev,
 						     SWITCHDEV_OBJ_PORT_VLAN(obj),
 						     trans);
 		break;
-	case SWITCHDEV_OBJ_ID_PORT_FDB:
-		err = rocker_world_port_obj_fdb_add(rocker_port,
-						    SWITCHDEV_OBJ_PORT_FDB(obj),
-						    trans);
-		break;
 	default:
 		err = -EOPNOTSUPP;
 		break;
@@ -2174,31 +2127,6 @@ static int rocker_port_obj_del(struct net_device *dev,
 		err = rocker_world_port_obj_vlan_del(rocker_port,
 						     SWITCHDEV_OBJ_PORT_VLAN(obj));
 		break;
-	case SWITCHDEV_OBJ_ID_PORT_FDB:
-		err = rocker_world_port_obj_fdb_del(rocker_port,
-						    SWITCHDEV_OBJ_PORT_FDB(obj));
-		break;
-	default:
-		err = -EOPNOTSUPP;
-		break;
-	}
-
-	return err;
-}
-
-static int rocker_port_obj_dump(struct net_device *dev,
-				struct switchdev_obj *obj,
-				switchdev_obj_dump_cb_t *cb)
-{
-	const struct rocker_port *rocker_port = netdev_priv(dev);
-	int err = 0;
-
-	switch (obj->id) {
-	case SWITCHDEV_OBJ_ID_PORT_FDB:
-		err = rocker_world_port_obj_fdb_dump(rocker_port,
-						     SWITCHDEV_OBJ_PORT_FDB(obj),
-						     cb);
-		break;
 	default:
 		err = -EOPNOTSUPP;
 		break;
@@ -2212,7 +2140,6 @@ static const struct switchdev_ops rocker_port_switchdev_ops = {
 	.switchdev_port_attr_set	= rocker_port_attr_set,
 	.switchdev_port_obj_add		= rocker_port_obj_add,
 	.switchdev_port_obj_del		= rocker_port_obj_del,
-	.switchdev_port_obj_dump	= rocker_port_obj_dump,
 };
 
 struct rocker_fib_event_work {
diff --git a/drivers/net/ethernet/rocker/rocker_ofdpa.c b/drivers/net/ethernet/rocker/rocker_ofdpa.c
index 5510ad0..bd0e3f1 100644
--- a/drivers/net/ethernet/rocker/rocker_ofdpa.c
+++ b/drivers/net/ethernet/rocker/rocker_ofdpa.c
@@ -2608,35 +2608,6 @@ static int ofdpa_port_obj_fdb_del(struct rocker_port *rocker_port,
 	return ofdpa_port_fdb(ofdpa_port, addr, vlan_id, flags);
 }
 
-static int ofdpa_port_obj_fdb_dump(const struct rocker_port *rocker_port,
-				   struct switchdev_obj_port_fdb *fdb,
-				   switchdev_obj_dump_cb_t *cb)
-{
-	const struct ofdpa_port *ofdpa_port = rocker_port->wpriv;
-	struct ofdpa *ofdpa = ofdpa_port->ofdpa;
-	struct ofdpa_fdb_tbl_entry *found;
-	struct hlist_node *tmp;
-	unsigned long lock_flags;
-	int bkt;
-	int err = 0;
-
-	spin_lock_irqsave(&ofdpa->fdb_tbl_lock, lock_flags);
-	hash_for_each_safe(ofdpa->fdb_tbl, bkt, tmp, found, entry) {
-		if (found->key.ofdpa_port != ofdpa_port)
-			continue;
-		ether_addr_copy(fdb->addr, found->key.addr);
-		fdb->ndm_state = NUD_REACHABLE;
-		fdb->vid = ofdpa_port_vlan_to_vid(ofdpa_port,
-						  found->key.vlan_id);
-		err = cb(&fdb->obj);
-		if (err)
-			break;
-	}
-	spin_unlock_irqrestore(&ofdpa->fdb_tbl_lock, lock_flags);
-
-	return err;
-}
-
 static int ofdpa_port_bridge_join(struct ofdpa_port *ofdpa_port,
 				  struct net_device *bridge)
 {
@@ -2861,7 +2832,6 @@ struct rocker_world_ops rocker_ofdpa_ops = {
 	.port_obj_vlan_del = ofdpa_port_obj_vlan_del,
 	.port_obj_fdb_add = ofdpa_port_obj_fdb_add,
 	.port_obj_fdb_del = ofdpa_port_obj_fdb_del,
-	.port_obj_fdb_dump = ofdpa_port_obj_fdb_dump,
 	.port_master_linked = ofdpa_port_master_linked,
 	.port_master_unlinked = ofdpa_port_master_unlinked,
 	.port_neigh_update = ofdpa_port_neigh_update,
-- 
2.9.3

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

* [patch iproute2] bridge: Distinguish between externally learned vs offloaded FDBs
  2017-06-05  9:20 [patch net-next 00/19] Remove support from bridge bypass for mlxsw/rocker drivers Jiri Pirko
                   ` (18 preceding siblings ...)
  2017-06-05  9:20 ` [patch net-next 19/19] rocker: Remove support bridge bypass FDB Jiri Pirko
@ 2017-06-05 10:07 ` Jiri Pirko
  2017-06-14 16:52   ` Stephen Hemminger
  19 siblings, 1 reply; 30+ messages in thread
From: Jiri Pirko @ 2017-06-05 10:07 UTC (permalink / raw)
  To: netdev; +Cc: davem, idosch, arkadis, mlxsw, roopa, stephen, ivecera

From: Arkadi Sharshevsky <arkadis@mellanox.com>

Distinguish between externally learned vs offloaded FDBs. This is done
in order to indicate that FDBs added by software was successfully
offloaded.

Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 bridge/fdb.c              | 6 ++++++
 include/linux/neighbour.h | 1 +
 2 files changed, 7 insertions(+)

diff --git a/bridge/fdb.c b/bridge/fdb.c
index a71a78f..e5cebf9 100644
--- a/bridge/fdb.c
+++ b/bridge/fdb.c
@@ -262,6 +262,10 @@ int print_fdb(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
 		}
 		if (r->ndm_flags & NTF_EXT_LEARNED) {
 			start_json_fdb_flags_array(&fdb_flags);
+			jsonw_string(jw_global, "extern_learn");
+		}
+		if (r->ndm_flags & NTF_OFFLOADED) {
+			start_json_fdb_flags_array(&fdb_flags);
 			jsonw_string(jw_global, "offload");
 		}
 		if (r->ndm_flags & NTF_MASTER)
@@ -280,6 +284,8 @@ int print_fdb(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
 		if (r->ndm_flags & NTF_ROUTER)
 			fprintf(fp, "router ");
 		if (r->ndm_flags & NTF_EXT_LEARNED)
+			fprintf(fp, "extern_learn ");
+		if (r->ndm_flags & NTF_OFFLOADED)
 			fprintf(fp, "offload ");
 		if (tb[NDA_MASTER]) {
 			fprintf(fp, "master %s ",
diff --git a/include/linux/neighbour.h b/include/linux/neighbour.h
index f3d16db..3199d28 100644
--- a/include/linux/neighbour.h
+++ b/include/linux/neighbour.h
@@ -41,6 +41,7 @@ enum {
 #define NTF_MASTER	0x04
 #define NTF_PROXY	0x08	/* == ATF_PUBL */
 #define NTF_EXT_LEARNED	0x10
+#define NTF_OFFLOADED   0x20
 #define NTF_ROUTER	0x80
 
 /*
-- 
2.9.3

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

* Re: [patch net-next 02/19] net: bridge: Add support for offloading port attributes
  2017-06-05  9:20 ` [patch net-next 02/19] net: bridge: Add support for offloading port attributes Jiri Pirko
@ 2017-06-05 13:29   ` Nikolay Aleksandrov
  2017-06-06 13:08     ` Arkadi Sharshevsky
  0 siblings, 1 reply; 30+ messages in thread
From: Nikolay Aleksandrov @ 2017-06-05 13:29 UTC (permalink / raw)
  To: Jiri Pirko, netdev; +Cc: davem, idosch, arkadis, mlxsw, roopa, stephen, ivecera

On 05/06/17 12:20, Jiri Pirko wrote:
> From: Arkadi Sharshevsky <arkadis@mellanox.com>
> 
> Currently the flood, learning and learning_sync port attributes are
> offloaded by setting the SELF flag. Add support for offloading the
> flood and learning attribute through the bridge code. In case of
> setting an unsupported flag on a offloded port the operation will
> fail.
> 
> The learning_sync attribute doesn't have any software representation
> and cannot be offloaded through the bridge code.
> 
> Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com>
> Reviewed-by: Ido Schimmel <idosch@mellanox.com>
> Signed-off-by: Jiri Pirko <jiri@mellanox.com>
> ---
>  net/bridge/br_netlink.c | 112 +++++++++++++++++++++++++++++++++++++++---------
>  net/bridge/br_private.h |   4 ++
>  2 files changed, 96 insertions(+), 20 deletions(-)
> 

Hi Arkadi,
A few comments below

> diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
> index 1e63ec4..1afafb7 100644
> --- a/net/bridge/br_netlink.c
> +++ b/net/bridge/br_netlink.c
> @@ -17,6 +17,7 @@
>  #include <net/net_namespace.h>
>  #include <net/sock.h>
>  #include <uapi/linux/if_bridge.h>
> +#include <net/switchdev.h>
>  
>  #include "br_private.h"
>  #include "br_private_stp.h"
> @@ -662,16 +663,52 @@ static int br_set_port_state(struct net_bridge_port *p, u8 state)
>  }
>  
>  /* Set/clear or port flags based on attribute */
> -static void br_set_port_flag(struct net_bridge_port *p, struct nlattr *tb[],
> -			   int attrtype, unsigned long mask)
> +static int br_set_port_flag(struct net_bridge_port *p, struct nlattr *tb[],
> +			    int attrtype, unsigned long mask)
>  {
> -	if (tb[attrtype]) {
> -		u8 flag = nla_get_u8(tb[attrtype]);
> -		if (flag)
> -			p->flags |= mask;
> -		else
> -			p->flags &= ~mask;
> +	struct switchdev_attr attr = {
> +		.orig_dev = p->dev,
> +		.id = SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT,
> +	};
> +	unsigned long flags;
> +	int err;
> +
> +	if (!tb[attrtype])
> +		return 0;
> +
> +	if (nla_get_u8(tb[attrtype]))
> +		flags = p->flags | mask;
> +	else
> +		flags = p->flags & ~mask;
> +
> +	if (mask & ~BR_PORT_FLAGS_HW_OFFLOAD)
> +		goto out;
> +
> +	err = switchdev_port_attr_get(p->dev, &attr);
> +	if (err == -EOPNOTSUPP)
> +		goto out;
> +	if (err)
> +		return err;
> +
> +	/* Check if specific bridge flag attribute offload is supported */
> +	if (!(attr.u.brport_flags_support & mask)) {
> +		br_warn(p->br, "bridge flag offload is not supported %u(%s)\n",
> +			(unsigned int)p->port_no, p->dev->name);
> +		return -EOPNOTSUPP;
> +	}
> +
> +	attr.id = SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS;
> +	attr.flags = SWITCHDEV_F_DEFER;
> +	attr.u.brport_flags = flags;
> +	err = switchdev_port_attr_set(p->dev, &attr);
> +	if (err) {
> +		br_warn(p->br, "error setting offload FLAG on port %u(%s)\n",

Why all caps (FLAG) ?

> +			(unsigned int)p->port_no, p->dev->name);
> +		return err;
>  	}

I think all of this switchdev-specific code should be contained into br_switchdev.c and
exported via some function. Anyone changing only the bridge can easily get confused.

> +out:
> +	p->flags = flags;
> +	return 0;
>  }
>  
>  /* Process bridge protocol info on port */
> @@ -681,20 +718,55 @@ static int br_setport(struct net_bridge_port *p, struct nlattr *tb[])
>  	bool br_vlan_tunnel_old = false;
>  	int err;
>  
> -	br_set_port_flag(p, tb, IFLA_BRPORT_MODE, BR_HAIRPIN_MODE);
> -	br_set_port_flag(p, tb, IFLA_BRPORT_GUARD, BR_BPDU_GUARD);
> -	br_set_port_flag(p, tb, IFLA_BRPORT_FAST_LEAVE, BR_MULTICAST_FAST_LEAVE);
> -	br_set_port_flag(p, tb, IFLA_BRPORT_PROTECT, BR_ROOT_BLOCK);
> -	br_set_port_flag(p, tb, IFLA_BRPORT_LEARNING, BR_LEARNING);
> -	br_set_port_flag(p, tb, IFLA_BRPORT_UNICAST_FLOOD, BR_FLOOD);
> -	br_set_port_flag(p, tb, IFLA_BRPORT_MCAST_FLOOD, BR_MCAST_FLOOD);
> -	br_set_port_flag(p, tb, IFLA_BRPORT_MCAST_TO_UCAST, BR_MULTICAST_TO_UNICAST);
> -	br_set_port_flag(p, tb, IFLA_BRPORT_BCAST_FLOOD, BR_BCAST_FLOOD);
> -	br_set_port_flag(p, tb, IFLA_BRPORT_PROXYARP, BR_PROXYARP);
> -	br_set_port_flag(p, tb, IFLA_BRPORT_PROXYARP_WIFI, BR_PROXYARP_WIFI);
> +	err = br_set_port_flag(p, tb, IFLA_BRPORT_MODE, BR_HAIRPIN_MODE);
> +	if (err)
> +		return err;
> +
> +	err = br_set_port_flag(p, tb, IFLA_BRPORT_GUARD, BR_BPDU_GUARD);
> +	if (err)
> +		return err;
> +
> +	err = br_set_port_flag(p, tb, IFLA_BRPORT_FAST_LEAVE, BR_MULTICAST_FAST_LEAVE);
> +	if (err)
> +		return err;
> +
> +	err = br_set_port_flag(p, tb, IFLA_BRPORT_PROTECT, BR_ROOT_BLOCK);
> +	if (err)
> +		return err;
> +
> +	err = br_set_port_flag(p, tb, IFLA_BRPORT_LEARNING, BR_LEARNING);
> +	if (err)
> +		return err;
> +
> +	err = br_set_port_flag(p, tb, IFLA_BRPORT_UNICAST_FLOOD, BR_FLOOD);
> +	if (err)
> +		return err;
> +
> +	err = br_set_port_flag(p, tb, IFLA_BRPORT_MCAST_FLOOD, BR_MCAST_FLOOD);
> +	if (err)
> +		return err;
> +
> +	err = br_set_port_flag(p, tb, IFLA_BRPORT_MCAST_TO_UCAST, BR_MULTICAST_TO_UNICAST);
> +	if (err)
> +		return err;
> +
> +	err = br_set_port_flag(p, tb, IFLA_BRPORT_BCAST_FLOOD, BR_BCAST_FLOOD);
> +	if (err)
> +		return err;
> +
> +	err = br_set_port_flag(p, tb, IFLA_BRPORT_PROXYARP, BR_PROXYARP);
> +	if (err)
> +		return err;
> +
> +	err = br_set_port_flag(p, tb, IFLA_BRPORT_PROXYARP_WIFI, BR_PROXYARP_WIFI);
> +	if (err)
> +		return err;
>  
>  	br_vlan_tunnel_old = (p->flags & BR_VLAN_TUNNEL) ? true : false;
> -	br_set_port_flag(p, tb, IFLA_BRPORT_VLAN_TUNNEL, BR_VLAN_TUNNEL);
> +	err = br_set_port_flag(p, tb, IFLA_BRPORT_VLAN_TUNNEL, BR_VLAN_TUNNEL);
> +	if (err)
> +		return err;
> +
>  	if (br_vlan_tunnel_old && !(p->flags & BR_VLAN_TUNNEL))
>  		nbp_vlan_tunnel_info_flush(p);
>  
> diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
> index 2062692..5dc30ed 100644
> --- a/net/bridge/br_private.h
> +++ b/net/bridge/br_private.h
> @@ -42,6 +42,10 @@
>  /* Path to usermode spanning tree program */
>  #define BR_STP_PROG	"/sbin/bridge-stp"
>  
> +/* Flags that can be offloaded to hardware */
> +#define BR_PORT_FLAGS_HW_OFFLOAD (BR_LEARNING | BR_FLOOD | \
> +				  BR_MCAST_FLOOD | BR_BCAST_FLOOD)
> +
>  typedef struct bridge_id bridge_id;
>  typedef struct mac_addr mac_addr;
>  typedef __u16 port_id;
> 

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

* Re: [patch net-next 05/19] net: bridge: Add support for notifying devices about FDB add/del
  2017-06-05  9:20 ` [patch net-next 05/19] net: bridge: Add support for notifying devices about FDB add/del Jiri Pirko
@ 2017-06-05 13:35   ` Nikolay Aleksandrov
  2017-06-06 14:19     ` Arkadi Sharshevsky
  0 siblings, 1 reply; 30+ messages in thread
From: Nikolay Aleksandrov @ 2017-06-05 13:35 UTC (permalink / raw)
  To: Jiri Pirko, netdev; +Cc: davem, idosch, arkadis, mlxsw, roopa, stephen, ivecera

On 05/06/17 12:20, Jiri Pirko wrote:
> From: Arkadi Sharshevsky <arkadis@mellanox.com>
> 
> Currently the bridge doesn't notify the underlying devices about new
> FDBs learned. The FDB sync is placed on the switchdev notifier chain
> because devices may potentially learn FDB that are not directly related
> to their ports, for example:
> 
> 1. Mixed SW/HW bridge - FDBs that point to the ASICs external devices
>                         should be offloaded as CPU traps in order to
> 			perform forwarding in slow path.
> 2. EVPN - Externally learned FDBs for the vtep device.
> 
> Notification is sent only about static FDB add/del. This is done due
> to fact that currently this is the only scenario supported by switch
> drivers.
> 
> Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com>
> Reviewed-by: Ido Schimmel <idosch@mellanox.com>
> Signed-off-by: Jiri Pirko <jiri@mellanox.com>
> ---
>  .../ethernet/mellanox/mlxsw/spectrum_switchdev.c   |  2 +-
>  drivers/net/ethernet/rocker/rocker_ofdpa.c         |  4 ++--
>  include/net/switchdev.h                            |  6 ++++--
>  net/bridge/br.c                                    |  4 ++--
>  net/bridge/br_fdb.c                                | 22 ++++++++++++++++++++++
>  net/bridge/br_private.h                            |  8 ++++++++
>  net/bridge/br_switchdev.c                          | 13 +++++++++++++
>  7 files changed, 52 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
> index edcc273..0111a77 100644
> --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
> +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
> @@ -1867,7 +1867,7 @@ static void mlxsw_sp_fdb_call_notifiers(bool learning_sync, bool adding,
>  	if (learning_sync) {
>  		info.addr = mac;
>  		info.vid = vid;
> -		notifier_type = adding ? SWITCHDEV_FDB_ADD : SWITCHDEV_FDB_DEL;
> +		notifier_type = adding ? SWITCHDEV_FDB_ADD_TO_BRIDGE : SWITCHDEV_FDB_DEL_TO_BRIDGE;
>  		call_switchdev_notifiers(notifier_type, dev, &info.info);
>  	}
>  }
> diff --git a/drivers/net/ethernet/rocker/rocker_ofdpa.c b/drivers/net/ethernet/rocker/rocker_ofdpa.c
> index 2ae8524..f659dad 100644
> --- a/drivers/net/ethernet/rocker/rocker_ofdpa.c
> +++ b/drivers/net/ethernet/rocker/rocker_ofdpa.c
> @@ -1939,10 +1939,10 @@ static void ofdpa_port_fdb_learn_work(struct work_struct *work)
>  
>  	rtnl_lock();
>  	if (learned && removing)
> -		call_switchdev_notifiers(SWITCHDEV_FDB_DEL,
> +		call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_BRIDGE,
>  					 lw->ofdpa_port->dev, &info.info);
>  	else if (learned && !removing)
> -		call_switchdev_notifiers(SWITCHDEV_FDB_ADD,
> +		call_switchdev_notifiers(SWITCHDEV_FDB_ADD_TO_BRIDGE,
>  					 lw->ofdpa_port->dev, &info.info);
>  	rtnl_unlock();
>  
> diff --git a/include/net/switchdev.h b/include/net/switchdev.h
> index 63a754d..8165ed9 100644
> --- a/include/net/switchdev.h
> +++ b/include/net/switchdev.h
> @@ -155,8 +155,10 @@ struct switchdev_ops {
>  };
>  
>  enum switchdev_notifier_type {
> -	SWITCHDEV_FDB_ADD = 1,
> -	SWITCHDEV_FDB_DEL,
> +	SWITCHDEV_FDB_ADD_TO_BRIDGE = 1,
> +	SWITCHDEV_FDB_DEL_TO_BRIDGE,
> +	SWITCHDEV_FDB_ADD_TO_DEVICE,
> +	SWITCHDEV_FDB_DEL_TO_DEVICE,
>  };
>  
>  struct switchdev_notifier_info {
> diff --git a/net/bridge/br.c b/net/bridge/br.c
> index e962fff..96d209c 100644
> --- a/net/bridge/br.c
> +++ b/net/bridge/br.c
> @@ -138,14 +138,14 @@ static int br_switchdev_event(struct notifier_block *unused,
>  	br = p->br;
>  
>  	switch (event) {
> -	case SWITCHDEV_FDB_ADD:
> +	case SWITCHDEV_FDB_ADD_TO_BRIDGE:
>  		fdb_info = ptr;
>  		err = br_fdb_external_learn_add(br, p, fdb_info->addr,
>  						fdb_info->vid);
>  		if (err)
>  			err = notifier_from_errno(err);
>  		break;
> -	case SWITCHDEV_FDB_DEL:
> +	case SWITCHDEV_FDB_DEL_TO_BRIDGE:
>  		fdb_info = ptr;
>  		err = br_fdb_external_learn_del(br, p, fdb_info->addr,
>  						fdb_info->vid);
> diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
> index 5c780cd..21bf9d2 100644
> --- a/net/bridge/br_fdb.c
> +++ b/net/bridge/br_fdb.c
> @@ -683,6 +683,26 @@ static inline size_t fdb_nlmsg_size(void)
>  		+ nla_total_size(sizeof(struct nda_cacheinfo));
>  }
>  
> +static void
> +fdb_notify_switchdev(const struct net_bridge_fdb_entry *fdb, int type)
> +{
> +	if (!fdb->added_by_user)
> +		return;
> +
> +	switch (type) {
> +	case RTM_DELNEIGH:
> +		br_switchdev_fdb_call_notifiers(false, fdb->addr.addr,
> +						fdb->vlan_id,
> +						fdb->dst->dev);
> +		break;
> +	case RTM_NEWNEIGH:
> +		br_switchdev_fdb_call_notifiers(true, fdb->addr.addr,
> +						fdb->vlan_id,
> +						fdb->dst->dev);
> +		break;
> +	}
> +}

Same comment here, this switchdev-specific logic can be contained in
br_switchdev_fdb_call_notifiers().

> +
>  static void fdb_notify(struct net_bridge *br,
>  		       const struct net_bridge_fdb_entry *fdb, int type)
>  {
> @@ -690,6 +710,8 @@ static void fdb_notify(struct net_bridge *br,
>  	struct sk_buff *skb;
>  	int err = -ENOBUFS;
>  
> +	fdb_notify_switchdev(fdb, type);
> +
>  	skb = nlmsg_new(fdb_nlmsg_size(), GFP_ATOMIC);
>  	if (skb == NULL)
>  		goto errout;
> diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
> index 69ba3ba..5e944e9 100644
> --- a/net/bridge/br_private.h
> +++ b/net/bridge/br_private.h
> @@ -1086,6 +1086,8 @@ void nbp_switchdev_frame_mark(const struct net_bridge_port *p,
>  			      struct sk_buff *skb);
>  bool nbp_switchdev_allowed_egress(const struct net_bridge_port *p,
>  				  const struct sk_buff *skb);
> +void br_switchdev_fdb_call_notifiers(bool adding, const unsigned char *mac,
> +				     u16 vid, struct net_device *dev);
>  #else
>  static inline int nbp_switchdev_mark_set(struct net_bridge_port *p)
>  {
> @@ -1102,6 +1104,12 @@ static inline bool nbp_switchdev_allowed_egress(const struct net_bridge_port *p,
>  {
>  	return true;
>  }
> +
> +static inline void
> +br_switchdev_fdb_call_notifiers(bool adding, const unsigned char *mac,
> +				u16 vid, struct net_device *dev)
> +{
> +}
>  #endif /* CONFIG_NET_SWITCHDEV */
>  
>  #endif
> diff --git a/net/bridge/br_switchdev.c b/net/bridge/br_switchdev.c
> index f4097b9..c07dceb 100644
> --- a/net/bridge/br_switchdev.c
> +++ b/net/bridge/br_switchdev.c
> @@ -55,3 +55,16 @@ bool nbp_switchdev_allowed_egress(const struct net_bridge_port *p,
>  	return !skb->offload_fwd_mark ||
>  	       BR_INPUT_SKB_CB(skb)->offload_fwd_mark != p->offload_fwd_mark;
>  }
> +
> +void
> +br_switchdev_fdb_call_notifiers(bool adding, const unsigned char *mac,
> +				u16 vid, struct net_device *dev)
> +{
> +	struct switchdev_notifier_fdb_info info;
> +	unsigned long notifier_type;
> +
> +	info.addr = mac;
> +	info.vid = vid;
> +	notifier_type = adding ? SWITCHDEV_FDB_ADD_TO_DEVICE : SWITCHDEV_FDB_DEL_TO_DEVICE;
> +	call_switchdev_notifiers(notifier_type, dev, &info.info);
> +}
> 

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

* Re: [patch net-next 03/19] net: bridge: Add support for calling FDB external learning under rcu
  2017-06-05  9:20 ` [patch net-next 03/19] net: bridge: Add support for calling FDB external learning under rcu Jiri Pirko
@ 2017-06-05 13:36   ` Nikolay Aleksandrov
  0 siblings, 0 replies; 30+ messages in thread
From: Nikolay Aleksandrov @ 2017-06-05 13:36 UTC (permalink / raw)
  To: Jiri Pirko, netdev; +Cc: davem, idosch, arkadis, mlxsw, roopa, stephen, ivecera

On 05/06/17 12:20, Jiri Pirko wrote:
> From: Arkadi Sharshevsky <arkadis@mellanox.com>
> 
> This is done as a preparation to moving the switchdev notifier chain
> to be atomic. The FDB external learning should be called under rtnl
> or rcu.
> 
> Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com>
> Reviewed-by: Ido Schimmel <idosch@mellanox.com>
> Signed-off-by: Jiri Pirko <jiri@mellanox.com>
> ---
>  net/bridge/br.c         | 4 ++--
>  net/bridge/br_fdb.c     | 2 --
>  net/bridge/br_private.h | 6 ++++++
>  3 files changed, 8 insertions(+), 4 deletions(-)
> 

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

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

* Re: [patch net-next 06/19] net: bridge: Receive notification about successful FDB offload
  2017-06-05  9:20 ` [patch net-next 06/19] net: bridge: Receive notification about successful FDB offload Jiri Pirko
@ 2017-06-05 13:44   ` Nikolay Aleksandrov
  0 siblings, 0 replies; 30+ messages in thread
From: Nikolay Aleksandrov @ 2017-06-05 13:44 UTC (permalink / raw)
  To: Jiri Pirko, netdev; +Cc: davem, idosch, arkadis, mlxsw, roopa, stephen, ivecera

On 05/06/17 12:20, Jiri Pirko wrote:
> From: Arkadi Sharshevsky <arkadis@mellanox.com>
> 
> When a new static FDB is added to the bridge a notification is sent to
> the driver for offload. In case of successful offload the driver should
> notify the bridge back, which in turn should mark the FDB as offloaded.
> 
> Currently, externally learned is equivalent for being offloaded which is
> not correct due to the fact that FDBs which are added from user-space are
> also marked as externally learned. In order to specify if an FDB was
> successfully offloaded a new flag is introduced.
> 
> Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com>
> Reviewed-by: Ido Schimmel <idosch@mellanox.com>
> Signed-off-by: Jiri Pirko <jiri@mellanox.com>
> ---
>  include/net/switchdev.h        |  1 +
>  include/uapi/linux/neighbour.h |  1 +
>  net/bridge/br.c                | 11 ++++++++++-
>  net/bridge/br_fdb.c            | 22 +++++++++++++++++++++-
>  net/bridge/br_private.h        |  5 ++++-
>  5 files changed, 37 insertions(+), 3 deletions(-)
> 

Overall the patch looks good to me, one thing to note is that there's a race
window between the call to br_fdb_external_learn_add() and br_fdb_offloaded_set()
where a sw port can take over the entry (and thus set added_by_external_learn = 0)
but have br_fdb_offloaded_set() set its offloaded flag to 1. Now I know the bridge
generally has these known race conditions between fdb flag manipulations so just wanted
to mention it.

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

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

* Re: [patch net-next 04/19] net: switchdev: Change notifier chain to be atomic
  2017-06-05  9:20 ` [patch net-next 04/19] net: switchdev: Change notifier chain to be atomic Jiri Pirko
@ 2017-06-05 13:59   ` Ivan Vecera
  0 siblings, 0 replies; 30+ messages in thread
From: Ivan Vecera @ 2017-06-05 13:59 UTC (permalink / raw)
  To: Jiri Pirko, netdev; +Cc: davem, idosch, arkadis, mlxsw, roopa, stephen

On 5.6.2017 11:20, Jiri Pirko wrote:
> From: Arkadi Sharshevsky <arkadis@mellanox.com>
> 
> In order to use the switchdev notifier chain for FDB sync with the
> device it has to be changed to atomic. The is done because the bridge
> can learn new FDBs in atomic context.
> 
> Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com>
> Reviewed-by: Ido Schimmel <idosch@mellanox.com>
> Signed-off-by: Jiri Pirko <jiri@mellanox.com>
> ---
>  net/switchdev/switchdev.c | 30 ++++++------------------------
>  1 file changed, 6 insertions(+), 24 deletions(-)
> 
> diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c
> index 8d40a7d..25dc67e 100644
> --- a/net/switchdev/switchdev.c
> +++ b/net/switchdev/switchdev.c
> @@ -571,24 +571,17 @@ int switchdev_port_obj_dump(struct net_device *dev, struct switchdev_obj *obj,
>  }
>  EXPORT_SYMBOL_GPL(switchdev_port_obj_dump);
>  
> -static RAW_NOTIFIER_HEAD(switchdev_notif_chain);
> +static ATOMIC_NOTIFIER_HEAD(switchdev_notif_chain);
>  
>  /**
>   *	register_switchdev_notifier - Register notifier
>   *	@nb: notifier_block
>   *
> - *	Register switch device notifier. This should be used by code
> - *	which needs to monitor events happening in particular device.
> - *	Return values are same as for atomic_notifier_chain_register().
> + *	Register switch device notifier.
>   */
>  int register_switchdev_notifier(struct notifier_block *nb)
>  {
> -	int err;
> -
> -	rtnl_lock();
> -	err = raw_notifier_chain_register(&switchdev_notif_chain, nb);
> -	rtnl_unlock();
> -	return err;
> +	return atomic_notifier_chain_register(&switchdev_notif_chain, nb);
>  }
>  EXPORT_SYMBOL_GPL(register_switchdev_notifier);
>  
> @@ -597,16 +590,10 @@ EXPORT_SYMBOL_GPL(register_switchdev_notifier);
>   *	@nb: notifier_block
>   *
>   *	Unregister switch device notifier.
> - *	Return values are same as for atomic_notifier_chain_unregister().
>   */
>  int unregister_switchdev_notifier(struct notifier_block *nb)
>  {
> -	int err;
> -
> -	rtnl_lock();
> -	err = raw_notifier_chain_unregister(&switchdev_notif_chain, nb);
> -	rtnl_unlock();
> -	return err;
> +	return atomic_notifier_chain_unregister(&switchdev_notif_chain, nb);
>  }
>  EXPORT_SYMBOL_GPL(unregister_switchdev_notifier);
>  
> @@ -616,18 +603,13 @@ EXPORT_SYMBOL_GPL(unregister_switchdev_notifier);
>   *	@dev: port device
>   *	@info: notifier information data
>   *
> - *	Call all network notifier blocks. This should be called by driver
> - *	when it needs to propagate hardware event.
> - *	Return values are same as for atomic_notifier_call_chain().
> - *	rtnl_lock must be held.
> + *	Call all network notifier blocks.
>   */
>  int call_switchdev_notifiers(unsigned long val, struct net_device *dev,
>  			     struct switchdev_notifier_info *info)
>  {
> -	ASSERT_RTNL();
> -
>  	info->dev = dev;
> -	return raw_notifier_call_chain(&switchdev_notif_chain, val, info);
> +	return atomic_notifier_call_chain(&switchdev_notif_chain, val, info);
>  }
>  EXPORT_SYMBOL_GPL(call_switchdev_notifiers);
>  
> 

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

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

* Re: [patch net-next 01/19] net: switchdev: Add support for querying supported bridge flags by hardware
  2017-06-05  9:20 ` [patch net-next 01/19] net: switchdev: Add support for querying supported bridge flags by hardware Jiri Pirko
@ 2017-06-05 14:00   ` Ivan Vecera
  0 siblings, 0 replies; 30+ messages in thread
From: Ivan Vecera @ 2017-06-05 14:00 UTC (permalink / raw)
  To: Jiri Pirko, netdev; +Cc: davem, idosch, arkadis, mlxsw, roopa, stephen

On 5.6.2017 11:20, Jiri Pirko wrote:
> From: Arkadi Sharshevsky <arkadis@mellanox.com>
> 
> This is done as a preparation stage before setting the bridge port flags
> from the bridge code. Currently the device can be queried for the bridge
> flags state, but the querier cannot distinguish if the flag is disabled
> or if it is not supported at all. Thus, add new attr and a bit-mask which
> include information regarding the support on a per-flag basis.
> 
> Drivers that support bridge offload but not support bridge flags should
> return zeroed bitmask.
> 
> Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com>
> Reviewed-by: Ido Schimmel <idosch@mellanox.com>
> Signed-off-by: Jiri Pirko <jiri@mellanox.com>
> ---
>  include/net/switchdev.h | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/include/net/switchdev.h b/include/net/switchdev.h
> index 929d6af..63a754d 100644
> --- a/include/net/switchdev.h
> +++ b/include/net/switchdev.h
> @@ -46,6 +46,7 @@ enum switchdev_attr_id {
>  	SWITCHDEV_ATTR_ID_PORT_PARENT_ID,
>  	SWITCHDEV_ATTR_ID_PORT_STP_STATE,
>  	SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS,
> +	SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT,
>  	SWITCHDEV_ATTR_ID_PORT_MROUTER,
>  	SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME,
>  	SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING,
> @@ -62,6 +63,7 @@ struct switchdev_attr {
>  		struct netdev_phys_item_id ppid;	/* PORT_PARENT_ID */
>  		u8 stp_state;				/* PORT_STP_STATE */
>  		unsigned long brport_flags;		/* PORT_BRIDGE_FLAGS */
> +		unsigned long brport_flags_support;	/* PORT_BRIDGE_FLAGS_SUPPORT */
>  		bool mrouter;				/* PORT_MROUTER */
>  		clock_t ageing_time;			/* BRIDGE_AGEING_TIME */
>  		bool vlan_filtering;			/* BRIDGE_VLAN_FILTERING */
> 

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

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

* Re: [patch net-next 02/19] net: bridge: Add support for offloading port attributes
  2017-06-05 13:29   ` Nikolay Aleksandrov
@ 2017-06-06 13:08     ` Arkadi Sharshevsky
  0 siblings, 0 replies; 30+ messages in thread
From: Arkadi Sharshevsky @ 2017-06-06 13:08 UTC (permalink / raw)
  To: Nikolay Aleksandrov, Jiri Pirko, netdev
  Cc: davem, idosch, mlxsw, roopa, stephen, ivecera



On 06/05/2017 04:29 PM, Nikolay Aleksandrov wrote:
> On 05/06/17 12:20, Jiri Pirko wrote:
>> From: Arkadi Sharshevsky <arkadis@mellanox.com>
>>
>> Currently the flood, learning and learning_sync port attributes are
>> offloaded by setting the SELF flag. Add support for offloading the
>> flood and learning attribute through the bridge code. In case of
>> setting an unsupported flag on a offloded port the operation will
>> fail.
>>
>> The learning_sync attribute doesn't have any software representation
>> and cannot be offloaded through the bridge code.
>>
>> Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com>
>> Reviewed-by: Ido Schimmel <idosch@mellanox.com>
>> Signed-off-by: Jiri Pirko <jiri@mellanox.com>
>> ---
>>  net/bridge/br_netlink.c | 112 +++++++++++++++++++++++++++++++++++++++---------
>>  net/bridge/br_private.h |   4 ++
>>  2 files changed, 96 insertions(+), 20 deletions(-)
>>
> 
> Hi Arkadi,
> A few comments below
> 

Hi Nikolay,
Thank you very much for the review, will fix.

>> diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
>> index 1e63ec4..1afafb7 100644
>> --- a/net/bridge/br_netlink.c
>> +++ b/net/bridge/br_netlink.c
>> @@ -17,6 +17,7 @@
>>  #include <net/net_namespace.h>
>>  #include <net/sock.h>
>>  #include <uapi/linux/if_bridge.h>
>> +#include <net/switchdev.h>
>>  
>>  #include "br_private.h"
>>  #include "br_private_stp.h"
>> @@ -662,16 +663,52 @@ static int br_set_port_state(struct net_bridge_port *p, u8 state)
>>  }
>>  
>>  /* Set/clear or port flags based on attribute */
>> -static void br_set_port_flag(struct net_bridge_port *p, struct nlattr *tb[],
>> -			   int attrtype, unsigned long mask)
>> +static int br_set_port_flag(struct net_bridge_port *p, struct nlattr *tb[],
>> +			    int attrtype, unsigned long mask)
>>  {
>> -	if (tb[attrtype]) {
>> -		u8 flag = nla_get_u8(tb[attrtype]);
>> -		if (flag)
>> -			p->flags |= mask;
>> -		else
>> -			p->flags &= ~mask;
>> +	struct switchdev_attr attr = {
>> +		.orig_dev = p->dev,
>> +		.id = SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT,
>> +	};
>> +	unsigned long flags;
>> +	int err;
>> +
>> +	if (!tb[attrtype])
>> +		return 0;
>> +
>> +	if (nla_get_u8(tb[attrtype]))
>> +		flags = p->flags | mask;
>> +	else
>> +		flags = p->flags & ~mask;
>> +
>> +	if (mask & ~BR_PORT_FLAGS_HW_OFFLOAD)
>> +		goto out;
>> +
>> +	err = switchdev_port_attr_get(p->dev, &attr);
>> +	if (err == -EOPNOTSUPP)
>> +		goto out;
>> +	if (err)
>> +		return err;
>> +
>> +	/* Check if specific bridge flag attribute offload is supported */
>> +	if (!(attr.u.brport_flags_support & mask)) {
>> +		br_warn(p->br, "bridge flag offload is not supported %u(%s)\n",
>> +			(unsigned int)p->port_no, p->dev->name);
>> +		return -EOPNOTSUPP;
>> +	}
>> +
>> +	attr.id = SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS;
>> +	attr.flags = SWITCHDEV_F_DEFER;
>> +	attr.u.brport_flags = flags;
>> +	err = switchdev_port_attr_set(p->dev, &attr);
>> +	if (err) {
>> +		br_warn(p->br, "error setting offload FLAG on port %u(%s)\n",
> 
> Why all caps (FLAG) ?
> 
>> +			(unsigned int)p->port_no, p->dev->name);
>> +		return err;
>>  	}
> 
> I think all of this switchdev-specific code should be contained into br_switchdev.c and
> exported via some function. Anyone changing only the bridge can easily get confused.
> 
>> +out:
>> +	p->flags = flags;
>> +	return 0;
>>  }
>>  
>>  /* Process bridge protocol info on port */
>> @@ -681,20 +718,55 @@ static int br_setport(struct net_bridge_port *p, struct nlattr *tb[])
>>  	bool br_vlan_tunnel_old = false;
>>  	int err;
>>  
>> -	br_set_port_flag(p, tb, IFLA_BRPORT_MODE, BR_HAIRPIN_MODE);
>> -	br_set_port_flag(p, tb, IFLA_BRPORT_GUARD, BR_BPDU_GUARD);
>> -	br_set_port_flag(p, tb, IFLA_BRPORT_FAST_LEAVE, BR_MULTICAST_FAST_LEAVE);
>> -	br_set_port_flag(p, tb, IFLA_BRPORT_PROTECT, BR_ROOT_BLOCK);
>> -	br_set_port_flag(p, tb, IFLA_BRPORT_LEARNING, BR_LEARNING);
>> -	br_set_port_flag(p, tb, IFLA_BRPORT_UNICAST_FLOOD, BR_FLOOD);
>> -	br_set_port_flag(p, tb, IFLA_BRPORT_MCAST_FLOOD, BR_MCAST_FLOOD);
>> -	br_set_port_flag(p, tb, IFLA_BRPORT_MCAST_TO_UCAST, BR_MULTICAST_TO_UNICAST);
>> -	br_set_port_flag(p, tb, IFLA_BRPORT_BCAST_FLOOD, BR_BCAST_FLOOD);
>> -	br_set_port_flag(p, tb, IFLA_BRPORT_PROXYARP, BR_PROXYARP);
>> -	br_set_port_flag(p, tb, IFLA_BRPORT_PROXYARP_WIFI, BR_PROXYARP_WIFI);
>> +	err = br_set_port_flag(p, tb, IFLA_BRPORT_MODE, BR_HAIRPIN_MODE);
>> +	if (err)
>> +		return err;
>> +
>> +	err = br_set_port_flag(p, tb, IFLA_BRPORT_GUARD, BR_BPDU_GUARD);
>> +	if (err)
>> +		return err;
>> +
>> +	err = br_set_port_flag(p, tb, IFLA_BRPORT_FAST_LEAVE, BR_MULTICAST_FAST_LEAVE);
>> +	if (err)
>> +		return err;
>> +
>> +	err = br_set_port_flag(p, tb, IFLA_BRPORT_PROTECT, BR_ROOT_BLOCK);
>> +	if (err)
>> +		return err;
>> +
>> +	err = br_set_port_flag(p, tb, IFLA_BRPORT_LEARNING, BR_LEARNING);
>> +	if (err)
>> +		return err;
>> +
>> +	err = br_set_port_flag(p, tb, IFLA_BRPORT_UNICAST_FLOOD, BR_FLOOD);
>> +	if (err)
>> +		return err;
>> +
>> +	err = br_set_port_flag(p, tb, IFLA_BRPORT_MCAST_FLOOD, BR_MCAST_FLOOD);
>> +	if (err)
>> +		return err;
>> +
>> +	err = br_set_port_flag(p, tb, IFLA_BRPORT_MCAST_TO_UCAST, BR_MULTICAST_TO_UNICAST);
>> +	if (err)
>> +		return err;
>> +
>> +	err = br_set_port_flag(p, tb, IFLA_BRPORT_BCAST_FLOOD, BR_BCAST_FLOOD);
>> +	if (err)
>> +		return err;
>> +
>> +	err = br_set_port_flag(p, tb, IFLA_BRPORT_PROXYARP, BR_PROXYARP);
>> +	if (err)
>> +		return err;
>> +
>> +	err = br_set_port_flag(p, tb, IFLA_BRPORT_PROXYARP_WIFI, BR_PROXYARP_WIFI);
>> +	if (err)
>> +		return err;
>>  
>>  	br_vlan_tunnel_old = (p->flags & BR_VLAN_TUNNEL) ? true : false;
>> -	br_set_port_flag(p, tb, IFLA_BRPORT_VLAN_TUNNEL, BR_VLAN_TUNNEL);
>> +	err = br_set_port_flag(p, tb, IFLA_BRPORT_VLAN_TUNNEL, BR_VLAN_TUNNEL);
>> +	if (err)
>> +		return err;
>> +
>>  	if (br_vlan_tunnel_old && !(p->flags & BR_VLAN_TUNNEL))
>>  		nbp_vlan_tunnel_info_flush(p);
>>  
>> diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
>> index 2062692..5dc30ed 100644
>> --- a/net/bridge/br_private.h
>> +++ b/net/bridge/br_private.h
>> @@ -42,6 +42,10 @@
>>  /* Path to usermode spanning tree program */
>>  #define BR_STP_PROG	"/sbin/bridge-stp"
>>  
>> +/* Flags that can be offloaded to hardware */
>> +#define BR_PORT_FLAGS_HW_OFFLOAD (BR_LEARNING | BR_FLOOD | \
>> +				  BR_MCAST_FLOOD | BR_BCAST_FLOOD)
>> +
>>  typedef struct bridge_id bridge_id;
>>  typedef struct mac_addr mac_addr;
>>  typedef __u16 port_id;
>>
> 

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

* Re: [patch net-next 05/19] net: bridge: Add support for notifying devices about FDB add/del
  2017-06-05 13:35   ` Nikolay Aleksandrov
@ 2017-06-06 14:19     ` Arkadi Sharshevsky
  0 siblings, 0 replies; 30+ messages in thread
From: Arkadi Sharshevsky @ 2017-06-06 14:19 UTC (permalink / raw)
  To: Nikolay Aleksandrov, Jiri Pirko, netdev
  Cc: davem, idosch, mlxsw, roopa, stephen, ivecera



On 06/05/2017 04:35 PM, Nikolay Aleksandrov wrote:
> On 05/06/17 12:20, Jiri Pirko wrote:
>> From: Arkadi Sharshevsky <arkadis@mellanox.com>
>>
>> Currently the bridge doesn't notify the underlying devices about new
>> FDBs learned. The FDB sync is placed on the switchdev notifier chain
>> because devices may potentially learn FDB that are not directly related
>> to their ports, for example:
>>
>> 1. Mixed SW/HW bridge - FDBs that point to the ASICs external devices
>>                         should be offloaded as CPU traps in order to
>> 			perform forwarding in slow path.
>> 2. EVPN - Externally learned FDBs for the vtep device.
>>
>> Notification is sent only about static FDB add/del. This is done due
>> to fact that currently this is the only scenario supported by switch
>> drivers.
>>
>> Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com>
>> Reviewed-by: Ido Schimmel <idosch@mellanox.com>
>> Signed-off-by: Jiri Pirko <jiri@mellanox.com>
>> ---
>>  .../ethernet/mellanox/mlxsw/spectrum_switchdev.c   |  2 +-
>>  drivers/net/ethernet/rocker/rocker_ofdpa.c         |  4 ++--
>>  include/net/switchdev.h                            |  6 ++++--
>>  net/bridge/br.c                                    |  4 ++--
>>  net/bridge/br_fdb.c                                | 22 ++++++++++++++++++++++
>>  net/bridge/br_private.h                            |  8 ++++++++
>>  net/bridge/br_switchdev.c                          | 13 +++++++++++++
>>  7 files changed, 52 insertions(+), 7 deletions(-)
>>
>> diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
>> index edcc273..0111a77 100644
>> --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
>> +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
>> @@ -1867,7 +1867,7 @@ static void mlxsw_sp_fdb_call_notifiers(bool learning_sync, bool adding,
>>  	if (learning_sync) {
>>  		info.addr = mac;
>>  		info.vid = vid;
>> -		notifier_type = adding ? SWITCHDEV_FDB_ADD : SWITCHDEV_FDB_DEL;
>> +		notifier_type = adding ? SWITCHDEV_FDB_ADD_TO_BRIDGE : SWITCHDEV_FDB_DEL_TO_BRIDGE;
>>  		call_switchdev_notifiers(notifier_type, dev, &info.info);
>>  	}
>>  }
>> diff --git a/drivers/net/ethernet/rocker/rocker_ofdpa.c b/drivers/net/ethernet/rocker/rocker_ofdpa.c
>> index 2ae8524..f659dad 100644
>> --- a/drivers/net/ethernet/rocker/rocker_ofdpa.c
>> +++ b/drivers/net/ethernet/rocker/rocker_ofdpa.c
>> @@ -1939,10 +1939,10 @@ static void ofdpa_port_fdb_learn_work(struct work_struct *work)
>>  
>>  	rtnl_lock();
>>  	if (learned && removing)
>> -		call_switchdev_notifiers(SWITCHDEV_FDB_DEL,
>> +		call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_BRIDGE,
>>  					 lw->ofdpa_port->dev, &info.info);
>>  	else if (learned && !removing)
>> -		call_switchdev_notifiers(SWITCHDEV_FDB_ADD,
>> +		call_switchdev_notifiers(SWITCHDEV_FDB_ADD_TO_BRIDGE,
>>  					 lw->ofdpa_port->dev, &info.info);
>>  	rtnl_unlock();
>>  
>> diff --git a/include/net/switchdev.h b/include/net/switchdev.h
>> index 63a754d..8165ed9 100644
>> --- a/include/net/switchdev.h
>> +++ b/include/net/switchdev.h
>> @@ -155,8 +155,10 @@ struct switchdev_ops {
>>  };
>>  
>>  enum switchdev_notifier_type {
>> -	SWITCHDEV_FDB_ADD = 1,
>> -	SWITCHDEV_FDB_DEL,
>> +	SWITCHDEV_FDB_ADD_TO_BRIDGE = 1,
>> +	SWITCHDEV_FDB_DEL_TO_BRIDGE,
>> +	SWITCHDEV_FDB_ADD_TO_DEVICE,
>> +	SWITCHDEV_FDB_DEL_TO_DEVICE,
>>  };
>>  
>>  struct switchdev_notifier_info {
>> diff --git a/net/bridge/br.c b/net/bridge/br.c
>> index e962fff..96d209c 100644
>> --- a/net/bridge/br.c
>> +++ b/net/bridge/br.c
>> @@ -138,14 +138,14 @@ static int br_switchdev_event(struct notifier_block *unused,
>>  	br = p->br;
>>  
>>  	switch (event) {
>> -	case SWITCHDEV_FDB_ADD:
>> +	case SWITCHDEV_FDB_ADD_TO_BRIDGE:
>>  		fdb_info = ptr;
>>  		err = br_fdb_external_learn_add(br, p, fdb_info->addr,
>>  						fdb_info->vid);
>>  		if (err)
>>  			err = notifier_from_errno(err);
>>  		break;
>> -	case SWITCHDEV_FDB_DEL:
>> +	case SWITCHDEV_FDB_DEL_TO_BRIDGE:
>>  		fdb_info = ptr;
>>  		err = br_fdb_external_learn_del(br, p, fdb_info->addr,
>>  						fdb_info->vid);
>> diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
>> index 5c780cd..21bf9d2 100644
>> --- a/net/bridge/br_fdb.c
>> +++ b/net/bridge/br_fdb.c
>> @@ -683,6 +683,26 @@ static inline size_t fdb_nlmsg_size(void)
>>  		+ nla_total_size(sizeof(struct nda_cacheinfo));
>>  }
>>  
>> +static void
>> +fdb_notify_switchdev(const struct net_bridge_fdb_entry *fdb, int type)
>> +{
>> +	if (!fdb->added_by_user)
>> +		return;
>> +
>> +	switch (type) {
>> +	case RTM_DELNEIGH:
>> +		br_switchdev_fdb_call_notifiers(false, fdb->addr.addr,
>> +						fdb->vlan_id,
>> +						fdb->dst->dev);
>> +		break;
>> +	case RTM_NEWNEIGH:
>> +		br_switchdev_fdb_call_notifiers(true, fdb->addr.addr,
>> +						fdb->vlan_id,
>> +						fdb->dst->dev);
>> +		break;
>> +	}
>> +}
> 
> Same comment here, this switchdev-specific logic can be contained in
> br_switchdev_fdb_call_notifiers().
> 

Thanks, will move it to br_switchdev.c.

>> +
>>  static void fdb_notify(struct net_bridge *br,
>>  		       const struct net_bridge_fdb_entry *fdb, int type)
>>  {
>> @@ -690,6 +710,8 @@ static void fdb_notify(struct net_bridge *br,
>>  	struct sk_buff *skb;
>>  	int err = -ENOBUFS;
>>  
>> +	fdb_notify_switchdev(fdb, type);
>> +
>>  	skb = nlmsg_new(fdb_nlmsg_size(), GFP_ATOMIC);
>>  	if (skb == NULL)
>>  		goto errout;
>> diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
>> index 69ba3ba..5e944e9 100644
>> --- a/net/bridge/br_private.h
>> +++ b/net/bridge/br_private.h
>> @@ -1086,6 +1086,8 @@ void nbp_switchdev_frame_mark(const struct net_bridge_port *p,
>>  			      struct sk_buff *skb);
>>  bool nbp_switchdev_allowed_egress(const struct net_bridge_port *p,
>>  				  const struct sk_buff *skb);
>> +void br_switchdev_fdb_call_notifiers(bool adding, const unsigned char *mac,
>> +				     u16 vid, struct net_device *dev);
>>  #else
>>  static inline int nbp_switchdev_mark_set(struct net_bridge_port *p)
>>  {
>> @@ -1102,6 +1104,12 @@ static inline bool nbp_switchdev_allowed_egress(const struct net_bridge_port *p,
>>  {
>>  	return true;
>>  }
>> +
>> +static inline void
>> +br_switchdev_fdb_call_notifiers(bool adding, const unsigned char *mac,
>> +				u16 vid, struct net_device *dev)
>> +{
>> +}
>>  #endif /* CONFIG_NET_SWITCHDEV */
>>  
>>  #endif
>> diff --git a/net/bridge/br_switchdev.c b/net/bridge/br_switchdev.c
>> index f4097b9..c07dceb 100644
>> --- a/net/bridge/br_switchdev.c
>> +++ b/net/bridge/br_switchdev.c
>> @@ -55,3 +55,16 @@ bool nbp_switchdev_allowed_egress(const struct net_bridge_port *p,
>>  	return !skb->offload_fwd_mark ||
>>  	       BR_INPUT_SKB_CB(skb)->offload_fwd_mark != p->offload_fwd_mark;
>>  }
>> +
>> +void
>> +br_switchdev_fdb_call_notifiers(bool adding, const unsigned char *mac,
>> +				u16 vid, struct net_device *dev)
>> +{
>> +	struct switchdev_notifier_fdb_info info;
>> +	unsigned long notifier_type;
>> +
>> +	info.addr = mac;
>> +	info.vid = vid;
>> +	notifier_type = adding ? SWITCHDEV_FDB_ADD_TO_DEVICE : SWITCHDEV_FDB_DEL_TO_DEVICE;
>> +	call_switchdev_notifiers(notifier_type, dev, &info.info);
>> +}
>>
> 

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

* Re: [patch iproute2] bridge: Distinguish between externally learned vs offloaded FDBs
  2017-06-05 10:07 ` [patch iproute2] bridge: Distinguish between externally learned vs offloaded FDBs Jiri Pirko
@ 2017-06-14 16:52   ` Stephen Hemminger
  0 siblings, 0 replies; 30+ messages in thread
From: Stephen Hemminger @ 2017-06-14 16:52 UTC (permalink / raw)
  To: Jiri Pirko; +Cc: netdev, davem, idosch, arkadis, mlxsw, roopa, ivecera

On Mon,  5 Jun 2017 12:07:05 +0200
Jiri Pirko <jiri@resnulli.us> wrote:

> From: Arkadi Sharshevsky <arkadis@mellanox.com>
> 
> Distinguish between externally learned vs offloaded FDBs. This is done
> in order to indicate that FDBs added by software was successfully
> offloaded.
> 
> Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com>
> Signed-off-by: Jiri Pirko <jiri@mellanox.com>

Applied to net-next

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

end of thread, other threads:[~2017-06-14 16:52 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-06-05  9:20 [patch net-next 00/19] Remove support from bridge bypass for mlxsw/rocker drivers Jiri Pirko
2017-06-05  9:20 ` [patch net-next 01/19] net: switchdev: Add support for querying supported bridge flags by hardware Jiri Pirko
2017-06-05 14:00   ` Ivan Vecera
2017-06-05  9:20 ` [patch net-next 02/19] net: bridge: Add support for offloading port attributes Jiri Pirko
2017-06-05 13:29   ` Nikolay Aleksandrov
2017-06-06 13:08     ` Arkadi Sharshevsky
2017-06-05  9:20 ` [patch net-next 03/19] net: bridge: Add support for calling FDB external learning under rcu Jiri Pirko
2017-06-05 13:36   ` Nikolay Aleksandrov
2017-06-05  9:20 ` [patch net-next 04/19] net: switchdev: Change notifier chain to be atomic Jiri Pirko
2017-06-05 13:59   ` Ivan Vecera
2017-06-05  9:20 ` [patch net-next 05/19] net: bridge: Add support for notifying devices about FDB add/del Jiri Pirko
2017-06-05 13:35   ` Nikolay Aleksandrov
2017-06-06 14:19     ` Arkadi Sharshevsky
2017-06-05  9:20 ` [patch net-next 06/19] net: bridge: Receive notification about successful FDB offload Jiri Pirko
2017-06-05 13:44   ` Nikolay Aleksandrov
2017-06-05  9:20 ` [patch net-next 07/19] mlxsw: spectrum: Remove support for bridge FDB learning sync Jiri Pirko
2017-06-05  9:20 ` [patch net-next 08/19] mlxsw: spectrum_switchdev: Add support for querying supported bridge flags Jiri Pirko
2017-06-05  9:20 ` [patch net-next 09/19] mlxsw: spectrum: Remove support for bypass bridge port attributes/vlan set Jiri Pirko
2017-06-05  9:20 ` [patch net-next 10/19] mlxsw: spectrum_switchdev: Change switchdev notifier API Jiri Pirko
2017-06-05  9:20 ` [patch net-next 11/19] mlxsw: spectrum_switchdev: Add support for learning FDB through notification Jiri Pirko
2017-06-05  9:20 ` [patch net-next 12/19] mlxsw: spectrum: Remove support for bridge bypass FDB add/del Jiri Pirko
2017-06-05  9:20 ` [patch net-next 13/19] net: Remove support for bridge bypass ndos from stacked devices Jiri Pirko
2017-06-05  9:20 ` [patch net-next 14/19] rocker: Remove support for bridge FDB learning sync Jiri Pirko
2017-06-05  9:20 ` [patch net-next 15/19] rocker: Add support for querying supported bridge flags Jiri Pirko
2017-06-05  9:20 ` [patch net-next 16/19] rocker: Change world_ops API and implementation to be switchdev independant Jiri Pirko
2017-06-05  9:20 ` [patch net-next 17/19] rocker: Add support for learning FDB through notification Jiri Pirko
2017-06-05  9:20 ` [patch net-next 18/19] rocker: Remove support for bypass bridge port attributes/vlan set Jiri Pirko
2017-06-05  9:20 ` [patch net-next 19/19] rocker: Remove support bridge bypass FDB Jiri Pirko
2017-06-05 10:07 ` [patch iproute2] bridge: Distinguish between externally learned vs offloaded FDBs Jiri Pirko
2017-06-14 16:52   ` Stephen Hemminger

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.