aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge/br_if.c
diff options
context:
space:
mode:
authorstephen hemminger <shemminger@vyatta.com>2011-09-30 10:37:26 -0400
committerDavid S. Miller <davem@davemloft.net>2011-10-03 12:17:33 -0400
commit77f9859837cbe262ef2aa12fc38d18458814c2ca (patch)
tree51653355c4a333e63551c58934629881bb0856a2 /net/bridge/br_if.c
parent3de09455cfcde1898fb435ad425b9ad5d13ed362 (diff)
bridge: fix ordering of NEWLINK and NEWNEIGH events
When port is added to a bridge, the old code would send the new neighbor netlink message before the subsequent new link message. This bug makes it difficult to use the monitoring API in an application. This code changes the ordering to add the forwarding entry after the port is setup. One of the error checks (for invalid address) is moved earlier in the process to avoid having to do unwind. Signed-off-by: Stephen Hemminger <shemminger@vyatta.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/bridge/br_if.c')
-rw-r--r--net/bridge/br_if.c15
1 files changed, 7 insertions, 8 deletions
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 13f34acb2a8e..c3b77dceb937 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>
@@ -322,7 +323,8 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
322 323
323 /* Don't allow bridging non-ethernet like devices */ 324 /* Don't allow bridging non-ethernet like devices */
324 if ((dev->flags & IFF_LOOPBACK) || 325 if ((dev->flags & IFF_LOOPBACK) ||
325 dev->type != ARPHRD_ETHER || dev->addr_len != ETH_ALEN) 326 dev->type != ARPHRD_ETHER || dev->addr_len != ETH_ALEN ||
327 !is_valid_ether_addr(dev->dev_addr))
326 return -EINVAL; 328 return -EINVAL;
327 329
328 /* No bridging of bridges */ 330 /* No bridging of bridges */
@@ -350,10 +352,6 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
350 err = kobject_init_and_add(&p->kobj, &brport_ktype, &(dev->dev.kobj), 352 err = kobject_init_and_add(&p->kobj, &brport_ktype, &(dev->dev.kobj),
351 SYSFS_BRIDGE_PORT_ATTR); 353 SYSFS_BRIDGE_PORT_ATTR);
352 if (err) 354 if (err)
353 goto err0;
354
355 err = br_fdb_insert(br, p, dev->dev_addr);
356 if (err)
357 goto err1; 355 goto err1;
358 356
359 err = br_sysfs_addif(p); 357 err = br_sysfs_addif(p);
@@ -394,6 +392,9 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
394 392
395 dev_set_mtu(br->dev, br_min_mtu(br)); 393 dev_set_mtu(br->dev, br_min_mtu(br));
396 394
395 if (br_fdb_insert(br, p, dev->dev_addr))
396 netdev_err(dev, "failed insert local address bridge forwarding table\n");
397
397 kobject_uevent(&p->kobj, KOBJ_ADD); 398 kobject_uevent(&p->kobj, KOBJ_ADD);
398 399
399 return 0; 400 return 0;
@@ -403,11 +404,9 @@ err4:
403err3: 404err3:
404 sysfs_remove_link(br->ifobj, p->dev->name); 405 sysfs_remove_link(br->ifobj, p->dev->name);
405err2: 406err2:
406 br_fdb_delete_by_port(br, p, 1);
407err1:
408 kobject_put(&p->kobj); 407 kobject_put(&p->kobj);
409 p = NULL; /* kobject_put frees */ 408 p = NULL; /* kobject_put frees */
410err0: 409err1:
411 dev_set_promiscuity(dev, -1); 410 dev_set_promiscuity(dev, -1);
412put_back: 411put_back:
413 dev_put(dev); 412 dev_put(dev);