cregit-Linux how code gets into the kernel

Release 4.8 net/bridge/br.c

Directory: net/bridge
 *      Generic parts
 *      Linux ethernet bridge
 *      Authors:
 *      Lennert Buytenhek               <>
 *      This program is free software; you can redistribute it and/or
 *      modify it under the terms of the GNU General Public License
 *      as published by the Free Software Foundation; either version
 *      2 of the License, or (at your option) any later version.

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
#include <linux/llc.h>
#include <net/llc.h>
#include <net/stp.h>
#include <net/switchdev.h>

#include "br_private.h"

 * Handle changes in state of network devices enslaved to a bridge.
 * Note: don't care about up/down if bridge itself is down, because
 *     port state is checked when bridge is brought up.

static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr) { struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct net_bridge_port *p; struct net_bridge *br; bool changed_addr; int err; /* register of bridge completed, add sysfs entries */ if ((dev->priv_flags & IFF_EBRIDGE) && event == NETDEV_REGISTER) { br_sysfs_addbr(dev); return NOTIFY_DONE; } /* not a port of a bridge */ p = br_port_get_rtnl(dev); if (!p) return NOTIFY_DONE; br = p->br; switch (event) { case NETDEV_CHANGEMTU: dev_set_mtu(br->dev, br_min_mtu(br)); break; case NETDEV_CHANGEADDR: spin_lock_bh(&br->lock); br_fdb_changeaddr(p, dev->dev_addr); changed_addr = br_stp_recalculate_bridge_id(br); spin_unlock_bh(&br->lock); if (changed_addr) call_netdevice_notifiers(NETDEV_CHANGEADDR, br->dev); break; case NETDEV_CHANGE: br_port_carrier_check(p); break; case NETDEV_FEAT_CHANGE: netdev_update_features(br->dev); break; case NETDEV_DOWN: spin_lock_bh(&br->lock); if (br->dev->flags & IFF_UP) br_stp_disable_port(p); spin_unlock_bh(&br->lock); break; case NETDEV_UP: if (netif_running(br->dev) && netif_oper_up(dev)) { spin_lock_bh(&br->lock); br_stp_enable_port(p); spin_unlock_bh(&br->lock); } break; case NETDEV_UNREGISTER: br_del_if(br, dev); break; case NETDEV_CHANGENAME: err = br_sysfs_renameif(p); if (err) return notifier_from_errno(err); break; case NETDEV_PRE_TYPE_CHANGE: /* Forbid underlaying device to change its type. */ return NOTIFY_BAD; case NETDEV_RESEND_IGMP: /* Propagate to master device */ call_netdevice_notifiers(event, br->dev); break; } /* Events that may cause spanning tree to refresh */ if (event == NETDEV_CHANGEADDR || event == NETDEV_UP || event == NETDEV_CHANGE || event == NETDEV_DOWN) br_ifinfo_notify(RTM_NEWLINK, p); return NOTIFY_DONE; }


americo wangamerico wang341100.00%1100.00%

static struct notifier_block br_device_notifier = { .notifier_call = br_device_event }; /* called with RTNL */
static int br_switchdev_event(struct notifier_block *unused, unsigned long event, void *ptr) { struct net_device *dev = switchdev_notifier_info_to_dev(ptr); struct net_bridge_port *p; struct net_bridge *br; struct switchdev_notifier_fdb_info *fdb_info; int err = NOTIFY_DONE; p = br_port_get_rtnl(dev); if (!p) goto out; br = p->br; switch (event) { case SWITCHDEV_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 SWITCHDEV_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: return err; }


jiri pirkojiri pirko153100.00%2100.00%

static struct notifier_block br_switchdev_notifier = { .notifier_call = br_switchdev_event, };
static void __net_exit br_net_exit(struct net *net) { struct net_device *dev; LIST_HEAD(list); rtnl_lock(); for_each_netdev(net, dev) if (dev->priv_flags & IFF_EBRIDGE) br_dev_delete(dev, &list); unregister_netdevice_many(&list); rtnl_unlock(); }


americo wangamerico wang56100.00%1100.00%

static struct pernet_operations br_net_ops = { .exit = br_net_exit, }; static const struct stp_proto br_stp_proto = { .rcv = br_stp_rcv, };
static int __init br_init(void) { int err; BUILD_BUG_ON(sizeof(struct br_input_skb_cb) > FIELD_SIZEOF(struct sk_buff, cb)); err = stp_proto_register(&br_stp_proto); if (err < 0) { pr_err("bridge: can't register sap for STP\n"); return err; } err = br_fdb_init(); if (err) goto err_out; err = register_pernet_subsys(&br_net_ops); if (err) goto err_out1; err = br_nf_core_init(); if (err) goto err_out2; err = register_netdevice_notifier(&br_device_notifier); if (err) goto err_out3; err = register_switchdev_notifier(&br_switchdev_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) br_fdb_test_addr_hook = br_fdb_test_addr; #endif pr_info("bridge: automatic filtering via arp/ip/ip6tables has been " "deprecated. Update your scripts to load br_netfilter if you " "need this.\n"); return 0; err_out5: unregister_switchdev_notifier(&br_switchdev_notifier); err_out4: unregister_netdevice_notifier(&br_device_notifier); err_out3: br_nf_core_fini(); err_out2: unregister_pernet_subsys(&br_net_ops); err_out1: br_fdb_fini(); err_out: stp_proto_unregister(&br_stp_proto); return err; }


stephen hemmingerstephen hemminger6129.61%626.09%
alexey dobriyanalexey dobriyan2713.11%14.35%
jiri pirkojiri pirko2411.65%28.70%
florian westphalflorian westphal178.25%14.35%
thomas grafthomas graf157.28%14.35%
patrick mchardypatrick mchardy115.34%14.35%
michal miroslawmichal miroslaw94.37%14.35%
pablo neira ayusopablo neira ayuso94.37%14.35%
akinobu mitaakinobu mita83.88%14.35%
pavel emelianovpavel emelianov62.91%14.35%
bart de schuymerbart de schuymer20.97%14.35%
igor maravicigor maravic10.49%14.35%

static void __exit br_deinit(void) { stp_proto_unregister(&br_stp_proto); br_netlink_fini(); unregister_switchdev_notifier(&br_switchdev_notifier); unregister_netdevice_notifier(&br_device_notifier); brioctl_set(NULL); unregister_pernet_subsys(&br_net_ops); rcu_barrier(); /* Wait for completion of call_rcu()'s */ br_nf_core_fini(); #if IS_ENABLED(CONFIG_ATM_LANE) br_fdb_test_addr_hook = NULL; #endif br_fdb_fini(); }


stephen hemmingerstephen hemminger1320.63%525.00%
michal miroslawmichal miroslaw812.70%15.00%
jiri pirkojiri pirko69.52%210.00%
alexey dobriyanalexey dobriyan57.94%15.00%
lennert buytenheklennert buytenhek34.76%15.00%
patrick mchardypatrick mchardy34.76%15.00%
bodo stroesserbodo stroesser23.17%15.00%
jesper dangaard brouerjesper dangaard brouer23.17%15.00%
igor maravicigor maravic11.59%15.00%
pablo neira ayusopablo neira ayuso11.59%15.00%

module_init(br_init) module_exit(br_deinit) MODULE_LICENSE("GPL"); MODULE_VERSION(BR_VERSION); MODULE_ALIAS_RTNL_LINK("bridge");

Overall Contributors

americo wangamerico wang41945.35%25.56%
jiri pirkojiri pirko19821.43%25.56%
stephen hemmingerstephen hemminger9310.06%925.00%
alexey dobriyanalexey dobriyan404.33%12.78%
patrick mchardypatrick mchardy222.38%12.78%
florian westphalflorian westphal171.84%12.78%
michal miroslawmichal miroslaw171.84%12.78%
thomas grafthomas graf151.62%12.78%
pablo neira ayusopablo neira ayuso101.08%12.78%
akinobu mitaakinobu mita80.87%12.78%
pavel emelianovpavel emelianov60.65%12.78%
linus torvaldslinus torvalds50.54%12.78%
lennert buytenheklennert buytenhek30.32%12.78%
bodo stroesserbodo stroesser20.22%12.78%
igor maravicigor maravic20.22%12.78%
jesper dangaard brouerjesper dangaard brouer20.22%12.78%
bart de schuymerbart de schuymer20.22%12.78%
adrian bunkadrian bunk10.11%12.78%
ido schimmelido schimmel10.11%12.78%
Directory: net/bridge
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.