X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fnet%2Fbonding%2Fbond_main.c;h=6482aed4bb7cddec1c6879e47a3a26a495332359;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=bcf9f17daf0d36944d5ec362de405e7be718ab08;hpb=76828883507a47dae78837ab5dec5a5b4513c667;p=linux-2.6.git diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index bcf9f17da..6482aed4b 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -33,7 +33,6 @@ //#define BONDING_DEBUG 1 -#include #include #include #include @@ -97,6 +96,7 @@ static char *lacp_rate = NULL; static char *xmit_hash_policy = NULL; static int arp_interval = BOND_LINK_ARP_INTERV; static char *arp_ip_target[BOND_MAX_ARP_TARGETS] = { NULL, }; +static char *arp_validate = NULL; struct bond_params bonding_defaults; module_param(max_bonds, int, 0); @@ -128,10 +128,12 @@ module_param(arp_interval, int, 0); MODULE_PARM_DESC(arp_interval, "arp interval in milliseconds"); module_param_array(arp_ip_target, charp, NULL, 0); MODULE_PARM_DESC(arp_ip_target, "arp targets in n.n.n.n form"); +module_param(arp_validate, charp, 0); +MODULE_PARM_DESC(arp_validate, "validate src/dst of ARP probes: none (default), active, backup or all"); /*----------------------------- Global variables ----------------------------*/ -static const char *version = +static const char * const version = DRV_DESCRIPTION ": v" DRV_VERSION " (" DRV_RELDATE ")\n"; LIST_HEAD(bond_dev_list); @@ -171,6 +173,14 @@ struct bond_parm_tbl xmit_hashtype_tbl[] = { { NULL, -1}, }; +struct bond_parm_tbl arp_validate_tbl[] = { +{ "none", BOND_ARP_VALIDATE_NONE}, +{ "active", BOND_ARP_VALIDATE_ACTIVE}, +{ "backup", BOND_ARP_VALIDATE_BACKUP}, +{ "all", BOND_ARP_VALIDATE_ALL}, +{ NULL, -1}, +}; + /*-------------------------- Forward declarations ---------------------------*/ static void bond_send_gratuitous_arp(struct bonding *bond); @@ -558,6 +568,42 @@ out: /*------------------------------- Link status -------------------------------*/ +/* + * Set the carrier state for the master according to the state of its + * slaves. If any slaves are up, the master is up. In 802.3ad mode, + * do special 802.3ad magic. + * + * Returns zero if carrier state does not change, nonzero if it does. + */ +static int bond_set_carrier(struct bonding *bond) +{ + struct slave *slave; + int i; + + if (bond->slave_cnt == 0) + goto down; + + if (bond->params.mode == BOND_MODE_8023AD) + return bond_3ad_set_carrier(bond); + + bond_for_each_slave(bond, slave, i) { + if (slave->link == BOND_LINK_UP) { + if (!netif_carrier_ok(bond->dev)) { + netif_carrier_on(bond->dev); + return 1; + } + return 0; + } + } + +down: + if (netif_carrier_ok(bond->dev)) { + netif_carrier_off(bond->dev); + return 1; + } + return 0; +} + /* * Get link speed and duplex from the slave's base driver * using ethtool. If for some reason the call fails or the @@ -603,6 +649,7 @@ verify: case SPEED_10: case SPEED_100: case SPEED_1000: + case SPEED_10000: break; default: return -1; @@ -1040,6 +1087,10 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active) if ((bond->params.mode == BOND_MODE_TLB) || (bond->params.mode == BOND_MODE_ALB)) { bond_alb_handle_active_change(bond, new_active); + if (old_active) + bond_set_slave_inactive_flags(old_active); + if (new_active) + bond_set_slave_active_flags(new_active); } else { bond->curr_active_slave = new_active; } @@ -1070,10 +1121,24 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active) void bond_select_active_slave(struct bonding *bond) { struct slave *best_slave; + int rv; best_slave = bond_find_best_slave(bond); if (best_slave != bond->curr_active_slave) { bond_change_active_slave(bond, best_slave); + rv = bond_set_carrier(bond); + if (!rv) + return; + + if (netif_carrier_ok(bond->dev)) { + printk(KERN_INFO DRV_NAME + ": %s: first active interface up!\n", + bond->dev->name); + } else { + printk(KERN_INFO DRV_NAME ": %s: " + "now running without any active interface !\n", + bond->dev->name); + } } } @@ -1145,8 +1210,7 @@ int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev) } #define BOND_INTERSECT_FEATURES \ - (NETIF_F_SG|NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM|\ - NETIF_F_TSO|NETIF_F_UFO) + (NETIF_F_SG | NETIF_F_ALL_CSUM | NETIF_F_TSO | NETIF_F_UFO) /* * Compute the common dev->feature set available to all slaves. Some @@ -1158,15 +1222,17 @@ static int bond_compute_features(struct bonding *bond) unsigned long features = BOND_INTERSECT_FEATURES; struct slave *slave; struct net_device *bond_dev = bond->dev; + unsigned short max_hard_header_len = ETH_HLEN; int i; - bond_for_each_slave(bond, slave, i) + bond_for_each_slave(bond, slave, i) { features &= (slave->dev->features & BOND_INTERSECT_FEATURES); + if (slave->dev->hard_header_len > max_hard_header_len) + max_hard_header_len = slave->dev->hard_header_len; + } if ((features & NETIF_F_SG) && - !(features & (NETIF_F_IP_CSUM | - NETIF_F_NO_CSUM | - NETIF_F_HW_CSUM))) + !(features & NETIF_F_ALL_CSUM)) features &= ~NETIF_F_SG; /* @@ -1181,6 +1247,7 @@ static int bond_compute_features(struct bonding *bond) features |= (bond_dev->features & ~BOND_INTERSECT_FEATURES); bond_dev->features = features; + bond_dev->hard_header_len = max_hard_header_len; return 0; } @@ -1269,6 +1336,13 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) goto err_undo_flags; } + if (slave_dev->get_stats == NULL) { + printk(KERN_NOTICE DRV_NAME + ": %s: the driver for slave device %s does not provide " + "get_stats function, network statistics will be " + "inaccurate.\n", bond_dev->name, slave_dev->name); + } + new_slave = kmalloc(sizeof(struct slave), GFP_KERNEL); if (!new_slave) { res = -ENOMEM; @@ -1315,6 +1389,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) } new_slave->dev = slave_dev; + slave_dev->priv_flags |= IFF_BONDING; if ((bond->params.mode == BOND_MODE_TLB) || (bond->params.mode == BOND_MODE_ALB)) { @@ -1367,6 +1442,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) bond_compute_features(bond); + new_slave->last_arp_rx = jiffies; + if (bond->params.miimon && !bond->params.use_carrier) { link_reporting = bond_check_dev_link(bond, slave_dev, 1); @@ -1443,24 +1520,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) switch (bond->params.mode) { case BOND_MODE_ACTIVEBACKUP: - /* if we're in active-backup mode, we need one and only one active - * interface. The backup interfaces will have their NOARP flag set - * because we need them to be completely deaf and not to respond to - * any ARP request on the network to avoid fooling a switch. Thus, - * since we guarantee that curr_active_slave always point to the last - * usable interface, we just have to verify this interface's flag. - */ - if (((!bond->curr_active_slave) || - (bond->curr_active_slave->dev->flags & IFF_NOARP)) && - (new_slave->link != BOND_LINK_DOWN)) { - dprintk("This is the first active slave\n"); - /* first slave or no active slave yet, and this link - is OK, so make this interface the active one */ - bond_change_active_slave(bond, new_slave); - } else { - dprintk("This is just a backup slave\n"); - bond_set_slave_inactive_flags(new_slave); - } + bond_set_slave_inactive_flags(new_slave); + bond_select_active_slave(bond); break; case BOND_MODE_8023AD: /* in 802.3ad mode, the internal mechanism @@ -1492,6 +1553,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) * is OK, so make this interface the active one */ bond_change_active_slave(bond, new_slave); + } else { + bond_set_slave_inactive_flags(new_slave); } break; default: @@ -1510,6 +1573,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) break; } /* switch(bond_mode) */ + bond_set_carrier(bond); + write_unlock_bh(&bond->lock); res = bond_create_slave_symlinks(bond_dev, slave_dev); @@ -1649,18 +1714,12 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) bond_alb_deinit_slave(bond, slave); } - if (oldcurrent == slave) { + if (oldcurrent == slave) bond_select_active_slave(bond); - if (!bond->curr_active_slave) { - printk(KERN_INFO DRV_NAME - ": %s: now running without any active " - "interface !\n", - bond_dev->name); - } - } - if (bond->slave_cnt == 0) { + bond_set_carrier(bond); + /* if the last slave was removed, zero the mac address * of the master so it will be set by the application * to the mac address of the first slave @@ -1724,13 +1783,9 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) addr.sa_family = slave_dev->type; dev_set_mac_address(slave_dev, &addr); - /* restore the original state of the - * IFF_NOARP flag that might have been - * set by bond_set_slave_inactive_flags() - */ - if ((slave->original_flags & IFF_NOARP) == 0) { - slave_dev->flags &= ~IFF_NOARP; - } + slave_dev->priv_flags &= ~(IFF_MASTER_8023AD | IFF_MASTER_ALB | + IFF_SLAVE_INACTIVE | IFF_BONDING | + IFF_SLAVE_NEEDARP); kfree(slave); @@ -1749,6 +1804,8 @@ static int bond_release_all(struct net_device *bond_dev) write_lock_bh(&bond->lock); + netif_carrier_off(bond_dev); + if (bond->slave_cnt == 0) { goto out; } @@ -1816,12 +1873,8 @@ static int bond_release_all(struct net_device *bond_dev) addr.sa_family = slave_dev->type; dev_set_mac_address(slave_dev, &addr); - /* restore the original state of the IFF_NOARP flag that might have - * been set by bond_set_slave_inactive_flags() - */ - if ((slave->original_flags & IFF_NOARP) == 0) { - slave_dev->flags &= ~IFF_NOARP; - } + slave_dev->priv_flags &= ~(IFF_MASTER_8023AD | IFF_MASTER_ALB | + IFF_SLAVE_INACTIVE); kfree(slave); @@ -2189,15 +2242,9 @@ void bond_mii_monitor(struct net_device *bond_dev) bond_select_active_slave(bond); - if (oldcurrent && !bond->curr_active_slave) { - printk(KERN_INFO DRV_NAME - ": %s: now running without any active " - "interface !\n", - bond_dev->name); - } - write_unlock(&bond->curr_slave_lock); - } + } else + bond_set_carrier(bond); re_arm: if (bond->params.miimon) { @@ -2212,7 +2259,7 @@ static u32 bond_glean_dev_ip(struct net_device *dev) { struct in_device *idev; struct in_ifaddr *ifa; - u32 addr = 0; + __be32 addr = 0; if (!dev) return 0; @@ -2251,6 +2298,25 @@ static int bond_has_ip(struct bonding *bond) return 0; } +static int bond_has_this_ip(struct bonding *bond, u32 ip) +{ + struct vlan_entry *vlan, *vlan_next; + + if (ip == bond->master_ip) + return 1; + + if (list_empty(&bond->vlan_list)) + return 0; + + list_for_each_entry_safe(vlan, vlan_next, &bond->vlan_list, + vlan_list) { + if (ip == vlan->vlan_ip) + return 1; + } + + return 0; +} + /* * We go to the (large) trouble of VLAN tagging ARP frames because * switches in VLAN mode (especially if ports are configured as @@ -2389,6 +2455,93 @@ static void bond_send_gratuitous_arp(struct bonding *bond) } } +static void bond_validate_arp(struct bonding *bond, struct slave *slave, u32 sip, u32 tip) +{ + int i; + u32 *targets = bond->params.arp_targets; + + targets = bond->params.arp_targets; + for (i = 0; (i < BOND_MAX_ARP_TARGETS) && targets[i]; i++) { + dprintk("bva: sip %u.%u.%u.%u tip %u.%u.%u.%u t[%d] " + "%u.%u.%u.%u bhti(tip) %d\n", + NIPQUAD(sip), NIPQUAD(tip), i, NIPQUAD(targets[i]), + bond_has_this_ip(bond, tip)); + if (sip == targets[i]) { + if (bond_has_this_ip(bond, tip)) + slave->last_arp_rx = jiffies; + return; + } + } +} + +static int bond_arp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) +{ + struct arphdr *arp; + struct slave *slave; + struct bonding *bond; + unsigned char *arp_ptr; + u32 sip, tip; + + if (!(dev->priv_flags & IFF_BONDING) || !(dev->flags & IFF_MASTER)) + goto out; + + bond = dev->priv; + read_lock(&bond->lock); + + dprintk("bond_arp_rcv: bond %s skb->dev %s orig_dev %s\n", + bond->dev->name, skb->dev ? skb->dev->name : "NULL", + orig_dev ? orig_dev->name : "NULL"); + + slave = bond_get_slave_by_dev(bond, orig_dev); + if (!slave || !slave_do_arp_validate(bond, slave)) + goto out_unlock; + + /* ARP header, plus 2 device addresses, plus 2 IP addresses. */ + if (!pskb_may_pull(skb, (sizeof(struct arphdr) + + (2 * dev->addr_len) + + (2 * sizeof(u32))))) + goto out_unlock; + + arp = skb->nh.arph; + if (arp->ar_hln != dev->addr_len || + skb->pkt_type == PACKET_OTHERHOST || + skb->pkt_type == PACKET_LOOPBACK || + arp->ar_hrd != htons(ARPHRD_ETHER) || + arp->ar_pro != htons(ETH_P_IP) || + arp->ar_pln != 4) + goto out_unlock; + + arp_ptr = (unsigned char *)(arp + 1); + arp_ptr += dev->addr_len; + memcpy(&sip, arp_ptr, 4); + arp_ptr += 4 + dev->addr_len; + memcpy(&tip, arp_ptr, 4); + + dprintk("bond_arp_rcv: %s %s/%d av %d sv %d sip %u.%u.%u.%u" + " tip %u.%u.%u.%u\n", bond->dev->name, slave->dev->name, + slave->state, bond->params.arp_validate, + slave_do_arp_validate(bond, slave), NIPQUAD(sip), NIPQUAD(tip)); + + /* + * Backup slaves won't see the ARP reply, but do come through + * here for each ARP probe (so we swap the sip/tip to validate + * the probe). In a "redundant switch, common router" type of + * configuration, the ARP probe will (hopefully) travel from + * the active, through one switch, the router, then the other + * switch before reaching the backup. + */ + if (slave->state == BOND_STATE_ACTIVE) + bond_validate_arp(bond, slave, sip, tip); + else + bond_validate_arp(bond, slave, tip, sip); + +out_unlock: + read_unlock(&bond->lock); +out: + dev_kfree_skb(skb); + return NET_RX_SUCCESS; +} + /* * this function is called regularly to monitor each slave's link * ensuring that traffic is being sent and received when arp monitoring @@ -2501,13 +2654,6 @@ void bond_loadbalance_arp_mon(struct net_device *bond_dev) bond_select_active_slave(bond); - if (oldcurrent && !bond->curr_active_slave) { - printk(KERN_INFO DRV_NAME - ": %s: now running without any active " - "interface !\n", - bond_dev->name); - } - write_unlock(&bond->curr_slave_lock); } @@ -2560,7 +2706,8 @@ void bond_activebackup_arp_mon(struct net_device *bond_dev) */ bond_for_each_slave(bond, slave, i) { if (slave->link != BOND_LINK_UP) { - if ((jiffies - slave->dev->last_rx) <= delta_in_ticks) { + if ((jiffies - slave_last_rx(bond, slave)) <= + delta_in_ticks) { slave->link = BOND_LINK_UP; @@ -2581,12 +2728,15 @@ void bond_activebackup_arp_mon(struct net_device *bond_dev) bond->current_arp_slave = NULL; } + bond_set_carrier(bond); + if (slave == bond->curr_active_slave) { printk(KERN_INFO DRV_NAME ": %s: %s is up and now the " "active interface\n", bond_dev->name, slave->dev->name); + netif_carrier_on(bond->dev); } else { printk(KERN_INFO DRV_NAME ": %s: backup interface %s is " @@ -2602,7 +2752,7 @@ void bond_activebackup_arp_mon(struct net_device *bond_dev) if ((slave != bond->curr_active_slave) && (!bond->current_arp_slave) && - (((jiffies - slave->dev->last_rx) >= 3*delta_in_ticks) && + (((jiffies - slave_last_rx(bond, slave)) >= 3*delta_in_ticks) && bond_has_ip(bond))) { /* a backup slave has gone down; three times * the delta allows the current slave to be @@ -2649,7 +2799,7 @@ void bond_activebackup_arp_mon(struct net_device *bond_dev) * if it is up and needs to take over as the curr_active_slave */ if ((((jiffies - slave->dev->trans_start) >= (2*delta_in_ticks)) || - (((jiffies - slave->dev->last_rx) >= (2*delta_in_ticks)) && + (((jiffies - slave_last_rx(bond, slave)) >= (2*delta_in_ticks)) && bond_has_ip(bond))) && ((jiffies - slave->jiffies) >= 2*delta_in_ticks)) { @@ -2846,7 +2996,8 @@ static void bond_info_show_master(struct seq_file *seq) (curr) ? curr->dev->name : "None"); } - seq_printf(seq, "MII Status: %s\n", (curr) ? "up" : "down"); + seq_printf(seq, "MII Status: %s\n", netif_carrier_ok(bond->dev) ? + "up" : "down"); seq_printf(seq, "MII Polling Interval (ms): %d\n", bond->params.miimon); seq_printf(seq, "Up Delay (ms): %d\n", bond->params.updelay * bond->params.miimon); @@ -2913,7 +3064,7 @@ static void bond_info_show_slave(struct seq_file *seq, const struct slave *slave seq_printf(seq, "\nSlave Interface: %s\n", slave->dev->name); seq_printf(seq, "MII Status: %s\n", (slave->link == BOND_LINK_UP) ? "up" : "down"); - seq_printf(seq, "Link Failure Count: %d\n", + seq_printf(seq, "Link Failure Count: %u\n", slave->link_failure_count); seq_printf(seq, @@ -3161,7 +3312,7 @@ static int bond_slave_netdev_event(unsigned long event, struct net_device *slave * bond_netdev_event: handle netdev notifier chain events. * * This function receives events for the netdev chain. The caller (an - * ioctl handler calling notifier_call_chain) holds the necessary + * ioctl handler calling blocking_notifier_call_chain) holds the necessary * locks for us to safely manipulate the slave devices (RTNL lock, * dev_probe_lock). */ @@ -3173,6 +3324,9 @@ static int bond_netdev_event(struct notifier_block *this, unsigned long event, v (event_dev ? event_dev->name : "None"), event); + if (!(event_dev->priv_flags & IFF_BONDING)) + return NOTIFY_DONE; + if (event_dev->flags & IFF_MASTER) { dprintk("IFF_MASTER\n"); return bond_master_netdev_event(event, event_dev); @@ -3268,6 +3422,21 @@ static void bond_unregister_lacpdu(struct bonding *bond) dev_remove_pack(&(BOND_AD_INFO(bond).ad_pkt_type)); } +void bond_register_arp(struct bonding *bond) +{ + struct packet_type *pt = &bond->arp_mon_pt; + + pt->type = htons(ETH_P_ARP); + pt->dev = NULL; /*bond->dev;XXX*/ + pt->func = bond_arp_rcv; + dev_add_pack(pt); +} + +void bond_unregister_arp(struct bonding *bond) +{ + dev_remove_pack(&bond->arp_mon_pt); +} + /*---------------------------- Hashing Policies -----------------------------*/ /* @@ -3354,6 +3523,9 @@ static int bond_open(struct net_device *bond_dev) } else { arp_timer->function = (void *)&bond_loadbalance_arp_mon; } + if (bond->params.arp_validate) + bond_register_arp(bond); + add_timer(arp_timer); } @@ -3381,9 +3553,11 @@ static int bond_close(struct net_device *bond_dev) bond_unregister_lacpdu(bond); } + if (bond->params.arp_validate) + bond_unregister_arp(bond); + write_lock_bh(&bond->lock); - bond_mc_list_destroy(bond); /* signal timers not to re-arm */ bond->kill_timers = 1; @@ -3414,8 +3588,6 @@ static int bond_close(struct net_device *bond_dev) break; } - /* Release the bonded slaves */ - bond_release_all(bond_dev); if ((bond->params.mode == BOND_MODE_TLB) || (bond->params.mode == BOND_MODE_ALB)) { @@ -3440,33 +3612,35 @@ static struct net_device_stats *bond_get_stats(struct net_device *bond_dev) read_lock_bh(&bond->lock); bond_for_each_slave(bond, slave, i) { - sstats = slave->dev->get_stats(slave->dev); - - stats->rx_packets += sstats->rx_packets; - stats->rx_bytes += sstats->rx_bytes; - stats->rx_errors += sstats->rx_errors; - stats->rx_dropped += sstats->rx_dropped; - - stats->tx_packets += sstats->tx_packets; - stats->tx_bytes += sstats->tx_bytes; - stats->tx_errors += sstats->tx_errors; - stats->tx_dropped += sstats->tx_dropped; - - stats->multicast += sstats->multicast; - stats->collisions += sstats->collisions; - - stats->rx_length_errors += sstats->rx_length_errors; - stats->rx_over_errors += sstats->rx_over_errors; - stats->rx_crc_errors += sstats->rx_crc_errors; - stats->rx_frame_errors += sstats->rx_frame_errors; - stats->rx_fifo_errors += sstats->rx_fifo_errors; - stats->rx_missed_errors += sstats->rx_missed_errors; - - stats->tx_aborted_errors += sstats->tx_aborted_errors; - stats->tx_carrier_errors += sstats->tx_carrier_errors; - stats->tx_fifo_errors += sstats->tx_fifo_errors; - stats->tx_heartbeat_errors += sstats->tx_heartbeat_errors; - stats->tx_window_errors += sstats->tx_window_errors; + if (slave->dev->get_stats) { + sstats = slave->dev->get_stats(slave->dev); + + stats->rx_packets += sstats->rx_packets; + stats->rx_bytes += sstats->rx_bytes; + stats->rx_errors += sstats->rx_errors; + stats->rx_dropped += sstats->rx_dropped; + + stats->tx_packets += sstats->tx_packets; + stats->tx_bytes += sstats->tx_bytes; + stats->tx_errors += sstats->tx_errors; + stats->tx_dropped += sstats->tx_dropped; + + stats->multicast += sstats->multicast; + stats->collisions += sstats->collisions; + + stats->rx_length_errors += sstats->rx_length_errors; + stats->rx_over_errors += sstats->rx_over_errors; + stats->rx_crc_errors += sstats->rx_crc_errors; + stats->rx_frame_errors += sstats->rx_frame_errors; + stats->rx_fifo_errors += sstats->rx_fifo_errors; + stats->rx_missed_errors += sstats->rx_missed_errors; + + stats->tx_aborted_errors += sstats->tx_aborted_errors; + stats->tx_carrier_errors += sstats->tx_carrier_errors; + stats->tx_fifo_errors += sstats->tx_fifo_errors; + stats->tx_heartbeat_errors += sstats->tx_heartbeat_errors; + stats->tx_window_errors += sstats->tx_window_errors; + } } read_unlock_bh(&bond->lock); @@ -3510,7 +3684,7 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd mii->val_out = 0; read_lock_bh(&bond->lock); read_lock(&bond->curr_slave_lock); - if (bond->curr_active_slave) { + if (netif_carrier_ok(bond->dev)) { mii->val_out = BMSR_LSTATUS; } read_unlock(&bond->curr_slave_lock); @@ -4061,14 +4235,17 @@ void bond_set_mode_ops(struct bonding *bond, int mode) bond_dev->hard_start_xmit = bond_xmit_broadcast; break; case BOND_MODE_8023AD: + bond_set_master_3ad_flags(bond); bond_dev->hard_start_xmit = bond_3ad_xmit_xor; if (bond->params.xmit_policy == BOND_XMIT_POLICY_LAYER34) bond->xmit_hash_policy = bond_xmit_hash_policy_l34; else bond->xmit_hash_policy = bond_xmit_hash_policy_l2; break; - case BOND_MODE_TLB: case BOND_MODE_ALB: + bond_set_master_alb_flags(bond); + /* FALLTHRU */ + case BOND_MODE_TLB: bond_dev->hard_start_xmit = bond_alb_xmit; bond_dev->set_mac_address = bond_alb_set_mac_address; break; @@ -4090,7 +4267,7 @@ static void bond_ethtool_get_drvinfo(struct net_device *bond_dev, snprintf(drvinfo->fw_version, 32, "%d", BOND_ABI_VERSION); } -static struct ethtool_ops bond_ethtool_ops = { +static const struct ethtool_ops bond_ethtool_ops = { .get_tx_csum = ethtool_op_get_tx_csum, .get_tso = ethtool_op_get_tso, .get_ufo = ethtool_op_get_ufo, @@ -4139,6 +4316,7 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params) /* Initialize the device options */ bond_dev->tx_queue_len = 0; bond_dev->flags |= IFF_MASTER|IFF_MULTICAST; + bond_dev->priv_flags |= IFF_BONDING; /* At first, we block adding VLANs. That's the only way to * prevent problems that occur when adding VLANs over an @@ -4147,7 +4325,7 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params) */ bond_dev->features |= NETIF_F_VLAN_CHALLENGED; - /* don't acquire bond device's xmit_lock when + /* don't acquire bond device's netif_tx_lock when * transmitting */ bond_dev->features |= NETIF_F_LLTX; @@ -4197,6 +4375,9 @@ static void bond_free_all(void) list_for_each_entry_safe(bond, nxt, &bond_dev_list, bond_list) { struct net_device *bond_dev = bond->dev; + bond_mc_list_destroy(bond); + /* Release the bonded slaves */ + bond_release_all(bond_dev); unregister_netdevice(bond_dev); bond_deinit(bond_dev); } @@ -4230,6 +4411,8 @@ int bond_parse_parm(char *mode_arg, struct bond_parm_tbl *tbl) static int bond_check_params(struct bond_params *params) { + int arp_validate_value; + /* * Convert string parameters. */ @@ -4433,6 +4616,29 @@ static int bond_check_params(struct bond_params *params) arp_interval = 0; } + if (arp_validate) { + if (bond_mode != BOND_MODE_ACTIVEBACKUP) { + printk(KERN_ERR DRV_NAME + ": arp_validate only supported in active-backup mode\n"); + return -EINVAL; + } + if (!arp_interval) { + printk(KERN_ERR DRV_NAME + ": arp_validate requires arp_interval\n"); + return -EINVAL; + } + + arp_validate_value = bond_parse_parm(arp_validate, + arp_validate_tbl); + if (arp_validate_value == -1) { + printk(KERN_ERR DRV_NAME + ": Error: invalid arp_validate \"%s\"\n", + arp_validate == NULL ? "NULL" : arp_validate); + return -EINVAL; + } + } else + arp_validate_value = 0; + if (miimon) { printk(KERN_INFO DRV_NAME ": MII link monitoring set to %d ms\n", @@ -4441,8 +4647,10 @@ static int bond_check_params(struct bond_params *params) int i; printk(KERN_INFO DRV_NAME - ": ARP monitoring set to %d ms with %d target(s):", - arp_interval, arp_ip_count); + ": ARP monitoring set to %d ms, validate %s, with %d target(s):", + arp_interval, + arp_validate_tbl[arp_validate_value].modename, + arp_ip_count); for (i = 0; i < arp_ip_count; i++) printk (" %s", arp_ip_target[i]); @@ -4476,6 +4684,7 @@ static int bond_check_params(struct bond_params *params) params->xmit_policy = xmit_hashtype; params->miimon = miimon; params->arp_interval = arp_interval; + params->arp_validate = arp_validate_value; params->updelay = updelay; params->downdelay = downdelay; params->use_carrier = use_carrier; @@ -4492,6 +4701,8 @@ static int bond_check_params(struct bond_params *params) return 0; } +static struct lock_class_key bonding_netdev_xmit_lock_key; + /* Create a new bond based on the specified name and bonding parameters. * Caller must NOT hold rtnl_lock; we need to release it here before we * set up our sysfs entries. @@ -4527,9 +4738,14 @@ int bond_create(char *name, struct bond_params *params, struct bonding **newbond if (res < 0) { goto out_bond; } + + lockdep_set_class(&bond_dev->_xmit_lock, &bonding_netdev_xmit_lock_key); + if (newbond) *newbond = bond_dev->priv; + netif_carrier_off(bond_dev); + rtnl_unlock(); /* allows sysfs registration of net device */ res = bond_create_sysfs_entry(bond_dev->priv); goto done;