]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - net/bridge/br_if.c
bridge: add local MAC address to forwarding table (v2)
[karo-tx-linux.git] / net / bridge / br_if.c
index e73815456adf2763f72d15ee649e2a3b1d6052a5..0a942fbccc9a64592d486199608e6527ebc8de8f 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
+#include <linux/etherdevice.h>
 #include <linux/netpoll.h>
 #include <linux/ethtool.h>
 #include <linux/if_arp.h>
  */
 static int port_cost(struct net_device *dev)
 {
-       if (dev->ethtool_ops && dev->ethtool_ops->get_settings) {
-               struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET, };
-
-               if (!dev_ethtool_get_settings(dev, &ecmd)) {
-                       switch (ethtool_cmd_speed(&ecmd)) {
-                       case SPEED_10000:
-                               return 2;
-                       case SPEED_1000:
-                               return 4;
-                       case SPEED_100:
-                               return 19;
-                       case SPEED_10:
-                               return 100;
-                       }
+       struct ethtool_cmd ecmd;
+
+       if (!__ethtool_get_settings(dev, &ecmd)) {
+               switch (ethtool_cmd_speed(&ecmd)) {
+               case SPEED_10000:
+                       return 2;
+               case SPEED_1000:
+                       return 4;
+               case SPEED_100:
+                       return 19;
+               case SPEED_10:
+                       return 100;
                }
        }
 
@@ -161,9 +160,10 @@ static void del_nbp(struct net_bridge_port *p)
        call_rcu(&p->rcu, destroy_nbp_rcu);
 }
 
-/* called with RTNL */
-static void del_br(struct net_bridge *br, struct list_head *head)
+/* Delete bridge device */
+void br_dev_delete(struct net_device *dev, struct list_head *head)
 {
+       struct net_bridge *br = netdev_priv(dev);
        struct net_bridge_port *p, *n;
 
        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)
        }
 
        else
-               del_br(netdev_priv(dev), NULL);
+               br_dev_delete(dev, NULL);
 
        rtnl_unlock();
        return ret;
@@ -296,10 +296,11 @@ int br_min_mtu(const struct net_bridge *br)
 /*
  * Recomputes features using slave's features
  */
-u32 br_features_recompute(struct net_bridge *br, u32 features)
+netdev_features_t br_features_recompute(struct net_bridge *br,
+       netdev_features_t features)
 {
        struct net_bridge_port *p;
-       u32 mask;
+       netdev_features_t mask;
 
        if (list_empty(&br->port_list))
                return features;
@@ -324,7 +325,8 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
 
        /* Don't allow bridging non-ethernet like devices */
        if ((dev->flags & IFF_LOOPBACK) ||
-           dev->type != ARPHRD_ETHER || dev->addr_len != ETH_ALEN)
+           dev->type != ARPHRD_ETHER || dev->addr_len != ETH_ALEN ||
+           !is_valid_ether_addr(dev->dev_addr))
                return -EINVAL;
 
        /* No bridging of bridges */
@@ -351,10 +353,6 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
 
        err = kobject_init_and_add(&p->kobj, &brport_ktype, &(dev->dev.kobj),
                                   SYSFS_BRIDGE_PORT_ATTR);
-       if (err)
-               goto err0;
-
-       err = br_fdb_insert(br, p, dev->dev_addr);
        if (err)
                goto err1;
 
@@ -396,6 +394,9 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
 
        dev_set_mtu(br->dev, br_min_mtu(br));
 
+       if (br_fdb_insert(br, p, dev->dev_addr))
+               netdev_err(dev, "failed insert local address bridge forwarding table\n");
+
        kobject_uevent(&p->kobj, KOBJ_ADD);
 
        return 0;
@@ -405,11 +406,9 @@ err4:
 err3:
        sysfs_remove_link(br->ifobj, p->dev->name);
 err2:
-       br_fdb_delete_by_port(br, p, 1);
-err1:
        kobject_put(&p->kobj);
        p = NULL; /* kobject_put frees */
-err0:
+err1:
        dev_set_promiscuity(dev, -1);
 put_back:
        dev_put(dev);
@@ -449,7 +448,7 @@ void __net_exit br_net_exit(struct net *net)
        rtnl_lock();
        for_each_netdev(net, dev)
                if (dev->priv_flags & IFF_EBRIDGE)
-                       del_br(netdev_priv(dev), &list);
+                       br_dev_delete(dev, &list);
 
        unregister_netdevice_many(&list);
        rtnl_unlock();