diff options
author | Steven Luong <sluong@cisco.com> | 2019-03-05 09:38:33 -0800 |
---|---|---|
committer | Damjan Marion <dmarion@me.com> | 2019-04-03 16:32:37 +0000 |
commit | 82c5dda455ce56ffaf8813b7fbee661e6dbb7cea (patch) | |
tree | 0a4b607e46396ac28fe7f573b6b237de4ed8c16d /src/plugins/lacp | |
parent | 5ae793ac4e5b3fa288ed5838d8d92ce15eb950bd (diff) |
lacp: passive mode support [VPP-1551]
By definition, passive mode means the node does not start sending lacp pdu until
it first hears from the partner or remote.
- Rename ptx machine's BEGIN state to NO_PERIODIC state.
- Put periodic machine in NO_PERIDOIC state when the interface is enabled for
lacp. ptx machine will transition out of NO_PERIODIC state when the local node
hears from the remote or when the local node is configured for active mode.
- Also add send and receive statistics for debugging.
Change-Id: I747953b9595ed31328b2f4f3e7a8d15d01e04d7f
Signed-off-by: Steven Luong <sluong@cisco.com>
Diffstat (limited to 'src/plugins/lacp')
-rw-r--r-- | src/plugins/lacp/cli.c | 29 | ||||
-rw-r--r-- | src/plugins/lacp/input.c | 15 | ||||
-rw-r--r-- | src/plugins/lacp/lacp.c | 10 | ||||
-rw-r--r-- | src/plugins/lacp/ptx_machine.c | 97 | ||||
-rw-r--r-- | src/plugins/lacp/ptx_machine.h | 12 | ||||
-rw-r--r-- | src/plugins/lacp/rx_machine.c | 12 | ||||
-rw-r--r-- | src/plugins/lacp/tx_machine.c | 5 |
7 files changed, 124 insertions, 56 deletions
diff --git a/src/plugins/lacp/cli.c b/src/plugins/lacp/cli.c index d210139c4b4..d188db6165e 100644 --- a/src/plugins/lacp/cli.c +++ b/src/plugins/lacp/cli.c @@ -159,6 +159,29 @@ show_lacp_details (vlib_main_t * vm, u32 * sw_if_indices) continue; vlib_cli_output (vm, " %U", format_vnet_sw_if_index_name, vnet_get_main (), sif->sw_if_index); + vlib_cli_output (vm, " Good LACP PDUs received: %llu", + sif->pdu_received); + vlib_cli_output (vm, " Bad LACP PDUs received: %llu", + sif->bad_pdu_received); + vlib_cli_output (vm, " LACP PDUs sent: %llu", sif->pdu_sent); + if (lacp_timer_is_running (sif->last_lacpdu_recd_time)) + vlib_cli_output (vm, + " last LACP PDU received: %10.2f seconds ago", + now - sif->last_lacpdu_recd_time); + if (lacp_timer_is_running (sif->last_lacpdu_sent_time)) + vlib_cli_output (vm, " last LACP PDU sent: %10.2f seconds ago", + now - sif->last_lacpdu_sent_time); + vlib_cli_output (vm, " Good Marker PDUs received: %llu", + sif->marker_pdu_received); + vlib_cli_output (vm, " Bad Marker PDUs received: %llu", + sif->marker_bad_pdu_received); + if (lacp_timer_is_running (sif->last_marker_pdu_recd_time)) + vlib_cli_output (vm, + " last Marker PDU received: %10.2f seconds ago", + now - sif->last_marker_pdu_recd_time); + if (lacp_timer_is_running (sif->last_marker_pdu_sent_time)) + vlib_cli_output (vm, " last Marker PDU sent: %10.2f seconds ago", + now - sif->last_marker_pdu_sent_time); vlib_cli_output (vm, " debug: %d", sif->debug); vlib_cli_output (vm, " loopback port: %d", sif->loopback_port); vlib_cli_output (vm, " port moved: %d", sif->port_moved); @@ -209,17 +232,17 @@ show_lacp_details (vlib_main_t * vm, u32 * sw_if_indices) if (!lacp_timer_is_running (sif->wait_while_timer)) vlib_cli_output (vm, " wait while timer: not running"); else - vlib_cli_output (vm, " wait while timer: %=10.2f seconds", + vlib_cli_output (vm, " wait while timer: %10.2f seconds", sif->wait_while_timer - now); if (!lacp_timer_is_running (sif->current_while_timer)) vlib_cli_output (vm, " current while timer: not running"); else - vlib_cli_output (vm, " current while timer: %=10.2f seconds", + vlib_cli_output (vm, " current while timer: %10.2f seconds", sif->current_while_timer - now); if (!lacp_timer_is_running (sif->periodic_timer)) vlib_cli_output (vm, " periodic timer: not running"); else - vlib_cli_output (vm, " periodic timer: %=10.2f seconds", + vlib_cli_output (vm, " periodic timer: %10.2f seconds", sif->periodic_timer - now); vlib_cli_output (vm, " RX-state: %U", format_rx_sm_state, sif->rx_state); diff --git a/src/plugins/lacp/input.c b/src/plugins/lacp/input.c index 9b1f3b68abf..8212b119784 100644 --- a/src/plugins/lacp/input.c +++ b/src/plugins/lacp/input.c @@ -108,6 +108,8 @@ send_ethernet_marker_response_pdu (slave_if_t * sif) f->n_vectors = 1; vlib_put_frame_to_node (vm, hw->output_node_index, f); + sif->last_marker_pdu_sent_time = vlib_time_now (lm->vlib_main); + sif->marker_pdu_sent++; } static int @@ -153,6 +155,7 @@ lacp_input (vlib_main_t * vm, vlib_buffer_t * b0, u32 bi0) marker = (marker_pdu_t *) (b0->data + b0->current_data); if (marker->subtype == MARKER_SUBTYPE) { + sif->last_marker_pdu_recd_time = vlib_time_now (lm->vlib_main); if (sif->last_marker_pkt) _vec_len (sif->last_marker_pkt) = 0; vec_validate (sif->last_marker_pkt, @@ -160,8 +163,13 @@ lacp_input (vlib_main_t * vm, vlib_buffer_t * b0, u32 bi0) nbytes = vlib_buffer_contents (vm, bi0, sif->last_marker_pkt); ASSERT (nbytes <= vec_len (sif->last_marker_pkt)); if (nbytes < sizeof (lacp_pdu_t)) - return LACP_ERROR_TOO_SMALL; - return (handle_marker_protocol (vm, sif)); + { + sif->marker_bad_pdu_received++; + return LACP_ERROR_TOO_SMALL; + } + e = handle_marker_protocol (vm, sif); + sif->marker_pdu_received++; + return e; } /* @@ -185,8 +193,10 @@ lacp_input (vlib_main_t * vm, vlib_buffer_t * b0, u32 bi0) nbytes = vlib_buffer_contents (vm, bi0, sif->last_rx_pkt); ASSERT (nbytes <= vec_len (sif->last_rx_pkt)); + sif->last_lacpdu_recd_time = vlib_time_now (lm->vlib_main); if (nbytes < sizeof (lacp_pdu_t)) { + sif->bad_pdu_received++; return LACP_ERROR_TOO_SMALL; } @@ -209,6 +219,7 @@ lacp_input (vlib_main_t * vm, vlib_buffer_t * b0, u32 bi0) sif->last_packet_signature_valid = 1; sif->last_packet_signature = last_packet_signature; } + sif->pdu_received++; if (sif->last_rx_pkt) _vec_len (sif->last_rx_pkt) = 0; diff --git a/src/plugins/lacp/lacp.c b/src/plugins/lacp/lacp.c index 473458af4e4..0ecb1df7329 100644 --- a/src/plugins/lacp/lacp.c +++ b/src/plugins/lacp/lacp.c @@ -89,7 +89,8 @@ lacp_send_ethernet_lacp_pdu (slave_if_t * sif) vlib_put_frame_to_node (vm, hw->output_node_index, f); - sif->last_lacpdu_time = vlib_time_now (lm->vlib_main); + sif->last_lacpdu_sent_time = vlib_time_now (lm->vlib_main); + sif->pdu_sent++; } /* @@ -307,7 +308,10 @@ lacp_init_neighbor (slave_if_t * sif, u8 * hw_address, u16 port_number, lacp_stop_timer (&sif->actor_churn_timer); lacp_stop_timer (&sif->partner_churn_timer); lacp_stop_timer (&sif->periodic_timer); - lacp_stop_timer (&sif->last_lacpdu_time); + lacp_stop_timer (&sif->last_lacpdu_sent_time); + lacp_stop_timer (&sif->last_lacpdu_recd_time); + lacp_stop_timer (&sif->last_marker_pdu_sent_time); + lacp_stop_timer (&sif->last_marker_pdu_recd_time); sif->lacp_enabled = 1; sif->loopback_port = 0; sif->ready = 0; @@ -331,7 +335,7 @@ lacp_init_neighbor (slave_if_t * sif, u8 * hw_address, u16 port_number, sif->partner.port_number = htons (port_number); sif->partner.port_priority = htons (LACP_DEFAULT_PORT_PRIORITY); sif->partner.key = htons (group); - sif->partner.state = LACP_STATE_LACP_ACTIVITY; + sif->partner.state = 0; sif->actor_admin = sif->actor; sif->partner_admin = sif->partner; diff --git a/src/plugins/lacp/ptx_machine.c b/src/plugins/lacp/ptx_machine.c index 5a1c6d88621..7e604cc489d 100644 --- a/src/plugins/lacp/ptx_machine.c +++ b/src/plugins/lacp/ptx_machine.c @@ -22,17 +22,17 @@ * LACP State = NO_PERIODIC */ static lacp_fsm_state_t lacp_ptx_state_no_periodic[] = { - {LACP_ACTION_NO_PERIODIC, LACP_PTX_STATE_FAST_PERIODIC}, // event 0 BEGIN - {LACP_NOACTION, LACP_PTX_STATE_NO_PERIODIC}, // event 1 LONG_TIMEOUT - {LACP_NOACTION, LACP_PTX_STATE_NO_PERIODIC}, // event 2 TIMER_EXPIRED - {LACP_NOACTION, LACP_PTX_STATE_NO_PERIODIC}, // event 3 SHORT_TIMEOUT + {LACP_ACTION_NO_PERIODIC, LACP_PTX_STATE_NO_PERIODIC}, // event 0 NO_PERIODIC + {LACP_ACTION_SLOW_PERIODIC, LACP_PTX_STATE_SLOW_PERIODIC}, // event 1 LONG_TIMEOUT + {LACP_ACTION_NO_PERIODIC, LACP_PTX_STATE_NO_PERIODIC}, // event 2 TIMER_EXPIRED + {LACP_ACTION_FAST_PERIODIC, LACP_PTX_STATE_FAST_PERIODIC}, // event 3 SHORT_TIMEOUT }; /* * LACP State = FAST_PERIODIC */ static lacp_fsm_state_t lacp_ptx_state_fast_periodic[] = { - {LACP_ACTION_FAST_PERIODIC, LACP_PTX_STATE_FAST_PERIODIC}, // event 0 BEGIN + {LACP_ACTION_NO_PERIODIC, LACP_PTX_STATE_NO_PERIODIC}, // event 0 NO_PERIODIC {LACP_ACTION_SLOW_PERIODIC, LACP_PTX_STATE_SLOW_PERIODIC}, // event 1 LONG_TIMEOUT {LACP_ACTION_TIMER_EXPIRED, LACP_PTX_STATE_PERIODIC_TX}, // event 2 TIMER_EXPIRED {LACP_ACTION_FAST_PERIODIC, LACP_PTX_STATE_FAST_PERIODIC}, // event 3 SHORT_TIMEOUT @@ -42,7 +42,7 @@ static lacp_fsm_state_t lacp_ptx_state_fast_periodic[] = { * LACP State = SLOW_PERIODIC */ static lacp_fsm_state_t lacp_ptx_state_slow_periodic[] = { - {LACP_ACTION_NO_PERIODIC, LACP_PTX_STATE_NO_PERIODIC}, // event 0 BEGIN + {LACP_ACTION_NO_PERIODIC, LACP_PTX_STATE_NO_PERIODIC}, // event 0 NO_PERIODIC {LACP_ACTION_SLOW_PERIODIC, LACP_PTX_STATE_SLOW_PERIODIC}, // event 1 LONG_TIMEOUT {LACP_ACTION_TIMER_EXPIRED, LACP_PTX_STATE_PERIODIC_TX}, // event 2 TIMER_EXPIRED {LACP_ACTION_FAST_PERIODIC, LACP_PTX_STATE_FAST_PERIODIC}, // event 3 SHORT_TIMEOUT @@ -52,7 +52,7 @@ static lacp_fsm_state_t lacp_ptx_state_slow_periodic[] = { * LACP State = PERIODIC_TX */ static lacp_fsm_state_t lacp_ptx_state_periodic_tx[] = { - {LACP_ACTION_NO_PERIODIC, LACP_PTX_STATE_NO_PERIODIC}, // event 0 BEGIN + {LACP_ACTION_NO_PERIODIC, LACP_PTX_STATE_NO_PERIODIC}, // event 0 NO_PERIODIC {LACP_NOACTION, LACP_PTX_STATE_PERIODIC_TX}, // event 1 LONG_TIMEOUT {LACP_ACTION_TIMER_EXPIRED, LACP_PTX_STATE_PERIODIC_TX}, // event 2 TIMER_EXPIRED {LACP_NOACTION, LACP_PTX_STATE_PERIODIC_TX}, // event 3 SHORT_TIMEOUT @@ -78,10 +78,7 @@ lacp_ptx_action_no_periodic (void *p1, void *p2) slave_if_t *sif = (slave_if_t *) p2; lacp_stop_timer (&sif->periodic_timer); - - lacp_machine_dispatch (&lacp_ptx_machine, vm, sif, - LACP_PTX_EVENT_BEGIN, &sif->ptx_state); - + lacp_ptx_post_short_timeout_event (vm, sif); return 0; } @@ -93,17 +90,24 @@ lacp_ptx_action_slow_periodic (void *p1, void *p2) u8 timer_expired; lacp_main_t *lm = &lacp_main; - if (lacp_timer_is_running (sif->periodic_timer) && - lacp_timer_is_expired (lm->vlib_main, sif->periodic_timer)) - timer_expired = 1; + if (!(sif->partner.state & LACP_STATE_LACP_ACTIVITY) && + !(sif->actor.state & LACP_STATE_LACP_ACTIVITY)) + lacp_machine_dispatch (&lacp_ptx_machine, vm, sif, + LACP_PTX_EVENT_NO_PERIODIC, &sif->ptx_state); else - timer_expired = 0; + { + if (lacp_timer_is_running (sif->periodic_timer) && + lacp_timer_is_expired (lm->vlib_main, sif->periodic_timer)) + timer_expired = 1; + else + timer_expired = 0; - lacp_schedule_periodic_timer (lm->vlib_main, sif); + lacp_schedule_periodic_timer (lm->vlib_main, sif); - if (timer_expired || (sif->partner.state & LACP_STATE_LACP_TIMEOUT)) - lacp_machine_dispatch (&lacp_ptx_machine, vm, sif, - LACP_PTX_EVENT_TIMER_EXPIRED, &sif->ptx_state); + if (timer_expired || (sif->partner.state & LACP_STATE_LACP_TIMEOUT)) + lacp_machine_dispatch (&lacp_ptx_machine, vm, sif, + LACP_PTX_EVENT_TIMER_EXPIRED, &sif->ptx_state); + } return 0; } @@ -116,21 +120,29 @@ lacp_ptx_action_fast_periodic (void *p1, void *p2) u8 timer_expired; lacp_main_t *lm = &lacp_main; - if (lacp_timer_is_running (sif->periodic_timer) && - lacp_timer_is_expired (lm->vlib_main, sif->periodic_timer)) - timer_expired = 1; + if (!(sif->partner.state & LACP_STATE_LACP_ACTIVITY) && + !(sif->actor.state & LACP_STATE_LACP_ACTIVITY)) + lacp_machine_dispatch (&lacp_ptx_machine, vm, sif, + LACP_PTX_EVENT_NO_PERIODIC, &sif->ptx_state); else - timer_expired = 0; + { + if (lacp_timer_is_running (sif->periodic_timer) && + lacp_timer_is_expired (lm->vlib_main, sif->periodic_timer)) + timer_expired = 1; + else + timer_expired = 0; - lacp_start_periodic_timer (lm->vlib_main, sif, LACP_FAST_PERIODIC_TIMER); + lacp_start_periodic_timer (lm->vlib_main, sif, + LACP_FAST_PERIODIC_TIMER); - if (timer_expired) - lacp_machine_dispatch (&lacp_ptx_machine, vm, sif, - LACP_PTX_EVENT_TIMER_EXPIRED, &sif->ptx_state); + if (timer_expired) + lacp_machine_dispatch (&lacp_ptx_machine, vm, sif, + LACP_PTX_EVENT_TIMER_EXPIRED, &sif->ptx_state); - if (!(sif->partner.state & LACP_STATE_LACP_TIMEOUT)) - lacp_machine_dispatch (&lacp_ptx_machine, vm, sif, - LACP_PTX_EVENT_LONG_TIMEOUT, &sif->ptx_state); + if (!(sif->partner.state & LACP_STATE_LACP_TIMEOUT)) + lacp_machine_dispatch (&lacp_ptx_machine, vm, sif, + LACP_PTX_EVENT_LONG_TIMEOUT, &sif->ptx_state); + } return 0; } @@ -141,15 +153,22 @@ lacp_ptx_action_timer_expired (void *p1, void *p2) vlib_main_t *vm = (vlib_main_t *) p1; slave_if_t *sif = (slave_if_t *) p2; - sif->ntt = 1; - lacp_machine_dispatch (&lacp_tx_machine, vm, sif, LACP_TX_EVENT_NTT, - &sif->tx_state); - if (sif->partner.state & LACP_STATE_LACP_TIMEOUT) + if (!(sif->partner.state & LACP_STATE_LACP_ACTIVITY) && + !(sif->actor.state & LACP_STATE_LACP_ACTIVITY)) lacp_machine_dispatch (&lacp_ptx_machine, vm, sif, - LACP_PTX_EVENT_SHORT_TIMEOUT, &sif->ptx_state); + LACP_PTX_EVENT_NO_PERIODIC, &sif->ptx_state); else - lacp_machine_dispatch (&lacp_ptx_machine, vm, sif, - LACP_PTX_EVENT_LONG_TIMEOUT, &sif->ptx_state); + { + sif->ntt = 1; + lacp_machine_dispatch (&lacp_tx_machine, vm, sif, LACP_TX_EVENT_NTT, + &sif->tx_state); + if (sif->partner.state & LACP_STATE_LACP_TIMEOUT) + lacp_machine_dispatch (&lacp_ptx_machine, vm, sif, + LACP_PTX_EVENT_SHORT_TIMEOUT, &sif->ptx_state); + else + lacp_machine_dispatch (&lacp_ptx_machine, vm, sif, + LACP_PTX_EVENT_LONG_TIMEOUT, &sif->ptx_state); + } return 0; } @@ -189,8 +208,8 @@ lacp_ptx_debug_func (slave_if_t * sif, int event, int state, void lacp_init_ptx_machine (vlib_main_t * vm, slave_if_t * sif) { - lacp_machine_dispatch (&lacp_ptx_machine, vm, sif, LACP_PTX_EVENT_BEGIN, - &sif->ptx_state); + lacp_machine_dispatch (&lacp_ptx_machine, vm, sif, + LACP_PTX_EVENT_NO_PERIODIC, &sif->ptx_state); } /* diff --git a/src/plugins/lacp/ptx_machine.h b/src/plugins/lacp/ptx_machine.h index 9b4f2805ee4..4b4f4134254 100644 --- a/src/plugins/lacp/ptx_machine.h +++ b/src/plugins/lacp/ptx_machine.h @@ -20,7 +20,7 @@ #include <lacp/machine.h> #define foreach_lacp_ptx_event \ - _(0, BEGIN, "begin") \ + _(0, NO_PERIODIC, "no periodic") \ _(1, LONG_TIMEOUT, "long tiemout") \ _(2, TIMER_EXPIRED, "timer expired") \ _(3, SHORT_TIMEOUT, "short timeout") @@ -86,6 +86,16 @@ lacp_schedule_periodic_timer (vlib_main_t * vm, slave_if_t * sif) lacp_start_periodic_timer (vm, sif, LACP_SLOW_PERIODIC_TIMER); } +static inline void +lacp_ptx_post_short_timeout_event (vlib_main_t * vm, slave_if_t * sif) +{ + if (sif->lacp_enabled && sif->port_enabled && + ((sif->partner.state & LACP_STATE_LACP_ACTIVITY) || + (sif->actor.state & LACP_STATE_LACP_ACTIVITY))) + lacp_machine_dispatch (&lacp_ptx_machine, vm, sif, + LACP_PTX_EVENT_SHORT_TIMEOUT, &sif->ptx_state); +} + #endif /* __LACP_PTX_MACHINE_H__ */ /* diff --git a/src/plugins/lacp/rx_machine.c b/src/plugins/lacp/rx_machine.c index fd65aa3ae8e..070b9089cd2 100644 --- a/src/plugins/lacp/rx_machine.c +++ b/src/plugins/lacp/rx_machine.c @@ -206,11 +206,15 @@ lacp_compare_partner (slave_if_t * sif) } static void -lacp_record_pdu (slave_if_t * sif) +lacp_record_pdu (vlib_main_t * vm, slave_if_t * sif) { lacp_pdu_t *lacpdu = (lacp_pdu_t *) sif->last_rx_pkt; u8 match; + /* Transition PTX out of NO_PERIODIC if needed */ + if (!(sif->partner.state & LACP_STATE_LACP_ACTIVITY) && + (lacpdu->actor.port_info.state & LACP_STATE_LACP_ACTIVITY)) + lacp_ptx_post_short_timeout_event (vm, sif); match = lacp_compare_partner (sif); sif->partner = lacpdu->actor.port_info; sif->actor.state &= ~LACP_STATE_DEFAULTED; @@ -285,8 +289,7 @@ lacp_rx_action_expired (void *p1, void *p2) sif->partner.state &= ~LACP_STATE_SYNCHRONIZATION; sif->partner.state |= LACP_STATE_LACP_TIMEOUT; - lacp_machine_dispatch (&lacp_ptx_machine, vm, sif, - LACP_PTX_EVENT_SHORT_TIMEOUT, &sif->ptx_state); + lacp_ptx_post_short_timeout_event (vm, sif); if (lacp_timer_is_running (sif->current_while_timer) && lacp_timer_is_expired (lm->vlib_main, sif->current_while_timer)) timer_expired = 1; @@ -324,6 +327,7 @@ lacp_rx_action_defaulted (void *p1, void *p2) vlib_main_t *vm = (vlib_main_t *) p1; slave_if_t *sif = (slave_if_t *) p2; + lacp_stop_timer (&sif->current_while_timer); lacp_update_default_selected (vm, sif); lacp_record_default (sif); sif->actor.state &= ~LACP_STATE_EXPIRED; @@ -365,7 +369,7 @@ lacp_rx_action_current (void *p1, void *p2) lacp_update_selected (vm, sif); lacp_update_ntt (vm, sif); - lacp_record_pdu (sif); + lacp_record_pdu (vm, sif); lacp_start_current_while_timer (lm->vlib_main, sif, sif->ttl_in_seconds); sif->actor.state &= ~LACP_STATE_EXPIRED; if (lacp_port_is_moved (vm, sif)) diff --git a/src/plugins/lacp/tx_machine.c b/src/plugins/lacp/tx_machine.c index 21b767c39d2..4cc4e68a103 100644 --- a/src/plugins/lacp/tx_machine.c +++ b/src/plugins/lacp/tx_machine.c @@ -47,7 +47,7 @@ lacp_tx_action_transmit (void *p1, void *p2) return 0; // No more than 3 LACPDUs per fast interval - if (now <= (sif->last_lacpdu_time + 0.333)) + if (now <= (sif->last_lacpdu_sent_time + 0.333)) return 0; if (sif->ntt) @@ -97,9 +97,6 @@ lacp_init_tx_machine (vlib_main_t * vm, slave_if_t * sif) { lacp_machine_dispatch (&lacp_tx_machine, vm, sif, LACP_TX_EVENT_BEGIN, &sif->tx_state); - if (sif->is_passive == 0) - lacp_machine_dispatch (&lacp_tx_machine, vm, sif, LACP_TX_EVENT_NTT, - &sif->tx_state); } /* |