aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bonding
diff options
context:
space:
mode:
authorJay Vosburgh <fubar@us.ibm.com>2009-11-13 08:13:01 -0500
committerDavid S. Miller <davem@davemloft.net>2009-11-16 01:21:34 -0500
commit2d6682db114cb53bc94991659478756302e6a600 (patch)
tree7854ccf1c9b0098fa84c444c07d88a360d662aa8 /drivers/net/bonding
parentb93ab837a2d3eb394082c9eae4ee0a4f83060027 (diff)
bonding: fix 802.3ad standards compliance error
The language of 802.3ad 43.4.9 requires the "recordPDU" function to, in part, compare the Partner parameter values in a received LACPDU to the stored Actor values. If those match, then the Partner's synchronization state is set to true. The current 802.3ad implementation is performing these steps out of order; first, the synchronization check is done, then the paramters are checked to see if they match (the synch check being done against a match check of a prior LACPDU). This causes delays in establishing aggregators in some circumstances. This patch modifies the 802.3ad code to call __choose_matched, the function that does the "match" comparisions, as the first step of __record_pdu, instead of immediately afterwards. This new behavior is in compliance with the language of the standard. Some additional commentary relating to code vs. standard is also added. Reported by Martin Patterson <martin@gear6.com> who also supplied the logic of the fix and verified the patch. Signed-off-by: Jay Vosburgh <fubar@us.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/bonding')
-rw-r--r--drivers/net/bonding/bond_3ad.c85
1 files changed, 43 insertions, 42 deletions
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index 1d0581923287..88c3fe80b355 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -446,6 +446,48 @@ static u16 __ad_timer_to_ticks(u16 timer_type, u16 par)
446///////////////////////////////////////////////////////////////////////////////// 446/////////////////////////////////////////////////////////////////////////////////
447 447
448/** 448/**
449 * __choose_matched - update a port's matched variable from a received lacpdu
450 * @lacpdu: the lacpdu we've received
451 * @port: the port we're looking at
452 *
453 * Update the value of the matched variable, using parameter values from a
454 * newly received lacpdu. Parameter values for the partner carried in the
455 * received PDU are compared with the corresponding operational parameter
456 * values for the actor. Matched is set to TRUE if all of these parameters
457 * match and the PDU parameter partner_state.aggregation has the same value as
458 * actor_oper_port_state.aggregation and lacp will actively maintain the link
459 * in the aggregation. Matched is also set to TRUE if the value of
460 * actor_state.aggregation in the received PDU is set to FALSE, i.e., indicates
461 * an individual link and lacp will actively maintain the link. Otherwise,
462 * matched is set to FALSE. LACP is considered to be actively maintaining the
463 * link if either the PDU's actor_state.lacp_activity variable is TRUE or both
464 * the actor's actor_oper_port_state.lacp_activity and the PDU's
465 * partner_state.lacp_activity variables are TRUE.
466 *
467 * Note: the AD_PORT_MATCHED "variable" is not specified by 802.3ad; it is
468 * used here to implement the language from 802.3ad 43.4.9 that requires
469 * recordPDU to "match" the LACPDU parameters to the stored values.
470 */
471static void __choose_matched(struct lacpdu *lacpdu, struct port *port)
472{
473 // check if all parameters are alike
474 if (((ntohs(lacpdu->partner_port) == port->actor_port_number) &&
475 (ntohs(lacpdu->partner_port_priority) == port->actor_port_priority) &&
476 !MAC_ADDRESS_COMPARE(&(lacpdu->partner_system), &(port->actor_system)) &&
477 (ntohs(lacpdu->partner_system_priority) == port->actor_system_priority) &&
478 (ntohs(lacpdu->partner_key) == port->actor_oper_port_key) &&
479 ((lacpdu->partner_state & AD_STATE_AGGREGATION) == (port->actor_oper_port_state & AD_STATE_AGGREGATION))) ||
480 // or this is individual link(aggregation == FALSE)
481 ((lacpdu->actor_state & AD_STATE_AGGREGATION) == 0)
482 ) {
483 // update the state machine Matched variable
484 port->sm_vars |= AD_PORT_MATCHED;
485 } else {
486 port->sm_vars &= ~AD_PORT_MATCHED;
487 }
488}
489
490/**
449 * __record_pdu - record parameters from a received lacpdu 491 * __record_pdu - record parameters from a received lacpdu
450 * @lacpdu: the lacpdu we've received 492 * @lacpdu: the lacpdu we've received
451 * @port: the port we're looking at 493 * @port: the port we're looking at
@@ -459,6 +501,7 @@ static void __record_pdu(struct lacpdu *lacpdu, struct port *port)
459 if (lacpdu && port) { 501 if (lacpdu && port) {
460 struct port_params *partner = &port->partner_oper; 502 struct port_params *partner = &port->partner_oper;
461 503
504 __choose_matched(lacpdu, port);
462 // record the new parameter values for the partner operational 505 // record the new parameter values for the partner operational
463 partner->port_number = ntohs(lacpdu->actor_port); 506 partner->port_number = ntohs(lacpdu->actor_port);
464 partner->port_priority = ntohs(lacpdu->actor_port_priority); 507 partner->port_priority = ntohs(lacpdu->actor_port_priority);
@@ -563,47 +606,6 @@ static void __update_default_selected(struct port *port)
563} 606}
564 607
565/** 608/**
566 * __choose_matched - update a port's matched variable from a received lacpdu
567 * @lacpdu: the lacpdu we've received
568 * @port: the port we're looking at
569 *
570 * Update the value of the matched variable, using parameter values from a
571 * newly received lacpdu. Parameter values for the partner carried in the
572 * received PDU are compared with the corresponding operational parameter
573 * values for the actor. Matched is set to TRUE if all of these parameters
574 * match and the PDU parameter partner_state.aggregation has the same value as
575 * actor_oper_port_state.aggregation and lacp will actively maintain the link
576 * in the aggregation. Matched is also set to TRUE if the value of
577 * actor_state.aggregation in the received PDU is set to FALSE, i.e., indicates
578 * an individual link and lacp will actively maintain the link. Otherwise,
579 * matched is set to FALSE. LACP is considered to be actively maintaining the
580 * link if either the PDU's actor_state.lacp_activity variable is TRUE or both
581 * the actor's actor_oper_port_state.lacp_activity and the PDU's
582 * partner_state.lacp_activity variables are TRUE.
583 */
584static void __choose_matched(struct lacpdu *lacpdu, struct port *port)
585{
586 // validate lacpdu and port
587 if (lacpdu && port) {
588 // check if all parameters are alike
589 if (((ntohs(lacpdu->partner_port) == port->actor_port_number) &&
590 (ntohs(lacpdu->partner_port_priority) == port->actor_port_priority) &&
591 !MAC_ADDRESS_COMPARE(&(lacpdu->partner_system), &(port->actor_system)) &&
592 (ntohs(lacpdu->partner_system_priority) == port->actor_system_priority) &&
593 (ntohs(lacpdu->partner_key) == port->actor_oper_port_key) &&
594 ((lacpdu->partner_state & AD_STATE_AGGREGATION) == (port->actor_oper_port_state & AD_STATE_AGGREGATION))) ||
595 // or this is individual link(aggregation == FALSE)
596 ((lacpdu->actor_state & AD_STATE_AGGREGATION) == 0)
597 ) {
598 // update the state machine Matched variable
599 port->sm_vars |= AD_PORT_MATCHED;
600 } else {
601 port->sm_vars &= ~AD_PORT_MATCHED;
602 }
603 }
604}
605
606/**
607 * __update_ntt - update a port's ntt variable from a received lacpdu 609 * __update_ntt - update a port's ntt variable from a received lacpdu
608 * @lacpdu: the lacpdu we've received 610 * @lacpdu: the lacpdu we've received
609 * @port: the port we're looking at 611 * @port: the port we're looking at
@@ -1134,7 +1136,6 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
1134 __update_selected(lacpdu, port); 1136 __update_selected(lacpdu, port);
1135 __update_ntt(lacpdu, port); 1137 __update_ntt(lacpdu, port);
1136 __record_pdu(lacpdu, port); 1138 __record_pdu(lacpdu, port);
1137 __choose_matched(lacpdu, port);
1138 port->sm_rx_timer_counter = __ad_timer_to_ticks(AD_CURRENT_WHILE_TIMER, (u16)(port->actor_oper_port_state & AD_STATE_LACP_TIMEOUT)); 1139 port->sm_rx_timer_counter = __ad_timer_to_ticks(AD_CURRENT_WHILE_TIMER, (u16)(port->actor_oper_port_state & AD_STATE_LACP_TIMEOUT));
1139 port->actor_oper_port_state &= ~AD_STATE_EXPIRED; 1140 port->actor_oper_port_state &= ~AD_STATE_EXPIRED;
1140 // verify that if the aggregator is enabled, the port is enabled too. 1141 // verify that if the aggregator is enabled, the port is enabled too.