aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge/br_device.c
diff options
context:
space:
mode:
authorstephen hemminger <shemminger@vyatta.com>2011-04-04 10:03:32 -0400
committerDavid S. Miller <davem@davemloft.net>2011-04-04 20:22:28 -0400
commitbb900b27a2f49b37bc38c08e656ea13048fee13b (patch)
treedbea65f697ee131de15a7b6d94466744ad346594 /net/bridge/br_device.c
parent36fd2b63e3b4336744cf3f6a6c9543ecbec334a7 (diff)
bridge: allow creating bridge devices with netlink
Add netlink device ops to allow creating bridge device via netlink. This works in a manner similar to vlan, macvlan and bonding. Example: # ip link add link dev br0 type bridge # ip link del dev br0 The change required rearranging initializtion code to deal with being called by create link. Most of the initialization happens in br_dev_setup, but allocation of stats is done in ndo_init callback to deal with allocation failure. Sysfs setup has to wait until after the network device kobject is registered. Signed-off-by: Stephen Hemminger <shemminger@vyatta.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/bridge/br_device.c')
-rw-r--r--net/bridge/br_device.c41
1 files changed, 41 insertions, 0 deletions
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 21e5901186ea..45cfd54b06d3 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -74,6 +74,17 @@ out:
74 return NETDEV_TX_OK; 74 return NETDEV_TX_OK;
75} 75}
76 76
77static int br_dev_init(struct net_device *dev)
78{
79 struct net_bridge *br = netdev_priv(dev);
80
81 br->stats = alloc_percpu(struct br_cpu_netstats);
82 if (!br->stats)
83 return -ENOMEM;
84
85 return 0;
86}
87
77static int br_dev_open(struct net_device *dev) 88static int br_dev_open(struct net_device *dev)
78{ 89{
79 struct net_bridge *br = netdev_priv(dev); 90 struct net_bridge *br = netdev_priv(dev);
@@ -334,6 +345,7 @@ static const struct ethtool_ops br_ethtool_ops = {
334static const struct net_device_ops br_netdev_ops = { 345static const struct net_device_ops br_netdev_ops = {
335 .ndo_open = br_dev_open, 346 .ndo_open = br_dev_open,
336 .ndo_stop = br_dev_stop, 347 .ndo_stop = br_dev_stop,
348 .ndo_init = br_dev_init,
337 .ndo_start_xmit = br_dev_xmit, 349 .ndo_start_xmit = br_dev_xmit,
338 .ndo_get_stats64 = br_get_stats64, 350 .ndo_get_stats64 = br_get_stats64,
339 .ndo_set_mac_address = br_set_mac_address, 351 .ndo_set_mac_address = br_set_mac_address,
@@ -357,18 +369,47 @@ static void br_dev_free(struct net_device *dev)
357 free_netdev(dev); 369 free_netdev(dev);
358} 370}
359 371
372static struct device_type br_type = {
373 .name = "bridge",
374};
375
360void br_dev_setup(struct net_device *dev) 376void br_dev_setup(struct net_device *dev)
361{ 377{
378 struct net_bridge *br = netdev_priv(dev);
379
362 random_ether_addr(dev->dev_addr); 380 random_ether_addr(dev->dev_addr);
363 ether_setup(dev); 381 ether_setup(dev);
364 382
365 dev->netdev_ops = &br_netdev_ops; 383 dev->netdev_ops = &br_netdev_ops;
366 dev->destructor = br_dev_free; 384 dev->destructor = br_dev_free;
367 SET_ETHTOOL_OPS(dev, &br_ethtool_ops); 385 SET_ETHTOOL_OPS(dev, &br_ethtool_ops);
386 SET_NETDEV_DEVTYPE(dev, &br_type);
368 dev->tx_queue_len = 0; 387 dev->tx_queue_len = 0;
369 dev->priv_flags = IFF_EBRIDGE; 388 dev->priv_flags = IFF_EBRIDGE;
370 389
371 dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | 390 dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA |
372 NETIF_F_GSO_MASK | NETIF_F_NO_CSUM | NETIF_F_LLTX | 391 NETIF_F_GSO_MASK | NETIF_F_NO_CSUM | NETIF_F_LLTX |
373 NETIF_F_NETNS_LOCAL | NETIF_F_GSO | NETIF_F_HW_VLAN_TX; 392 NETIF_F_NETNS_LOCAL | NETIF_F_GSO | NETIF_F_HW_VLAN_TX;
393
394 br->dev = dev;
395 spin_lock_init(&br->lock);
396 INIT_LIST_HEAD(&br->port_list);
397 spin_lock_init(&br->hash_lock);
398
399 br->bridge_id.prio[0] = 0x80;
400 br->bridge_id.prio[1] = 0x00;
401
402 memcpy(br->group_addr, br_group_address, ETH_ALEN);
403
404 br->feature_mask = dev->features;
405 br->stp_enabled = BR_NO_STP;
406 br->designated_root = br->bridge_id;
407 br->bridge_max_age = br->max_age = 20 * HZ;
408 br->bridge_hello_time = br->hello_time = 2 * HZ;
409 br->bridge_forward_delay = br->forward_delay = 15 * HZ;
410 br->ageing_time = 300 * HZ;
411
412 br_netfilter_rtable_init(br);
413 br_stp_timer_init(br);
414 br_multicast_init(br);
374} 415}