[PATCH] bonding: inherit zero-copy flags of slaves

This change allows a bonding device to inherit the "zero-copy"
features of its slave devices.

It was inspired by a couple of previous postings on this topic:
http://marc.theaimsgroup.com/?l=bonding-devel&m=111924607327794&w=2
http://marc.theaimsgroup.com/?l=bonding-devel&m=111925242706297&w=2
and it's largely a combination of the patches that appear in those
emails.

Signed-off-by: Arthur Kepner <akepner@sgi.com>
This commit is contained in:
Arthur Kepner 2005-08-23 01:34:53 -04:00 committed by Jeff Garzik
parent efcce83936
commit 8531c5ffbc
2 changed files with 60 additions and 1 deletions

View File

@ -1604,6 +1604,44 @@ static int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_
return 0; return 0;
} }
#define BOND_INTERSECT_FEATURES \
(NETIF_F_SG|NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM)
/*
* Compute the features available to the bonding device by
* intersection of all of the slave devices' BOND_INTERSECT_FEATURES.
* Call this after attaching or detaching a slave to update the
* bond's features.
*/
static int bond_compute_features(struct bonding *bond)
{
int i;
struct slave *slave;
struct net_device *bond_dev = bond->dev;
int features = bond->bond_features;
bond_for_each_slave(bond, slave, i) {
struct net_device * slave_dev = slave->dev;
if (i == 0) {
features |= BOND_INTERSECT_FEATURES;
}
features &=
~(~slave_dev->features & BOND_INTERSECT_FEATURES);
}
/* turn off NETIF_F_SG if we need a csum and h/w can't do it */
if ((features & NETIF_F_SG) &&
!(features & (NETIF_F_IP_CSUM |
NETIF_F_NO_CSUM |
NETIF_F_HW_CSUM))) {
features &= ~NETIF_F_SG;
}
bond_dev->features = features;
return 0;
}
/* enslave device <slave> to bond device <master> */ /* enslave device <slave> to bond device <master> */
static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
{ {
@ -1811,6 +1849,8 @@ static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_de
new_slave->delay = 0; new_slave->delay = 0;
new_slave->link_failure_count = 0; new_slave->link_failure_count = 0;
bond_compute_features(bond);
if (bond->params.miimon && !bond->params.use_carrier) { if (bond->params.miimon && !bond->params.use_carrier) {
link_reporting = bond_check_dev_link(bond, slave_dev, 1); link_reporting = bond_check_dev_link(bond, slave_dev, 1);
@ -2015,7 +2055,7 @@ err_free:
err_undo_flags: err_undo_flags:
bond_dev->features = old_features; bond_dev->features = old_features;
return res; return res;
} }
@ -2100,6 +2140,8 @@ static int bond_release(struct net_device *bond_dev, struct net_device *slave_de
/* release the slave from its bond */ /* release the slave from its bond */
bond_detach_slave(bond, slave); bond_detach_slave(bond, slave);
bond_compute_features(bond);
if (bond->primary_slave == slave) { if (bond->primary_slave == slave) {
bond->primary_slave = NULL; bond->primary_slave = NULL;
} }
@ -2243,6 +2285,8 @@ static int bond_release_all(struct net_device *bond_dev)
bond_alb_deinit_slave(bond, slave); bond_alb_deinit_slave(bond, slave);
} }
bond_compute_features(bond);
/* now that the slave is detached, unlock and perform /* now that the slave is detached, unlock and perform
* all the undo steps that should not be called from * all the undo steps that should not be called from
* within a lock. * within a lock.
@ -3588,6 +3632,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) static int bond_slave_netdev_event(unsigned long event, struct net_device *slave_dev)
{ {
struct net_device *bond_dev = slave_dev->master; struct net_device *bond_dev = slave_dev->master;
struct bonding *bond = bond_dev->priv;
switch (event) { switch (event) {
case NETDEV_UNREGISTER: case NETDEV_UNREGISTER:
@ -3626,6 +3671,9 @@ static int bond_slave_netdev_event(unsigned long event, struct net_device *slave
* TODO: handle changing the primary's name * TODO: handle changing the primary's name
*/ */
break; break;
case NETDEV_FEAT_CHANGE:
bond_compute_features(bond);
break;
default: default:
break; break;
} }
@ -4526,6 +4574,11 @@ static inline void bond_set_mode_ops(struct bonding *bond, int mode)
} }
} }
static struct ethtool_ops bond_ethtool_ops = {
.get_tx_csum = ethtool_op_get_tx_csum,
.get_sg = ethtool_op_get_sg,
};
/* /*
* Does not allocate but creates a /proc entry. * Does not allocate but creates a /proc entry.
* Allowed to fail. * Allowed to fail.
@ -4555,6 +4608,7 @@ static int __init bond_init(struct net_device *bond_dev, struct bond_params *par
bond_dev->stop = bond_close; bond_dev->stop = bond_close;
bond_dev->get_stats = bond_get_stats; bond_dev->get_stats = bond_get_stats;
bond_dev->do_ioctl = bond_do_ioctl; bond_dev->do_ioctl = bond_do_ioctl;
bond_dev->ethtool_ops = &bond_ethtool_ops;
bond_dev->set_multicast_list = bond_set_multicast_list; bond_dev->set_multicast_list = bond_set_multicast_list;
bond_dev->change_mtu = bond_change_mtu; bond_dev->change_mtu = bond_change_mtu;
bond_dev->set_mac_address = bond_set_mac_address; bond_dev->set_mac_address = bond_set_mac_address;
@ -4591,6 +4645,8 @@ static int __init bond_init(struct net_device *bond_dev, struct bond_params *par
NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_RX |
NETIF_F_HW_VLAN_FILTER); NETIF_F_HW_VLAN_FILTER);
bond->bond_features = bond_dev->features;
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
bond_create_proc_entry(bond); bond_create_proc_entry(bond);
#endif #endif

View File

@ -211,6 +211,9 @@ struct bonding {
struct bond_params params; struct bond_params params;
struct list_head vlan_list; struct list_head vlan_list;
struct vlan_group *vlgrp; struct vlan_group *vlgrp;
/* the features the bonding device supports, independently
* of any slaves */
int bond_features;
}; };
/** /**