Commit c5df2502 authored by Amir Noam's avatar Amir Noam Committed by Stephen Hemminger

[PATCH] [bonding 2.6] Add support for changing HW address and MTU

parent bb71b2f8
......@@ -592,6 +592,11 @@ static struct slave *find_best_interface(struct bonding *bond);
/* #define BONDING_DEBUG 1 */
#ifdef BONDING_DEBUG
#define dprintk(x...) printk(x...)
#else /* BONDING_DEBUG */
#define dprintk(x...) do {} while (0)
#endif /* BONDING_DEBUG */
/* several macros */
......@@ -3047,10 +3052,6 @@ static int bond_ioctl(struct net_device *master_dev, struct ifreq *ifr, int cmd)
case SIOCBONDRELEASE:
ret = bond_release(master_dev, slave_dev);
break;
case BOND_SETHWADDR_OLD:
case SIOCBONDSETHWADDR:
ret = bond_sethwaddr(master_dev, slave_dev);
break;
case BOND_CHANGE_ACTIVE_OLD:
case SIOCBONDCHANGEACTIVE:
if (USES_PRIMARY(bond_mode)) {
......@@ -3490,6 +3491,132 @@ static int bond_read_proc(char *buf, char **start, off_t off, int count, int *eo
}
#endif /* CONFIG_PROC_FS */
/*
* Change HW address
*
* Note that many devices must be down to change the HW address, and
* downing the master releases all slaves. We can make bonds full of
* bonding devices to test this, however.
*/
static inline int
bond_set_mac_address(struct net_device *dev, void *addr)
{
struct bonding *bond = dev->priv;
struct sockaddr *sa = addr, tmp_sa;
struct slave *slave;
int error;
dprintk(KERN_INFO "bond_set_mac_address %p %s\n", dev,
dev->name);
if (!is_valid_ether_addr(sa->sa_data)) {
return -EADDRNOTAVAIL;
}
for (slave = bond->prev; slave != (struct slave *)bond;
slave = slave->prev) {
dprintk(KERN_INFO "bond_set_mac: slave %p %s\n", slave,
slave->dev->name);
if (slave->dev->set_mac_address == NULL) {
error = -EOPNOTSUPP;
dprintk(KERN_INFO "bond_set_mac EOPNOTSUPP %s\n",
slave->dev->name);
goto unwind;
}
error = slave->dev->set_mac_address(slave->dev, addr);
if (error) {
/* TODO: consider downing the slave
* and retry ?
* User should expect communications
* breakage anyway until ARP finish
* updating, so...
*/
dprintk(KERN_INFO "bond_set_mac err %d %s\n",
error, slave->dev->name);
goto unwind;
}
}
/* success */
memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);
return 0;
unwind:
memcpy(tmp_sa.sa_data, dev->dev_addr, dev->addr_len);
tmp_sa.sa_family = dev->type;
for (slave = slave->next; slave != bond->next;
slave = slave->next) {
int tmp_error;
tmp_error = slave->dev->set_mac_address(slave->dev, &tmp_sa);
if (tmp_error) {
dprintk(KERN_INFO "bond_set_mac_address: "
"unwind err %d dev %s\n",
tmp_error, slave->dev->name);
}
}
return error;
}
/*
* Change the MTU of all of a master's slaves to match the master
*/
static inline int
bond_change_mtu(struct net_device *dev, int newmtu)
{
bonding_t *bond = dev->priv;
slave_t *slave;
int error;
dprintk(KERN_INFO "CM: b %p nm %d\n", bond, newmtu);
for (slave = bond->prev; slave != (slave_t *)bond;
slave = slave->prev) {
dprintk(KERN_INFO "CM: s %p s->p %p c_m %p\n", slave,
slave->prev, slave->dev->change_mtu);
if (slave->dev->change_mtu) {
error = slave->dev->change_mtu(slave->dev, newmtu);
} else {
slave->dev->mtu = newmtu;
error = 0;
}
if (error) {
/* If we failed to set the slave's mtu to the new value
* we must abort the operation even in ACTIVE_BACKUP
* mode, because if we allow the backup slaves to have
* different mtu values than the active slave we'll
* need to change their mtu when doing a failover. That
* means changing their mtu from timer context, which
* is probably not a good idea.
*/
dprintk(KERN_INFO "bond_change_mtu err %d %s\n",
error, slave->dev->name);
goto unwind;
}
}
dev->mtu = newmtu;
return 0;
unwind:
for (slave = slave->next; slave != bond->next;
slave = slave->next) {
if (slave->dev->change_mtu) {
slave->dev->change_mtu(slave->dev, dev->mtu);
} else {
slave->dev->mtu = dev->mtu;
}
}
return error;
}
static int bond_event(struct notifier_block *this, unsigned long event,
void *ptr)
{
......@@ -3582,7 +3709,8 @@ static int __init bond_init(struct net_device *dev)
dev->stop = bond_close;
dev->set_multicast_list = set_multicast_list;
dev->do_ioctl = bond_ioctl;
dev->change_mtu = bond_change_mtu;
dev->set_mac_address = bond_set_mac_address;
dev->tx_queue_len = 0;
dev->flags |= IFF_MASTER|IFF_MULTICAST;
#ifdef CONFIG_NET_FASTROUTE
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment