⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bond_3ad.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
			port->sm_vars |= AD_PORT_SELECTED;			dprintk("Port %d joined LAG %d(new LAG)\n", port->actor_port_number, port->aggregator->aggregator_identifier);		} else {			printk(KERN_ERR DRV_NAME ": Port %d (on %s) did not find a suitable aggregator\n",			       port->actor_port_number, port->slave->dev->name);		}	}	// if all aggregator's ports are READY_N == TRUE, set ready=TRUE in all aggregator's ports	// else set ready=FALSE in all aggregator's ports	__set_agg_ports_ready(port->aggregator, __agg_ports_are_ready(port->aggregator));	if (!__check_agg_selection_timer(port) && (aggregator = __get_first_agg(port))) {		ad_agg_selection_logic(aggregator);	}}/** * ad_agg_selection_logic - select an aggregation group for a team * @aggregator: the aggregator we're looking at * * It is assumed that only one aggregator may be selected for a team. * The logic of this function is to select (at first time) the aggregator with * the most ports attached to it, and to reselect the active aggregator only if * the previous aggregator has no more ports related to it. * * FIXME: this function MUST be called with the first agg in the bond, or * __get_active_agg() won't work correctly. This function should be better * called with the bond itself, and retrieve the first agg from it. */static void ad_agg_selection_logic(struct aggregator *aggregator){	struct aggregator *best_aggregator = NULL, *active_aggregator = NULL;	struct aggregator *last_active_aggregator = NULL, *origin_aggregator;	struct port *port;	u16 num_of_aggs=0;	origin_aggregator = aggregator;	//get current active aggregator	last_active_aggregator = __get_active_agg(aggregator);	// search for the aggregator with the most ports attached to it.	do {		// count how many candidate lag's we have		if (aggregator->lag_ports) {			num_of_aggs++;		}		if (aggregator->is_active && !aggregator->is_individual &&   // if current aggregator is the active aggregator		    MAC_ADDRESS_COMPARE(&(aggregator->partner_system), &(null_mac_addr))) {   // and partner answers to 802.3ad PDUs			if (aggregator->num_of_ports) {	// if any ports attached to the current aggregator				best_aggregator=NULL;	 // disregard the best aggregator that was chosen by now				break;		 // stop the selection of other aggregator if there are any ports attached to this active aggregator			} else { // no ports attached to this active aggregator				aggregator->is_active = 0; // mark this aggregator as not active anymore			}		}		if (aggregator->num_of_ports) {	// if any ports attached			if (best_aggregator) {	// if there is a candidte aggregator				//The reasons for choosing new best aggregator:				// 1. if current agg is NOT individual and the best agg chosen so far is individual OR				// current and best aggs are both individual or both not individual, AND				// 2a.  current agg partner reply but best agg partner do not reply OR				// 2b.  current agg partner reply OR current agg partner do not reply AND best agg partner also do not reply AND				//      current has more ports/bandwidth, or same amount of ports but current has faster ports, THEN				//      current agg become best agg so far				//if current agg is NOT individual and the best agg chosen so far is individual change best_aggregator				if (!aggregator->is_individual && best_aggregator->is_individual) {					best_aggregator=aggregator;				}				// current and best aggs are both individual or both not individual				else if ((aggregator->is_individual && best_aggregator->is_individual) ||					 (!aggregator->is_individual && !best_aggregator->is_individual)) {					//  current and best aggs are both individual or both not individual AND					//  current agg partner reply but best agg partner do not reply					if ((MAC_ADDRESS_COMPARE(&(aggregator->partner_system), &(null_mac_addr)) &&					     !MAC_ADDRESS_COMPARE(&(best_aggregator->partner_system), &(null_mac_addr)))) {						best_aggregator=aggregator;					}					//  current agg partner reply OR current agg partner do not reply AND best agg partner also do not reply					else if (! (!MAC_ADDRESS_COMPARE(&(aggregator->partner_system), &(null_mac_addr)) &&						    MAC_ADDRESS_COMPARE(&(best_aggregator->partner_system), &(null_mac_addr)))) {						if ((__get_agg_selection_mode(aggregator->lag_ports) == AD_BANDWIDTH)&&						    (__get_agg_bandwidth(aggregator) > __get_agg_bandwidth(best_aggregator))) {							best_aggregator=aggregator;						} else if (__get_agg_selection_mode(aggregator->lag_ports) == AD_COUNT) {							if (((aggregator->num_of_ports > best_aggregator->num_of_ports) &&							     (aggregator->actor_oper_aggregator_key & AD_SPEED_KEY_BITS))||							    ((aggregator->num_of_ports == best_aggregator->num_of_ports) &&							     ((u16)(aggregator->actor_oper_aggregator_key & AD_SPEED_KEY_BITS) >							      (u16)(best_aggregator->actor_oper_aggregator_key & AD_SPEED_KEY_BITS)))) {								best_aggregator=aggregator;							}						}					}				}			} else {				best_aggregator=aggregator;			}		}		aggregator->is_active = 0; // mark all aggregators as not active anymore	} while ((aggregator = __get_next_agg(aggregator)));	// if we have new aggregator selected, don't replace the old aggregator if it has an answering partner,	// or if both old aggregator and new aggregator don't have answering partner	if (best_aggregator) {		if (last_active_aggregator && last_active_aggregator->lag_ports && last_active_aggregator->lag_ports->is_enabled &&		    (MAC_ADDRESS_COMPARE(&(last_active_aggregator->partner_system), &(null_mac_addr)) ||   // partner answers OR		     (!MAC_ADDRESS_COMPARE(&(last_active_aggregator->partner_system), &(null_mac_addr)) &&	// both old and new		      !MAC_ADDRESS_COMPARE(&(best_aggregator->partner_system), &(null_mac_addr))))     // partner do not answer		   ) {			// if new aggregator has link, and old aggregator does not, replace old aggregator.(do nothing)			// -> don't replace otherwise.			if (!(!last_active_aggregator->actor_oper_aggregator_key && best_aggregator->actor_oper_aggregator_key)) {				best_aggregator=NULL;				last_active_aggregator->is_active = 1; // don't replace good old aggregator			}		}	}	// if there is new best aggregator, activate it	if (best_aggregator) {		for (aggregator = __get_first_agg(best_aggregator->lag_ports);		    aggregator;		    aggregator = __get_next_agg(aggregator)) {			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);		}		// check if any partner replys		if (best_aggregator->is_individual) {			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) {			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;		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);		// disable the ports that were related to the former active_aggregator		if (last_active_aggregator) {			for (port=last_active_aggregator->lag_ports; port; port=port->next_port_in_aggregator) {				__disable_port(port);			}		}	}	// if the selected aggregator is of join individuals(partner_system is NULL), enable their ports	active_aggregator = __get_active_agg(origin_aggregator);	if (active_aggregator) {		if (!MAC_ADDRESS_COMPARE(&(active_aggregator->partner_system), &(null_mac_addr))) {			for (port=active_aggregator->lag_ports; port; port=port->next_port_in_aggregator) {				__enable_port(port);			}		}	}}/** * ad_clear_agg - clear a given aggregator's parameters * @aggregator: the aggregator we're looking at * */static void ad_clear_agg(struct aggregator *aggregator){	if (aggregator) {		aggregator->is_individual = 0;		aggregator->actor_admin_aggregator_key = 0;		aggregator->actor_oper_aggregator_key = 0;		aggregator->partner_system = null_mac_addr;		aggregator->partner_system_priority = 0;		aggregator->partner_oper_aggregator_key = 0;		aggregator->receive_state = 0;		aggregator->transmit_state = 0;		aggregator->lag_ports = NULL;		aggregator->is_active = 0;		aggregator->num_of_ports = 0;		dprintk("LAG %d was cleared\n", aggregator->aggregator_identifier);	}}/** * ad_initialize_agg - initialize a given aggregator's parameters * @aggregator: the aggregator we're looking at * */static void ad_initialize_agg(struct aggregator *aggregator){	if (aggregator) {		ad_clear_agg(aggregator);		aggregator->aggregator_mac_address = null_mac_addr;		aggregator->aggregator_identifier = 0;		aggregator->slave = NULL;	}}/** * ad_initialize_port - initialize a given port's parameters * @aggregator: the aggregator we're looking at * @lacp_fast: boolean. whether fast periodic should be used * */static void ad_initialize_port(struct port *port, int lacp_fast){	if (port) {		port->actor_port_number = 1;		port->actor_port_priority = 0xff;		port->actor_system = null_mac_addr;		port->actor_system_priority = 0xffff;		port->actor_port_aggregator_identifier = 0;		port->ntt = 0;		port->actor_admin_port_key = 1;		port->actor_oper_port_key  = 1;		port->actor_admin_port_state = AD_STATE_AGGREGATION | AD_STATE_LACP_ACTIVITY;		port->actor_oper_port_state  = AD_STATE_AGGREGATION | AD_STATE_LACP_ACTIVITY;		if (lacp_fast) {			port->actor_oper_port_state |= AD_STATE_LACP_TIMEOUT;		}		port->partner_admin_system = null_mac_addr;		port->partner_oper_system  = null_mac_addr;		port->partner_admin_system_priority = 0xffff;		port->partner_oper_system_priority  = 0xffff;		port->partner_admin_key = 1;		port->partner_oper_key  = 1;		port->partner_admin_port_number = 1;		port->partner_oper_port_number  = 1;		port->partner_admin_port_priority = 0xff;		port->partner_oper_port_priority  = 0xff;		port->partner_admin_port_state = 1;		port->partner_oper_port_state  = 1;		port->is_enabled = 1;		// ****** private parameters ******		port->sm_vars = 0x3;		port->sm_rx_state = 0;		port->sm_rx_timer_counter = 0;		port->sm_periodic_state = 0;		port->sm_periodic_timer_counter = 0;		port->sm_mux_state = 0;		port->sm_mux_timer_counter = 0;		port->sm_tx_state = 0;		port->sm_tx_timer_counter = 0;		port->slave = NULL;		port->aggregator = NULL;		port->next_port_in_aggregator = NULL;		port->transaction_id = 0;		ad_initialize_lacpdu(&(port->lacpdu));	}}/** * ad_enable_collecting_distributing - enable a port's transmit/receive * @port: the port we're looking at * * Enable @port if it's in an active aggregator */static void ad_enable_collecting_distributing(struct port *port){	if (port->aggregator->is_active) {		dprintk("Enabling port %d(LAG %d)\n", port->actor_port_number, port->aggregator->aggregator_identifier);		__enable_port(port);	}}/** * ad_disable_collecting_distributing - disable a port's transmit/receive * @port: the port we're looking at * */static void ad_disable_collecting_distributing(struct port *port){	if (port->aggregator && MAC_ADDRESS_COMPARE(&(port->aggregator->partner_system), &(null_mac_addr))) {		dprintk("Disabling port %d(LAG %d)\n", port->actor_port_number, port->aggregator->aggregator_identifier);		__disable_port(port);	}}#if 0/** * ad_marker_info_send - send a marker information frame * @port: the port we're looking at * * This function does nothing since we decided not to implement send and handle * response for marker PDU's, in this stage, but only to respond to marker * information. */static void ad_marker_info_send(struct port *port){	struct marker marker;	u16 index;	// fill the marker PDU with the appropriate values	marker.subtype = 0x02;	marker.version_number = 0x01;	marker.tlv_type = AD_MARKER_INFORMATION_SUBTYPE;	marker.marker_length = 0x16;	// convert requester_port to Big Endian	marker.requester_port = (((port->actor_port_number & 0xFF) << 8) |((u16)(port->actor_port_number & 0xFF00) >> 8));	marker.requester_system = port->actor_system;	// convert requester_port(u32) to Big Endian	marker.requester_transaction_id = (((++port->transaction_id & 0xFF) << 24) |((port->transaction_id & 0xFF00) << 8) |((port->transaction_id & 0xFF0000) >> 8) |((port->transaction_id & 0xFF000000) >> 24));	marker.pad = 0;	marker.tlv_type_terminator = 0x00;	marker.terminator_length = 0x00;	for (index=0; index<90; index++) {		marker.reserved_90[index]=0;	}	// send the marker information	if (ad_marker_send(port, &marker) >= 0) {		dprintk("Sent Marker Information on port %d\n", port->actor_port_number);	}}#endif/** * ad_marker_info_received - handle receive of a Marker information frame * @marker_info: Marker info received * @port: the port we're looking at * */static void ad_marker_info_received(struct marker *marker_info,struct port *port){	struct marker marker;	// copy the received marker data to the response marker	//marker = *marker_info;	memcpy(&marker, marker_info, sizeof(struct marker));	// change the marker subtype to marker response	marker.tlv_type=AD_MARKER_RESPONSE_SUBTYPE;	// send the marker response	if (ad_marker_send(port, &marker) >= 0) {		dprintk("Sent Marker Response on port %d\n", port->actor_port_number);	}}/** * ad_marker_response_received - handle receive of a marker response frame * @marker: marker PDU received * @port: the por

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -