summaryrefslogtreecommitdiff
path: root/net/bridge
diff options
context:
space:
mode:
Diffstat (limited to 'net/bridge')
-rw-r--r--net/bridge/br_fdb.c1
-rw-r--r--net/bridge/br_mdb.c1
-rw-r--r--net/bridge/br_private.h25
-rw-r--r--net/bridge/br_switchdev.c75
-rw-r--r--net/bridge/br_vlan.c1
5 files changed, 97 insertions, 6 deletions
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index 47f190b6bfa3..7747442e6572 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -795,7 +795,6 @@ int br_fdb_replay(const struct net_device *br_dev, const struct net_device *dev,
return err;
}
-EXPORT_SYMBOL_GPL(br_fdb_replay);
static void fdb_notify(struct net_bridge *br,
const struct net_bridge_fdb_entry *fdb, int type,
diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c
index e58f1a4ac962..73a8915b0148 100644
--- a/net/bridge/br_mdb.c
+++ b/net/bridge/br_mdb.c
@@ -689,7 +689,6 @@ out_free_mdb:
return err;
}
-EXPORT_SYMBOL_GPL(br_mdb_replay);
static void br_mdb_switchdev_host_port(struct net_device *dev,
struct net_device *lower_dev,
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index fbf73a5256d0..2f32d330b648 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -769,6 +769,8 @@ int br_fdb_external_learn_del(struct net_bridge *br, struct net_bridge_port *p,
bool swdev_notify);
void br_fdb_offloaded_set(struct net_bridge *br, struct net_bridge_port *p,
const unsigned char *addr, u16 vid, bool offloaded);
+int br_fdb_replay(const struct net_device *br_dev, const struct net_device *dev,
+ const void *ctx, bool adding, struct notifier_block *nb);
/* br_forward.c */
enum br_pkt_type {
@@ -929,6 +931,10 @@ int br_multicast_toggle_vlan_snooping(struct net_bridge *br, bool on,
struct netlink_ext_ack *extack);
bool br_multicast_toggle_global_vlan(struct net_bridge_vlan *vlan, bool on);
+int br_mdb_replay(struct net_device *br_dev, struct net_device *dev,
+ const void *ctx, bool adding, struct notifier_block *nb,
+ struct netlink_ext_ack *extack);
+
static inline bool br_group_is_l2(const struct br_ip *group)
{
return group->proto == 0;
@@ -1307,6 +1313,14 @@ static inline bool br_multicast_toggle_global_vlan(struct net_bridge_vlan *vlan,
{
return false;
}
+
+static inline int br_mdb_replay(struct net_device *br_dev,
+ struct net_device *dev, const void *ctx,
+ bool adding, struct notifier_block *nb,
+ struct netlink_ext_ack *extack)
+{
+ return -EOPNOTSUPP;
+}
#endif
/* br_vlan.c */
@@ -1358,6 +1372,9 @@ void br_vlan_notify(const struct net_bridge *br,
const struct net_bridge_port *p,
u16 vid, u16 vid_range,
int cmd);
+int br_vlan_replay(struct net_device *br_dev, struct net_device *dev,
+ const void *ctx, bool adding, struct notifier_block *nb,
+ struct netlink_ext_ack *extack);
bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr,
const struct net_bridge_vlan *range_end);
@@ -1603,6 +1620,14 @@ static inline bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr,
{
return true;
}
+
+static inline int br_vlan_replay(struct net_device *br_dev,
+ struct net_device *dev, const void *ctx,
+ bool adding, struct notifier_block *nb,
+ struct netlink_ext_ack *extack)
+{
+ return -EOPNOTSUPP;
+}
#endif
/* br_vlan_options.c */
diff --git a/net/bridge/br_switchdev.c b/net/bridge/br_switchdev.c
index 39f0787fde01..6bfff28ede23 100644
--- a/net/bridge/br_switchdev.c
+++ b/net/bridge/br_switchdev.c
@@ -206,11 +206,62 @@ static void nbp_switchdev_del(struct net_bridge_port *p)
nbp_switchdev_hwdom_put(p);
}
+static int nbp_switchdev_sync_objs(struct net_bridge_port *p, const void *ctx,
+ struct notifier_block *atomic_nb,
+ struct notifier_block *blocking_nb,
+ struct netlink_ext_ack *extack)
+{
+ struct net_device *br_dev = p->br->dev;
+ struct net_device *dev = p->dev;
+ int err;
+
+ err = br_vlan_replay(br_dev, dev, ctx, true, blocking_nb, extack);
+ if (err && err != -EOPNOTSUPP)
+ return err;
+
+ err = br_mdb_replay(br_dev, dev, ctx, true, blocking_nb, extack);
+ if (err && err != -EOPNOTSUPP)
+ return err;
+
+ /* Forwarding and termination FDB entries on the port */
+ err = br_fdb_replay(br_dev, dev, ctx, true, atomic_nb);
+ if (err && err != -EOPNOTSUPP)
+ return err;
+
+ /* Termination FDB entries on the bridge itself */
+ err = br_fdb_replay(br_dev, br_dev, ctx, true, atomic_nb);
+ if (err && err != -EOPNOTSUPP)
+ return err;
+
+ return 0;
+}
+
+static void nbp_switchdev_unsync_objs(struct net_bridge_port *p,
+ const void *ctx,
+ struct notifier_block *atomic_nb,
+ struct notifier_block *blocking_nb)
+{
+ struct net_device *br_dev = p->br->dev;
+ struct net_device *dev = p->dev;
+
+ br_vlan_replay(br_dev, dev, ctx, false, blocking_nb, NULL);
+
+ br_mdb_replay(br_dev, dev, ctx, false, blocking_nb, NULL);
+
+ /* Forwarding and termination FDB entries on the port */
+ br_fdb_replay(br_dev, dev, ctx, false, atomic_nb);
+
+ /* Termination FDB entries on the bridge itself */
+ br_fdb_replay(br_dev, br_dev, ctx, false, atomic_nb);
+}
+
/* Let the bridge know that this port is offloaded, so that it can assign a
* switchdev hardware domain to it.
*/
int switchdev_bridge_port_offload(struct net_device *brport_dev,
- struct net_device *dev,
+ struct net_device *dev, const void *ctx,
+ struct notifier_block *atomic_nb,
+ struct notifier_block *blocking_nb,
struct netlink_ext_ack *extack)
{
struct netdev_phys_item_id ppid;
@@ -227,11 +278,27 @@ int switchdev_bridge_port_offload(struct net_device *brport_dev,
if (err)
return err;
- return nbp_switchdev_add(p, ppid, extack);
+ err = nbp_switchdev_add(p, ppid, extack);
+ if (err)
+ return err;
+
+ err = nbp_switchdev_sync_objs(p, ctx, atomic_nb, blocking_nb, extack);
+ if (err)
+ goto out_switchdev_del;
+
+ return 0;
+
+out_switchdev_del:
+ nbp_switchdev_del(p);
+
+ return err;
}
EXPORT_SYMBOL_GPL(switchdev_bridge_port_offload);
-void switchdev_bridge_port_unoffload(struct net_device *brport_dev)
+void switchdev_bridge_port_unoffload(struct net_device *brport_dev,
+ const void *ctx,
+ struct notifier_block *atomic_nb,
+ struct notifier_block *blocking_nb)
{
struct net_bridge_port *p;
@@ -241,6 +308,8 @@ void switchdev_bridge_port_unoffload(struct net_device *brport_dev)
if (!p)
return;
+ nbp_switchdev_unsync_objs(p, ctx, atomic_nb, blocking_nb);
+
nbp_switchdev_del(p);
}
EXPORT_SYMBOL_GPL(switchdev_bridge_port_unoffload);
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
index 45ef07f682f1..382ab992badf 100644
--- a/net/bridge/br_vlan.c
+++ b/net/bridge/br_vlan.c
@@ -1905,7 +1905,6 @@ int br_vlan_replay(struct net_device *br_dev, struct net_device *dev,
return err;
}
-EXPORT_SYMBOL_GPL(br_vlan_replay);
/* check if v_curr can enter a range ending in range_end */
bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr,