net: Simplify the bond drivers pernet operations.
[pandora-kernel.git] / drivers / net / bonding / bond_main.c
index 40fb5ee..ac3fe20 100644 (file)
@@ -75,6 +75,7 @@
 #include <linux/jiffies.h>
 #include <net/route.h>
 #include <net/net_namespace.h>
+#include <net/netns/generic.h>
 #include "bonding.h"
 #include "bond_3ad.h"
 #include "bond_alb.h"
@@ -94,6 +95,7 @@ static int downdelay;
 static int use_carrier = 1;
 static char *mode;
 static char *primary;
+static char *primary_reselect;
 static char *lacp_rate;
 static char *ad_select;
 static char *xmit_hash_policy;
@@ -126,6 +128,14 @@ MODULE_PARM_DESC(mode, "Mode of operation : 0 for balance-rr, "
                       "6 for balance-alb");
 module_param(primary, charp, 0);
 MODULE_PARM_DESC(primary, "Primary network device to use");
+module_param(primary_reselect, charp, 0);
+MODULE_PARM_DESC(primary_reselect, "Reselect primary slave "
+                                  "once it comes up; "
+                                  "0 for always (default), "
+                                  "1 for only if speed of primary is "
+                                  "better, "
+                                  "2 for only on active slave "
+                                  "failure");
 module_param(lacp_rate, charp, 0);
 MODULE_PARM_DESC(lacp_rate, "LACPDU tx rate to request from 802.3ad partner "
                            "(slow/fast)");
@@ -148,11 +158,7 @@ MODULE_PARM_DESC(fail_over_mac, "For active-backup, do not set all slaves to the
 static const char * const version =
        DRV_DESCRIPTION ": v" DRV_VERSION " (" DRV_RELDATE ")\n";
 
-LIST_HEAD(bond_dev_list);
-
-#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry *bond_proc_dir;
-#endif
+int bond_net_id __read_mostly;
 
 static __be32 arp_target[BOND_MAX_ARP_TARGETS];
 static int arp_ip_count;
@@ -200,6 +206,13 @@ const struct bond_parm_tbl fail_over_mac_tbl[] = {
 {      NULL,                   -1},
 };
 
+const struct bond_parm_tbl pri_reselect_tbl[] = {
+{      "always",               BOND_PRI_RESELECT_ALWAYS},
+{      "better",               BOND_PRI_RESELECT_BETTER},
+{      "failure",              BOND_PRI_RESELECT_FAILURE},
+{      NULL,                   -1},
+};
+
 struct bond_parm_tbl ad_select_tbl[] = {
 {      "stable",       BOND_AD_STABLE},
 {      "bandwidth",    BOND_AD_BANDWIDTH},
@@ -211,7 +224,7 @@ struct bond_parm_tbl ad_select_tbl[] = {
 
 static void bond_send_gratuitous_arp(struct bonding *bond);
 static int bond_init(struct net_device *bond_dev);
-static void bond_deinit(struct net_device *bond_dev);
+static void bond_uninit(struct net_device *bond_dev);
 
 /*---------------------------- General routines -----------------------------*/
 
@@ -1070,6 +1083,25 @@ out:
 
 }
 
+static bool bond_should_change_active(struct bonding *bond)
+{
+       struct slave *prim = bond->primary_slave;
+       struct slave *curr = bond->curr_active_slave;
+
+       if (!prim || !curr || curr->link != BOND_LINK_UP)
+               return true;
+       if (bond->force_primary) {
+               bond->force_primary = false;
+               return true;
+       }
+       if (bond->params.primary_reselect == BOND_PRI_RESELECT_BETTER &&
+           (prim->speed < curr->speed ||
+            (prim->speed == curr->speed && prim->duplex <= curr->duplex)))
+               return false;
+       if (bond->params.primary_reselect == BOND_PRI_RESELECT_FAILURE)
+               return false;
+       return true;
+}
 
 /**
  * find_best_interface - select the best available slave to be the active one
@@ -1084,7 +1116,7 @@ static struct slave *bond_find_best_slave(struct bonding *bond)
        int mintime = bond->params.updelay;
        int i;
 
-       new_active = old_active = bond->curr_active_slave;
+       new_active = bond->curr_active_slave;
 
        if (!new_active) { /* there were no active slaves left */
                if (bond->slave_cnt > 0)   /* found one slave */
@@ -1094,7 +1126,8 @@ static struct slave *bond_find_best_slave(struct bonding *bond)
        }
 
        if ((bond->primary_slave) &&
-           bond->primary_slave->link == BOND_LINK_UP) {
+           bond->primary_slave->link == BOND_LINK_UP &&
+           bond_should_change_active(bond)) {
                new_active = bond->primary_slave;
        }
 
@@ -1678,8 +1711,10 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 
        if (USES_PRIMARY(bond->params.mode) && bond->params.primary[0]) {
                /* if there is a primary slave, remember it */
-               if (strcmp(bond->params.primary, new_slave->dev->name) == 0)
+               if (strcmp(bond->params.primary, new_slave->dev->name) == 0) {
                        bond->primary_slave = new_slave;
+                       bond->force_primary = true;
+               }
        }
 
        write_lock_bh(&bond->curr_slave_lock);
@@ -1964,25 +1999,6 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
        return 0;  /* deletion OK */
 }
 
-/*
-* Destroy a bonding device.
-* Must be under rtnl_lock when this function is called.
-*/
-static void bond_uninit(struct net_device *bond_dev)
-{
-       struct bonding *bond = netdev_priv(bond_dev);
-
-       bond_deinit(bond_dev);
-       bond_destroy_sysfs_entry(bond);
-
-       if (bond->wq)
-               destroy_workqueue(bond->wq);
-
-       netif_addr_lock_bh(bond_dev);
-       bond_mc_list_destroy(bond);
-       netif_addr_unlock_bh(bond_dev);
-}
-
 /*
 * First release a slave and than destroy the bond if no more slaves are left.
 * Must be under rtnl_lock when this function is called.
@@ -2567,7 +2583,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
                fl.fl4_dst = targets[i];
                fl.fl4_tos = RTO_ONLINK;
 
-               rv = ip_route_output_key(&init_net, &rt, &fl);
+               rv = ip_route_output_key(dev_net(bond->dev), &rt, &fl);
                if (rv) {
                        if (net_ratelimit()) {
                                pr_warning(DRV_NAME
@@ -2675,9 +2691,6 @@ static int bond_arp_rcv(struct sk_buff *skb, struct net_device *dev, struct pack
        unsigned char *arp_ptr;
        __be32 sip, tip;
 
-       if (dev_net(dev) != &init_net)
-               goto out;
-
        if (!(dev->priv_flags & IFF_BONDING) || !(dev->flags & IFF_MASTER))
                goto out;
 
@@ -3201,11 +3214,14 @@ static void bond_info_show_master(struct seq_file *seq)
        }
 
        if (USES_PRIMARY(bond->params.mode)) {
-               seq_printf(seq, "Primary Slave: %s\n",
+               seq_printf(seq, "Primary Slave: %s",
                           (bond->primary_slave) ?
                           bond->primary_slave->dev->name : "None");
+               if (bond->primary_slave)
+                       seq_printf(seq, " (primary_reselect %s)",
+                  pri_reselect_tbl[bond->params.primary_reselect].modename);
 
-               seq_printf(seq, "Currently Active Slave: %s\n",
+               seq_printf(seq, "\nCurrently Active Slave: %s\n",
                           (curr) ? curr->dev->name : "None");
        }
 
@@ -3334,13 +3350,14 @@ static const struct file_operations bond_info_fops = {
        .release = seq_release,
 };
 
-static int bond_create_proc_entry(struct bonding *bond)
+static void bond_create_proc_entry(struct bonding *bond)
 {
        struct net_device *bond_dev = bond->dev;
+       struct bond_net *bn = net_generic(dev_net(bond_dev), bond_net_id);
 
-       if (bond_proc_dir) {
+       if (bn->proc_dir) {
                bond->proc_entry = proc_create_data(bond_dev->name,
-                                                   S_IRUGO, bond_proc_dir,
+                                                   S_IRUGO, bn->proc_dir,
                                                    &bond_info_fops, bond);
                if (bond->proc_entry == NULL)
                        pr_warning(DRV_NAME
@@ -3349,14 +3366,15 @@ static int bond_create_proc_entry(struct bonding *bond)
                else
                        memcpy(bond->proc_file_name, bond_dev->name, IFNAMSIZ);
        }
-
-       return 0;
 }
 
 static void bond_remove_proc_entry(struct bonding *bond)
 {
-       if (bond_proc_dir && bond->proc_entry) {
-               remove_proc_entry(bond->proc_file_name, bond_proc_dir);
+       struct net_device *bond_dev = bond->dev;
+       struct bond_net *bn = net_generic(dev_net(bond_dev), bond_net_id);
+
+       if (bn->proc_dir && bond->proc_entry) {
+               remove_proc_entry(bond->proc_file_name, bn->proc_dir);
                memset(bond->proc_file_name, 0, IFNAMSIZ);
                bond->proc_entry = NULL;
        }
@@ -3365,11 +3383,11 @@ static void bond_remove_proc_entry(struct bonding *bond)
 /* Create the bonding directory under /proc/net, if doesn't exist yet.
  * Caller must hold rtnl_lock.
  */
-static void bond_create_proc_dir(void)
+static void bond_create_proc_dir(struct bond_net *bn)
 {
-       if (!bond_proc_dir) {
-               bond_proc_dir = proc_mkdir(DRV_NAME, init_net.proc_net);
-               if (!bond_proc_dir)
+       if (!bn->proc_dir) {
+               bn->proc_dir = proc_mkdir(DRV_NAME, bn->net->proc_net);
+               if (!bn->proc_dir)
                        pr_warning(DRV_NAME
                                ": Warning: cannot create /proc/net/%s\n",
                                DRV_NAME);
@@ -3379,17 +3397,17 @@ static void bond_create_proc_dir(void)
 /* Destroy the bonding directory under /proc/net, if empty.
  * Caller must hold rtnl_lock.
  */
-static void bond_destroy_proc_dir(void)
+static void bond_destroy_proc_dir(struct bond_net *bn)
 {
-       if (bond_proc_dir) {
-               remove_proc_entry(DRV_NAME, init_net.proc_net);
-               bond_proc_dir = NULL;
+       if (bn->proc_dir) {
+               remove_proc_entry(DRV_NAME, bn->net->proc_net);
+               bn->proc_dir = NULL;
        }
 }
 
 #else /* !CONFIG_PROC_FS */
 
-static int bond_create_proc_entry(struct bonding *bond)
+static void bond_create_proc_entry(struct bonding *bond)
 {
 }
 
@@ -3397,11 +3415,11 @@ static void bond_remove_proc_entry(struct bonding *bond)
 {
 }
 
-static void bond_create_proc_dir(void)
+static void bond_create_proc_dir(struct bond_net *bn)
 {
 }
 
-static void bond_destroy_proc_dir(void)
+static void bond_destroy_proc_dir(struct bond_net *bn)
 {
 }
 
@@ -3418,9 +3436,6 @@ static int bond_event_changename(struct bonding *bond)
        bond_remove_proc_entry(bond);
        bond_create_proc_entry(bond);
 
-       bond_destroy_sysfs_entry(bond);
-       bond_create_sysfs_entry(bond);
-
        return NOTIFY_DONE;
 }
 
@@ -3432,9 +3447,6 @@ static int bond_master_netdev_event(unsigned long event,
        switch (event) {
        case NETDEV_CHANGENAME:
                return bond_event_changename(event_bond);
-       case NETDEV_UNREGISTER:
-               bond_release_all(event_bond->dev);
-               break;
        default:
                break;
        }
@@ -3526,9 +3538,6 @@ static int bond_netdev_event(struct notifier_block *this,
 {
        struct net_device *event_dev = (struct net_device *)ptr;
 
-       if (dev_net(event_dev) != &init_net)
-               return NOTIFY_DONE;
-
        pr_debug("event_dev: %s, event: %lx\n",
                (event_dev ? event_dev->name : "None"),
                event);
@@ -3561,13 +3570,11 @@ static int bond_inetaddr_event(struct notifier_block *this, unsigned long event,
 {
        struct in_ifaddr *ifa = ptr;
        struct net_device *vlan_dev, *event_dev = ifa->ifa_dev->dev;
+       struct bond_net *bn = net_generic(dev_net(event_dev), bond_net_id);
        struct bonding *bond;
        struct vlan_entry *vlan;
 
-       if (dev_net(ifa->ifa_dev->dev) != &init_net)
-               return NOTIFY_DONE;
-
-       list_for_each_entry(bond, &bond_dev_list, bond_list) {
+       list_for_each_entry(bond, &bn->dev_list, bond_list) {
                if (bond->dev == event_dev) {
                        switch (event) {
                        case NETDEV_UP:
@@ -3657,8 +3664,7 @@ void bond_unregister_arp(struct bonding *bond)
  * Hash for the output device based upon layer 2 and layer 3 data. If
  * the packet is not IP mimic bond_xmit_hash_policy_l2()
  */
-static int bond_xmit_hash_policy_l23(struct sk_buff *skb,
-                                    struct net_device *bond_dev, int count)
+static int bond_xmit_hash_policy_l23(struct sk_buff *skb, int count)
 {
        struct ethhdr *data = (struct ethhdr *)skb->data;
        struct iphdr *iph = ip_hdr(skb);
@@ -3676,8 +3682,7 @@ static int bond_xmit_hash_policy_l23(struct sk_buff *skb,
  * the packet is a frag or not TCP or UDP, just use layer 3 data.  If it is
  * altogether not IP, mimic bond_xmit_hash_policy_l2()
  */
-static int bond_xmit_hash_policy_l34(struct sk_buff *skb,
-                                   struct net_device *bond_dev, int count)
+static int bond_xmit_hash_policy_l34(struct sk_buff *skb, int count)
 {
        struct ethhdr *data = (struct ethhdr *)skb->data;
        struct iphdr *iph = ip_hdr(skb);
@@ -3701,8 +3706,7 @@ static int bond_xmit_hash_policy_l34(struct sk_buff *skb,
 /*
  * Hash for the output device based upon layer 2 data
  */
-static int bond_xmit_hash_policy_l2(struct sk_buff *skb,
-                                  struct net_device *bond_dev, int count)
+static int bond_xmit_hash_policy_l2(struct sk_buff *skb, int count)
 {
        struct ethhdr *data = (struct ethhdr *)skb->data;
 
@@ -3939,7 +3943,7 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd
        if (!capable(CAP_NET_ADMIN))
                return -EPERM;
 
-       slave_dev = dev_get_by_name(&init_net, ifr->ifr_slave);
+       slave_dev = dev_get_by_name(dev_net(bond_dev), ifr->ifr_slave);
 
        pr_debug("slave_dev=%p: \n", slave_dev);
 
@@ -4295,7 +4299,7 @@ static int bond_xmit_xor(struct sk_buff *skb, struct net_device *bond_dev)
        if (!BOND_IS_OK(bond))
                goto out;
 
-       slave_no = bond->xmit_hash_policy(skb, bond_dev, bond->slave_cnt);
+       slave_no = bond->xmit_hash_policy(skb, bond->slave_cnt);
 
        bond_for_each_slave(bond, slave, i) {
                slave_no--;
@@ -4576,37 +4580,29 @@ static void bond_work_cancel_all(struct bonding *bond)
                cancel_delayed_work(&bond->ad_work);
 }
 
-/* De-initialize device specific data.
- * Caller must hold rtnl_lock.
- */
-static void bond_deinit(struct net_device *bond_dev)
+/*
+* Destroy a bonding device.
+* Must be under rtnl_lock when this function is called.
+*/
+static void bond_uninit(struct net_device *bond_dev)
 {
        struct bonding *bond = netdev_priv(bond_dev);
 
+       /* Release the bonded slaves */
+       bond_release_all(bond_dev);
+
        list_del(&bond->bond_list);
 
        bond_work_cancel_all(bond);
 
        bond_remove_proc_entry(bond);
-}
-
-/* Unregister and free all bond devices.
- * Caller must hold rtnl_lock.
- */
-static void bond_free_all(void)
-{
-       struct bonding *bond, *nxt;
 
-       list_for_each_entry_safe(bond, nxt, &bond_dev_list, bond_list) {
-               struct net_device *bond_dev = bond->dev;
-
-               bond_work_cancel_all(bond);
-               /* Release the bonded slaves */
-               bond_release_all(bond_dev);
-               unregister_netdevice(bond_dev);
-       }
+       if (bond->wq)
+               destroy_workqueue(bond->wq);
 
-       bond_destroy_proc_dir();
+       netif_addr_lock_bh(bond_dev);
+       bond_mc_list_destroy(bond);
+       netif_addr_unlock_bh(bond_dev);
 }
 
 /*------------------------- Module initialization ---------------------------*/
@@ -4646,7 +4642,7 @@ int bond_parse_parm(const char *buf, const struct bond_parm_tbl *tbl)
 
 static int bond_check_params(struct bond_params *params)
 {
-       int arp_validate_value, fail_over_mac_value;
+       int arp_validate_value, fail_over_mac_value, primary_reselect_value;
 
        /*
         * Convert string parameters.
@@ -4665,7 +4661,8 @@ static int bond_check_params(struct bond_params *params)
                if ((bond_mode != BOND_MODE_XOR) &&
                    (bond_mode != BOND_MODE_8023AD)) {
                        pr_info(DRV_NAME
-                              ": xor_mode param is irrelevant in mode %s\n",
+                               ": xmit_hash_policy param is irrelevant in"
+                               " mode %s\n",
                               bond_mode_name(bond_mode));
                } else {
                        xmit_hashtype = bond_parse_parm(xmit_hash_policy,
@@ -4945,6 +4942,20 @@ static int bond_check_params(struct bond_params *params)
                primary = NULL;
        }
 
+       if (primary && primary_reselect) {
+               primary_reselect_value = bond_parse_parm(primary_reselect,
+                                                        pri_reselect_tbl);
+               if (primary_reselect_value == -1) {
+                       pr_err(DRV_NAME
+                              ": Error: Invalid primary_reselect \"%s\"\n",
+                              primary_reselect ==
+                                       NULL ? "NULL" : primary_reselect);
+                       return -EINVAL;
+               }
+       } else {
+               primary_reselect_value = BOND_PRI_RESELECT_ALWAYS;
+       }
+
        if (fail_over_mac) {
                fail_over_mac_value = bond_parse_parm(fail_over_mac,
                                                      fail_over_mac_tbl);
@@ -4976,6 +4987,7 @@ static int bond_check_params(struct bond_params *params)
        params->use_carrier = use_carrier;
        params->lacp_fast = lacp_fast;
        params->primary[0] = 0;
+       params->primary_reselect = primary_reselect_value;
        params->fail_over_mac = fail_over_mac_value;
 
        if (primary) {
@@ -5012,6 +5024,7 @@ static void bond_set_lockdep_class(struct net_device *dev)
 static int bond_init(struct net_device *bond_dev)
 {
        struct bonding *bond = netdev_priv(bond_dev);
+       struct bond_net *bn = net_generic(dev_net(bond_dev), bond_net_id);
 
        pr_debug("Begin bond_init for %s\n", bond_dev->name);
 
@@ -5024,30 +5037,41 @@ static int bond_init(struct net_device *bond_dev)
        netif_carrier_off(bond_dev);
 
        bond_create_proc_entry(bond);
-       list_add_tail(&bond->bond_list, &bond_dev_list);
+       list_add_tail(&bond->bond_list, &bn->dev_list);
 
+       bond_prepare_sysfs_group(bond);
+       return 0;
+}
+
+static int bond_validate(struct nlattr *tb[], struct nlattr *data[])
+{
+       if (tb[IFLA_ADDRESS]) {
+               if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
+                       return -EINVAL;
+               if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
+                       return -EADDRNOTAVAIL;
+       }
        return 0;
 }
 
+static struct rtnl_link_ops bond_link_ops __read_mostly = {
+       .kind           = "bond",
+       .priv_size      = sizeof(struct bonding),
+       .setup          = bond_setup,
+       .validate       = bond_validate,
+};
+
 /* Create a new bond based on the specified name and bonding parameters.
  * If name is NULL, obtain a suitable "bond%d" name for us.
  * Caller must NOT hold rtnl_lock; we need to release it here before we
  * set up our sysfs entries.
  */
-int bond_create(const char *name)
+int bond_create(struct net *net, const char *name)
 {
        struct net_device *bond_dev;
        int res;
 
        rtnl_lock();
-       /* Check to see if the bond already exists. */
-       /* FIXME: pass netns from caller */
-       if (name && __dev_get_by_name(&init_net, name)) {
-               pr_err(DRV_NAME ": cannot add bond %s; already exists\n",
-                      name);
-               res = -EEXIST;
-               goto out_rtnl;
-       }
 
        bond_dev = alloc_netdev(sizeof(struct bonding), name ? name : "",
                                bond_setup);
@@ -5055,9 +5079,12 @@ int bond_create(const char *name)
                pr_err(DRV_NAME ": %s: eek! can't alloc netdev!\n",
                       name);
                res = -ENOMEM;
-               goto out_rtnl;
+               goto out;
        }
 
+       dev_net_set(bond_dev, net);
+       bond_dev->rtnl_link_ops = &bond_link_ops;
+
        if (!name) {
                res = dev_alloc_name(bond_dev, "bond%d");
                if (res < 0)
@@ -5065,27 +5092,41 @@ int bond_create(const char *name)
        }
 
        res = register_netdevice(bond_dev);
-       if (res < 0)
-               goto out_bond;
-
-       res = bond_create_sysfs_entry(netdev_priv(bond_dev));
-       if (res < 0)
-               goto out_unreg;
 
+out:
        rtnl_unlock();
-       return 0;
-
-out_unreg:
-       unregister_netdevice(bond_dev);
-out_bond:
-       bond_deinit(bond_dev);
+       return res;
 out_netdev:
        free_netdev(bond_dev);
-out_rtnl:
-       rtnl_unlock();
-       return res;
+       goto out;
+}
+
+static int bond_net_init(struct net *net)
+{
+       struct bond_net *bn = net_generic(net, bond_net_id);
+
+       bn->net = net;
+       INIT_LIST_HEAD(&bn->dev_list);
+
+       bond_create_proc_dir(bn);
+       
+       return 0;
 }
 
+static void bond_net_exit(struct net *net)
+{
+       struct bond_net *bn = net_generic(net, bond_net_id);
+
+       bond_destroy_proc_dir(bn);
+}
+
+static struct pernet_operations bond_net_ops = {
+       .init = bond_net_init,
+       .exit = bond_net_exit,
+       .id   = &bond_net_id,
+       .size = sizeof(struct bond_net),
+};
+
 static int __init bonding_init(void)
 {
        int i;
@@ -5097,10 +5138,16 @@ static int __init bonding_init(void)
        if (res)
                goto out;
 
-       bond_create_proc_dir();
+       res = register_pernet_subsys(&bond_net_ops);
+       if (res)
+               goto out;
+
+       res = rtnl_link_register(&bond_link_ops);
+       if (res)
+               goto err_link;
 
        for (i = 0; i < max_bonds; i++) {
-               res = bond_create(NULL);
+               res = bond_create(&init_net, NULL);
                if (res)
                        goto err;
        }
@@ -5112,14 +5159,13 @@ static int __init bonding_init(void)
        register_netdevice_notifier(&bond_netdev_notifier);
        register_inetaddr_notifier(&bond_inetaddr_notifier);
        bond_register_ipv6_notifier();
-
-       goto out;
-err:
-       rtnl_lock();
-       bond_free_all();
-       rtnl_unlock();
 out:
        return res;
+err:
+       rtnl_link_unregister(&bond_link_ops);
+err_link:
+       unregister_pernet_subsys(&bond_net_ops);
+       goto out;
 
 }
 
@@ -5131,9 +5177,8 @@ static void __exit bonding_exit(void)
 
        bond_destroy_sysfs();
 
-       rtnl_lock();
-       bond_free_all();
-       rtnl_unlock();
+       rtnl_link_unregister(&bond_link_ops);
+       unregister_pernet_subsys(&bond_net_ops);
 }
 
 module_init(bonding_init);
@@ -5142,3 +5187,4 @@ MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
 MODULE_DESCRIPTION(DRV_DESCRIPTION ", v" DRV_VERSION);
 MODULE_AUTHOR("Thomas Davis, tadavis@lbl.gov and many others");
+MODULE_ALIAS_RTNL_LINK("bond");