X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fbridge%2Fbr_if.c;h=f36b35edd60cefcbb27c7f3752a9ca3348242f94;hb=987b0145d94eecf292d8b301228356f44611ab7c;hp=f55ef682ef846e979b7e1b24569399a7c2fbd7da;hpb=9464c7cf61b9433057924c36e6e02f303a00e768;p=linux-2.6.git diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index f55ef682e..f36b35edd 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -210,8 +210,7 @@ static struct net_device *new_bridge_dev(const char *name) br->bridge_id.prio[0] = 0x80; br->bridge_id.prio[1] = 0x00; - - memcpy(br->group_addr, br_group_address, ETH_ALEN); + memset(br->bridge_id.addr, 0, ETH_ALEN); br->feature_mask = dev->features; br->stp_enabled = 0; @@ -238,11 +237,12 @@ static int find_portno(struct net_bridge *br) struct net_bridge_port *p; unsigned long *inuse; - inuse = kcalloc(BITS_TO_LONGS(BR_MAX_PORTS), sizeof(unsigned long), + inuse = kmalloc(BITS_TO_LONGS(BR_MAX_PORTS)*sizeof(unsigned long), GFP_KERNEL); if (!inuse) return -ENOMEM; + memset(inuse, 0, BITS_TO_LONGS(BR_MAX_PORTS)*sizeof(unsigned long)); set_bit(0, inuse); /* zero is reserved */ list_for_each_entry(p, &br->port_list, list) { set_bit(p->port_no, inuse); @@ -264,10 +264,11 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br, if (index < 0) return ERR_PTR(index); - p = kzalloc(sizeof(*p), GFP_KERNEL); + p = kmalloc(sizeof(*p), GFP_KERNEL); if (p == NULL) return ERR_PTR(-ENOMEM); + memset(p, 0, sizeof(*p)); p->br = br; dev_hold(dev); p->dev = dev; @@ -300,22 +301,34 @@ int br_add_bridge(const char *name) rtnl_lock(); if (strchr(dev->name, '%')) { ret = dev_alloc_name(dev, dev->name); - if (ret < 0) { - free_netdev(dev); - goto out; - } + if (ret < 0) + goto err1; } ret = register_netdevice(dev); if (ret) - goto out; + goto err2; + + /* network device kobject is not setup until + * after rtnl_unlock does it's hotplug magic. + * so hold reference to avoid race. + */ + dev_hold(dev); + rtnl_unlock(); ret = br_sysfs_addbr(dev); - if (ret) - unregister_netdevice(dev); + dev_put(dev); + + if (ret) + unregister_netdev(dev); out: - rtnl_unlock(); return ret; + + err2: + free_netdev(dev); + err1: + rtnl_unlock(); + goto out; } int br_del_bridge(const char *name) @@ -372,28 +385,17 @@ void br_features_recompute(struct net_bridge *br) struct net_bridge_port *p; unsigned long features, checksum; - checksum = br->feature_mask & NETIF_F_ALL_CSUM ? NETIF_F_NO_CSUM : 0; - features = br->feature_mask & ~NETIF_F_ALL_CSUM; + features = br->feature_mask &~ NETIF_F_IP_CSUM; + checksum = br->feature_mask & NETIF_F_IP_CSUM; list_for_each_entry(p, &br->port_list, list) { - unsigned long feature = p->dev->features; - - if (checksum & NETIF_F_NO_CSUM && !(feature & NETIF_F_NO_CSUM)) - checksum ^= NETIF_F_NO_CSUM | NETIF_F_HW_CSUM; - if (checksum & NETIF_F_HW_CSUM && !(feature & NETIF_F_HW_CSUM)) - checksum ^= NETIF_F_HW_CSUM | NETIF_F_IP_CSUM; - if (!(feature & NETIF_F_IP_CSUM)) + if (!(p->dev->features + & (NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM))) checksum = 0; - - if (feature & NETIF_F_GSO) - feature |= NETIF_F_TSO; - feature |= NETIF_F_GSO; - - features &= feature; + features &= p->dev->features; } - br->dev->features = features | checksum | NETIF_F_LLTX | - NETIF_F_GSO_ROBUST; + br->dev->features = features | checksum | NETIF_F_LLTX; } /* called with RTNL */