summaryrefslogtreecommitdiff
path: root/net/bridge/br.c
diff options
context:
space:
mode:
authorJiri Pirko <jiri@resnulli.us>2015-01-15 23:49:37 +0100
committerDavid S. Miller <davem@davemloft.net>2015-01-18 00:23:57 -0500
commit3aeb66176ffa8fefd7a9f7d37bda1d8adcf469a1 (patch)
tree9f2232db459c95cf0d000ab95322c6b7aac86235 /net/bridge/br.c
parent03bf0c281234028388108d0aee720954f5fe6924 (diff)
net: replace br_fdb_external_learn_* calls with switchdev notifier events
This patch benefits from newly introduced switchdev notifier and uses it to propagate fdb learn events from rocker driver to bridge. That avoids direct function calls and possible use by other listeners (ovs). Suggested-by: Thomas Graf <tgraf@suug.ch> Signed-off-by: Jiri Pirko <jiri@resnulli.us> Signed-off-by: Scott Feldman <sfeldma@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/bridge/br.c')
-rw-r--r--net/bridge/br.c52
1 files changed, 51 insertions, 1 deletions
diff --git a/net/bridge/br.c b/net/bridge/br.c
index 44425aff7cba..fb57ab6b24f9 100644
--- a/net/bridge/br.c
+++ b/net/bridge/br.c
@@ -19,6 +19,7 @@
#include <linux/llc.h>
#include <net/llc.h>
#include <net/stp.h>
+#include <net/switchdev.h>
#include "br_private.h"
@@ -120,6 +121,48 @@ static struct notifier_block br_device_notifier = {
.notifier_call = br_device_event
};
+static int br_netdev_switch_event(struct notifier_block *unused,
+ unsigned long event, void *ptr)
+{
+ struct net_device *dev = netdev_switch_notifier_info_to_dev(ptr);
+ struct net_bridge_port *p;
+ struct net_bridge *br;
+ struct netdev_switch_notifier_fdb_info *fdb_info;
+ int err = NOTIFY_DONE;
+
+ rtnl_lock();
+ p = br_port_get_rtnl(dev);
+ if (!p)
+ goto out;
+
+ br = p->br;
+
+ switch (event) {
+ case NETDEV_SWITCH_FDB_ADD:
+ 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 NETDEV_SWITCH_FDB_DEL:
+ fdb_info = ptr;
+ err = br_fdb_external_learn_del(br, p, fdb_info->addr,
+ fdb_info->vid);
+ if (err)
+ err = notifier_from_errno(err);
+ break;
+ }
+
+out:
+ rtnl_unlock();
+ return err;
+}
+
+static struct notifier_block br_netdev_switch_notifier = {
+ .notifier_call = br_netdev_switch_event,
+};
+
static void __net_exit br_net_exit(struct net *net)
{
struct net_device *dev;
@@ -169,10 +212,14 @@ static int __init br_init(void)
if (err)
goto err_out3;
- err = br_netlink_init();
+ err = register_netdev_switch_notifier(&br_netdev_switch_notifier);
if (err)
goto err_out4;
+ err = br_netlink_init();
+ if (err)
+ goto err_out5;
+
brioctl_set(br_ioctl_deviceless_stub);
#if IS_ENABLED(CONFIG_ATM_LANE)
@@ -185,6 +232,8 @@ static int __init br_init(void)
return 0;
+err_out5:
+ unregister_netdev_switch_notifier(&br_netdev_switch_notifier);
err_out4:
unregister_netdevice_notifier(&br_device_notifier);
err_out3:
@@ -202,6 +251,7 @@ static void __exit br_deinit(void)
{
stp_proto_unregister(&br_stp_proto);
br_netlink_fini();
+ unregister_netdev_switch_notifier(&br_netdev_switch_notifier);
unregister_netdevice_notifier(&br_device_notifier);
brioctl_set(NULL);
unregister_pernet_subsys(&br_net_ops);