diff options
Diffstat (limited to 'drivers/net/bonding/bond_main.c')
-rw-r--r-- | drivers/net/bonding/bond_main.c | 261 |
1 files changed, 160 insertions, 101 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index a3efba59eee..614656c8187 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -89,6 +89,7 @@ static int max_bonds = BOND_DEFAULT_MAX_BONDS; static int num_grat_arp = 1; +static int num_unsol_na = 1; static int miimon = BOND_LINK_MON_INTERV; static int updelay = 0; static int downdelay = 0; @@ -96,6 +97,7 @@ static int use_carrier = 1; static char *mode = NULL; static char *primary = NULL; static char *lacp_rate = NULL; +static char *ad_select = 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, }; @@ -107,6 +109,8 @@ module_param(max_bonds, int, 0); MODULE_PARM_DESC(max_bonds, "Max number of bonded devices"); module_param(num_grat_arp, int, 0644); MODULE_PARM_DESC(num_grat_arp, "Number of gratuitous ARP packets to send on failover event"); +module_param(num_unsol_na, int, 0644); +MODULE_PARM_DESC(num_unsol_na, "Number of unsolicited IPv6 Neighbor Advertisements packets to send on failover event"); module_param(miimon, int, 0); MODULE_PARM_DESC(miimon, "Link check interval in milliseconds"); module_param(updelay, int, 0); @@ -127,6 +131,8 @@ MODULE_PARM_DESC(primary, "Primary network device to use"); module_param(lacp_rate, charp, 0); MODULE_PARM_DESC(lacp_rate, "LACPDU tx rate to request from 802.3ad partner " "(slow/fast)"); +module_param(ad_select, charp, 0); +MODULE_PARM_DESC(ad_select, "803.ad aggregation selection logic: stable (0, default), bandwidth (1), count (2)"); module_param(xmit_hash_policy, charp, 0); MODULE_PARM_DESC(xmit_hash_policy, "XOR hashing method: 0 for layer 2 (default)" ", 1 for layer 3+4"); @@ -197,6 +203,13 @@ struct bond_parm_tbl fail_over_mac_tbl[] = { { NULL, -1}, }; +struct bond_parm_tbl ad_select_tbl[] = { +{ "stable", BOND_AD_STABLE}, +{ "bandwidth", BOND_AD_BANDWIDTH}, +{ "count", BOND_AD_COUNT}, +{ NULL, -1}, +}; + /*-------------------------- Forward declarations ---------------------------*/ static void bond_send_gratuitous_arp(struct bonding *bond); @@ -242,14 +255,13 @@ static int bond_add_vlan(struct bonding *bond, unsigned short vlan_id) dprintk("bond: %s, vlan id %d\n", (bond ? bond->dev->name: "None"), vlan_id); - vlan = kmalloc(sizeof(struct vlan_entry), GFP_KERNEL); + vlan = kzalloc(sizeof(struct vlan_entry), GFP_KERNEL); if (!vlan) { return -ENOMEM; } INIT_LIST_HEAD(&vlan->vlan_list); vlan->vlan_id = vlan_id; - vlan->vlan_ip = 0; write_lock_bh(&bond->lock); @@ -442,7 +454,7 @@ int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_de */ static void bond_vlan_rx_register(struct net_device *bond_dev, struct vlan_group *grp) { - struct bonding *bond = bond_dev->priv; + struct bonding *bond = netdev_priv(bond_dev); struct slave *slave; int i; @@ -450,10 +462,11 @@ static void bond_vlan_rx_register(struct net_device *bond_dev, struct vlan_group 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_dev->vlan_rx_register) { - slave_dev->vlan_rx_register(slave_dev, grp); + slave_ops->ndo_vlan_rx_register) { + slave_ops->ndo_vlan_rx_register(slave_dev, grp); } } } @@ -465,16 +478,17 @@ static void bond_vlan_rx_register(struct net_device *bond_dev, struct vlan_group */ static void bond_vlan_rx_add_vid(struct net_device *bond_dev, uint16_t vid) { - struct bonding *bond = bond_dev->priv; + struct bonding *bond = netdev_priv(bond_dev); struct slave *slave; int i, res; 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_FILTER) && - slave_dev->vlan_rx_add_vid) { - slave_dev->vlan_rx_add_vid(slave_dev, vid); + slave_ops->ndo_vlan_rx_add_vid) { + slave_ops->ndo_vlan_rx_add_vid(slave_dev, vid); } } @@ -493,21 +507,22 @@ static void bond_vlan_rx_add_vid(struct net_device *bond_dev, uint16_t vid) */ static void bond_vlan_rx_kill_vid(struct net_device *bond_dev, uint16_t vid) { - struct bonding *bond = bond_dev->priv; + 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) { 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_FILTER) && - slave_dev->vlan_rx_kill_vid) { + 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_dev->vlan_rx_kill_vid(slave_dev, vid); + slave_ops->ndo_vlan_rx_kill_vid(slave_dev, vid); vlan_group_set_device(bond->vlgrp, vid, vlan_dev); } } @@ -523,26 +538,23 @@ static void bond_vlan_rx_kill_vid(struct net_device *bond_dev, uint16_t vid) static void bond_add_vlans_on_slave(struct bonding *bond, struct net_device *slave_dev) { struct vlan_entry *vlan; + const struct net_device_ops *slave_ops = slave_dev->netdev_ops; write_lock_bh(&bond->lock); - if (list_empty(&bond->vlan_list)) { + if (list_empty(&bond->vlan_list)) goto out; - } if ((slave_dev->features & NETIF_F_HW_VLAN_RX) && - slave_dev->vlan_rx_register) { - slave_dev->vlan_rx_register(slave_dev, bond->vlgrp); - } + 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_dev->vlan_rx_add_vid)) { + !(slave_ops->ndo_vlan_rx_add_vid)) goto out; - } - list_for_each_entry(vlan, &bond->vlan_list, vlan_list) { - slave_dev->vlan_rx_add_vid(slave_dev, vlan->vlan_id); - } + list_for_each_entry(vlan, &bond->vlan_list, vlan_list) + slave_ops->ndo_vlan_rx_add_vid(slave_dev, vlan->vlan_id); out: write_unlock_bh(&bond->lock); @@ -550,34 +562,32 @@ out: static void bond_del_vlans_from_slave(struct bonding *bond, struct net_device *slave_dev) { + const struct net_device_ops *slave_ops = slave_dev->netdev_ops; struct vlan_entry *vlan; struct net_device *vlan_dev; write_lock_bh(&bond->lock); - if (list_empty(&bond->vlan_list)) { + if (list_empty(&bond->vlan_list)) goto out; - } if (!(slave_dev->features & NETIF_F_HW_VLAN_FILTER) || - !(slave_dev->vlan_rx_kill_vid)) { + !(slave_ops->ndo_vlan_rx_kill_vid)) goto unreg; - } list_for_each_entry(vlan, &bond->vlan_list, vlan_list) { /* 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_dev->vlan_rx_kill_vid(slave_dev, 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_dev->vlan_rx_register) { - slave_dev->vlan_rx_register(slave_dev, NULL); - } + slave_ops->ndo_vlan_rx_register) + slave_ops->ndo_vlan_rx_register(slave_dev, NULL); out: write_unlock_bh(&bond->lock); @@ -686,15 +696,15 @@ static int bond_update_speed_duplex(struct slave *slave) */ static int bond_check_dev_link(struct bonding *bond, struct net_device *slave_dev, int reporting) { + const struct net_device_ops *slave_ops = slave_dev->netdev_ops; static int (* ioctl)(struct net_device *, struct ifreq *, int); struct ifreq ifr; struct mii_ioctl_data *mii; - if (bond->params.use_carrier) { + if (bond->params.use_carrier) return netif_carrier_ok(slave_dev) ? BMSR_LSTATUS : 0; - } - ioctl = slave_dev->do_ioctl; + ioctl = slave_ops->ndo_do_ioctl; if (ioctl) { /* TODO: set pointer to correct ioctl on a per team member */ /* bases to make this more efficient. that is, once */ @@ -927,7 +937,7 @@ static int bond_mc_list_copy(struct dev_mc_list *mc_list, struct bonding *bond, */ static void bond_mc_list_flush(struct net_device *bond_dev, struct net_device *slave_dev) { - struct bonding *bond = bond_dev->priv; + struct bonding *bond = netdev_priv(bond_dev); struct dev_mc_list *dmi; for (dmi = bond_dev->mc_list; dmi; dmi = dmi->next) { @@ -1208,6 +1218,9 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active) bond->send_grat_arp = bond->params.num_grat_arp; bond_send_gratuitous_arp(bond); + bond->send_unsol_na = bond->params.num_unsol_na; + bond_send_unsolicited_na(bond); + write_unlock_bh(&bond->curr_slave_lock); read_unlock(&bond->lock); @@ -1368,7 +1381,7 @@ done: static void bond_setup_by_slave(struct net_device *bond_dev, struct net_device *slave_dev) { - struct bonding *bond = bond_dev->priv; + struct bonding *bond = netdev_priv(bond_dev); bond_dev->neigh_setup = slave_dev->neigh_setup; bond_dev->header_ops = slave_dev->header_ops; @@ -1385,7 +1398,8 @@ static void bond_setup_by_slave(struct net_device *bond_dev, /* enslave device <slave> to bond device <master> */ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) { - struct bonding *bond = bond_dev->priv; + struct bonding *bond = netdev_priv(bond_dev); + const struct net_device_ops *slave_ops = slave_dev->netdev_ops; struct slave *new_slave = NULL; struct dev_mc_list *dmi; struct sockaddr addr; @@ -1394,7 +1408,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) int res = 0; if (!bond->params.use_carrier && slave_dev->ethtool_ops == NULL && - slave_dev->do_ioctl == NULL) { + slave_ops->ndo_do_ioctl == NULL) { printk(KERN_WARNING DRV_NAME ": %s: Warning: no link monitoring support for %s\n", bond_dev->name, slave_dev->name); @@ -1476,7 +1490,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) goto err_undo_flags; } - if (slave_dev->set_mac_address == NULL) { + if (slave_ops->ndo_set_mac_address == NULL) { if (bond->slave_cnt == 0) { printk(KERN_WARNING DRV_NAME ": %s: Warning: The first slave device " @@ -1787,11 +1801,10 @@ err_undo_flags: */ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) { - struct bonding *bond = bond_dev->priv; + struct bonding *bond = netdev_priv(bond_dev); struct slave *slave, *oldcurrent; struct sockaddr addr; int mac_addr_differ; - DECLARE_MAC_BUF(mac); /* slave is not a slave or master is not master of this slave */ if (!(slave_dev->flags & IFF_SLAVE) || @@ -1820,11 +1833,11 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) if (!mac_addr_differ && (bond->slave_cnt > 1)) printk(KERN_WARNING DRV_NAME ": %s: Warning: the permanent HWaddr of %s - " - "%s - is still in use by %s. " + "%pM - is still in use by %s. " "Set the HWaddr of %s to a different address " "to avoid conflicts.\n", bond_dev->name, slave_dev->name, - print_mac(mac, slave->perm_hwaddr), + slave->perm_hwaddr, bond_dev->name, slave_dev->name); } @@ -1999,7 +2012,7 @@ static void bond_destructor(struct net_device *bond_dev) */ int bond_release_and_destroy(struct net_device *bond_dev, struct net_device *slave_dev) { - struct bonding *bond = bond_dev->priv; + struct bonding *bond = netdev_priv(bond_dev); int ret; ret = bond_release(bond_dev, slave_dev); @@ -2016,7 +2029,7 @@ int bond_release_and_destroy(struct net_device *bond_dev, struct net_device *sl */ static int bond_release_all(struct net_device *bond_dev) { - struct bonding *bond = bond_dev->priv; + struct bonding *bond = netdev_priv(bond_dev); struct slave *slave; struct net_device *slave_dev; struct sockaddr addr; @@ -2147,7 +2160,7 @@ out: */ static int bond_ioctl_change_active(struct net_device *bond_dev, struct net_device *slave_dev) { - struct bonding *bond = bond_dev->priv; + struct bonding *bond = netdev_priv(bond_dev); struct slave *old_active = NULL; struct slave *new_active = NULL; int res = 0; @@ -2196,7 +2209,7 @@ static int bond_ioctl_change_active(struct net_device *bond_dev, struct net_devi static int bond_info_query(struct net_device *bond_dev, struct ifbond *info) { - struct bonding *bond = bond_dev->priv; + struct bonding *bond = netdev_priv(bond_dev); info->bond_mode = bond->params.mode; info->miimon = bond->params.miimon; @@ -2210,7 +2223,7 @@ static int bond_info_query(struct net_device *bond_dev, struct ifbond *info) static int bond_slave_info_query(struct net_device *bond_dev, struct ifslave *info) { - struct bonding *bond = bond_dev->priv; + struct bonding *bond = netdev_priv(bond_dev); struct slave *slave; int i, found = 0; @@ -2464,6 +2477,12 @@ void bond_mii_monitor(struct work_struct *work) read_unlock(&bond->curr_slave_lock); } + if (bond->send_unsol_na) { + read_lock(&bond->curr_slave_lock); + bond_send_unsolicited_na(bond); + read_unlock(&bond->curr_slave_lock); + } + if (bond_miimon_inspect(bond)) { read_unlock(&bond->lock); rtnl_lock(); @@ -2586,8 +2605,8 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave) if (rv) { if (net_ratelimit()) { printk(KERN_WARNING DRV_NAME - ": %s: no route to arp_ip_target %u.%u.%u.%u\n", - bond->dev->name, NIPQUAD(fl.fl4_dst)); + ": %s: no route to arp_ip_target %pI4\n", + bond->dev->name, &fl.fl4_dst); } continue; } @@ -2623,8 +2642,8 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave) if (net_ratelimit()) { printk(KERN_WARNING DRV_NAME - ": %s: no path to arp_ip_target %u.%u.%u.%u via rt.dev %s\n", - bond->dev->name, NIPQUAD(fl.fl4_dst), + ": %s: no path to arp_ip_target %pI4 via rt.dev %s\n", + bond->dev->name, &fl.fl4_dst, rt->u.dst.dev ? rt->u.dst.dev->name : "NULL"); } ip_rt_put(rt); @@ -2673,10 +2692,8 @@ static void bond_validate_arp(struct bonding *bond, struct slave *slave, __be32 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)); + dprintk("bva: sip %pI4 tip %pI4 t[%d] %pI4 bhti(tip) %d\n", + &sip, &tip, i, &targets[i], bond_has_this_ip(bond, tip)); if (sip == targets[i]) { if (bond_has_this_ip(bond, tip)) slave->last_arp_rx = jiffies; @@ -2699,7 +2716,7 @@ static int bond_arp_rcv(struct sk_buff *skb, struct net_device *dev, struct pack if (!(dev->priv_flags & IFF_BONDING) || !(dev->flags & IFF_MASTER)) goto out; - bond = dev->priv; + bond = netdev_priv(dev); read_lock(&bond->lock); dprintk("bond_arp_rcv: bond %s skb->dev %s orig_dev %s\n", @@ -2728,10 +2745,10 @@ static int bond_arp_rcv(struct sk_buff *skb, struct net_device *dev, struct pack 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)); + dprintk("bond_arp_rcv: %s %s/%d av %d sv %d sip %pI4 tip %pI4\n", + bond->dev->name, slave->dev->name, slave->state, + bond->params.arp_validate, slave_do_arp_validate(bond, slave), + &sip, &tip); /* * Backup slaves won't see the ARP reply, but do come through @@ -3161,6 +3178,12 @@ void bond_activebackup_arp_mon(struct work_struct *work) read_unlock(&bond->curr_slave_lock); } + if (bond->send_unsol_na) { + read_lock(&bond->curr_slave_lock); + bond_send_unsolicited_na(bond); + read_unlock(&bond->curr_slave_lock); + } + if (bond_ab_arp_inspect(bond, delta_in_ticks)) { read_unlock(&bond->lock); rtnl_lock(); @@ -3239,7 +3262,6 @@ static void bond_info_show_master(struct seq_file *seq) struct bonding *bond = seq->private; struct slave *curr; int i; - u32 target; read_lock(&bond->curr_slave_lock); curr = bond->curr_active_slave; @@ -3293,8 +3315,7 @@ static void bond_info_show_master(struct seq_file *seq) continue; if (printed) seq_printf(seq, ","); - target = ntohl(bond->params.arp_targets[i]); - seq_printf(seq, " %d.%d.%d.%d", HIPQUAD(target)); + seq_printf(seq, " %pI4", &bond->params.arp_targets[i]); printed = 1; } seq_printf(seq, "\n"); @@ -3302,11 +3323,12 @@ static void bond_info_show_master(struct seq_file *seq) if (bond->params.mode == BOND_MODE_8023AD) { struct ad_info ad_info; - DECLARE_MAC_BUF(mac); seq_puts(seq, "\n802.3ad info\n"); seq_printf(seq, "LACP rate: %s\n", (bond->params.lacp_fast) ? "fast" : "slow"); + seq_printf(seq, "Aggregator selection policy (ad_select): %s\n", + ad_select_tbl[bond->params.ad_select].modename); if (bond_3ad_get_active_agg_info(bond, &ad_info)) { seq_printf(seq, "bond %s has no active aggregator\n", @@ -3322,8 +3344,8 @@ static void bond_info_show_master(struct seq_file *seq) ad_info.actor_key); seq_printf(seq, "\tPartner Key: %d\n", ad_info.partner_key); - seq_printf(seq, "\tPartner Mac Address: %s\n", - print_mac(mac, ad_info.partner_system)); + seq_printf(seq, "\tPartner Mac Address: %pM\n", + ad_info.partner_system); } } } @@ -3331,7 +3353,6 @@ static void bond_info_show_master(struct seq_file *seq) static void bond_info_show_slave(struct seq_file *seq, const struct slave *slave) { struct bonding *bond = seq->private; - DECLARE_MAC_BUF(mac); seq_printf(seq, "\nSlave Interface: %s\n", slave->dev->name); seq_printf(seq, "MII Status: %s\n", @@ -3339,9 +3360,7 @@ static void bond_info_show_slave(struct seq_file *seq, const struct slave *slave seq_printf(seq, "Link Failure Count: %u\n", slave->link_failure_count); - seq_printf(seq, - "Permanent HW addr: %s\n", - print_mac(mac, slave->perm_hwaddr)); + seq_printf(seq, "Permanent HW addr: %pM\n", slave->perm_hwaddr); if (bond->params.mode == BOND_MODE_8023AD) { const struct aggregator *agg @@ -3506,7 +3525,7 @@ static int bond_event_changename(struct bonding *bond) static int bond_master_netdev_event(unsigned long event, struct net_device *bond_dev) { - struct bonding *event_bond = bond_dev->priv; + struct bonding *event_bond = netdev_priv(bond_dev); switch (event) { case NETDEV_CHANGENAME: @@ -3524,7 +3543,7 @@ static int bond_master_netdev_event(unsigned long event, struct net_device *bond static int bond_slave_netdev_event(unsigned long event, struct net_device *slave_dev) { struct net_device *bond_dev = slave_dev->master; - struct bonding *bond = bond_dev->priv; + struct bonding *bond = netdev_priv(bond_dev); switch (event) { case NETDEV_UNREGISTER: @@ -3775,7 +3794,7 @@ static int bond_xmit_hash_policy_l2(struct sk_buff *skb, static int bond_open(struct net_device *bond_dev) { - struct bonding *bond = bond_dev->priv; + struct bonding *bond = netdev_priv(bond_dev); bond->kill_timers = 0; @@ -3816,6 +3835,7 @@ static int bond_open(struct net_device *bond_dev) queue_delayed_work(bond->wq, &bond->ad_work, 0); /* register to receive LACPDUs */ bond_register_lacpdu(bond); + bond_3ad_initiate_agg_selection(bond, 1); } return 0; @@ -3823,7 +3843,7 @@ static int bond_open(struct net_device *bond_dev) static int bond_close(struct net_device *bond_dev) { - struct bonding *bond = bond_dev->priv; + struct bonding *bond = netdev_priv(bond_dev); if (bond->params.mode == BOND_MODE_8023AD) { /* Unregister the receive of LACPDUs */ @@ -3836,6 +3856,7 @@ static int bond_close(struct net_device *bond_dev) write_lock_bh(&bond->lock); bond->send_grat_arp = 0; + bond->send_unsol_na = 0; /* signal timers not to re-arm */ bond->kill_timers = 1; @@ -3876,8 +3897,8 @@ static int bond_close(struct net_device *bond_dev) static struct net_device_stats *bond_get_stats(struct net_device *bond_dev) { - struct bonding *bond = bond_dev->priv; - struct net_device_stats *stats = &(bond->stats), *sstats; + struct bonding *bond = netdev_priv(bond_dev); + struct net_device_stats *stats = &bond->stats; struct net_device_stats local_stats; struct slave *slave; int i; @@ -3887,7 +3908,8 @@ 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); + const struct net_device_stats *sstats = dev_get_stats(slave->dev); + local_stats.rx_packets += sstats->rx_packets; local_stats.rx_bytes += sstats->rx_bytes; local_stats.rx_errors += sstats->rx_errors; @@ -3954,7 +3976,7 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd } if (mii->reg_num == 1) { - struct bonding *bond = bond_dev->priv; + struct bonding *bond = netdev_priv(bond_dev); mii->val_out = 0; read_lock(&bond->lock); read_lock(&bond->curr_slave_lock); @@ -4046,7 +4068,7 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd static void bond_set_multicast_list(struct net_device *bond_dev) { - struct bonding *bond = bond_dev->priv; + struct bonding *bond = netdev_priv(bond_dev); struct dev_mc_list *dmi; /* @@ -4107,7 +4129,7 @@ static void bond_set_multicast_list(struct net_device *bond_dev) */ static int bond_change_mtu(struct net_device *bond_dev, int new_mtu) { - struct bonding *bond = bond_dev->priv; + struct bonding *bond = netdev_priv(bond_dev); struct slave *slave, *stop_at; int res = 0; int i; @@ -4179,12 +4201,16 @@ unwind: */ static int bond_set_mac_address(struct net_device *bond_dev, void *addr) { - struct bonding *bond = bond_dev->priv; + struct bonding *bond = netdev_priv(bond_dev); struct sockaddr *sa = addr, tmp_sa; struct slave *slave, *stop_at; int res = 0; int i; + if (bond->params.mode == BOND_MODE_ALB) + return bond_alb_set_mac_address(bond_dev, addr); + + dprintk("bond=%p, name=%s\n", bond, (bond_dev ? bond_dev->name : "None")); /* @@ -4214,9 +4240,10 @@ static int bond_set_mac_address(struct net_device *bond_dev, void *addr) */ bond_for_each_slave(bond, slave, i) { + const struct net_device_ops *slave_ops = slave->dev->netdev_ops; dprintk("slave %p %s\n", slave, slave->dev->name); - if (slave->dev->set_mac_address == NULL) { + if (slave_ops->ndo_set_mac_address == NULL) { res = -EOPNOTSUPP; dprintk("EOPNOTSUPP %s\n", slave->dev->name); goto unwind; @@ -4260,7 +4287,7 @@ unwind: static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *bond_dev) { - struct bonding *bond = bond_dev->priv; + struct bonding *bond = netdev_priv(bond_dev); struct slave *slave, *start_at; int i, slave_no, res = 1; @@ -4309,7 +4336,7 @@ out: */ static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *bond_dev) { - struct bonding *bond = bond_dev->priv; + struct bonding *bond = netdev_priv(bond_dev); int res = 1; read_lock(&bond->lock); @@ -4341,7 +4368,7 @@ out: */ static int bond_xmit_xor(struct sk_buff *skb, struct net_device *bond_dev) { - struct bonding *bond = bond_dev->priv; + struct bonding *bond = netdev_priv(bond_dev); struct slave *slave, *start_at; int slave_no; int i; @@ -4387,7 +4414,7 @@ out: */ static int bond_xmit_broadcast(struct sk_buff *skb, struct net_device *bond_dev) { - struct bonding *bond = bond_dev->priv; + struct bonding *bond = netdev_priv(bond_dev); struct slave *slave, *start_at; struct net_device *tx_dev = NULL; int i; @@ -4494,7 +4521,6 @@ void bond_set_mode_ops(struct bonding *bond, int mode) /* FALLTHRU */ case BOND_MODE_TLB: bond_dev->hard_start_xmit = bond_alb_xmit; - bond_dev->set_mac_address = bond_alb_set_mac_address; break; default: /* Should never happen, mode already checked */ @@ -4524,13 +4550,27 @@ static const struct ethtool_ops bond_ethtool_ops = { .get_flags = ethtool_op_get_flags, }; +static const struct net_device_ops bond_netdev_ops = { + .ndo_open = bond_open, + .ndo_stop = bond_close, + .ndo_get_stats = bond_get_stats, + .ndo_do_ioctl = bond_do_ioctl, + .ndo_set_multicast_list = bond_set_multicast_list, + .ndo_change_mtu = bond_change_mtu, + .ndo_validate_addr = NULL, + .ndo_set_mac_address = bond_set_mac_address, + .ndo_vlan_rx_register = bond_vlan_rx_register, + .ndo_vlan_rx_add_vid = bond_vlan_rx_add_vid, + .ndo_vlan_rx_kill_vid = bond_vlan_rx_kill_vid, +}; + /* * Does not allocate but creates a /proc entry. * Allowed to fail. */ static int bond_init(struct net_device *bond_dev, struct bond_params *params) { - struct bonding *bond = bond_dev->priv; + struct bonding *bond = netdev_priv(bond_dev); dprintk("Begin bond_init for %s\n", bond_dev->name); @@ -4551,20 +4591,13 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params) bond->primary_slave = NULL; bond->dev = bond_dev; bond->send_grat_arp = 0; + bond->send_unsol_na = 0; bond->setup_by_slave = 0; INIT_LIST_HEAD(&bond->vlan_list); /* Initialize the device entry points */ - bond_dev->open = bond_open; - bond_dev->stop = bond_close; - bond_dev->get_stats = bond_get_stats; - bond_dev->do_ioctl = bond_do_ioctl; + bond_dev->netdev_ops = &bond_netdev_ops; bond_dev->ethtool_ops = &bond_ethtool_ops; - bond_dev->set_multicast_list = bond_set_multicast_list; - bond_dev->change_mtu = bond_change_mtu; - bond_dev->set_mac_address = bond_set_mac_address; - bond_dev->validate_addr = NULL; - bond_set_mode_ops(bond, bond->params.mode); bond_dev->destructor = bond_destructor; @@ -4573,6 +4606,8 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params) bond_dev->tx_queue_len = 0; bond_dev->flags |= IFF_MASTER|IFF_MULTICAST; bond_dev->priv_flags |= IFF_BONDING; + if (bond->params.arp_interval) + bond_dev->priv_flags |= IFF_MASTER_ARPMON; /* At first, we block adding VLANs. That's the only way to * prevent problems that occur when adding VLANs over an @@ -4591,9 +4626,6 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params) * when there are slaves that are not hw accel * capable */ - bond_dev->vlan_rx_register = bond_vlan_rx_register; - bond_dev->vlan_rx_add_vid = bond_vlan_rx_add_vid; - bond_dev->vlan_rx_kill_vid = bond_vlan_rx_kill_vid; bond_dev->features |= (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER); @@ -4632,7 +4664,7 @@ static void bond_work_cancel_all(struct bonding *bond) */ static void bond_deinit(struct net_device *bond_dev) { - struct bonding *bond = bond_dev->priv; + struct bonding *bond = netdev_priv(bond_dev); list_del(&bond->bond_list); @@ -4751,6 +4783,23 @@ static int bond_check_params(struct bond_params *params) } } + if (ad_select) { + params->ad_select = bond_parse_parm(ad_select, ad_select_tbl); + if (params->ad_select == -1) { + printk(KERN_ERR DRV_NAME + ": Error: Invalid ad_select \"%s\"\n", + ad_select == NULL ? "NULL" : ad_select); + return -EINVAL; + } + + if (bond_mode != BOND_MODE_8023AD) { + printk(KERN_WARNING DRV_NAME + ": ad_select param only affects 802.3ad mode\n"); + } + } else { + params->ad_select = BOND_AD_STABLE; + } + if (max_bonds < 0 || max_bonds > INT_MAX) { printk(KERN_WARNING DRV_NAME ": Warning: max_bonds (%d) not in range %d-%d, so it " @@ -4798,6 +4847,13 @@ static int bond_check_params(struct bond_params *params) num_grat_arp = 1; } + if (num_unsol_na < 0 || num_unsol_na > 255) { + printk(KERN_WARNING DRV_NAME + ": Warning: num_unsol_na (%d) not in range 0-255 so it " + "was reset to 1 \n", num_unsol_na); + num_unsol_na = 1; + } + /* reset values for 802.3ad */ if (bond_mode == BOND_MODE_8023AD) { if (!miimon) { @@ -4999,6 +5055,7 @@ static int bond_check_params(struct bond_params *params) params->xmit_policy = xmit_hashtype; params->miimon = miimon; params->num_grat_arp = num_grat_arp; + params->num_unsol_na = num_unsol_na; params->arp_interval = arp_interval; params->arp_validate = arp_validate_value; params->updelay = updelay; @@ -5099,7 +5156,7 @@ int bond_create(char *name, struct bond_params *params) up_write(&bonding_rwsem); rtnl_unlock(); /* allows sysfs registration of net device */ - res = bond_create_sysfs_entry(bond_dev->priv); + res = bond_create_sysfs_entry(netdev_priv(bond_dev)); if (res < 0) { rtnl_lock(); down_write(&bonding_rwsem); @@ -5151,6 +5208,7 @@ 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: @@ -5173,6 +5231,7 @@ static void __exit bonding_exit(void) { unregister_netdevice_notifier(&bond_netdev_notifier); unregister_inetaddr_notifier(&bond_inetaddr_notifier); + bond_unregister_ipv6_notifier(); bond_destroy_sysfs(); |