diff options
Diffstat (limited to 'drivers/net/bonding/bond_main.c')
-rw-r--r-- | drivers/net/bonding/bond_main.c | 51 |
1 files changed, 33 insertions, 18 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 6ba4c83fe5fc..e75acb14d066 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1026,12 +1026,38 @@ out: } +/** + * bond_choose_primary_or_current - select the primary or high priority slave + * @bond: our bonding struct + * + * - Check if there is a primary link. If the primary link was set and is up, + * go on and do link reselection. + * + * - If primary link is not set or down, find the highest priority link. + * If the highest priority link is not current slave, set it as primary + * link and do link reselection. + */ static struct slave *bond_choose_primary_or_current(struct bonding *bond) { struct slave *prim = rtnl_dereference(bond->primary_slave); struct slave *curr = rtnl_dereference(bond->curr_active_slave); + struct slave *slave, *hprio = NULL; + struct list_head *iter; if (!prim || prim->link != BOND_LINK_UP) { + bond_for_each_slave(bond, slave, iter) { + if (slave->link == BOND_LINK_UP) { + hprio = hprio ?: slave; + if (slave->prio > hprio->prio) + hprio = slave; + } + } + + if (hprio && hprio != curr) { + prim = hprio; + goto link_reselect; + } + if (!curr || curr->link != BOND_LINK_UP) return NULL; return curr; @@ -1042,6 +1068,7 @@ static struct slave *bond_choose_primary_or_current(struct bonding *bond) return prim; } +link_reselect: if (!curr || curr->link != BOND_LINK_UP) return prim; @@ -6220,45 +6247,33 @@ int bond_create(struct net *net, const char *name) { struct net_device *bond_dev; struct bonding *bond; - struct alb_bond_info *bond_info; - int res; + int res = -ENOMEM; rtnl_lock(); bond_dev = alloc_netdev_mq(sizeof(struct bonding), name ? name : "bond%d", NET_NAME_UNKNOWN, bond_setup, tx_queues); - if (!bond_dev) { - pr_err("%s: eek! can't alloc netdev!\n", name); - rtnl_unlock(); - return -ENOMEM; - } + if (!bond_dev) + goto out; - /* - * Initialize rx_hashtbl_used_head to RLB_NULL_INDEX. - * It is set to 0 by default which is wrong. - */ bond = netdev_priv(bond_dev); - bond_info = &(BOND_ALB_INFO(bond)); - bond_info->rx_hashtbl_used_head = RLB_NULL_INDEX; - dev_net_set(bond_dev, net); bond_dev->rtnl_link_ops = &bond_link_ops; res = register_netdevice(bond_dev); if (res < 0) { free_netdev(bond_dev); - rtnl_unlock(); - - return res; + goto out; } netif_carrier_off(bond_dev); bond_work_init_all(bond); +out: rtnl_unlock(); - return 0; + return res; } static int __net_init bond_net_init(struct net *net) |