diff options
Diffstat (limited to 'net/bridge/br_if.c')
-rw-r--r-- | net/bridge/br_if.c | 50 |
1 files changed, 24 insertions, 26 deletions
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index e73815456adf..f603e5b0b930 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c | |||
@@ -13,6 +13,7 @@ | |||
13 | 13 | ||
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/netdevice.h> | 15 | #include <linux/netdevice.h> |
16 | #include <linux/etherdevice.h> | ||
16 | #include <linux/netpoll.h> | 17 | #include <linux/netpoll.h> |
17 | #include <linux/ethtool.h> | 18 | #include <linux/ethtool.h> |
18 | #include <linux/if_arp.h> | 19 | #include <linux/if_arp.h> |
@@ -33,20 +34,18 @@ | |||
33 | */ | 34 | */ |
34 | static int port_cost(struct net_device *dev) | 35 | static int port_cost(struct net_device *dev) |
35 | { | 36 | { |
36 | if (dev->ethtool_ops && dev->ethtool_ops->get_settings) { | 37 | struct ethtool_cmd ecmd; |
37 | struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET, }; | 38 | |
38 | 39 | if (!__ethtool_get_settings(dev, &ecmd)) { | |
39 | if (!dev_ethtool_get_settings(dev, &ecmd)) { | 40 | switch (ethtool_cmd_speed(&ecmd)) { |
40 | switch (ethtool_cmd_speed(&ecmd)) { | 41 | case SPEED_10000: |
41 | case SPEED_10000: | 42 | return 2; |
42 | return 2; | 43 | case SPEED_1000: |
43 | case SPEED_1000: | 44 | return 4; |
44 | return 4; | 45 | case SPEED_100: |
45 | case SPEED_100: | 46 | return 19; |
46 | return 19; | 47 | case SPEED_10: |
47 | case SPEED_10: | 48 | return 100; |
48 | return 100; | ||
49 | } | ||
50 | } | 49 | } |
51 | } | 50 | } |
52 | 51 | ||
@@ -161,9 +160,10 @@ static void del_nbp(struct net_bridge_port *p) | |||
161 | call_rcu(&p->rcu, destroy_nbp_rcu); | 160 | call_rcu(&p->rcu, destroy_nbp_rcu); |
162 | } | 161 | } |
163 | 162 | ||
164 | /* called with RTNL */ | 163 | /* Delete bridge device */ |
165 | static void del_br(struct net_bridge *br, struct list_head *head) | 164 | void br_dev_delete(struct net_device *dev, struct list_head *head) |
166 | { | 165 | { |
166 | struct net_bridge *br = netdev_priv(dev); | ||
167 | struct net_bridge_port *p, *n; | 167 | struct net_bridge_port *p, *n; |
168 | 168 | ||
169 | list_for_each_entry_safe(p, n, &br->port_list, list) { | 169 | list_for_each_entry_safe(p, n, &br->port_list, list) { |
@@ -268,7 +268,7 @@ int br_del_bridge(struct net *net, const char *name) | |||
268 | } | 268 | } |
269 | 269 | ||
270 | else | 270 | else |
271 | del_br(netdev_priv(dev), NULL); | 271 | br_dev_delete(dev, NULL); |
272 | 272 | ||
273 | rtnl_unlock(); | 273 | rtnl_unlock(); |
274 | return ret; | 274 | return ret; |
@@ -324,7 +324,8 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) | |||
324 | 324 | ||
325 | /* Don't allow bridging non-ethernet like devices */ | 325 | /* Don't allow bridging non-ethernet like devices */ |
326 | if ((dev->flags & IFF_LOOPBACK) || | 326 | if ((dev->flags & IFF_LOOPBACK) || |
327 | dev->type != ARPHRD_ETHER || dev->addr_len != ETH_ALEN) | 327 | dev->type != ARPHRD_ETHER || dev->addr_len != ETH_ALEN || |
328 | !is_valid_ether_addr(dev->dev_addr)) | ||
328 | return -EINVAL; | 329 | return -EINVAL; |
329 | 330 | ||
330 | /* No bridging of bridges */ | 331 | /* No bridging of bridges */ |
@@ -352,10 +353,6 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) | |||
352 | err = kobject_init_and_add(&p->kobj, &brport_ktype, &(dev->dev.kobj), | 353 | err = kobject_init_and_add(&p->kobj, &brport_ktype, &(dev->dev.kobj), |
353 | SYSFS_BRIDGE_PORT_ATTR); | 354 | SYSFS_BRIDGE_PORT_ATTR); |
354 | if (err) | 355 | if (err) |
355 | goto err0; | ||
356 | |||
357 | err = br_fdb_insert(br, p, dev->dev_addr); | ||
358 | if (err) | ||
359 | goto err1; | 356 | goto err1; |
360 | 357 | ||
361 | err = br_sysfs_addif(p); | 358 | err = br_sysfs_addif(p); |
@@ -396,6 +393,9 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) | |||
396 | 393 | ||
397 | dev_set_mtu(br->dev, br_min_mtu(br)); | 394 | dev_set_mtu(br->dev, br_min_mtu(br)); |
398 | 395 | ||
396 | if (br_fdb_insert(br, p, dev->dev_addr)) | ||
397 | netdev_err(dev, "failed insert local address bridge forwarding table\n"); | ||
398 | |||
399 | kobject_uevent(&p->kobj, KOBJ_ADD); | 399 | kobject_uevent(&p->kobj, KOBJ_ADD); |
400 | 400 | ||
401 | return 0; | 401 | return 0; |
@@ -405,11 +405,9 @@ err4: | |||
405 | err3: | 405 | err3: |
406 | sysfs_remove_link(br->ifobj, p->dev->name); | 406 | sysfs_remove_link(br->ifobj, p->dev->name); |
407 | err2: | 407 | err2: |
408 | br_fdb_delete_by_port(br, p, 1); | ||
409 | err1: | ||
410 | kobject_put(&p->kobj); | 408 | kobject_put(&p->kobj); |
411 | p = NULL; /* kobject_put frees */ | 409 | p = NULL; /* kobject_put frees */ |
412 | err0: | 410 | err1: |
413 | dev_set_promiscuity(dev, -1); | 411 | dev_set_promiscuity(dev, -1); |
414 | put_back: | 412 | put_back: |
415 | dev_put(dev); | 413 | dev_put(dev); |
@@ -449,7 +447,7 @@ void __net_exit br_net_exit(struct net *net) | |||
449 | rtnl_lock(); | 447 | rtnl_lock(); |
450 | for_each_netdev(net, dev) | 448 | for_each_netdev(net, dev) |
451 | if (dev->priv_flags & IFF_EBRIDGE) | 449 | if (dev->priv_flags & IFF_EBRIDGE) |
452 | del_br(netdev_priv(dev), &list); | 450 | br_dev_delete(dev, &list); |
453 | 451 | ||
454 | unregister_netdevice_many(&list); | 452 | unregister_netdevice_many(&list); |
455 | rtnl_unlock(); | 453 | rtnl_unlock(); |