19cd2d7a5SSteven/*
29cd2d7a5SSteven * Copyright (c) 2017 Cisco and/or its affiliates.
39cd2d7a5SSteven * Licensed under the Apache License, Version 2.0 (the "License");
49cd2d7a5SSteven * you may not use this file except in compliance with the License.
59cd2d7a5SSteven * You may obtain a copy of the License at:
69cd2d7a5SSteven *
79cd2d7a5SSteven *     http://www.apache.org/licenses/LICENSE-2.0
89cd2d7a5SSteven *
99cd2d7a5SSteven * Unless required by applicable law or agreed to in writing, software
109cd2d7a5SSteven * distributed under the License is distributed on an "AS IS" BASIS,
119cd2d7a5SSteven * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
129cd2d7a5SSteven * See the License for the specific language governing permissions and
139cd2d7a5SSteven * limitations under the License.
149cd2d7a5SSteven */
159cd2d7a5SSteven
169cd2d7a5SSteven#define _GNU_SOURCE
179cd2d7a5SSteven
189cd2d7a5SSteven#include <vnet/bonding/node.h>
199cd2d7a5SSteven#include <lacp/node.h>
209cd2d7a5SSteven
219cd2d7a5SSteven/*
229cd2d7a5SSteven *  LACP State = INITIALIZE
239cd2d7a5SSteven */
249cd2d7a5SStevenstatic lacp_fsm_state_t lacp_rx_state_initialize[] = {
259cd2d7a5SSteven  {LACP_ACTION_INITIALIZE, LACP_RX_STATE_PORT_DISABLED},	// event 0 BEGIN
269cd2d7a5SSteven  {LACP_ACTION_INITIALIZE, LACP_RX_STATE_PORT_DISABLED},	// event 1 PORT_DISABLED
279cd2d7a5SSteven  {LACP_ACTION_INITIALIZE, LACP_RX_STATE_PORT_DISABLED},	// event 2 PORT_MOVED
289cd2d7a5SSteven  {LACP_NOACTION, LACP_RX_STATE_INITIALIZE},	// event 3 LACP_ENABLED
299cd2d7a5SSteven  {LACP_NOACTION, LACP_RX_STATE_INITIALIZE},	// event 4 LACP_DISABLED
309cd2d7a5SSteven  {LACP_NOACTION, LACP_RX_STATE_INITIALIZE},	// event 5 PDU_RECEIVED
319cd2d7a5SSteven  {LACP_NOACTION, LACP_RX_STATE_INITIALIZE},	// event 6 TIMER_EXPIRED
329cd2d7a5SSteven};
339cd2d7a5SSteven
349cd2d7a5SSteven/*
359cd2d7a5SSteven *  LACP State = PORT_DISABLED
369cd2d7a5SSteven */
379cd2d7a5SStevenstatic lacp_fsm_state_t lacp_rx_state_port_disabled[] = {
389cd2d7a5SSteven  {LACP_ACTION_PORT_DISABLED, LACP_RX_STATE_PORT_DISABLED},	// event 0 BEGIN
399cd2d7a5SSteven  {LACP_ACTION_PORT_DISABLED, LACP_RX_STATE_PORT_DISABLED},	// event 1 PORT_DISABLED
409cd2d7a5SSteven  {LACP_ACTION_INITIALIZE, LACP_RX_STATE_INITIALIZE},	// event 2 PORT_MOVED
419cd2d7a5SSteven  {LACP_ACTION_EXPIRED, LACP_RX_STATE_EXPIRED},	// event 3 LACP_ENABLED
429cd2d7a5SSteven  {LACP_ACTION_LACP_DISABLED, LACP_RX_STATE_LACP_DISABLED},	// event 4 LACP_DISABLED
439cd2d7a5SSteven  {LACP_NOACTION, LACP_RX_STATE_PORT_DISABLED},	// event 5 PDU_RECEIVED
449cd2d7a5SSteven  {LACP_NOACTION, LACP_RX_STATE_PORT_DISABLED},	// event 6 TIMER_EXPIRED
459cd2d7a5SSteven};
469cd2d7a5SSteven
479cd2d7a5SSteven/*
489cd2d7a5SSteven *  LACP State = EXPIRED
499cd2d7a5SSteven */
509cd2d7a5SStevenstatic lacp_fsm_state_t lacp_rx_state_expired[] = {
519cd2d7a5SSteven  {LACP_ACTION_INITIALIZE, LACP_RX_STATE_INITIALIZE},	// event 0 BEGIN
529cd2d7a5SSteven  {LACP_NOACTION, LACP_RX_STATE_EXPIRED},	// event 1 PORT_DISABLED
539cd2d7a5SSteven  {LACP_NOACTION, LACP_RX_STATE_EXPIRED},	// event 2 PORT_MOVED
549cd2d7a5SSteven  {LACP_NOACTION, LACP_RX_STATE_EXPIRED},	// event 3 LACP_ENABLED
559cd2d7a5SSteven  {LACP_NOACTION, LACP_RX_STATE_EXPIRED},	// event 4 LACP_DISABLED
569cd2d7a5SSteven  {LACP_ACTION_CURRENT, LACP_RX_STATE_CURRENT},	// event 5 PDU_RECEIVED
579cd2d7a5SSteven  {LACP_ACTION_DEFAULTED, LACP_RX_STATE_DEFAULTED},	// event 6 TIMER_EXPIRED
589cd2d7a5SSteven};
599cd2d7a5SSteven
609cd2d7a5SSteven/*
619cd2d7a5SSteven *  LACP State = LACP_DISABLED
629cd2d7a5SSteven */
639cd2d7a5SStevenstatic lacp_fsm_state_t lacp_rx_state_lacp_disabled[] = {
649cd2d7a5SSteven  {LACP_ACTION_INITIALIZE, LACP_RX_STATE_INITIALIZE},	// event 0 BEGIN
659cd2d7a5SSteven  {LACP_NOACTION, LACP_RX_STATE_LACP_DISABLED},	// event 1 PORT_DISABLED
669cd2d7a5SSteven  {LACP_NOACTION, LACP_RX_STATE_LACP_DISABLED},	// event 2 PORT_MOVED
679cd2d7a5SSteven  {LACP_ACTION_EXPIRED, LACP_RX_STATE_EXPIRED},	// event 3 LACP_ENABLED XXX
689cd2d7a5SSteven  {LACP_ACTION_LACP_DISABLED, LACP_RX_STATE_LACP_DISABLED},	// event 4 LACP_DISABLED
699cd2d7a5SSteven  {LACP_NOACTION, LACP_RX_STATE_LACP_DISABLED},	// event 5 PDU_RECEIVED
709cd2d7a5SSteven  {LACP_NOACTION, LACP_RX_STATE_LACP_DISABLED},	// event 6 TIMER_EXPIRED
719cd2d7a5SSteven};
729cd2d7a5SSteven
739cd2d7a5SSteven/*
749cd2d7a5SSteven *  LACP State = DEFAULTED
759cd2d7a5SSteven */
769cd2d7a5SStevenstatic lacp_fsm_state_t lacp_rx_state_defaulted[] = {
779cd2d7a5SSteven  {LACP_ACTION_INITIALIZE, LACP_RX_STATE_INITIALIZE},	// event 0 BEGIN
789cd2d7a5SSteven  {LACP_NOACTION, LACP_RX_STATE_DEFAULTED},	// event 1 PORT_DISABLED
799cd2d7a5SSteven  {LACP_NOACTION, LACP_RX_STATE_DEFAULTED},	// event 2 PORT_MOVED
809cd2d7a5SSteven  {LACP_NOACTION, LACP_RX_STATE_DEFAULTED},	// event 3 LACP_ENABLED
819cd2d7a5SSteven  {LACP_ACTION_LACP_DISABLED, LACP_RX_STATE_LACP_DISABLED},	// event 4 LACP_DISABLED
829cd2d7a5SSteven  {LACP_ACTION_CURRENT, LACP_RX_STATE_CURRENT},	// event 5 PDU_RECEIVED
839cd2d7a5SSteven  {LACP_ACTION_DEFAULTED, LACP_RX_STATE_DEFAULTED},	// event 6 TIMER_EXPIRED
849cd2d7a5SSteven};
859cd2d7a5SSteven
869cd2d7a5SSteven/*
879cd2d7a5SSteven *  LACP State = CURRENT
889cd2d7a5SSteven */
899cd2d7a5SStevenstatic lacp_fsm_state_t lacp_rx_state_current[] = {
909cd2d7a5SSteven  {LACP_ACTION_INITIALIZE, LACP_RX_STATE_INITIALIZE},	// event 0 BEGIN
919cd2d7a5SSteven  {LACP_NOACTION, LACP_RX_STATE_CURRENT},	// event 1 PORT_DISABLED
929cd2d7a5SSteven  {LACP_NOACTION, LACP_RX_STATE_CURRENT},	// event 1 PORT_MOVED
939cd2d7a5SSteven  {LACP_NOACTION, LACP_RX_STATE_CURRENT},	// event 2 LACP_ENABLED
949cd2d7a5SSteven  {LACP_ACTION_LACP_DISABLED, LACP_RX_STATE_LACP_DISABLED},	// event 3 LACP_DISABLED
959cd2d7a5SSteven  {LACP_ACTION_CURRENT, LACP_RX_STATE_CURRENT},	// event 4 PDU_RECEIVED
969cd2d7a5SSteven  {LACP_ACTION_EXPIRED, LACP_RX_STATE_EXPIRED},	// event 5 TIMER_EXPIRED
979cd2d7a5SSteven};
989cd2d7a5SSteven
999cd2d7a5SStevenstatic lacp_fsm_machine_t lacp_rx_fsm_table[] = {
1009cd2d7a5SSteven  {lacp_rx_state_initialize},
1019cd2d7a5SSteven  {lacp_rx_state_port_disabled},
1029cd2d7a5SSteven  {lacp_rx_state_expired},
1039cd2d7a5SSteven  {lacp_rx_state_lacp_disabled},
1049cd2d7a5SSteven  {lacp_rx_state_defaulted},
1059cd2d7a5SSteven  {lacp_rx_state_current},
1069cd2d7a5SSteven};
1079cd2d7a5SSteven
1089cd2d7a5SStevenlacp_machine_t lacp_rx_machine = {
1099cd2d7a5SSteven  lacp_rx_fsm_table,
1109cd2d7a5SSteven  lacp_rx_debug_func,
1119cd2d7a5SSteven};
1129cd2d7a5SSteven
1139cd2d7a5SStevenstatic void
1149cd2d7a5SStevenlacp_set_port_unselected (vlib_main_t * vm, slave_if_t * sif)
1159cd2d7a5SSteven{
1169cd2d7a5SSteven  sif->selected = LACP_PORT_UNSELECTED;
1179cd2d7a5SSteven
1189cd2d7a5SSteven  switch (sif->mux_state)
1199cd2d7a5SSteven    {
1209cd2d7a5SSteven    case LACP_MUX_STATE_DETACHED:
1219cd2d7a5SSteven      break;
1229cd2d7a5SSteven    case LACP_MUX_STATE_WAITING:
1239cd2d7a5SSteven      break;
1249cd2d7a5SSteven    case LACP_MUX_STATE_ATTACHED:
1259cd2d7a5SSteven      return;
1269cd2d7a5SSteven      break;
1279cd2d7a5SSteven    case LACP_MUX_STATE_COLLECTING_DISTRIBUTING:
1289cd2d7a5SSteven      if (sif->partner.state & LACP_STATE_SYNCHRONIZATION)
1299cd2d7a5SSteven	return;
1309cd2d7a5SSteven      break;
1319cd2d7a5SSteven    default:
1329cd2d7a5SSteven      break;
1339cd2d7a5SSteven    }
1349cd2d7a5SSteven  lacp_machine_dispatch (&lacp_mux_machine, vm, sif,
1359cd2d7a5SSteven			 LACP_MUX_EVENT_UNSELECTED, &sif->mux_state);
1369cd2d7a5SSteven}
1379cd2d7a5SSteven
1389cd2d7a5SStevenstatic void
1399cd2d7a5SStevenlacp_update_default_selected (vlib_main_t * vm, slave_if_t * sif)
1409cd2d7a5SSteven{
1419cd2d7a5SSteven  if ((sif->partner_admin.state & LACP_STATE_AGGREGATION) !=
1429cd2d7a5SSteven      (sif->partner.state & LACP_STATE_AGGREGATION) ||
1439cd2d7a5SSteven      memcmp (&sif->partner, &sif->partner_admin,
1449cd2d7a5SSteven	      sizeof (sif->partner) - sizeof (sif->partner.state)))
1459cd2d7a5SSteven    {
1469cd2d7a5SSteven      lacp_set_port_unselected (vm, sif);
1479cd2d7a5SSteven    }
1489cd2d7a5SSteven}
1499cd2d7a5SSteven
1509cd2d7a5SStevenstatic void
1519cd2d7a5SStevenlacp_record_default (slave_if_t * sif)
1529cd2d7a5SSteven{
1539cd2d7a5SSteven  sif->partner = sif->partner_admin;
1549cd2d7a5SSteven  sif->actor.state |= LACP_STATE_DEFAULTED;
1559cd2d7a5SSteven}
1569cd2d7a5SSteven
1579cd2d7a5SStevenstatic void
1589cd2d7a5SStevenlacp_update_selected (vlib_main_t * vm, slave_if_t * sif)
1599cd2d7a5SSteven{
1609cd2d7a5SSteven  lacp_pdu_t *lacpdu = (lacp_pdu_t *) sif->last_rx_pkt;
1619cd2d7a5SSteven
1629cd2d7a5SSteven  if ((lacpdu->actor.port_info.state & LACP_STATE_AGGREGATION) !=
1639cd2d7a5SSteven      (sif->partner.state & LACP_STATE_AGGREGATION) ||
1649cd2d7a5SSteven      memcmp (&sif->partner, &lacpdu->actor.port_info,
1659cd2d7a5SSteven	      sizeof (sif->partner) - sizeof (sif->partner.state)))
1669cd2d7a5SSteven    {
1679cd2d7a5SSteven      lacp_set_port_unselected (vm, sif);
1689cd2d7a5SSteven    }
1699cd2d7a5SSteven}
1709cd2d7a5SSteven
1719cd2d7a5SStevenstatic void
1729cd2d7a5SStevenlacp_update_ntt (vlib_main_t * vm, slave_if_t * sif)
1739cd2d7a5SSteven{
1749cd2d7a5SSteven  lacp_pdu_t *lacpdu = (lacp_pdu_t *) sif->last_rx_pkt;
1759cd2d7a5SSteven  u8 states = LACP_STATE_LACP_ACTIVITY | LACP_STATE_LACP_TIMEOUT |
1769cd2d7a5SSteven    LACP_STATE_SYNCHRONIZATION | LACP_STATE_AGGREGATION;
1779cd2d7a5SSteven
1789cd2d7a5SSteven  if ((states & lacpdu->partner.port_info.state) !=
1799cd2d7a5SSteven      (states & sif->actor.state)
1809cd2d7a5SSteven      || memcmp (&sif->actor, &lacpdu->partner.port_info,
1819cd2d7a5SSteven		 sizeof (sif->actor) - sizeof (sif->actor.state)))
1829cd2d7a5SSteven    {
1839cd2d7a5SSteven      sif->ntt = 1;
18492e1b83aSElias Rudberg      lacp_start_periodic_timer (vm, sif, 0);
1859cd2d7a5SSteven    }
1869cd2d7a5SSteven}
1879cd2d7a5SSteven
1889cd2d7a5SSteven/*
1899cd2d7a5SSteven * compare lacpdu partner info against sif->partner. Return 1 if they match, 0
1909cd2d7a5SSteven * otherwise.
1919cd2d7a5SSteven */
1929cd2d7a5SStevenstatic u8
1939cd2d7a5SStevenlacp_compare_partner (slave_if_t * sif)
1949cd2d7a5SSteven{
1959cd2d7a5SSteven  lacp_pdu_t *lacpdu = (lacp_pdu_t *) sif->last_rx_pkt;
1969cd2d7a5SSteven
1979cd2d7a5SSteven  if ((!memcmp (&sif->partner, &lacpdu->actor.port_info,
1989cd2d7a5SSteven		sizeof (sif->partner) - sizeof (sif->partner.state)) &&
1999cd2d7a5SSteven       ((sif->actor.state & LACP_STATE_AGGREGATION) ==
2009cd2d7a5SSteven	(lacpdu->partner.port_info.state & LACP_STATE_AGGREGATION))) ||
2019cd2d7a5SSteven      ((lacpdu->actor.port_info.state & LACP_STATE_AGGREGATION) == 0))
2029cd2d7a5SSteven    return 1;
2039cd2d7a5SSteven
2049cd2d7a5SSteven  return 0;
2059cd2d7a5SSteven}
2069cd2d7a5SSteven
2079cd2d7a5SStevenstatic void
20882c5dda4SSteven Luonglacp_record_pdu (vlib_main_t * vm, slave_if_t * sif)
2099cd2d7a5SSteven{
2109cd2d7a5SSteven  lacp_pdu_t *lacpdu = (lacp_pdu_t *) sif->last_rx_pkt;
2119cd2d7a5SSteven  u8 match;
2129cd2d7a5SSteven
21382c5dda4SSteven Luong  /* Transition PTX out of NO_PERIODIC if needed */
21482c5dda4SSteven Luong  if (!(sif->partner.state & LACP_STATE_LACP_ACTIVITY) &&
21582c5dda4SSteven Luong      (lacpdu->actor.port_info.state & LACP_STATE_LACP_ACTIVITY))
21682c5dda4SSteven Luong    lacp_ptx_post_short_timeout_event (vm, sif);
2179cd2d7a5SSteven  match = lacp_compare_partner (sif);
2189cd2d7a5SSteven  sif->partner = lacpdu->actor.port_info;
2199cd2d7a5SSteven  sif->actor.state &= ~LACP_STATE_DEFAULTED;
2209cd2d7a5SSteven  if (match && (lacpdu->actor.port_info.state & LACP_STATE_SYNCHRONIZATION))
2219cd2d7a5SSteven    sif->partner.state |= LACP_STATE_SYNCHRONIZATION;
2229cd2d7a5SSteven  else
2239cd2d7a5SSteven    sif->partner.state &= ~LACP_STATE_SYNCHRONIZATION;
2249cd2d7a5SSteven}
2259cd2d7a5SSteven
2269cd2d7a5SStevenstatic void
2279cd2d7a5SStevenlacp_set_port_moved (vlib_main_t * vm, slave_if_t * sif, u8 val)
2289cd2d7a5SSteven{
2299cd2d7a5SSteven  sif->port_moved = val;
2309cd2d7a5SSteven
2319cd2d7a5SSteven  if (sif->port_moved)
2329cd2d7a5SSteven    lacp_machine_dispatch (&lacp_rx_machine, vm, sif,
2339cd2d7a5SSteven			   LACP_RX_EVENT_PORT_MOVED, &sif->rx_state);
2349cd2d7a5SSteven  else if (!sif->port_enabled)
2359cd2d7a5SSteven    lacp_machine_dispatch (&lacp_rx_machine, vm, sif,
2369cd2d7a5SSteven			   LACP_RX_EVENT_PORT_DISABLED, &sif->rx_state);
2379cd2d7a5SSteven}
2389cd2d7a5SSteven
2399cd2d7a5SStevenint
2409cd2d7a5SStevenlacp_rx_action_initialize (void *p1, void *p2)
2419cd2d7a5SSteven{
24291c51291SZhiyong Yang  vlib_main_t *vm = p1;
24391c51291SZhiyong Yang  slave_if_t *sif = p2;
2449cd2d7a5SSteven
2459cd2d7a5SSteven  lacp_set_port_unselected (vm, sif);
2469cd2d7a5SSteven  lacp_record_default (sif);
2479cd2d7a5SSteven  sif->actor.state &= ~LACP_STATE_EXPIRED;
2489cd2d7a5SSteven  lacp_set_port_moved (vm, sif, 0);
2499cd2d7a5SSteven  /* UCT */
2509cd2d7a5SSteven  lacp_machine_dispatch (&lacp_rx_machine, vm, sif,
2519cd2d7a5SSteven			 LACP_RX_EVENT_BEGIN, &sif->rx_state);
2529cd2d7a5SSteven
2539cd2d7a5SSteven  return 0;
2549cd2d7a5SSteven}
2559cd2d7a5SSteven
2569cd2d7a5SStevenint
2579cd2d7a5SStevenlacp_rx_action_port_disabled (void *p1, void *p2)
2589cd2d7a5SSteven{
25991c51291SZhiyong Yang  vlib_main_t *vm = p1;
26091c51291SZhiyong Yang  slave_if_t *sif = p2;
2619cd2d7a5SSteven
2629cd2d7a5SSteven  sif->partner.state &= ~LACP_STATE_SYNCHRONIZATION;
2639cd2d7a5SSteven  if (sif->port_moved)
2649cd2d7a5SSteven    {
2659cd2d7a5SSteven      lacp_machine_dispatch (&lacp_rx_machine, vm, sif,
2669cd2d7a5SSteven			     LACP_RX_EVENT_PORT_MOVED, &sif->rx_state);
2679cd2d7a5SSteven    }
2689cd2d7a5SSteven  if (sif->port_enabled)
2699cd2d7a5SSteven    {
2709cd2d7a5SSteven      if (sif->lacp_enabled)
2719cd2d7a5SSteven	lacp_machine_dispatch (&lacp_rx_machine, vm, sif,
2729cd2d7a5SSteven			       LACP_RX_EVENT_LACP_ENABLED, &sif->rx_state);
2739cd2d7a5SSteven      else
2749cd2d7a5SSteven	lacp_machine_dispatch (&lacp_rx_machine, vm, sif,
2759cd2d7a5SSteven			       LACP_RX_EVENT_LACP_DISABLED, &sif->rx_state);
2769cd2d7a5SSteven    }
2779cd2d7a5SSteven
2789cd2d7a5SSteven  return 0;
2799cd2d7a5SSteven}
2809cd2d7a5SSteven
2819cd2d7a5SStevenint
2829cd2d7a5SStevenlacp_rx_action_expired (void *p1, void *p2)
2839cd2d7a5SSteven{
28491c51291SZhiyong Yang  vlib_main_t *vm = p1;
28591c51291SZhiyong Yang  slave_if_t *sif = p2;
2869cd2d7a5SSteven  u8 timer_expired;
2879cd2d7a5SSteven
2889cd2d7a5SSteven  sif->partner.state &= ~LACP_STATE_SYNCHRONIZATION;
2899cd2d7a5SSteven  sif->partner.state |= LACP_STATE_LACP_TIMEOUT;
29082c5dda4SSteven Luong  lacp_ptx_post_short_timeout_event (vm, sif);
2919cd2d7a5SSteven  if (lacp_timer_is_running (sif->current_while_timer) &&
29292e1b83aSElias Rudberg      lacp_timer_is_expired (vm, sif->current_while_timer))
2939cd2d7a5SSteven    timer_expired = 1;
2949cd2d7a5SSteven  else
2959cd2d7a5SSteven    timer_expired = 0;
29692e1b83aSElias Rudberg  lacp_start_current_while_timer (vm, sif, sif->ttl_in_seconds);
2979cd2d7a5SSteven  sif->actor.state |= LACP_STATE_EXPIRED;
2989cd2d7a5SSteven  if (timer_expired)
2999cd2d7a5SSteven    lacp_machine_dispatch (&lacp_rx_machine, vm, sif,
3009cd2d7a5SSteven			   LACP_RX_EVENT_TIMER_EXPIRED, &sif->rx_state);
3019cd2d7a5SSteven  if (sif->last_rx_pkt && vec_len (sif->last_rx_pkt))
3029cd2d7a5SSteven    lacp_machine_dispatch (&lacp_rx_machine, vm, sif,
3039cd2d7a5SSteven			   LACP_RX_EVENT_PDU_RECEIVED, &sif->rx_state);
3049cd2d7a5SSteven
3059cd2d7a5SSteven  return 0;
3069cd2d7a5SSteven}
3079cd2d7a5SSteven
3089cd2d7a5SStevenint
3099cd2d7a5SStevenlacp_rx_action_lacp_disabled (void *p1, void *p2)
3109cd2d7a5SSteven{
31191c51291SZhiyong Yang  vlib_main_t *vm = p1;
31291c51291SZhiyong Yang  slave_if_t *sif = p2;
3139cd2d7a5SSteven
3149cd2d7a5SSteven  lacp_set_port_unselected (vm, sif);
3159cd2d7a5SSteven  lacp_record_default (sif);
3169cd2d7a5SSteven  sif->partner.state &= ~LACP_STATE_AGGREGATION;
3179cd2d7a5SSteven  sif->actor.state &= ~LACP_STATE_EXPIRED;
3189cd2d7a5SSteven
3199cd2d7a5SSteven  return 0;
3209cd2d7a5SSteven}
3219cd2d7a5SSteven
3229cd2d7a5SStevenint
3239cd2d7a5SStevenlacp_rx_action_defaulted (void *p1, void *p2)
3249cd2d7a5SSteven{
32591c51291SZhiyong Yang  vlib_main_t *vm = p1;
32691c51291SZhiyong Yang  slave_if_t *sif = p2;
3279cd2d7a5SSteven
32882c5dda4SSteven Luong  lacp_stop_timer (&sif->current_while_timer);
3299cd2d7a5SSteven  lacp_update_default_selected (vm, sif);
3309cd2d7a5SSteven  lacp_record_default (sif);
3319cd2d7a5SSteven  sif->actor.state &= ~LACP_STATE_EXPIRED;
3329cd2d7a5SSteven  if (sif->last_rx_pkt && vec_len (sif->last_rx_pkt))
3339cd2d7a5SSteven    lacp_machine_dispatch (&lacp_rx_machine, vm, sif,
3349cd2d7a5SSteven			   LACP_RX_EVENT_PDU_RECEIVED, &sif->rx_state);
3359cd2d7a5SSteven
3369cd2d7a5SSteven  return 0;
3379cd2d7a5SSteven}
3389cd2d7a5SSteven
3399cd2d7a5SStevenstatic int
3409cd2d7a5SStevenlacp_port_is_moved (vlib_main_t * vm, slave_if_t * sif)
3419cd2d7a5SSteven{
3429cd2d7a5SSteven  bond_main_t *bm = &bond_main;
3439cd2d7a5