net/bonding: ADD IPoIB support for the bonding driver
Subsystems (4)
v7 cover net/bonding: ADD IPoIB support for the bonding driver
This is the 7th version of this patch series. See link to V6 below.
Changes from the previous version
---------------------------------
* Some patches required modifications to remove offsets so they can be applied with git-apply
* Patch #3 was first modified by Jay and later by me to make it work with header_ops
* patch #8 was changed to fix the problem that caused 'ifconfig down' to stuck (dev_close was called twice)
Jay,
I removed the Acked-by lines from patches 3 & 8. Can you please add them back after you approve?
thanks
MoniS
Link to V6:
http://lists.openfabrics.org/pipermail/general/2007-September/041139.html
PATCH v7 1/8 IB/ipoib: Bound the net device to the ipoib_neigh structue
IPoIB uses a two layer neighboring scheme, such that for each struct neighbour whose device is an ipoib one, there is a struct ipoib_neigh buddy which is created on demand at the tx flow by an ipoib_neigh_alloc(skb->dst->neighbour) call.
When using the bonding driver, neighbours are created by the net stack on behalf of the bonding (master) device. On the tx flow the bonding code gets an skb such that skb->dev points to the master device, it changes this skb to point on the slave device and calls the slave hard_start_xmit function.
Under this scheme, ipoib_neigh_destructor assumption that for each struct neighbour it gets, n->dev is an ipoib device and hence netdev_priv(n->dev) can be casted to struct ipoib_dev_priv is buggy.
To fix it, this patch adds a dev field to struct ipoib_neigh which is used instead of the struct neighbour dev one, when n->dev->flags has the IFF_MASTER bit set.
--- drivers/infiniband/ulp/ipoib/ipoib.h | 4 +++- drivers/infiniband/ulp/ipoib/ipoib_main.c | 24 +++++++++++++++--------- drivers/infiniband/ulp/ipoib/ipoib_multicast.c | 3 ++- 3 files changed, 20 insertions(+), 11 deletions(-)
drivers/infiniband/ulp/ipoib/ipoib.h +3 -1
@@ -349,6 +349,7 @@ #endifstruct sk_buff_head queue;struct neighbour *neighbour; +struct net_device *dev;struct list_head list; };
@@ -365,7 +366,8 @@ static inline struct ipoib_neigh **to_ip INFINIBAND_ALEN, sizeof(void *)); } -struct ipoib_neigh *ipoib_neigh_alloc (struct neighbour *neigh); +struct ipoib_neigh *ipoib_neigh_alloc (struct neighbour *neigh, +struct net_device *dev);void ipoib_neigh_free (struct net_device *dev,struct ipoib_neigh *neigh);extern struct workqueue_struct *ipoib_workqueue;
drivers/infiniband/ulp/ipoib/ipoib_main.c +15 -9
@@ -517,7 +517,7 @@ static void neigh_add_path(struct sk_bufstruct ipoib_path *path;struct ipoib_neigh *neigh; - neigh =ipoib_neigh_alloc (skb->dst->neighbour); + neigh =ipoib_neigh_alloc (skb->dst->neighbour, skb->dev);if (!neigh) { ++dev->stats.tx_dropped;dev_kfree_skb_any (skb);
@@ -817,6 +817,13 @@ static void ipoib_neigh_cleanup(struct nunsigned long flags;struct ipoib_ah *ah =NULL ; + neigh = *to_ipoib_neigh (n); +if (neigh) { + priv =netdev_priv (neigh->dev); +ipoib_dbg (priv,"neigh_destructor for bonding device: %s\n" , + n->dev->name); + }else +return ; ipoib_dbg(priv, "neigh_cleanup for %06x " IPOIB_GID_FMT "\n", IPOIB_QPN(n->ha),
@@ -824,13 +831,10 @@ static void ipoib_neigh_cleanup(struct nspin_lock_irqsave (&priv->lock, flags); - neigh = *to_ipoib_neigh (n); -if (neigh) { -if (neigh->ah) - ah = neigh->ah; -list_del (&neigh->list); -ipoib_neigh_free (n->dev, neigh); - } +if (neigh->ah) + ah = neigh->ah; +list_del (&neigh->list); +ipoib_neigh_free (n->dev, neigh);spin_unlock_irqrestore (&priv->lock, flags);
@@ -838,7 +842,8 @@ static void ipoib_neigh_cleanup(struct nipoib_put_ah (ah); } -struct ipoib_neigh *ipoib_neigh_alloc (struct neighbour *neighbour) +struct ipoib_neigh *ipoib_neigh_alloc (struct neighbour *neighbour, +struct net_device *dev) {struct ipoib_neigh *neigh;
@@ -847,6 +852,7 @@ struct ipoib_neigh *ipoib_neigh_alloc(streturn NULL ; neigh->neighbour = neighbour; + neigh->dev = dev; *to_ipoib_neigh (neighbour) = neigh;skb_queue_head_init (&neigh->queue);ipoib_cm_set (neigh,NULL );
drivers/infiniband/ulp/ipoib/ipoib_multicast.c +2 -1
@@ -705,7 +705,8 @@ out:if (skb->dst && skb->dst->neighbour && !*to_ipoib_neigh (skb->dst->neighbour)) { -struct ipoib_neigh *neigh =ipoib_neigh_alloc (skb->dst->neighbour); +struct ipoib_neigh *neigh =ipoib_neigh_alloc (skb->dst->neighbour, + skb->dev);if (neigh) {kref_get (&mcast->ah->ref);
Quoted 2 lines · Moni Shoua
This is the 7th version of this patch series. See link to V6 below.
I forgot to mention that the patches are relative to jgarzik/netdev-2.6.git#master. I couldn't compile the 2.6.24 or the upstream branches so I used master branch to test the fixes.
PATCH v7 2/8 IB/ipoib: Verify address handle validity on send
In reply to Moni ShouaWhen the bonding device senses a carrier loss of its active slave it replaces that slave with a new one. In between the times when the carrier of an IPoIB device goes down and ipoib_neigh is destroyed, it is possible that the bonding driver will send a packet on a new slave that uses an old ipoib_neigh. This patch detects and prevents this from happenning.
--- drivers/infiniband/ulp/ipoib/ipoib_main.c | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-)
drivers/infiniband/ulp/ipoib/ipoib_main.c +3 -2
@@ -692,9 +692,10 @@ static int ipoib_start_xmit(struct sk_bu goto out; } }else if (neigh->ah) { -if (unlikely (memcmp (&neigh->dgid.raw, +if (unlikely ((memcmp (&neigh->dgid.raw, skb->dst->neighbour->ha +4 , -sizeof (union ib_gid )))) { +sizeof (union ib_gid ))) || + (neigh->dev != dev))) {spin_lock (&priv->lock);/* * It's safe to call ipoib_put_ah() inside
PATCH v7 3/8 net/bonding: Enable bonding to enslave non ARPHRD_ETHER
In reply to Moni ShouaThis patch changes some of the bond netdevice attributes and functions to be that of the active slave for the case of the enslaved device not being of ARPHRD_ETHER type. Basically it overrides those setting done by ether_setup(), which are netdevice **type** dependent and hence might be not appropriate for devices of other types. It also enforces mutual exclusion on bonding slaves from dissimilar ether types, as was concluded over the v1 discussion.
IPoIB (see Documentation/infiniband/ipoib.txt) MAC address is made of a 3 bytes IB QP (Queue Pair) number and 16 bytes IB port GID (Global ID) of the port this IPoIB device is bounded to. The QP is a resource created by the IB HW and the GID is an identifier burned into the HCA (i have omitted here some details which are not important for the bonding RFC).
--- drivers/net/bonding/bond_main.c | 34 ++++++++++++++++++++++++++++++++++ 1 files changed, 34 insertions(+)
drivers/net/bonding/bond_main.c +34 -0
@@ -1238,6 +1238,21 @@ static int bond_compute_features(structreturn 0 ; } + +static void bond_setup_by_slave (struct net_device *bond_dev, +struct net_device *slave_dev) +{ + bond_dev->neigh_setup = slave_dev->neigh_setup; + + bond_dev->type = slave_dev->type; + bond_dev->hard_header_len = slave_dev->hard_header_len; + bond_dev->addr_len = slave_dev->addr_len; + bond_dev->header_ops = slave_dev->header_ops; + +memcpy (bond_dev->broadcast, slave_dev->broadcast, + slave_dev->addr_len); +} +/* enslave device <slave> to bond device <master> */ int bond_enslave (struct net_device *bond_dev,struct net_device *slave_dev) {
@@ -1312,6 +1327,25 @@ int bond_enslave(struct net_device *bond goto err_undo_flags; } +/* set bonding device ether type by slave - bonding netdevices are +* created with ether_setup, so when the slave type is not ARPHRD_ETHER +* there is a need to override some of the type dependent attribs/funcs. +* +* bond ether type mutual exclusion - don't allow slaves of dissimilar +* ether type (eg ARPHRD_ETHER and ARPHRD_INFINIBAND) share the same bond +*/ +if (bond->slave_cnt ==0 ) { +if (slave_dev->type !=ARPHRD_ETHER ) +bond_setup_by_slave (bond_dev, slave_dev); + }else if (bond_dev->type != slave_dev->type) { + printk(KERN_ERR DRV_NAME ": %s ether type (%d) is different " +"from other slaves (%d), can not enslave it.\n" , + slave_dev->name, + slave_dev->type, bond_dev->type); + res = -EINVAL ; + goto err_undo_flags; + } +if (slave_dev->set_mac_address ==NULL ) { printk(KERN_ERR DRV_NAME": %s: Error: The slave device you specified does "
PATCH v7 4/8 net/bonding: Enable bonding to enslave netdevices not supporting set_mac_address()
In reply to Moni ShouaThis patch allows for enslaving netdevices which do not support the set_mac_address() function. In that case the bond mac address is the one of the active slave, where remote peers are notified on the mac address (neighbour) change by Gratuitous ARP sent by bonding when fail-over occurs (this is already done by the bonding code).
--- drivers/net/bonding/bond_main.c | 87 +++++++++++++++++++++++++++------------- drivers/net/bonding/bonding.h | 1 2 files changed, 60 insertions(+), 28 deletions(-)
drivers/net/bonding/bond_main.c +59 -28
@@ -1096,6 +1096,14 @@ void bond_change_active_slave(struct bonif (new_active) {bond_set_slave_active_flags (new_active); } + +/* when bonding does not set the slave MAC address, the bond MAC +* address is the one of the active slave. +*/ +if (new_active && !bond->do_set_mac_addr) +memcpy (bond->dev->dev_addr, new_active->dev->dev_addr, + new_active->dev->addr_len); +bond_send_gratuitous_arp (bond); } }
@@ -1347,13 +1355,22 @@ int bond_enslave(struct net_device *bond }if (slave_dev->set_mac_address ==NULL ) { - printk(KERN_ERR DRV_NAME -": %s: Error: The slave device you specified does " -"not support setting the MAC address. " -"Your kernel likely does not support slave " - "devices.\n", bond_dev->name); - res = -EOPNOTSUPP ; - goto err_undo_flags; +if (bond->slave_cnt ==0 ) { + printk(KERN_WARNING DRV_NAME +": %s: Warning: The first slave device you " +"specified does not support setting the MAC " +"address. This bond MAC address would be that " + "of the active slave.\n", bond_dev->name); + bond->do_set_mac_addr =0 ; + }else if (bond->do_set_mac_addr) { + printk(KERN_ERR DRV_NAME +": %s: Error: The slave device you specified " +"does not support setting the MAC addres,." +"but this bond uses this practice. \n" + , bond_dev->name); + res = -EOPNOTSUPP ; + goto err_undo_flags; + } } new_slave =kzalloc (sizeof (struct slave ),GFP_KERNEL );
@@ -1374,16 +1391,18 @@ int bond_enslave(struct net_device *bond*/ memcpy (new_slave->perm_hwaddr, slave_dev->dev_addr,ETH_ALEN ); -/* -* Set slave to master's mac address. The application already -* set the master's mac address to that of the first slave -*/ -memcpy (addr.sa_data, bond_dev->dev_addr, bond_dev->addr_len); - addr.sa_family = slave_dev->type; - res =dev_set_mac_address (slave_dev, &addr); -if (res) { -dprintk ("Error %d calling set_mac_address\n" , res); - goto err_free; +if (bond->do_set_mac_addr) { +/* +* Set slave to master's mac address. The application already +* set the master's mac address to that of the first slave +*/ +memcpy (addr.sa_data, bond_dev->dev_addr, bond_dev->addr_len); + addr.sa_family = slave_dev->type; + res =dev_set_mac_address (slave_dev, &addr); +if (res) { +dprintk ("Error %d calling set_mac_address\n" , res); + goto err_free; + } } res =netdev_set_master (slave_dev, bond_dev);
@@ -1608,9 +1627,11 @@ err_close:dev_close (slave_dev); err_restore_mac: -memcpy (addr.sa_data, new_slave->perm_hwaddr,ETH_ALEN ); - addr.sa_family = slave_dev->type; -dev_set_mac_address (slave_dev, &addr); +if (bond->do_set_mac_addr) { +memcpy (addr.sa_data, new_slave->perm_hwaddr,ETH_ALEN ); + addr.sa_family = slave_dev->type; +dev_set_mac_address (slave_dev, &addr); + } err_free:kfree (new_slave);
@@ -1783,10 +1804,12 @@ int bond_release(struct net_device *bond/* close slave before restoring its mac address */ dev_close (slave_dev); -/* restore original ("permanent") mac address */ -memcpy (addr.sa_data, slave->perm_hwaddr,ETH_ALEN ); - addr.sa_family = slave_dev->type; -dev_set_mac_address (slave_dev, &addr); +if (bond->do_set_mac_addr) { +/* restore original ("permanent") mac address */ +memcpy (addr.sa_data, slave->perm_hwaddr,ETH_ALEN ); + addr.sa_family = slave_dev->type; +dev_set_mac_address (slave_dev, &addr); + } slave_dev->priv_flags &= ~(IFF_MASTER_8023AD | IFF_MASTER_ALB | IFF_SLAVE_INACTIVE | IFF_BONDING |
@@ -1873,10 +1896,12 @@ static int bond_release_all(struct net_d/* close slave before restoring its mac address */ dev_close (slave_dev); -/* restore original ("permanent") mac address*/ -memcpy (addr.sa_data, slave->perm_hwaddr,ETH_ALEN ); - addr.sa_family = slave_dev->type; -dev_set_mac_address (slave_dev, &addr); +if (bond->do_set_mac_addr) { +/* restore original ("permanent") mac address*/ +memcpy (addr.sa_data, slave->perm_hwaddr,ETH_ALEN ); + addr.sa_family = slave_dev->type; +dev_set_mac_address (slave_dev, &addr); + } slave_dev->priv_flags &= ~(IFF_MASTER_8023AD |IFF_MASTER_ALB |IFF_SLAVE_INACTIVE );
@@ -3914,6 +3939,9 @@ static int bond_set_mac_address(struct ndprintk ("bond=%p, name=%s\n" , bond, (bond_dev ? bond_dev->name :"None" )); +if (!bond->do_set_mac_addr) +return -EOPNOTSUPP ; +if (!is_valid_ether_addr (sa->sa_data)) {return -EADDRNOTAVAIL ; }
@@ -4300,6 +4328,9 @@ #ifdef CONFIG_PROC_FSbond_create_proc_entry (bond);#endif +/* set do_set_mac_addr to true on startup */ + bond->do_set_mac_addr =1 ; +list_add_tail (&bond->bond_list, &bond_dev_list);return 0 ;
drivers/net/bonding/bonding.h +1 -0
@@ -185,6 +185,7 @@ struct bonding {struct timer_list mii_timer;struct timer_list arp_timer;s8 kill_timers; +s8 do_set_mac_addr;struct net_device_stats stats;#ifdef CONFIG_PROC_FS struct proc_dir_entry *proc_entry;
PATCH v7 5/8 net/bonding: Enable IP multicast for bonding IPoIB devices
In reply to Moni ShouaAllow to enslave devices when the bonding device is not up. Over the discussion held at the previous post this seemed to be the most clean way to go, where it is not expected to cause instabilities.
Normally, the bonding driver is UP before any enslavement takes place. Once a netdevice is UP, the network stack acts to have it join some multicast groups (eg the all-hosts 224.0.0.1). Now, since ether_setup() have set the bonding device type to be ARPHRD_ETHER and address len to be ETHER_ALEN, the net core code computes a wrong multicast link address. This is b/c ip_eth_mc_map() is called where for multicast joins taking place after the enslavement another ip_xxx_mc_map() is called (eg ip_ib_mc_map() when the bond type is ARPHRD_INFINIBAND)
--- drivers/net/bonding/bond_main.c | 5 +++-- drivers/net/bonding/bond_sysfs.c | 6 ++---- 2 files changed, 5 insertions(+), 6 deletions(-)
drivers/net/bonding/bond_main.c +3 -2
@@ -1281,8 +1281,9 @@ int bond_enslave(struct net_device *bond/* bond must be initialized by bond_open() before enslaving */ if (!(bond_dev->flags &IFF_UP )) { -dprintk ("Error, master_dev is not up\n" ); -return -EPERM ; + printk(KERN_WARNING DRV_NAME +" %s: master_dev is not up in bond_enslave\n" , + bond_dev->name); }/* already enslaved */
drivers/net/bonding/bond_sysfs.c +2 -4
@@ -266,11 +266,9 @@ static ssize_t bonding_store_slaves(stru/* Quick sanity check -- is the bond interface up? */ if (!(bond->dev->flags &IFF_UP )) { - printk(KERN_ERR DRV_NAME -": %s: Unable to update slaves because interface is down.\n" , + printk(KERN_WARNING DRV_NAME +": %s: doing slave updates when interface is down.\n" , bond->dev->name); - ret = -EPERM ; - goto out; }/* Note: We can't hold bond->lock here, as bond_create grabs it. */
PATCH v7 6/8 net/bonding: Handlle wrong assumptions that slave is always an Ethernet device
In reply to Moni Shouabonding sometimes uses Ethernet constants (such as MTU and address length) which are not good when it enslaves non Ethernet devices (such as InfiniBand).
--- drivers/net/bonding/bond_main.c | 3 ++- drivers/net/bonding/bond_sysfs.c | 10 ++++++++-- drivers/net/bonding/bonding.h | 1 + 3 files changed, 11 insertions(+), 3 deletions(-)
drivers/net/bonding/bond_main.c +2 -1
@@ -1225,7 +1225,8 @@ static int bond_compute_features(structstruct slave *slave;struct net_device *bond_dev = bond->dev;unsigned long features = bond_dev->features; -unsigned short max_hard_header_len =ETH_HLEN ; +unsigned short max_hard_header_len =max ((u16 )ETH_HLEN , + bond_dev->hard_header_len);int i; features &= ~(NETIF_F_ALL_CSUM |BOND_VLAN_FEATURES );
drivers/net/bonding/bond_sysfs.c +8 -2
@@ -260,6 +260,7 @@ static ssize_t bonding_store_slaves(struchar command[IFNAMSIZ +1 ] = {0 , };char *ifname;int i, res, found, ret = count; +u32 original_mtu;struct slave *slave;struct net_device *dev =NULL ;struct bonding *bond =to_bond (d);
@@ -325,6 +326,7 @@ static ssize_t bonding_store_slaves(stru }/* Set the slave's MTU to match the bond */ + original_mtu = dev->mtu;if (dev->mtu != bond->dev->mtu) {if (dev->change_mtu) { res = dev->change_mtu(dev,
@@ -339,6 +341,9 @@ static ssize_t bonding_store_slaves(stru }rtnl_lock (); res =bond_enslave (bond->dev, dev); +bond_for_each_slave (bond, slave, i) +if (strnicmp (slave->dev->name, ifname,IFNAMSIZ ) ==0 ) + slave->original_mtu = original_mtu;rtnl_unlock ();if (res) { ret = res;
@@ -351,6 +356,7 @@ static ssize_t bonding_store_slaves(strubond_for_each_slave (bond, slave, i)if (strnicmp (slave->dev->name, ifname,IFNAMSIZ ) ==0 ) { dev = slave->dev; + original_mtu = slave->original_mtu;break ; }if (dev) {
@@ -365,9 +371,9 @@ static ssize_t bonding_store_slaves(stru }/* set the slave MTU to the default */ if (dev->change_mtu) { - dev->change_mtu (dev,1500 ); + dev->change_mtu (dev, original_mtu); }else { - dev->mtu =1500 ; + dev->mtu = original_mtu; } }else {
drivers/net/bonding/bonding.h +1 -0
@@ -156,6 +156,7 @@ struct slave {s8 link;/* one of BOND_LINK_XXXX */ s8 state;/* one of BOND_STATE_XXXX */ u32 original_flags; +u32 original_mtu;u32 link_failure_count;u16 speed;u8 duplex;
PATCH V6 7/8] net/bonding: Delay sending of gratuitous ARP to avoid failure
In reply to Moni ShouaDelay sending a gratuitous_arp when LINK_STATE_LINKWATCH_PENDING bit in dev->state field is on. This improves the chances for the arp packet to be transmitted.
--- drivers/net/bonding/bond_main.c | 24 +++++++++++++++++++++--- drivers/net/bonding/bonding.h | 1 + 2 files changed, 22 insertions(+), 3 deletions(-)
drivers/net/bonding/bond_main.c +21 -3
@@ -1103,8 +1103,14 @@ void bond_change_active_slave(struct bonif (new_active && !bond->do_set_mac_addr)memcpy (bond->dev->dev_addr, new_active->dev->dev_addr, new_active->dev->addr_len); - -bond_send_gratuitous_arp (bond); +if (bond->curr_active_slave && +test_bit (__LINK_STATE_LINKWATCH_PENDING, + &bond->curr_active_slave->dev->state)) { +dprintk ("delaying gratuitous arp on %s\n" , + bond->curr_active_slave->dev->name); + bond->send_grat_arp =1 ; + }else +bond_send_gratuitous_arp (bond); } }
@@ -2074,6 +2080,17 @@ void bond_mii_monitor(struct net_device* program could monitor the link itself if needed. */ +if (bond->send_grat_arp) { +if (bond->curr_active_slave &&test_bit (__LINK_STATE_LINKWATCH_PENDING, + &bond->curr_active_slave->dev->state)) +dprintk ("Needs to send gratuitous arp but not yet\n" ); +else { +dprintk ("sending delayed gratuitous arp on on %s\n" , + bond->curr_active_slave->dev->name); +bond_send_gratuitous_arp (bond); + bond->send_grat_arp =0 ; + } + }read_lock (&bond->curr_slave_lock); oldcurrent = bond->curr_active_slave;read_unlock (&bond->curr_slave_lock);
@@ -2475,7 +2492,7 @@ static void bond_send_gratuitous_arp(strif (bond->master_ip) {bond_arp_send (slave->dev,ARPOP_REPLY , bond->master_ip, - bond->master_ip,0 ); + bond->master_ip,0 ); }list_for_each_entry (vlan, &bond->vlan_list, vlan_list) {
@@ -4281,6 +4298,7 @@ static int bond_init(struct net_device * bond->current_arp_slave =NULL ; bond->primary_slave =NULL ; bond->dev = bond_dev; + bond->send_grat_arp =0 ;INIT_LIST_HEAD (&bond->vlan_list);/* Initialize the device entry points */
drivers/net/bonding/bonding.h +1 -0
@@ -187,6 +187,7 @@ struct bonding {struct timer_list arp_timer;s8 kill_timers;s8 do_set_mac_addr; +s8 send_grat_arp;struct net_device_stats stats;#ifdef CONFIG_PROC_FS struct proc_dir_entry *proc_entry;
PATCH v7 8/8 net/bonding: Destroy bonding master when last slave is gone
In reply to Moni ShouaWhen bonding enslaves non Ethernet devices it takes pointers to functions
in the module that owns the slaves. In this case it becomes unsafe
to keep the bonding master registered after last slave was unenslaved
because we don't know if the pointers are still valid. Destroying the bond when slave_cnt is zero ensures that these functions be used anymore.
--- drivers/net/bonding/bond_main.c | 37 ++++++++++++++++++++++++++++++++++++- drivers/net/bonding/bond_sysfs.c | 9 +++++---- drivers/net/bonding/bonding.h | 3 +++ 3 files changed, 44 insertions(+), 5 deletions(-)
drivers/net/bonding/bond_main.c +36 -1
@@ -1257,6 +1257,7 @@ static int bond_compute_features(structstatic void bond_setup_by_slave (struct net_device *bond_dev,struct net_device *slave_dev) { +struct bonding *bond = bond_dev->priv; bond_dev->neigh_setup = slave_dev->neigh_setup; bond_dev->type = slave_dev->type;
@@ -1266,6 +1267,7 @@ static void bond_setup_by_slave(struct nmemcpy (bond_dev->broadcast, slave_dev->broadcast, slave_dev->addr_len); + bond->setup_by_slave =1 ; }/* enslave device <slave> to bond device <master> */
@@ -1829,6 +1831,35 @@ int bond_release(struct net_device *bond }/* +* Destroy a bonding device. +* Must be under rtnl_lock when this function is called. +*/ +void bond_destroy (struct bonding *bond) +{ +bond_deinit (bond->dev); +bond_destroy_sysfs_entry (bond); +unregister_netdevice (bond->dev); +} + +/* +* First release a slave and than destroy the bond if no more slaves iare left. +* Must be under rtnl_lock when this function is called. +*/ +int bond_release_and_destroy (struct net_device *bond_dev,struct net_device *slave_dev) +{ +struct bonding *bond = bond_dev->priv; +int ret; + + ret =bond_release (bond_dev, slave_dev); +if ((ret ==0 ) && (bond->slave_cnt ==0 )) { + printk(KERN_INFO DRV_NAME ": %s: destroying bond %s.\n", + bond_dev->name, bond_dev->name); +bond_destroy (bond); + } +return ret; +} + +/* * This function releases all slaves. */ static int bond_release_all (struct net_device *bond_dev)
@@ -3311,7 +3342,10 @@ static int bond_slave_netdev_event(unsigswitch (event) {case NETDEV_UNREGISTER :if (bond_dev) { -bond_release (bond_dev, slave_dev); +if (bond->setup_by_slave) +bond_release_and_destroy (bond_dev, slave_dev); +else +bond_release (bond_dev, slave_dev); }break ;case NETDEV_CHANGE :
@@ -4299,6 +4333,7 @@ static int bond_init(struct net_device * bond->primary_slave =NULL ; bond->dev = bond_dev; bond->send_grat_arp =0 ; + bond->setup_by_slave =0 ;INIT_LIST_HEAD (&bond->vlan_list);/* Initialize the device entry points */
drivers/net/bonding/bond_sysfs.c +5 -4
@@ -164,9 +164,7 @@ static ssize_t bonding_store_bonds(struc printk(KERN_INFO DRV_NAME": %s is being deleted...\n" , bond->dev->name); -bond_deinit (bond->dev); -bond_destroy_sysfs_entry (bond); -unregister_netdevice (bond->dev); +bond_destroy (bond);rtnl_unlock (); goto out; }
@@ -363,7 +361,10 @@ static ssize_t bonding_store_slaves(stru printk(KERN_INFO DRV_NAME ": %s: Removing slave %s\n", bond->dev->name, dev->name);rtnl_lock (); - res =bond_release (bond->dev, dev); +if (bond->setup_by_slave) + res =bond_release_and_destroy (bond->dev, dev); +else + res =bond_release (bond->dev, dev);rtnl_unlock ();if (res) { ret = res;
drivers/net/bonding/bonding.h +3 -0
@@ -188,6 +188,7 @@ struct bonding {s8 kill_timers;s8 do_set_mac_addr;s8 send_grat_arp; +s8 setup_by_slave;struct net_device_stats stats;#ifdef CONFIG_PROC_FS struct proc_dir_entry *proc_entry;
@@ -295,6 +296,8 @@ static inline void bond_unset_master_albstruct vlan_entry *bond_next_vlan (struct bonding *bond,struct vlan_entry *curr);int bond_dev_queue_xmit (struct bonding *bond,struct sk_buff *skb,struct net_device *slave_dev);int bond_create (char *name,struct bond_params *params,struct bonding **newbond); +void bond_destroy (struct bonding *bond); +int bond_release_and_destroy (struct net_device *bond_dev,struct net_device *slave_dev);void bond_deinit (struct net_device *bond_dev);int bond_create_sysfs (void );void bond_destroy_sysfs (void );
Quoted 8 lines · Moni Shoua
This is the 7th version of this patch series. See link to V6 below.
Changes from the previous version
---------------------------------* Some patches required modifications to remove offsets so they can be applied with git-apply
* Patch #3 was first modified by Jay and later by me to make it work withheader_ops
* patch #8 was changed to fix the problem that caused 'ifconfig down' to stuck (dev_closewas called twice)
I just applied the latest version Jay sent, are there any remaining changes?
Quoted 11 lines · Jeff Garzik
Quoted 8 lines · Moni Shoua
This is the 7th version of this patch series. See link to V6 below.
Changes from the previous version
---------------------------------* Some patches required modifications to remove offsets so they can be applied with git-apply
* Patch #3 was first modified by Jay and later by me to make it work withheader_ops
* patch #8 was changed to fix the problem that caused 'ifconfig down' to stuck (dev_closewas called twice)I just applied the latest version Jay sent, are there any remaining changes?
Yes, Moni changed patches 3 and 8 from the series I posted to
fix a couple of problems. The others aren't changed from my posting of the series.
Since I see you've just pushed it, do you want a patch to
correct just the two individual things, or would you rather have new patches?
-J
---
-Jay Vosburgh, IBM Linux Technology Center, [email protected]
Quoted 3 lines · Jay Vosburgh
Since I see you've just pushed it, do you want a patch to
correct just the two individual things, or would you rather have new patches?
On top of what was just pushed, please.
Jeff
Quoted 7 lines · Jeff Garzik
Quoted 3 lines · Jay Vosburgh
Since I see you've just pushed it, do you want a patch to
correct just the two individual things, or would you rather have new patches?On top of what was just pushed, please.
Ok, I'll figure that out and then rebase the locking stuff on
top of that.
-J
---
-Jay Vosburgh, IBM Linux Technology Center, [email protected]
Quoted 11 lines · Jay Vosburgh
Quoted 6 lines · Jeff Garzik
Quoted 3 lines · Jay Vosburgh
Since I see you've just pushed it, do you want a patch to
correct just the two individual things, or would you rather have new patches?On top of what was just pushed, please.
Ok, I'll figure that out and then rebase the locking stuff on
top of that.
FWIW Linus just pulled, so you may diff against mainline if you wish.
Whatever is easiest for you...
Jeff
PATCH 1/1 bonding: two small fixes for IPoIB support
Two small fixes to IPoIB support for bonding:
1- copy header_ops from slave to bonding for IPoIB slaves 2- move release and destroy logic to UNREGISTER from GOING_DOWN
notifier to avoid double release
Set bonding to version 3.2.1.
--- drivers/net/bonding/bond_main.c | 11 +++++------ drivers/net/bonding/bonding.h | 4 ++-- 2 files changed, 7 insertions(+), 8 deletions(-)
drivers/net/bonding/bond_main.c +5 -6
@@ -1263,6 +1263,7 @@ static void bond_setup_by_slave(struct net_device *bond_dev,struct bonding *bond = bond_dev->priv; bond_dev->neigh_setup = slave_dev->neigh_setup; + bond_dev->header_ops = slave_dev->header_ops; bond_dev->type = slave_dev->type; bond_dev->hard_header_len = slave_dev->hard_header_len;
@@ -3351,7 +3352,10 @@ static int bond_slave_netdev_event(unsigned long event, struct net_device *slaveswitch (event) {case NETDEV_UNREGISTER :if (bond_dev) { -bond_release (bond_dev, slave_dev); +if (bond->setup_by_slave) +bond_release_and_destroy (bond_dev, slave_dev); +else +bond_release (bond_dev, slave_dev); }break ;case NETDEV_CHANGE :
@@ -3366,11 +3370,6 @@ static int bond_slave_netdev_event(unsigned long event, struct net_device *slave* ... Or is it this? */ break ; -case NETDEV_GOING_DOWN : -dprintk ("slave %s is going down\n" , slave_dev->name); -if (bond->setup_by_slave) -bond_release_and_destroy (bond_dev, slave_dev); -break ;case NETDEV_CHANGEMTU :/* * TODO: Should slaves be allowed to
drivers/net/bonding/bonding.h +2 -2
@@ -22,8 +22,8 @@#include "bond_3ad.h" #include "bond_alb.h" -#define DRV_VERSION "3.2.0" -#define DRV_RELDATE "September 13, 2007" +#define DRV_VERSION "3.2.1" +#define DRV_RELDATE "October 15, 2007"#define DRV_NAME "bonding"#define DRV_DESCRIPTION "Ethernet Channel Bonding Driver"
Signature · 1 line
1.5.3.1
Re: [PATCH linux-2.6] bonding: two small fixes for IPoIB support
Quoted 57 lines · Jay Vosburgh
Two small fixes to IPoIB support for bonding:
1- copy
header_opsfrom slave to bonding for IPoIB slaves 2- move release and destroy logic to UNREGISTER fromGOING_DOWN
notifier to avoid double releaseSet bonding to version 3.2.1.
Signed-off-by Moni Shoua <monis at voltaire.com>Signed-off-by Jay Vosburgh <[email protected]>--- drivers/net/bonding/bond_main.c | 11 +++++------ drivers/net/bonding/bonding.h | 4 ++-- 2 files changed, 7 insertions(+), 8 deletions(-)drivers/net/bonding/bond_main.c +5
-6@@ -1263,6 +1263,7 @@ static void bond_setup_by_slave(struct net_device *bond_dev,struct bonding *bond = bond_dev->priv; bond_dev->neigh_setup = slave_dev->neigh_setup; + bond_dev->header_ops = slave_dev->header_ops; bond_dev->type = slave_dev->type; bond_dev->hard_header_len = slave_dev->hard_header_len;@@ -3351,7 +3352,10 @@ static int bond_slave_netdev_event(unsigned long event, struct net_device *slaveswitch (event) {case NETDEV_UNREGISTER :if (bond_dev) { -bond_release (bond_dev, slave_dev); +if (bond->setup_by_slave) +bond_release_and_destroy (bond_dev, slave_dev); +else +bond_release (bond_dev, slave_dev); }break ;case NETDEV_CHANGE :@@ -3366,11 +3370,6 @@ static int bond_slave_netdev_event(unsigned long event, struct net_device *slave* ... Or is it this? */ break ; -case NETDEV_GOING_DOWN : -dprintk ("slave %s is going down\n" , slave_dev->name); -if (bond->setup_by_slave) -bond_release_and_destroy (bond_dev, slave_dev); -break ;case NETDEV_CHANGEMTU :/* * TODO: Should slaves be allowed to drivers/net/bonding/bonding.h +0
-0
drivers/net/bonding/bonding.h line 29
Quoted 10 lines
drivers/net/bonding/bonding.h +2
-2@@ -22,8 +22,8 @@#include "bond_3ad.h" #include "bond_alb.h" -#define DRV_VERSION "3.2.0" -#define DRV_RELDATE "September 13, 2007" +#define DRV_VERSION "3.2.1" +#define DRV_RELDATE "October 15, 2007"#define DRV_NAME "bonding"#define DRV_DESCRIPTION "Ethernet Channel Bonding Driver"
Jay,
Thanks for this work.
Jeff,
Thanks for applying.
I noticed that this patch isn't applied. It includes important fixes. Can you please apply it also?
MoniS
Jeff Garzik
Applied[ofa-general] Re: [PATCH linux-2.6] bonding: two small fixes for IPoIB support
In reply to Jay VosburghQuoted 11 lines · Jay Vosburgh
Two small fixes to IPoIB support for bonding:
1- copy
header_opsfrom slave to bonding for IPoIB slaves 2- move release and destroy logic to UNREGISTER fromGOING_DOWN
notifier to avoid double releaseSet bonding to version 3.2.1.
Signed-off-by Moni Shoua <monis at voltaire.com>Signed-off-by Jay Vosburgh <[email protected]>
applied