summaryrefslogtreecommitdiff
path: root/drivers/net/bonding/bond_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/bonding/bond_main.c')
-rw-r--r--drivers/net/bonding/bond_main.c315
1 files changed, 205 insertions, 110 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index a3efba59eee9..a339a8052737 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);
@@ -1364,14 +1377,12 @@ done:
return 0;
}
-
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;
+ bond_dev->header_ops = slave_dev->header_ops;
bond_dev->type = slave_dev->type;
bond_dev->hard_header_len = slave_dev->hard_header_len;
@@ -1385,7 +1396,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 +1406,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 +1488,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 +1799,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 +1831,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 +2010,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 +2027,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 +2158,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 +2207,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 +2221,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 +2475,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 +2603,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 +2640,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 +2690,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 +2714,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 +2743,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 +3176,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 +3260,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 +3313,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 +3321,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 +3342,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 +3351,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 +3358,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 +3523,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 +3541,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 +3792,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 +3833,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 +3841,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 +3854,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 +3895,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 +3906,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 +3974,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 +4066,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;
/*
@@ -4102,12 +4122,26 @@ static void bond_set_multicast_list(struct net_device *bond_dev)
read_unlock(&bond->lock);
}
+static int bond_neigh_setup(struct net_device *dev, struct neigh_parms *parms)
+{
+ struct bonding *bond = netdev_priv(dev);
+ struct slave *slave = bond->first_slave;
+
+ if (slave) {
+ const struct net_device_ops *slave_ops
+ = slave->dev->netdev_ops;
+ if (slave_ops->ndo_neigh_setup)
+ return slave_ops->ndo_neigh_setup(dev, parms);
+ }
+ return 0;
+}
+
/*
* Change the MTU of all of a master's slaves to match the master
*/
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 +4213,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 +4252,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 +4299,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 +4348,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 +4380,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 +4426,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;
@@ -4463,6 +4502,35 @@ static void bond_set_xmit_hash_policy(struct bonding *bond)
}
}
+static int bond_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ const struct bonding *bond = netdev_priv(dev);
+
+ switch (bond->params.mode) {
+ case BOND_MODE_ROUNDROBIN:
+ return bond_xmit_roundrobin(skb, dev);
+ case BOND_MODE_ACTIVEBACKUP:
+ return bond_xmit_activebackup(skb, dev);
+ case BOND_MODE_XOR:
+ return bond_xmit_xor(skb, dev);
+ case BOND_MODE_BROADCAST:
+ return bond_xmit_broadcast(skb, dev);
+ case BOND_MODE_8023AD:
+ return bond_3ad_xmit_xor(skb, dev);
+ case BOND_MODE_ALB:
+ case BOND_MODE_TLB:
+ return bond_alb_xmit(skb, dev);
+ default:
+ /* Should never happen, mode already checked */
+ printk(KERN_ERR DRV_NAME ": %s: Error: Unknown bonding mode %d\n",
+ dev->name, bond->params.mode);
+ WARN_ON_ONCE(1);
+ dev_kfree_skb(skb);
+ return NETDEV_TX_OK;
+ }
+}
+
+
/*
* set bond mode specific net device operations
*/
@@ -4472,29 +4540,22 @@ void bond_set_mode_ops(struct bonding *bond, int mode)
switch (mode) {
case BOND_MODE_ROUNDROBIN:
- bond_dev->hard_start_xmit = bond_xmit_roundrobin;
break;
case BOND_MODE_ACTIVEBACKUP:
- bond_dev->hard_start_xmit = bond_xmit_activebackup;
break;
case BOND_MODE_XOR:
- bond_dev->hard_start_xmit = bond_xmit_xor;
bond_set_xmit_hash_policy(bond);
break;
case BOND_MODE_BROADCAST:
- 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;
bond_set_xmit_hash_policy(bond);
break;
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;
default:
/* Should never happen, mode already checked */
@@ -4524,13 +4585,28 @@ 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_start_xmit = bond_start_xmit,
+ .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_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_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 +4627,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 +4642,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 +4662,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 +4700,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 +4819,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 +4883,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 +5091,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 +5192,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 +5244,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 +5267,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();