diff options
Diffstat (limited to 'drivers/net/bonding/bond_main.c')
-rw-r--r-- | drivers/net/bonding/bond_main.c | 173 |
1 files changed, 66 insertions, 107 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 63c22b0bb5ad..de3d351ccb6b 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -98,6 +98,7 @@ static char *mode; static char *primary; static char *primary_reselect; static char *lacp_rate; +static int min_links; static char *ad_select; static char *xmit_hash_policy; static int arp_interval = BOND_LINK_ARP_INTERV; @@ -150,6 +151,9 @@ module_param(ad_select, charp, 0); MODULE_PARM_DESC(ad_select, "803.ad aggregation selection logic; " "0 for stable (default), 1 for bandwidth, " "2 for count"); +module_param(min_links, int, 0); +MODULE_PARM_DESC(min_links, "Minimum number of available links before turning on carrier"); + module_param(xmit_hash_policy, charp, 0); MODULE_PARM_DESC(xmit_hash_policy, "balance-xor and 802.3ad hashing method; " "0 for layer 2 (default), 1 for layer 3+4, " @@ -329,16 +333,6 @@ static int bond_del_vlan(struct bonding *bond, unsigned short vlan_id) kfree(vlan); - if (list_empty(&bond->vlan_list) && - (bond->slave_cnt == 0)) { - /* Last VLAN removed and no slaves, so - * restore block on adding VLANs. This will - * be removed once new slaves that are not - * VLAN challenged will be added. - */ - bond->dev->features |= NETIF_F_VLAN_CHALLENGED; - } - res = 0; goto out; } @@ -414,9 +408,8 @@ int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, } /* - * In the following 3 functions, bond_vlan_rx_register(), bond_vlan_rx_add_vid - * and bond_vlan_rx_kill_vid, We don't protect the slave list iteration with a - * lock because: + * In the following 2 functions, bond_vlan_rx_add_vid and bond_vlan_rx_kill_vid, + * We don't protect the slave list iteration with a lock because: * a. This operation is performed in IOCTL context, * b. The operation is protected by the RTNL semaphore in the 8021q code, * c. Holding a lock with BH disabled while directly calling a base driver @@ -432,33 +425,6 @@ int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, */ /** - * bond_vlan_rx_register - Propagates registration to slaves - * @bond_dev: bonding net device that got called - * @grp: vlan group being registered - */ -static void bond_vlan_rx_register(struct net_device *bond_dev, - struct vlan_group *grp) -{ - struct bonding *bond = netdev_priv(bond_dev); - struct slave *slave; - int i; - - write_lock_bh(&bond->lock); - bond->vlgrp = grp; - write_unlock_bh(&bond->lock); - - bond_for_each_slave(bond, slave, i) { - struct net_device *slave_dev = slave->dev; - const struct net_device_ops *slave_ops = slave_dev->netdev_ops; - - if ((slave_dev->features & NETIF_F_HW_VLAN_RX) && - slave_ops->ndo_vlan_rx_register) { - slave_ops->ndo_vlan_rx_register(slave_dev, grp); - } - } -} - -/** * bond_vlan_rx_add_vid - Propagates adding an id to slaves * @bond_dev: bonding net device that got called * @vid: vlan id being added @@ -495,7 +461,6 @@ static void bond_vlan_rx_kill_vid(struct net_device *bond_dev, uint16_t vid) { struct bonding *bond = netdev_priv(bond_dev); struct slave *slave; - struct net_device *vlan_dev; int i, res; bond_for_each_slave(bond, slave, i) { @@ -504,12 +469,7 @@ static void bond_vlan_rx_kill_vid(struct net_device *bond_dev, uint16_t vid) if ((slave_dev->features & NETIF_F_HW_VLAN_FILTER) && slave_ops->ndo_vlan_rx_kill_vid) { - /* Save and then restore vlan_dev in the grp array, - * since the slave's driver might clear it. - */ - vlan_dev = vlan_group_get_device(bond->vlgrp, vid); slave_ops->ndo_vlan_rx_kill_vid(slave_dev, vid); - vlan_group_set_device(bond->vlgrp, vid, vlan_dev); } } @@ -525,13 +485,6 @@ static void bond_add_vlans_on_slave(struct bonding *bond, struct net_device *sla struct vlan_entry *vlan; const struct net_device_ops *slave_ops = slave_dev->netdev_ops; - if (!bond->vlgrp) - return; - - if ((slave_dev->features & NETIF_F_HW_VLAN_RX) && - slave_ops->ndo_vlan_rx_register) - slave_ops->ndo_vlan_rx_register(slave_dev, bond->vlgrp); - if (!(slave_dev->features & NETIF_F_HW_VLAN_FILTER) || !(slave_ops->ndo_vlan_rx_add_vid)) return; @@ -545,30 +498,16 @@ static void bond_del_vlans_from_slave(struct bonding *bond, { const struct net_device_ops *slave_ops = slave_dev->netdev_ops; struct vlan_entry *vlan; - struct net_device *vlan_dev; - - if (!bond->vlgrp) - return; if (!(slave_dev->features & NETIF_F_HW_VLAN_FILTER) || !(slave_ops->ndo_vlan_rx_kill_vid)) - goto unreg; + return; list_for_each_entry(vlan, &bond->vlan_list, vlan_list) { if (!vlan->vlan_id) continue; - /* Save and then restore vlan_dev in the grp array, - * since the slave's driver might clear it. - */ - vlan_dev = vlan_group_get_device(bond->vlgrp, vlan->vlan_id); slave_ops->ndo_vlan_rx_kill_vid(slave_dev, vlan->vlan_id); - vlan_group_set_device(bond->vlgrp, vlan->vlan_id, vlan_dev); } - -unreg: - if ((slave_dev->features & NETIF_F_HW_VLAN_RX) && - slave_ops->ndo_vlan_rx_register) - slave_ops->ndo_vlan_rx_register(slave_dev, NULL); } /*------------------------------- Link status -------------------------------*/ @@ -634,15 +573,8 @@ static int bond_update_speed_duplex(struct slave *slave) return -1; slave_speed = ethtool_cmd_speed(&etool); - switch (slave_speed) { - case SPEED_10: - case SPEED_100: - case SPEED_1000: - case SPEED_10000: - break; - default: + if (slave_speed == 0 || slave_speed == ((__u32) -1)) return -1; - } switch (etool.duplex) { case DUPLEX_FULL: @@ -845,22 +777,25 @@ static void bond_resend_igmp_join_requests(struct bonding *bond) read_lock(&bond->lock); + if (bond->kill_timers) + goto out; + /* rejoin all groups on bond device */ __bond_resend_igmp_join_requests(bond->dev); /* rejoin all groups on vlan devices */ - if (bond->vlgrp) { - list_for_each_entry(vlan, &bond->vlan_list, vlan_list) { - vlan_dev = vlan_group_get_device(bond->vlgrp, - vlan->vlan_id); - if (vlan_dev) - __bond_resend_igmp_join_requests(vlan_dev); - } + list_for_each_entry(vlan, &bond->vlan_list, vlan_list) { + rcu_read_lock(); + vlan_dev = __vlan_find_dev_deep(bond->dev, + vlan->vlan_id); + rcu_read_unlock(); + if (vlan_dev) + __bond_resend_igmp_join_requests(vlan_dev); } - if (--bond->igmp_retrans > 0) + if ((--bond->igmp_retrans > 0) && !bond->kill_timers) queue_delayed_work(bond->wq, &bond->mcast_work, HZ/5); - +out: read_unlock(&bond->lock); } @@ -1500,6 +1435,8 @@ static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb) struct sk_buff *skb = *pskb; struct slave *slave; struct bonding *bond; + void (*recv_probe)(struct sk_buff *, struct bonding *, + struct slave *); skb = skb_share_check(skb, GFP_ATOMIC); if (unlikely(!skb)) @@ -1513,11 +1450,12 @@ static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb) if (bond->params.arp_interval) slave->dev->last_rx = jiffies; - if (bond->recv_probe) { + recv_probe = ACCESS_ONCE(bond->recv_probe); + if (recv_probe) { struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC); if (likely(nskb)) { - bond->recv_probe(nskb, bond, slave); + recv_probe(nskb, bond, slave); dev_kfree_skb(nskb); } } @@ -1570,7 +1508,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) /* no need to lock since we're protected by rtnl_lock */ if (slave_dev->features & NETIF_F_VLAN_CHALLENGED) { pr_debug("%s: NETIF_F_VLAN_CHALLENGED\n", slave_dev->name); - if (bond->vlgrp) { + if (bond_vlan_used(bond)) { pr_err("%s: Error: cannot enslave VLAN challenged slave %s on VLAN enabled bond %s\n", bond_dev->name, slave_dev->name, bond_dev->name); return -EPERM; @@ -1625,8 +1563,10 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) if (slave_dev->type != ARPHRD_ETHER) bond_setup_by_slave(bond_dev, slave_dev); - else + else { ether_setup(bond_dev); + bond_dev->priv_flags &= ~IFF_TX_SKB_SHARING; + } netdev_bonding_change(bond_dev, NETDEV_POST_TYPE_CHANGE); @@ -1856,8 +1796,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) /* Initialize AD with the number of times that the AD timer is called in 1 second * can be called only after the mac address of the bond is set */ - bond_3ad_initialize(bond, 1000/AD_TIMER_INTERVAL, - bond->params.lacp_fast); + bond_3ad_initialize(bond, 1000/AD_TIMER_INTERVAL); } else { SLAVE_AD_INFO(new_slave).id = SLAVE_AD_INFO(new_slave->prev).id + 1; @@ -2079,7 +2018,7 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) */ memset(bond_dev->dev_addr, 0, bond_dev->addr_len); - if (bond->vlgrp) { + if (bond_vlan_used(bond)) { pr_warning("%s: Warning: clearing HW address of %s while it still has VLANs.\n", bond_dev->name, bond_dev->name); pr_warning("%s: When re-adding slaves, make sure the bond's HW address matches its VLANs'.\n", @@ -2261,7 +2200,7 @@ static int bond_release_all(struct net_device *bond_dev) */ memset(bond_dev->dev_addr, 0, bond_dev->addr_len); - if (bond->vlgrp) { + if (bond_vlan_used(bond)) { pr_warning("%s: Warning: clearing HW address of %s while it still has VLANs.\n", bond_dev->name, bond_dev->name); pr_warning("%s: When re-adding slaves, make sure the bond's HW address matches its VLANs'.\n", @@ -2605,7 +2544,7 @@ void bond_mii_monitor(struct work_struct *work) } re_arm: - if (bond->params.miimon) + if (bond->params.miimon && !bond->kill_timers) queue_delayed_work(bond->wq, &bond->mii_work, msecs_to_jiffies(bond->params.miimon)); out: @@ -2699,7 +2638,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave) if (!targets[i]) break; pr_debug("basa: target %x\n", targets[i]); - if (!bond->vlgrp) { + if (!bond_vlan_used(bond)) { pr_debug("basa: empty vlan: arp_send\n"); bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i], bond->master_ip, 0); @@ -2734,7 +2673,10 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave) vlan_id = 0; list_for_each_entry(vlan, &bond->vlan_list, vlan_list) { - vlan_dev = vlan_group_get_device(bond->vlgrp, vlan->vlan_id); + rcu_read_lock(); + vlan_dev = __vlan_find_dev_deep(bond->dev, + vlan->vlan_id); + rcu_read_unlock(); if (vlan_dev == rt->dst.dev) { vlan_id = vlan->vlan_id; pr_debug("basa: vlan match on %s %d\n", @@ -2950,7 +2892,7 @@ void bond_loadbalance_arp_mon(struct work_struct *work) } re_arm: - if (bond->params.arp_interval) + if (bond->params.arp_interval && !bond->kill_timers) queue_delayed_work(bond->wq, &bond->arp_work, delta_in_ticks); out: read_unlock(&bond->lock); @@ -3218,7 +3160,7 @@ void bond_activebackup_arp_mon(struct work_struct *work) bond_ab_arp_probe(bond); re_arm: - if (bond->params.arp_interval) + if (bond->params.arp_interval && !bond->kill_timers) queue_delayed_work(bond->wq, &bond->arp_work, delta_in_ticks); out: read_unlock(&bond->lock); @@ -3395,9 +3337,8 @@ static int bond_inetaddr_event(struct notifier_block *this, unsigned long event, } list_for_each_entry(vlan, &bond->vlan_list, vlan_list) { - if (!bond->vlgrp) - continue; - vlan_dev = vlan_group_get_device(bond->vlgrp, vlan->vlan_id); + vlan_dev = __vlan_find_dev_deep(bond->dev, + vlan->vlan_id); if (vlan_dev == event_dev) { switch (event) { case NETDEV_UP: @@ -3456,7 +3397,7 @@ static int bond_xmit_hash_policy_l34(struct sk_buff *skb, int count) int layer4_xor = 0; if (skb->protocol == htons(ETH_P_IP)) { - if (!(iph->frag_off & htons(IP_MF|IP_OFFSET)) && + if (!ip_is_fragment(iph) && (iph->protocol == IPPROTO_TCP || iph->protocol == IPPROTO_UDP)) { layer4_xor = ntohs((*layer4hdr ^ *(layer4hdr + 1))); @@ -3484,9 +3425,27 @@ static int bond_xmit_hash_policy_l2(struct sk_buff *skb, int count) static int bond_open(struct net_device *bond_dev) { struct bonding *bond = netdev_priv(bond_dev); + struct slave *slave; + int i; bond->kill_timers = 0; + /* reset slave->backup and slave->inactive */ + read_lock(&bond->lock); + if (bond->slave_cnt > 0) { + read_lock(&bond->curr_slave_lock); + bond_for_each_slave(bond, slave, i) { + if ((bond->params.mode == BOND_MODE_ACTIVEBACKUP) + && (slave != bond->curr_active_slave)) { + bond_set_slave_inactive_flags(slave); + } else { + bond_set_slave_active_flags(slave); + } + } + read_unlock(&bond->curr_slave_lock); + } + read_unlock(&bond->lock); + INIT_DELAYED_WORK(&bond->mcast_work, bond_resend_igmp_join_requests_delayed); if (bond_is_lb(bond)) { @@ -4349,10 +4308,9 @@ static const struct net_device_ops bond_netdev_ops = { .ndo_do_ioctl = bond_do_ioctl, .ndo_set_multicast_list = bond_set_multicast_list, .ndo_change_mtu = bond_change_mtu, - .ndo_set_mac_address = bond_set_mac_address, + .ndo_set_mac_address = bond_set_mac_address, .ndo_neigh_setup = bond_neigh_setup, - .ndo_vlan_rx_register = bond_vlan_rx_register, - .ndo_vlan_rx_add_vid = bond_vlan_rx_add_vid, + .ndo_vlan_rx_add_vid = bond_vlan_rx_add_vid, .ndo_vlan_rx_kill_vid = bond_vlan_rx_kill_vid, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_netpoll_setup = bond_netpoll_setup, @@ -4398,7 +4356,7 @@ static void bond_setup(struct net_device *bond_dev) bond_dev->tx_queue_len = 0; bond_dev->flags |= IFF_MASTER|IFF_MULTICAST; bond_dev->priv_flags |= IFF_BONDING; - bond_dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; + bond_dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING); /* At first, we block adding VLANs. That's the only way to * prevent problems that occur when adding VLANs over an @@ -4759,7 +4717,7 @@ static int bond_check_params(struct bond_params *params) /* miimon and arp_interval not set, we need one so things * work as expected, see bonding.txt for details */ - pr_warning("Warning: either miimon or arp_interval and arp_ip_target module parameters must be specified, otherwise bonding will not detect link failures! see bonding.txt for details.\n"); + pr_debug("Warning: either miimon or arp_interval and arp_ip_target module parameters must be specified, otherwise bonding will not detect link failures! see bonding.txt for details.\n"); } if (primary && !USES_PRIMARY(bond_mode)) { @@ -4816,6 +4774,7 @@ static int bond_check_params(struct bond_params *params) params->tx_queues = tx_queues; params->all_slaves_active = all_slaves_active; params->resend_igmp = resend_igmp; + params->min_links = min_links; if (primary) { strncpy(params->primary, primary, IFNAMSIZ); |