cregit-Linux how code gets into the kernel

Release 4.8 net/bridge/br_device.c

Directory: net/bridge
/*
 *      Device handling code
 *      Linux ethernet bridge
 *
 *      Authors:
 *      Lennert Buytenhek               <buytenh@gnu.org>
 *
 *      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/kernel.h>
#include <linux/netdevice.h>
#include <linux/netpoll.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
#include <linux/list.h>
#include <linux/netfilter_bridge.h>

#include <asm/uaccess.h>
#include "br_private.h"


#define COMMON_FEATURES (NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | \
                         NETIF_F_GSO_MASK | NETIF_F_HW_CSUM)


const struct nf_br_ops __rcu *nf_br_ops __read_mostly;

EXPORT_SYMBOL_GPL(nf_br_ops);


static struct lock_class_key bridge_netdev_addr_lock_key;

/* net device transmit always called with BH disabled */

netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) { struct net_bridge *br = netdev_priv(dev); const unsigned char *dest = skb->data; struct net_bridge_fdb_entry *dst; struct net_bridge_mdb_entry *mdst; struct pcpu_sw_netstats *brstats = this_cpu_ptr(br->stats); const struct nf_br_ops *nf_ops; u16 vid = 0; rcu_read_lock(); nf_ops = rcu_dereference(nf_br_ops); if (nf_ops && nf_ops->br_dev_xmit_hook(skb)) { rcu_read_unlock(); return NETDEV_TX_OK; } u64_stats_update_begin(&brstats->syncp); brstats->tx_packets++; brstats->tx_bytes += skb->len; u64_stats_update_end(&brstats->syncp); BR_INPUT_SKB_CB(skb)->brdev = dev; skb_reset_mac_header(skb); skb_pull(skb, ETH_HLEN); if (!br_allowed_ingress(br, br_vlan_group_rcu(br), skb, &vid)) goto out; if (is_broadcast_ether_addr(dest)) { br_flood(br, skb, false, false, true); } else if (is_multicast_ether_addr(dest)) { if (unlikely(netpoll_tx_running(dev))) { br_flood(br, skb, false, false, true); goto out; } if (br_multicast_rcv(br, NULL, skb, vid)) { kfree_skb(skb); goto out; } mdst = br_mdb_get(br, skb, vid); if ((mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) && br_multicast_querier_exists(br, eth_hdr(skb))) br_multicast_flood(mdst, skb, false, true); else br_flood(br, skb, false, false, true); } else if ((dst = __br_fdb_get(br, dest, vid)) != NULL) { br_forward(dst->dst, skb, false, true); } else { br_flood(br, skb, true, false, true); } out: rcu_read_unlock(); return NETDEV_TX_OK; }

Contributors

PersonTokensPropCommitsCommitProp
herbert xuherbert xu9024.66%514.71%
pre-gitpre-git8122.19%12.94%
stephen hemmingerstephen hemminger4712.88%720.59%
nikolay aleksandrovnikolay aleksandrov4111.23%38.82%
pablo neira ayusopablo neira ayuso205.48%25.88%
vlad yasevichvlad yasevich174.66%411.76%
toshiaki makitatoshiaki makita164.38%12.94%
eric dumazeteric dumazet164.38%12.94%
linus lussinglinus lussing123.29%25.88%
bart de schuymerbart de schuymer92.47%12.94%
linus torvaldslinus torvalds71.92%12.94%
arnaldo carvalho de meloarnaldo carvalho de melo30.82%12.94%
americo wangamerico wang20.55%12.94%
li rongqingli rongqing10.27%12.94%
hideaki yoshifujihideaki yoshifuji10.27%12.94%
pavel emelianovpavel emelianov10.27%12.94%
patrick mchardypatrick mchardy10.27%12.94%
Total365100.00%34100.00%


static void br_set_lockdep_class(struct net_device *dev) { lockdep_set_class(&dev->addr_list_lock, &bridge_netdev_addr_lock_key); }

Contributors

PersonTokensPropCommitsCommitProp
nikolay aleksandrovnikolay aleksandrov22100.00%1100.00%
Total22100.00%1100.00%


static int br_dev_init(struct net_device *dev) { struct net_bridge *br = netdev_priv(dev); int err; br->stats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); if (!br->stats) return -ENOMEM; err = br_vlan_init(br); if (err) { free_percpu(br->stats); return err; } err = br_multicast_init_stats(br); if (err) { free_percpu(br->stats); br_vlan_flush(br); } br_set_lockdep_class(dev); return err; }

Contributors

PersonTokensPropCommitsCommitProp
stephen hemmingerstephen hemminger4241.58%116.67%
nikolay aleksandrovnikolay aleksandrov3534.65%233.33%
vlad yasevichvlad yasevich2221.78%116.67%
li rongqingli rongqing10.99%116.67%
americo wangamerico wang10.99%116.67%
Total101100.00%6100.00%


static int br_dev_open(struct net_device *dev) { struct net_bridge *br = netdev_priv(dev); netdev_update_features(dev); netif_start_queue(dev); br_stp_enable_bridge(br); br_multicast_open(br); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
pre-gitpre-git2352.27%125.00%
stephen hemmingerstephen hemminger1431.82%125.00%
herbert xuherbert xu511.36%125.00%
michal miroslawmichal miroslaw24.55%125.00%
Total44100.00%4100.00%


static void br_dev_set_multicast_list(struct net_device *dev) { }

Contributors

PersonTokensPropCommitsCommitProp
pre-gitpre-git10100.00%1100.00%
Total10100.00%1100.00%


static void br_dev_change_rx_flags(struct net_device *dev, int change) { if (change & IFF_PROMISC) br_manage_promisc(netdev_priv(dev)); }

Contributors

PersonTokensPropCommitsCommitProp
vlad yasevichvlad yasevich28100.00%1100.00%
Total28100.00%1100.00%


static int br_dev_stop(struct net_device *dev) { struct net_bridge *br = netdev_priv(dev); br_stp_disable_bridge(br); br_multicast_stop(br); netif_stop_queue(dev); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
pre-gitpre-git2153.85%125.00%
herbert xuherbert xu1435.90%125.00%
stephen hemmingerstephen hemminger410.26%250.00%
Total39100.00%4100.00%


static struct rtnl_link_stats64 *br_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) { struct net_bridge *br = netdev_priv(dev); struct pcpu_sw_netstats tmp, sum = { 0 }; unsigned int cpu; for_each_possible_cpu(cpu) { unsigned int start; const struct pcpu_sw_netstats *bstats = per_cpu_ptr(br->stats, cpu); do { start = u64_stats_fetch_begin_irq(&bstats->syncp); memcpy(&tmp, bstats, sizeof(tmp)); } while (u64_stats_fetch_retry_irq(&bstats->syncp, start)); sum.tx_bytes += tmp.tx_bytes; sum.tx_packets += tmp.tx_packets; sum.rx_bytes += tmp.rx_bytes; sum.rx_packets += tmp.rx_packets; } stats->tx_bytes = sum.tx_bytes; stats->tx_packets = sum.tx_packets; stats->rx_bytes = sum.rx_bytes; stats->rx_packets = sum.rx_packets; return stats; }

Contributors

PersonTokensPropCommitsCommitProp
stephen hemmingerstephen hemminger11164.16%120.00%
eric dumazeteric dumazet5833.53%240.00%
eric w. biedermaneric w. biederman21.16%120.00%
li rongqingli rongqing21.16%120.00%
Total173100.00%5100.00%


static int br_change_mtu(struct net_device *dev, int new_mtu) { struct net_bridge *br = netdev_priv(dev); if (new_mtu < 68 || new_mtu > br_min_mtu(br)) return -EINVAL; dev->mtu = new_mtu; #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) /* remember the MTU in the rtable for PMTU */ dst_metric_set(&br->fake_rtable.dst, RTAX_MTU, new_mtu); #endif return 0; }

Contributors

PersonTokensPropCommitsCommitProp
stephen hemmingerstephen hemminger3953.42%125.00%
simon wunderlichsimon wunderlich2331.51%125.00%
david s. millerdavid s. miller68.22%125.00%
pablo neira ayusopablo neira ayuso56.85%125.00%
Total73100.00%4100.00%

/* Allow setting mac address to any valid ethernet address. */
static int br_set_mac_address(struct net_device *dev, void *p) { struct net_bridge *br = netdev_priv(dev); struct sockaddr *addr = p; if (!is_valid_ether_addr(addr->sa_data)) return -EADDRNOTAVAIL; spin_lock_bh(&br->lock); if (!ether_addr_equal(dev->dev_addr, addr->sa_data)) { /* Mac address will be changed in br_stp_change_bridge_id(). */ br_stp_change_bridge_id(br, addr->sa_data); } spin_unlock_bh(&br->lock); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
stephen hemmingerstephen hemminger8795.60%350.00%
joe perchesjoe perches22.20%116.67%
toshiaki makitatoshiaki makita11.10%116.67%
danny kukawkadanny kukawka11.10%116.67%
Total91100.00%6100.00%


static void br_getinfo(struct net_device *dev, struct ethtool_drvinfo *info) { strlcpy(info->driver, "bridge", sizeof(info->driver)); strlcpy(info->version, BR_VERSION, sizeof(info->version)); strlcpy(info->fw_version, "N/A", sizeof(info->fw_version)); strlcpy(info->bus_info, "N/A", sizeof(info->bus_info)); }

Contributors

PersonTokensPropCommitsCommitProp
stephen hemmingerstephen hemminger4860.00%150.00%
jiri pirkojiri pirko3240.00%150.00%
Total80100.00%2100.00%


static netdev_features_t br_fix_features(struct net_device *dev, netdev_features_t features) { struct net_bridge *br = netdev_priv(dev); return br_features_recompute(br, features); }

Contributors

PersonTokensPropCommitsCommitProp
stephen hemmingerstephen hemminger2371.88%125.00%
michal miroslawmichal miroslaw515.62%250.00%
jesse grossjesse gross412.50%125.00%
Total32100.00%4100.00%

#ifdef CONFIG_NET_POLL_CONTROLLER
static void br_poll_controller(struct net_device *br_dev) { }

Contributors

PersonTokensPropCommitsCommitProp
herbert xuherbert xu660.00%133.33%
americo wangamerico wang330.00%133.33%
stephen hemmingerstephen hemminger110.00%133.33%
Total10100.00%3100.00%


static void br_netpoll_cleanup(struct net_device *dev) { struct net_bridge *br = netdev_priv(dev); struct net_bridge_port *p; list_for_each_entry(p, &br->port_list, list) br_netpoll_disable(p); }

Contributors

PersonTokensPropCommitsCommitProp
herbert xuherbert xu2153.85%133.33%
americo wangamerico wang1846.15%266.67%
Total39100.00%3100.00%


static int __br_netpoll_enable(struct net_bridge_port *p) { struct netpoll *np; int err; np = kzalloc(sizeof(*p->np), GFP_KERNEL); if (!np) return -ENOMEM; err = __netpoll_setup(np, p->dev); if (err) { kfree(np); return err; } p->np = np; return err; }

Contributors

PersonTokensPropCommitsCommitProp
cong wangcong wang4153.25%125.00%
americo wangamerico wang2431.17%125.00%
herbert xuherbert xu1114.29%125.00%
eric w. biedermaneric w. biederman11.30%125.00%
Total77100.00%4100.00%


int br_netpoll_enable(struct net_bridge_port *p) { if (!p->br->dev->npinfo) return 0; return __br_netpoll_enable(p); }

Contributors

PersonTokensPropCommitsCommitProp
stephen hemmingerstephen hemminger1550.00%240.00%
herbert xuherbert xu723.33%120.00%
cong wangcong wang413.33%120.00%
americo wangamerico wang413.33%120.00%
Total30100.00%5100.00%


static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni) { struct net_bridge *br = netdev_priv(dev); struct net_bridge_port *p; int err = 0; list_for_each_entry(p, &br->port_list, list) { if (!p->dev) continue; err = __br_netpoll_enable(p); if (err) goto fail; } out: return err; fail: br_netpoll_cleanup(dev); goto out; }

Contributors

PersonTokensPropCommitsCommitProp
cong wangcong wang6477.11%120.00%
herbert xuherbert xu1012.05%120.00%
stephen hemmingerstephen hemminger67.23%120.00%
americo wangamerico wang22.41%120.00%
jiri pirkojiri pirko11.20%120.00%
Total83100.00%5100.00%


void br_netpoll_disable(struct net_bridge_port *p) { struct netpoll *np = p->np; if (!np) return; p->np = NULL; __netpoll_free_async(np); }

Contributors

PersonTokensPropCommitsCommitProp
herbert xuherbert xu1952.78%133.33%
stephen hemmingerstephen hemminger1644.44%133.33%
neil hormanneil horman12.78%133.33%
Total36100.00%3100.00%

#endif
static int br_add_slave(struct net_device *dev, struct net_device *slave_dev) { struct net_bridge *br = netdev_priv(dev); return br_add_if(br, slave_dev); }

Contributors

PersonTokensPropCommitsCommitProp
jiri pirkojiri pirko34100.00%1100.00%
Total34100.00%1100.00%


static int br_del_slave(struct net_device *dev, struct net_device *slave_dev) { struct net_bridge *br = netdev_priv(dev); return br_del_if(br, slave_dev); }

Contributors

PersonTokensPropCommitsCommitProp
jiri pirkojiri pirko34100.00%1100.00%
Total34100.00%1100.00%

static const struct ethtool_ops br_ethtool_ops = { .get_drvinfo = br_getinfo, .get_link = ethtool_op_get_link, }; static const struct net_device_ops br_netdev_ops = { .ndo_open = br_dev_open, .ndo_stop = br_dev_stop, .ndo_init = br_dev_init, .ndo_start_xmit = br_dev_xmit, .ndo_get_stats64 = br_get_stats64, .ndo_set_mac_address = br_set_mac_address, .ndo_set_rx_mode = br_dev_set_multicast_list, .ndo_change_rx_flags = br_dev_change_rx_flags, .ndo_change_mtu = br_change_mtu, .ndo_do_ioctl = br_dev_ioctl, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_netpoll_setup = br_netpoll_setup, .ndo_netpoll_cleanup = br_netpoll_cleanup, .ndo_poll_controller = br_poll_controller, #endif .ndo_add_slave = br_add_slave, .ndo_del_slave = br_del_slave, .ndo_fix_features = br_fix_features, .ndo_neigh_construct = netdev_default_l2upper_neigh_construct, .ndo_neigh_destroy = netdev_default_l2upper_neigh_destroy, .ndo_fdb_add = br_fdb_add, .ndo_fdb_del = br_fdb_delete, .ndo_fdb_dump = br_fdb_dump, .ndo_bridge_getlink = br_getlink, .ndo_bridge_setlink = br_setlink, .ndo_bridge_dellink = br_dellink, .ndo_features_check = passthru_features_check, };
static void br_dev_free(struct net_device *dev) { struct net_bridge *br = netdev_priv(dev); free_percpu(br->stats); free_netdev(dev); }

Contributors

PersonTokensPropCommitsCommitProp
stephen hemmingerstephen hemminger33100.00%1100.00%
Total33100.00%1100.00%

static struct device_type br_type = { .name = "bridge", };
void br_dev_setup(struct net_device *dev) { struct net_bridge *br = netdev_priv(dev); eth_hw_addr_random(dev); ether_setup(dev); dev->netdev_ops = &br_netdev_ops; dev->destructor = br_dev_free; dev->ethtool_ops = &br_ethtool_ops; SET_NETDEV_DEVTYPE(dev, &br_type); dev->priv_flags = IFF_EBRIDGE | IFF_NO_QUEUE; dev->features = COMMON_FEATURES | NETIF_F_LLTX | NETIF_F_NETNS_LOCAL | NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX; dev->hw_features = COMMON_FEATURES | NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX; dev->vlan_features = COMMON_FEATURES; br->dev = dev; spin_lock_init(&br->lock); INIT_LIST_HEAD(&br->port_list); spin_lock_init(&br->hash_lock); br->bridge_id.prio[0] = 0x80; br->bridge_id.prio[1] = 0x00; ether_addr_copy(br->group_addr, eth_reserved_addr_base); br->stp_enabled = BR_NO_STP; br->group_fwd_mask = BR_GROUPFWD_DEFAULT; br->group_fwd_mask_required = BR_GROUPFWD_DEFAULT; br->designated_root = br->bridge_id; br->bridge_max_age = br->max_age = 20 * HZ; br->bridge_hello_time = br->hello_time = 2 * HZ; br->bridge_forward_delay = br->forward_delay = 15 * HZ; br->ageing_time = BR_DEFAULT_AGEING_TIME; br_netfilter_rtable_init(br); br_stp_timer_init(br); br_multicast_init(br); }

Contributors

PersonTokensPropCommitsCommitProp
stephen hemmingerstephen hemminger18075.00%832.00%
pre-gitpre-git208.33%14.00%
toshiaki makitatoshiaki makita104.17%28.00%
vlad yasevichvlad yasevich83.33%14.00%
michal miroslawmichal miroslaw52.08%14.00%
herbert xuherbert xu31.25%312.00%
wilfried klaebewilfried klaebe31.25%14.00%
phil sutterphil sutter20.83%14.00%
patrick mchardypatrick mchardy20.83%14.00%
alexey dobriyanalexey dobriyan20.83%14.00%
scott feldmanscott feldman10.42%14.00%
joe perchesjoe perches10.42%14.00%
danny kukawkadanny kukawka10.42%14.00%
ben hutchingsben hutchings10.42%14.00%
jesse grossjesse gross10.42%14.00%
Total240100.00%25100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
stephen hemmingerstephen hemminger75339.65%2323.71%
herbert xuherbert xu19110.06%99.28%
pre-gitpre-git1678.79%11.03%
jiri pirkojiri pirko1226.42%55.15%
cong wangcong wang1095.74%11.03%
nikolay aleksandrovnikolay aleksandrov1035.42%55.15%
vlad yasevichvlad yasevich894.69%88.25%
americo wangamerico wang814.27%55.15%
eric dumazeteric dumazet764.00%22.06%
pablo neira ayusopablo neira ayuso382.00%33.09%
toshiaki makitatoshiaki makita321.69%55.15%
john fastabendjohn fastabend251.32%22.06%
simon wunderlichsimon wunderlich231.21%11.03%
michal miroslawmichal miroslaw170.90%22.06%
bart de schuymerbart de schuymer120.63%11.03%
linus lussinglinus lussing120.63%22.06%
linus torvaldslinus torvalds70.37%11.03%
david s. millerdavid s. miller60.32%11.03%
jesse grossjesse gross50.26%11.03%
li rongqingli rongqing40.21%11.03%
patrick mchardypatrick mchardy30.16%22.06%
wilfried klaebewilfried klaebe30.16%11.03%
eric w. biedermaneric w. biederman30.16%22.06%
arnaldo carvalho de meloarnaldo carvalho de melo30.16%11.03%
joe perchesjoe perches30.16%22.06%
danny kukawkadanny kukawka20.11%22.06%
phil sutterphil sutter20.11%11.03%
alexey dobriyanalexey dobriyan20.11%11.03%
neil hormanneil horman10.05%11.03%
ben hutchingsben hutchings10.05%11.03%
pavel emelianovpavel emelianov10.05%11.03%
scott feldmanscott feldman10.05%11.03%
adrian bunkadrian bunk10.05%11.03%
hideaki yoshifujihideaki yoshifuji10.05%11.03%
Total1899100.00%97100.00%
Directory: net/bridge
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.