patch-2.4.26 linux-2.4.26/drivers/net/bonding/bond_3ad.c

Next file: linux-2.4.26/drivers/net/bonding/bond_3ad.h
Previous file: linux-2.4.26/drivers/net/Makefile
Back to the patch index
Back to the overall index

diff -urN linux-2.4.25/drivers/net/bonding/bond_3ad.c linux-2.4.26/drivers/net/bonding/bond_3ad.c
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+ * Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the Free
@@ -47,8 +47,13 @@
  *	- Send LACPDU as highest priority packet to further fix the above
  *	  problem on very high Tx traffic load where packets may get dropped
  *	  by the slave.
+ *
+ * 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
+ *	- Code cleanup and style changes
  */
 
+//#define BONDING_DEBUG 1
+
 #include <linux/skbuff.h>
 #include <linux/if_ether.h>
 #include <linux/netdevice.h>
@@ -119,6 +124,7 @@
 
 static struct mac_addr null_mac_addr = {{0, 0, 0, 0, 0, 0}};
 static u16 ad_ticks_per_sec;
+static const int ad_delta_in_ticks = (AD_TIMER_INTERVAL * HZ) / 1000;
 
 // ================= 3AD api to bonding and kernel code ==================
 static u16 __get_link_speed(struct port *port);
@@ -196,13 +202,11 @@
  */
 static inline struct port *__get_first_port(struct bonding *bond)
 {
-	struct slave *slave = bond->next;
-
-	if (slave == (struct slave *)bond) {
+	if (bond->slave_cnt == 0) {
 		return NULL;
 	}
 
-	return &(SLAVE_AD_INFO(slave).port);
+	return &(SLAVE_AD_INFO(bond->first_slave).port);
 }
 
 /**
@@ -218,7 +222,7 @@
 	struct slave *slave = port->slave;
 
 	// If there's no bond for this port, or this is the last slave
-	if ((bond == NULL) || (slave->next == bond->next)) {
+	if ((bond == NULL) || (slave->next == bond->first_slave)) {
 		return NULL;
 	}
 
@@ -236,12 +240,12 @@
 {
 	struct bonding *bond = __get_bond_by_port(port);
 
-	// If there's no bond for this port, or this is the last slave
-	if ((bond == NULL) || (bond->next == (struct slave *)bond)) {
+	// If there's no bond for this port, or bond has no slaves
+	if ((bond == NULL) || (bond->slave_cnt == 0)) {
 		return NULL;
 	}
 
-	return &(SLAVE_AD_INFO(bond->next).aggregator);
+	return &(SLAVE_AD_INFO(bond->first_slave).aggregator);
 }
 
 /**
@@ -257,7 +261,7 @@
 	struct bonding *bond = bond_get_bond_by_slave(slave);
 
 	// If there's no bond for this aggregator, or this is the last slave
-	if ((bond == NULL) || (slave->next == bond->next)) {
+	if ((bond == NULL) || (slave->next == bond->first_slave)) {
 		return NULL;
 	}
 
@@ -392,7 +396,7 @@
 		}
 	}
 
-	BOND_PRINT_DBG(("Port %d Received link speed %d update from adapter", port->actor_port_number, speed));
+	dprintk("Port %d Received link speed %d update from adapter\n", port->actor_port_number, speed);
 	return speed;
 }
 
@@ -418,12 +422,12 @@
 		switch (slave->duplex) {
 		case DUPLEX_FULL:
 			retval=0x1;
-			BOND_PRINT_DBG(("Port %d Received status full duplex update from adapter", port->actor_port_number));
+			dprintk("Port %d Received status full duplex update from adapter\n", port->actor_port_number);
 			break;
 		case DUPLEX_HALF:
 		default:
 			retval=0x0;
-			BOND_PRINT_DBG(("Port %d Received status NOT full duplex update from adapter", port->actor_port_number));
+			dprintk("Port %d Received status NOT full duplex update from adapter\n", port->actor_port_number);
 			break;
 		}
 	}
@@ -1059,7 +1063,7 @@
 
 	// check if the state machine was changed
 	if (port->sm_mux_state != last_state) {
-		BOND_PRINT_DBG(("Mux Machine: Port=%d, Last State=%d, Curr State=%d", port->actor_port_number, last_state, port->sm_mux_state));
+		dprintk("Mux Machine: Port=%d, Last State=%d, Curr State=%d\n", port->actor_port_number, last_state, port->sm_mux_state);
 		switch (port->sm_mux_state) {
 		case AD_MUX_DETACHED:
 			__detach_bond_from_agg(port);
@@ -1158,7 +1162,7 @@
 
 	// check if the State machine was changed or new lacpdu arrived
 	if ((port->sm_rx_state != last_state) || (lacpdu)) {
-		BOND_PRINT_DBG(("Rx Machine: Port=%d, Last State=%d, Curr State=%d", port->actor_port_number, last_state, port->sm_rx_state));
+		dprintk("Rx Machine: Port=%d, Last State=%d, Curr State=%d\n", port->actor_port_number, last_state, port->sm_rx_state);
 		switch (port->sm_rx_state) {
 		case AD_RX_INITIALIZE:
 			if (!(port->actor_oper_port_key & AD_DUPLEX_KEY_BITS)) {
@@ -1204,7 +1208,7 @@
 			// detect loopback situation
 			if (!MAC_ADDRESS_COMPARE(&(lacpdu->actor_system), &(port->actor_system))) {
 				// INFO_RECEIVED_LOOPBACK_FRAMES
-				printk(KERN_ERR "bonding: An illegal loopback occurred on adapter (%s)\n",
+				printk(KERN_ERR DRV_NAME ": An illegal loopback occurred on adapter (%s)\n",
 						port->slave->dev->name);
 				printk(KERN_ERR "Check the configuration to verify that all Adapters "
 						"are connected to 802.3ad compliant switch ports\n");
@@ -1245,7 +1249,7 @@
 			__update_lacpdu_from_port(port);
 			// send the lacpdu
 			if (ad_lacpdu_send(port) >= 0) {
-				BOND_PRINT_DBG(("Sent LACPDU on port %d", port->actor_port_number));
+				dprintk("Sent LACPDU on port %d\n", port->actor_port_number);
 				// mark ntt as false, so it will not be sent again until demanded
 				port->ntt = 0;
 			}
@@ -1318,7 +1322,7 @@
 
 	// check if the state machine was changed
 	if (port->sm_periodic_state != last_state) {
-		BOND_PRINT_DBG(("Periodic Machine: Port=%d, Last State=%d, Curr State=%d", port->actor_port_number, last_state, port->sm_periodic_state));
+		dprintk("Periodic Machine: Port=%d, Last State=%d, Curr State=%d\n", port->actor_port_number, last_state, port->sm_periodic_state);
 		switch (port->sm_periodic_state) {
 		case AD_NO_PERIODIC:
 			port->sm_periodic_timer_counter = 0;	   // zero timer
@@ -1375,7 +1379,7 @@
 				port->next_port_in_aggregator=NULL;
 				port->actor_port_aggregator_identifier=0;
 
-				BOND_PRINT_DBG(("Port %d left LAG %d", port->actor_port_number, temp_aggregator->aggregator_identifier));
+				dprintk("Port %d left LAG %d\n", port->actor_port_number, temp_aggregator->aggregator_identifier);
 				// if the aggregator is empty, clear its parameters, and set it ready to be attached
 				if (!temp_aggregator->lag_ports) {
 					ad_clear_agg(temp_aggregator);
@@ -1384,7 +1388,7 @@
 			}
 		}
 		if (!curr_port) { // meaning: the port was related to an aggregator but was not on the aggregator port list
-			printk(KERN_WARNING "bonding: Warning: Port %d (on %s) was "
+			printk(KERN_WARNING DRV_NAME ": Warning: Port %d (on %s) was "
 			       "related to aggregator %d but was not on its port list\n",
 			       port->actor_port_number, port->slave->dev->name,
 			       port->aggregator->aggregator_identifier);
@@ -1417,7 +1421,7 @@
 			port->next_port_in_aggregator=aggregator->lag_ports;
 			port->aggregator->num_of_ports++;
 			aggregator->lag_ports=port;
-			BOND_PRINT_DBG(("Port %d joined LAG %d(existing LAG)", port->actor_port_number, port->aggregator->aggregator_identifier));
+			dprintk("Port %d joined LAG %d(existing LAG)\n", port->actor_port_number, port->aggregator->aggregator_identifier);
 
 			// mark this port as selected
 			port->sm_vars |= AD_PORT_SELECTED;
@@ -1454,9 +1458,9 @@
 			// mark this port as selected
 			port->sm_vars |= AD_PORT_SELECTED;
 
-			BOND_PRINT_DBG(("Port %d joined LAG %d(new LAG)", port->actor_port_number, port->aggregator->aggregator_identifier));
+			dprintk("Port %d joined LAG %d(new LAG)\n", port->actor_port_number, port->aggregator->aggregator_identifier);
 		} else {
-			printk(KERN_ERR "bonding: Port %d (on %s) did not find a suitable aggregator\n",
+			printk(KERN_ERR DRV_NAME ": Port %d (on %s) did not find a suitable aggregator\n",
 			       port->actor_port_number, port->slave->dev->name);
 		}
 	}
@@ -1580,30 +1584,30 @@
 		    aggregator;
 		    aggregator = __get_next_agg(aggregator)) {
 
-			BOND_PRINT_DBG(("Agg=%d; Ports=%d; a key=%d; p key=%d; Indiv=%d; Active=%d",
+			dprintk("Agg=%d; Ports=%d; a key=%d; p key=%d; Indiv=%d; Active=%d\n",
 					aggregator->aggregator_identifier, aggregator->num_of_ports,
 					aggregator->actor_oper_aggregator_key, aggregator->partner_oper_aggregator_key,
-					aggregator->is_individual, aggregator->is_active));
+					aggregator->is_individual, aggregator->is_active);
 		}
 
 		// check if any partner replys
 		if (best_aggregator->is_individual) {
-			printk(KERN_WARNING "bonding: Warning: No 802.3ad response from the link partner "
+			printk(KERN_WARNING DRV_NAME ": Warning: No 802.3ad response from the link partner "
 					"for any adapters in the bond\n");
 		}
 
 		// check if there are more than one aggregator
 		if (num_of_aggs > 1) {
-			BOND_PRINT_DBG(("Warning: More than one Link Aggregation Group was "
-					"found in the bond. Only one group will function in the bond"));
+			dprintk("Warning: More than one Link Aggregation Group was "
+				"found in the bond. Only one group will function in the bond\n");
 		}
 
 		best_aggregator->is_active = 1;
-		BOND_PRINT_DBG(("LAG %d choosed as the active LAG", best_aggregator->aggregator_identifier));
-		BOND_PRINT_DBG(("Agg=%d; Ports=%d; a key=%d; p key=%d; Indiv=%d; Active=%d",
+		dprintk("LAG %d choosed as the active LAG\n", best_aggregator->aggregator_identifier);
+		dprintk("Agg=%d; Ports=%d; a key=%d; p key=%d; Indiv=%d; Active=%d\n",
 				best_aggregator->aggregator_identifier, best_aggregator->num_of_ports,
 				best_aggregator->actor_oper_aggregator_key, best_aggregator->partner_oper_aggregator_key,
-				best_aggregator->is_individual, best_aggregator->is_active));
+				best_aggregator->is_individual, best_aggregator->is_active);
 
 		// disable the ports that were related to the former active_aggregator
 		if (last_active_aggregator) {
@@ -1644,7 +1648,7 @@
 		aggregator->lag_ports = NULL;
 		aggregator->is_active = 0;
 		aggregator->num_of_ports = 0;
-		BOND_PRINT_DBG(("LAG %d was cleared", aggregator->aggregator_identifier));
+		dprintk("LAG %d was cleared\n", aggregator->aggregator_identifier);
 	}
 }
 
@@ -1729,7 +1733,7 @@
 static void ad_enable_collecting_distributing(struct port *port)
 {
 	if (port->aggregator->is_active) {
-		BOND_PRINT_DBG(("Enabling port %d(LAG %d)", port->actor_port_number, port->aggregator->aggregator_identifier));
+		dprintk("Enabling port %d(LAG %d)\n", port->actor_port_number, port->aggregator->aggregator_identifier);
 		__enable_port(port);
 	}
 }
@@ -1742,7 +1746,7 @@
 static void ad_disable_collecting_distributing(struct port *port)
 {
 	if (port->aggregator && MAC_ADDRESS_COMPARE(&(port->aggregator->partner_system), &(null_mac_addr))) {
-		BOND_PRINT_DBG(("Disabling port %d(LAG %d)", port->actor_port_number, port->aggregator->aggregator_identifier));
+		dprintk("Disabling port %d(LAG %d)\n", port->actor_port_number, port->aggregator->aggregator_identifier);
 		__disable_port(port);
 	}
 }
@@ -1780,7 +1784,7 @@
 
 	// send the marker information
 	if (ad_marker_send(port, &marker) >= 0) {
-		BOND_PRINT_DBG(("Sent Marker Information on port %d", port->actor_port_number));
+		dprintk("Sent Marker Information on port %d\n", port->actor_port_number);
 	}
 }
 #endif
@@ -1803,7 +1807,7 @@
 	// send the marker response
 
 	if (ad_marker_send(port, &marker) >= 0) {
-		BOND_PRINT_DBG(("Sent Marker Response on port %d", port->actor_port_number));
+		dprintk("Sent Marker Response on port %d\n", port->actor_port_number);
 	}
 }
 
@@ -1890,13 +1894,13 @@
 void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution, int lacp_fast)
 {                         
 	// check that the bond is not initialized yet
-	if (MAC_ADDRESS_COMPARE(&(BOND_AD_INFO(bond).system.sys_mac_addr), &(bond->device->dev_addr))) {
+	if (MAC_ADDRESS_COMPARE(&(BOND_AD_INFO(bond).system.sys_mac_addr), &(bond->dev->dev_addr))) {
 
 		aggregator_identifier = 0;
 
 		BOND_AD_INFO(bond).lacp_fast = lacp_fast;
 		BOND_AD_INFO(bond).system.sys_priority = 0xFFFF;
-		BOND_AD_INFO(bond).system.sys_mac_addr = *((struct mac_addr *)bond->device->dev_addr);
+		BOND_AD_INFO(bond).system.sys_mac_addr = *((struct mac_addr *)bond->dev->dev_addr);
 
 		// initialize how many times this module is called in one second(should be about every 100ms)
 		ad_ticks_per_sec = tick_resolution;
@@ -1921,7 +1925,7 @@
 	struct aggregator *aggregator;
 
 	if (bond == NULL) {
-		printk(KERN_CRIT "The slave %s is not attached to its bond\n", slave->dev->name);
+		printk(KERN_ERR "The slave %s is not attached to its bond\n", slave->dev->name);
 		return -1;
 	}
 
@@ -1964,7 +1968,7 @@
 
 		ad_initialize_agg(aggregator);
 
-		aggregator->aggregator_mac_address = *((struct mac_addr *)bond->device->dev_addr);
+		aggregator->aggregator_mac_address = *((struct mac_addr *)bond->dev->dev_addr);
 		aggregator->aggregator_identifier = (++aggregator_identifier);
 		aggregator->slave = slave;
 		aggregator->is_active = 0;
@@ -1996,11 +2000,11 @@
 
 	// if slave is null, the whole port is not initialized
 	if (!port->slave) {
-		printk(KERN_WARNING "bonding: Trying to unbind an uninitialized port on %s\n", slave->dev->name);
+		printk(KERN_WARNING DRV_NAME ": Trying to unbind an uninitialized port on %s\n", slave->dev->name);
 		return;
 	}
 
-	BOND_PRINT_DBG(("Unbinding Link Aggregation Group %d", aggregator->aggregator_identifier));
+	dprintk("Unbinding Link Aggregation Group %d\n", aggregator->aggregator_identifier);
 
 	/* Tell the partner that this port is not suitable for aggregation */
 	port->actor_oper_port_state &= ~AD_STATE_AGGREGATION;
@@ -2024,10 +2028,10 @@
 			// if new aggregator found, copy the aggregator's parameters
 			// and connect the related lag_ports to the new aggregator
 			if ((new_aggregator) && ((!new_aggregator->lag_ports) || ((new_aggregator->lag_ports == port) && !new_aggregator->lag_ports->next_port_in_aggregator))) {
-				BOND_PRINT_DBG(("Some port(s) related to LAG %d - replaceing with LAG %d", aggregator->aggregator_identifier, new_aggregator->aggregator_identifier));
+				dprintk("Some port(s) related to LAG %d - replaceing with LAG %d\n", aggregator->aggregator_identifier, new_aggregator->aggregator_identifier);
 
 				if ((new_aggregator->lag_ports == port) && new_aggregator->is_active) {
-					printk(KERN_INFO "bonding: Removing an active aggregator\n");
+					printk(KERN_INFO DRV_NAME ": Removing an active aggregator\n");
 					// select new active aggregator
 					 select_new_active_agg = 1;
 				}
@@ -2057,7 +2061,7 @@
 					ad_agg_selection_logic(__get_first_agg(port));
 				}
 			} else {
-				printk(KERN_WARNING "bonding: Warning: unbinding aggregator, "
+				printk(KERN_WARNING DRV_NAME ": Warning: unbinding aggregator, "
 				       "and could not find a new aggregator for its ports\n");
 			}
 		} else { // in case that the only port related to this aggregator is the one we want to remove
@@ -2072,7 +2076,7 @@
 		}
 	}
 
-	BOND_PRINT_DBG(("Unbinding port %d", port->actor_port_number));
+	dprintk("Unbinding port %d\n", port->actor_port_number);
 	// find the aggregator that this port is connected to
 	temp_aggregator = __get_first_agg(port);
 	for (; temp_aggregator; temp_aggregator = __get_next_agg(temp_aggregator)) {
@@ -2123,13 +2127,13 @@
 
 	read_lock(&bond->lock);
 
-	//check if there are any slaves
-	if (bond->next == (struct slave *)bond) {
-		goto end;
+	if (bond->kill_timers) {
+		goto out;
 	}
 
-	if ((bond->device->flags & IFF_UP) != IFF_UP) {
-		goto end;
+	//check if there are any slaves
+	if (bond->slave_cnt == 0) {
+		goto re_arm;
 	}
 
 	// check if agg_select_timer timer after initialize is timed out
@@ -2137,8 +2141,8 @@
 		// select the active aggregator for the bond
 		if ((port = __get_first_port(bond))) {
 			if (!port->slave) {
-				printk(KERN_WARNING "bonding: Warning: bond's first port is uninitialized\n");
-				goto end;
+				printk(KERN_WARNING DRV_NAME ": Warning: bond's first port is uninitialized\n");
+				goto re_arm;
 			}
 
 			aggregator = __get_first_agg(port);
@@ -2149,8 +2153,8 @@
 	// for each port run the state machines
 	for (port = __get_first_port(bond); port; port = __get_next_port(port)) {
 		if (!port->slave) {
-			printk(KERN_WARNING "bonding: Warning: Found an uninitialized port\n");
-			goto end;
+			printk(KERN_WARNING DRV_NAME ": Warning: Found an uninitialized port\n");
+			goto re_arm;
 		}
 
 		ad_rx_machine(NULL, port);
@@ -2165,14 +2169,10 @@
 		}
 	}
 
-end:
+re_arm:
+	mod_timer(&(BOND_AD_INFO(bond).ad_timer), jiffies + ad_delta_in_ticks);
+out:
 	read_unlock(&bond->lock);
-
-
-	if ((bond->device->flags & IFF_UP) == IFF_UP) {
-		/* re-arm the timer */
-		mod_timer(&(BOND_AD_INFO(bond).ad_timer), jiffies + (AD_TIMER_INTERVAL * HZ / 1000));
-	}
 }
 
 /**
@@ -2194,14 +2194,14 @@
 		port = &(SLAVE_AD_INFO(slave).port);
 
 		if (!port->slave) {
-			printk(KERN_WARNING "bonding: Warning: port of slave %s is uninitialized\n", slave->dev->name);
+			printk(KERN_WARNING DRV_NAME ": Warning: port of slave %s is uninitialized\n", slave->dev->name);
 			return;
 		}
 
 		switch (lacpdu->subtype) {
 		case AD_TYPE_LACPDU:
 			__ntohs_lacpdu(lacpdu);
-			BOND_PRINT_DBG(("Received LACPDU on port %d", port->actor_port_number));
+			dprintk("Received LACPDU on port %d\n", port->actor_port_number);
 			ad_rx_machine(lacpdu, port);
 			break;
 
@@ -2210,17 +2210,17 @@
 
 			switch (((struct marker *)lacpdu)->tlv_type) {
 			case AD_MARKER_INFORMATION_SUBTYPE:
-				BOND_PRINT_DBG(("Received Marker Information on port %d", port->actor_port_number));
+				dprintk("Received Marker Information on port %d\n", port->actor_port_number);
 				ad_marker_info_received((struct marker *)lacpdu, port);
 				break;
 
 			case AD_MARKER_RESPONSE_SUBTYPE:
-				BOND_PRINT_DBG(("Received Marker Response on port %d", port->actor_port_number));
+				dprintk("Received Marker Response on port %d\n", port->actor_port_number);
 				ad_marker_response_received((struct marker *)lacpdu, port);
 				break;
 
 			default:
-				BOND_PRINT_DBG(("Received an unknown Marker subtype on slot %d", port->actor_port_number));
+				dprintk("Received an unknown Marker subtype on slot %d\n", port->actor_port_number);
 			}
 		}
 	}
@@ -2240,14 +2240,14 @@
 
 	// if slave is null, the whole port is not initialized
 	if (!port->slave) {
-		printk(KERN_WARNING "bonding: Warning: speed changed for uninitialized port on %s\n",
+		printk(KERN_WARNING DRV_NAME ": Warning: speed changed for uninitialized port on %s\n",
 		       slave->dev->name);
 		return;
 	}
 
 	port->actor_admin_port_key &= ~AD_SPEED_KEY_BITS;
 	port->actor_oper_port_key=port->actor_admin_port_key |= (__get_link_speed(port) << 1);
-	BOND_PRINT_DBG(("Port %d changed speed", port->actor_port_number));
+	dprintk("Port %d changed speed\n", port->actor_port_number);
 	// there is no need to reselect a new aggregator, just signal the
 	// state machines to reinitialize
 	port->sm_vars |= AD_PORT_BEGIN;
@@ -2267,14 +2267,14 @@
 
 	// if slave is null, the whole port is not initialized
 	if (!port->slave) {
-		printk(KERN_WARNING "bonding: Warning: duplex changed for uninitialized port on %s\n",
+		printk(KERN_WARNING DRV_NAME ": Warning: duplex changed for uninitialized port on %s\n",
 		       slave->dev->name);
 		return;
 	}
 
 	port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS;
 	port->actor_oper_port_key=port->actor_admin_port_key |= __get_duplex(port);
-	BOND_PRINT_DBG(("Port %d changed duplex", port->actor_port_number));
+	dprintk("Port %d changed duplex\n", port->actor_port_number);
 	// there is no need to reselect a new aggregator, just signal the
 	// state machines to reinitialize
 	port->sm_vars |= AD_PORT_BEGIN;
@@ -2295,10 +2295,8 @@
 
 	// if slave is null, the whole port is not initialized
 	if (!port->slave) {
-#ifdef BONDING_DEBUG
-		printk(KERN_WARNING "bonding: Warning: link status changed for uninitialized port on %s\n",
-		       slave->dev->name);
-#endif
+		printk(KERN_WARNING DRV_NAME ": Warning: link status changed for uninitialized port on %s\n",
+			slave->dev->name);
 		return;
 	}
 
@@ -2356,41 +2354,28 @@
 
 int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
 {
-	slave_t *slave, *start_at;
-	struct bonding *bond = (struct bonding *) dev->priv;
+	struct slave *slave, *start_at;
+	struct bonding *bond = dev->priv;
 	struct ethhdr *data = (struct ethhdr *)skb->data;
 	int slave_agg_no;
 	int slaves_in_agg;
 	int agg_id;
+	int i;
 	struct ad_info ad_info;
+	int res = 1;
 
-	if (!IS_UP(dev)) { /* bond down */
-		dev_kfree_skb(skb);
-		return 0;
-	}
-
-	if (bond == NULL) {
-		printk(KERN_CRIT "bonding: Error: bond is NULL on device %s\n", dev->name);
-		dev_kfree_skb(skb);
-		return 0;
-	}
-
+	/* make sure that the slaves list will
+	 * not change during tx
+	 */
 	read_lock(&bond->lock);
-	slave = bond->prev;
 
-	/* check if bond is empty */
-	if ((slave == (struct slave *) bond) || (bond->slave_cnt == 0)) {
-		printk(KERN_DEBUG "ERROR: bond is empty\n");
-		dev_kfree_skb(skb);
-		read_unlock(&bond->lock);
-		return 0;
+	if (!BOND_IS_OK(bond)) {
+		goto out;
 	}
 
 	if (bond_3ad_get_active_agg_info(bond, &ad_info)) {
 		printk(KERN_DEBUG "ERROR: bond_3ad_get_active_agg_info failed\n");
-		dev_kfree_skb(skb);
-		read_unlock(&bond->lock);
-		return 0;
+		goto out;
 	}
 
 	slaves_in_agg = ad_info.ports;
@@ -2399,21 +2384,12 @@
 	if (slaves_in_agg == 0) {
 		/*the aggregator is empty*/
 		printk(KERN_DEBUG "ERROR: active aggregator is empty\n");
-		dev_kfree_skb(skb);
-		read_unlock(&bond->lock);
-		return 0;
+		goto out;
 	}
 
-	/* we're at the root, get the first slave */
-	if ((slave == NULL) || (slave->dev == NULL)) {
-		/* no suitable interface, frame not sent */
-		dev_kfree_skb(skb);
-		read_unlock(&bond->lock);
-		return 0;
-	}
+	slave_agg_no = (data->h_dest[5]^bond->dev->dev_addr[5]) % slaves_in_agg;
 
-	slave_agg_no = (data->h_dest[5]^slave->dev->dev_addr[5]) % slaves_in_agg;
-	while (slave != (slave_t *)bond) {
+	bond_for_each_slave(bond, slave, i) {
 		struct aggregator *agg = SLAVE_AD_INFO(slave).port.aggregator;
 
 		if (agg && (agg->aggregator_identifier == agg_id)) {
@@ -2422,61 +2398,41 @@
 				break;
 			}
 		}
-
-		slave = slave->prev;
-		if (slave == NULL) {
-			printk(KERN_ERR "bonding: Error: slave is NULL\n");
-			dev_kfree_skb(skb);
-			read_unlock(&bond->lock);
-			return 0;
-		}
 	}
 
-	if (slave == (slave_t *)bond) {
-		printk(KERN_ERR "bonding: Error: Couldn't find a slave to tx on for aggregator ID %d\n", agg_id);
-		dev_kfree_skb(skb);
-		read_unlock(&bond->lock);
-		return 0;
+	if (slave_agg_no >= 0) {
+		printk(KERN_ERR DRV_NAME ": Error: Couldn't find a slave to tx on for aggregator ID %d\n", agg_id);
+		goto out;
 	}
 
 	start_at = slave;
 
-	do {
+	bond_for_each_slave_from(bond, slave, i, start_at) {
 		int slave_agg_id = 0;
-		struct aggregator *agg;
-
-		if (slave == NULL) {
-			printk(KERN_ERR "bonding: Error: slave is NULL\n");
-			dev_kfree_skb(skb);
-			read_unlock(&bond->lock);
-			return 0;
-		}
-
-		agg = SLAVE_AD_INFO(slave).port.aggregator;
+		struct aggregator *agg = SLAVE_AD_INFO(slave).port.aggregator;
 
 		if (agg) {
 			slave_agg_id = agg->aggregator_identifier;
 		}
 
-		if (SLAVE_IS_OK(slave) && 
-		    agg && (slave_agg_id == agg_id)) {
-			skb->dev = slave->dev;			
-			skb->priority = 1;
-			dev_queue_xmit(skb);
-			read_unlock(&bond->lock);
-			return 0;
+		if (SLAVE_IS_OK(slave) && agg && (slave_agg_id == agg_id)) {
+			res = bond_dev_queue_xmit(bond, skb, slave->dev);
+			break;
 		}
-	} while ((slave = slave->next) != start_at);
+	}
 
-	/* no suitable interface, frame not sent */
-	dev_kfree_skb(skb);
+out:
+	if (res) {
+		/* no suitable interface, frame not sent */
+		dev_kfree_skb(skb);
+	}
 	read_unlock(&bond->lock);
 	return 0;
 }
 
 int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type* ptype)
 {
-	struct bonding *bond = (struct bonding *)dev->priv;
+	struct bonding *bond = dev->priv;
 	struct slave *slave = NULL;
 	int ret = NET_RX_DROP;
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)