linux/net/bridge/br.c
<<
>>
Prefs
   1/*
   2 *      Generic parts
   3 *      Linux ethernet bridge
   4 *
   5 *      Authors:
   6 *      Lennert Buytenhek               <buytenh@gnu.org>
   7 *
   8 *      This program is free software; you can redistribute it and/or
   9 *      modify it under the terms of the GNU General Public License
  10 *      as published by the Free Software Foundation; either version
  11 *      2 of the License, or (at your option) any later version.
  12 */
  13
  14#include <linux/module.h>
  15#include <linux/kernel.h>
  16#include <linux/netdevice.h>
  17#include <linux/etherdevice.h>
  18#include <linux/init.h>
  19#include <linux/llc.h>
  20#include <net/llc.h>
  21#include <net/stp.h>
  22#include <net/switchdev.h>
  23
  24#include "br_private.h"
  25
  26/*
  27 * Handle changes in state of network devices enslaved to a bridge.
  28 *
  29 * Note: don't care about up/down if bridge itself is down, because
  30 *     port state is checked when bridge is brought up.
  31 */
  32static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr)
  33{
  34        struct net_device *dev = netdev_notifier_info_to_dev(ptr);
  35        struct net_bridge_port *p;
  36        struct net_bridge *br;
  37        bool notified = false;
  38        bool changed_addr;
  39        int err;
  40
  41        /* register of bridge completed, add sysfs entries */
  42        if ((dev->priv_flags & IFF_EBRIDGE) && event == NETDEV_REGISTER) {
  43                br_sysfs_addbr(dev);
  44                return NOTIFY_DONE;
  45        }
  46
  47        /* not a port of a bridge */
  48        p = br_port_get_rtnl(dev);
  49        if (!p)
  50                return NOTIFY_DONE;
  51
  52        br = p->br;
  53
  54        switch (event) {
  55        case NETDEV_CHANGEMTU:
  56                br_mtu_auto_adjust(br);
  57                break;
  58
  59        case NETDEV_CHANGEADDR:
  60                spin_lock_bh(&br->lock);
  61                br_fdb_changeaddr(p, dev->dev_addr);
  62                changed_addr = br_stp_recalculate_bridge_id(br);
  63                spin_unlock_bh(&br->lock);
  64
  65                if (changed_addr)
  66                        call_netdevice_notifiers(NETDEV_CHANGEADDR, br->dev);
  67
  68                break;
  69
  70        case NETDEV_CHANGE:
  71                br_port_carrier_check(p, &notified);
  72                break;
  73
  74        case NETDEV_FEAT_CHANGE:
  75                netdev_update_features(br->dev);
  76                break;
  77
  78        case NETDEV_DOWN:
  79                spin_lock_bh(&br->lock);
  80                if (br->dev->flags & IFF_UP) {
  81                        br_stp_disable_port(p);
  82                        notified = true;
  83                }
  84                spin_unlock_bh(&br->lock);
  85                break;
  86
  87        case NETDEV_UP:
  88                if (netif_running(br->dev) && netif_oper_up(dev)) {
  89                        spin_lock_bh(&br->lock);
  90                        br_stp_enable_port(p);
  91                        notified = true;
  92                        spin_unlock_bh(&br->lock);
  93                }
  94                break;
  95
  96        case NETDEV_UNREGISTER:
  97                br_del_if(br, dev);
  98                break;
  99
 100        case NETDEV_CHANGENAME:
 101                err = br_sysfs_renameif(p);
 102                if (err)
 103                        return notifier_from_errno(err);
 104                break;
 105
 106        case NETDEV_PRE_TYPE_CHANGE:
 107                /* Forbid underlaying device to change its type. */
 108                return NOTIFY_BAD;
 109
 110        case NETDEV_RESEND_IGMP:
 111                /* Propagate to master device */
 112                call_netdevice_notifiers(event, br->dev);
 113                break;
 114        }
 115
 116        /* Events that may cause spanning tree to refresh */
 117        if (!notified && (event == NETDEV_CHANGEADDR || event == NETDEV_UP ||
 118                          event == NETDEV_CHANGE || event == NETDEV_DOWN))
 119                br_ifinfo_notify(RTM_NEWLINK, NULL, p);
 120
 121        return NOTIFY_DONE;
 122}
 123
 124static struct notifier_block br_device_notifier = {
 125        .notifier_call = br_device_event
 126};
 127
 128/* called with RTNL or RCU */
 129static int br_switchdev_event(struct notifier_block *unused,
 130                              unsigned long event, void *ptr)
 131{
 132        struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
 133        struct net_bridge_port *p;
 134        struct net_bridge *br;
 135        struct switchdev_notifier_fdb_info *fdb_info;
 136        int err = NOTIFY_DONE;
 137
 138        p = br_port_get_rtnl_rcu(dev);
 139        if (!p)
 140                goto out;
 141
 142        br = p->br;
 143
 144        switch (event) {
 145        case SWITCHDEV_FDB_ADD_TO_BRIDGE:
 146                fdb_info = ptr;
 147                err = br_fdb_external_learn_add(br, p, fdb_info->addr,
 148                                                fdb_info->vid, false);
 149                if (err) {
 150                        err = notifier_from_errno(err);
 151                        break;
 152                }
 153                br_fdb_offloaded_set(br, p, fdb_info->addr,
 154                                     fdb_info->vid);
 155                break;
 156        case SWITCHDEV_FDB_DEL_TO_BRIDGE:
 157                fdb_info = ptr;
 158                err = br_fdb_external_learn_del(br, p, fdb_info->addr,
 159                                                fdb_info->vid, false);
 160                if (err)
 161                        err = notifier_from_errno(err);
 162                break;
 163        case SWITCHDEV_FDB_OFFLOADED:
 164                fdb_info = ptr;
 165                br_fdb_offloaded_set(br, p, fdb_info->addr,
 166                                     fdb_info->vid);
 167                break;
 168        }
 169
 170out:
 171        return err;
 172}
 173
 174static struct notifier_block br_switchdev_notifier = {
 175        .notifier_call = br_switchdev_event,
 176};
 177
 178static void __net_exit br_net_exit(struct net *net)
 179{
 180        struct net_device *dev;
 181        LIST_HEAD(list);
 182
 183        rtnl_lock();
 184        for_each_netdev(net, dev)
 185                if (dev->priv_flags & IFF_EBRIDGE)
 186                        br_dev_delete(dev, &list);
 187
 188        unregister_netdevice_many(&list);
 189        rtnl_unlock();
 190
 191}
 192
 193static struct pernet_operations br_net_ops = {
 194        .exit   = br_net_exit,
 195};
 196
 197static const struct stp_proto br_stp_proto = {
 198        .rcv    = br_stp_rcv,
 199};
 200
 201static int __init br_init(void)
 202{
 203        int err;
 204
 205        BUILD_BUG_ON(sizeof(struct br_input_skb_cb) > FIELD_SIZEOF(struct sk_buff, cb));
 206
 207        err = stp_proto_register(&br_stp_proto);
 208        if (err < 0) {
 209                pr_err("bridge: can't register sap for STP\n");
 210                return err;
 211        }
 212
 213        err = br_fdb_init();
 214        if (err)
 215                goto err_out;
 216
 217        err = register_pernet_subsys(&br_net_ops);
 218        if (err)
 219                goto err_out1;
 220
 221        err = br_nf_core_init();
 222        if (err)
 223                goto err_out2;
 224
 225        err = register_netdevice_notifier(&br_device_notifier);
 226        if (err)
 227                goto err_out3;
 228
 229        err = register_switchdev_notifier(&br_switchdev_notifier);
 230        if (err)
 231                goto err_out4;
 232
 233        err = br_netlink_init();
 234        if (err)
 235                goto err_out5;
 236
 237        brioctl_set(br_ioctl_deviceless_stub);
 238
 239#if IS_ENABLED(CONFIG_ATM_LANE)
 240        br_fdb_test_addr_hook = br_fdb_test_addr;
 241#endif
 242
 243#if IS_MODULE(CONFIG_BRIDGE_NETFILTER)
 244        pr_info("bridge: filtering via arp/ip/ip6tables is no longer available "
 245                "by default. Update your scripts to load br_netfilter if you "
 246                "need this.\n");
 247#endif
 248
 249        return 0;
 250
 251err_out5:
 252        unregister_switchdev_notifier(&br_switchdev_notifier);
 253err_out4:
 254        unregister_netdevice_notifier(&br_device_notifier);
 255err_out3:
 256        br_nf_core_fini();
 257err_out2:
 258        unregister_pernet_subsys(&br_net_ops);
 259err_out1:
 260        br_fdb_fini();
 261err_out:
 262        stp_proto_unregister(&br_stp_proto);
 263        return err;
 264}
 265
 266static void __exit br_deinit(void)
 267{
 268        stp_proto_unregister(&br_stp_proto);
 269        br_netlink_fini();
 270        unregister_switchdev_notifier(&br_switchdev_notifier);
 271        unregister_netdevice_notifier(&br_device_notifier);
 272        brioctl_set(NULL);
 273        unregister_pernet_subsys(&br_net_ops);
 274
 275        rcu_barrier(); /* Wait for completion of call_rcu()'s */
 276
 277        br_nf_core_fini();
 278#if IS_ENABLED(CONFIG_ATM_LANE)
 279        br_fdb_test_addr_hook = NULL;
 280#endif
 281        br_fdb_fini();
 282}
 283
 284module_init(br_init)
 285module_exit(br_deinit)
 286MODULE_LICENSE("GPL");
 287MODULE_VERSION(BR_VERSION);
 288MODULE_ALIAS_RTNL_LINK("bridge");
 289