2 * Copyright (c) 2017 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
18 #include <vlib/vlib.h>
19 #include <vnet/bonding/node.h>
20 #include <lacp/node.h>
23 * LACP State = DETACHED
25 static lacp_fsm_state_t lacp_mux_state_detached[] = {
26 {LACP_ACTION_DETACHED, LACP_MUX_STATE_DETACHED}, // event 0 BEGIN
27 {LACP_ACTION_WAITING, LACP_MUX_STATE_WAITING}, // event 1 SELECTED
28 {LACP_ACTION_WAITING, LACP_MUX_STATE_WAITING}, // event 2 STANDBY
29 {LACP_ACTION_DETACHED, LACP_MUX_STATE_DETACHED}, // event 3 UNSELECTED
30 {LACP_ACTION_DETACHED, LACP_MUX_STATE_DETACHED}, // event 4 READY
31 {LACP_ACTION_DETACHED, LACP_MUX_STATE_DETACHED}, // event 5 SYNC
35 * LACP State = WAITING
37 static lacp_fsm_state_t lacp_mux_state_waiting[] = {
38 {LACP_ACTION_DETACHED, LACP_MUX_STATE_DETACHED}, // event 0 BEGIN
39 {LACP_ACTION_WAITING, LACP_MUX_STATE_WAITING}, // event 1 SELECTED
40 {LACP_ACTION_WAITING, LACP_MUX_STATE_WAITING}, // event 2 STANDBY
41 {LACP_ACTION_DETACHED, LACP_MUX_STATE_DETACHED}, // event 3 UNSELECTED
42 {LACP_ACTION_ATTACHED, LACP_MUX_STATE_ATTACHED}, // event 4 READY
43 {LACP_ACTION_WAITING, LACP_MUX_STATE_WAITING}, // event 5 SYNC
47 * LACP State = ATTACHED
49 static lacp_fsm_state_t lacp_mux_state_attached[] = {
50 {LACP_ACTION_DETACHED, LACP_MUX_STATE_DETACHED}, // event 0 BEGIN
51 {LACP_ACTION_ATTACHED, LACP_MUX_STATE_ATTACHED}, // event 1 SELECTED
52 {LACP_ACTION_DETACHED, LACP_MUX_STATE_DETACHED}, // event 2 STANDBY
53 {LACP_ACTION_DETACHED, LACP_MUX_STATE_DETACHED}, // event 3 UNSELECTED
54 {LACP_ACTION_ATTACHED, LACP_MUX_STATE_ATTACHED}, // event 4 READY
55 {LACP_ACTION_COLLECTING_DISTRIBUTING, LACP_MUX_STATE_COLLECTING_DISTRIBUTING}, // event 5_SYNC
59 * LACP State = COLLECTING_DISTRIBUTING
61 static lacp_fsm_state_t lacp_mux_state_collecting_distributing[] = {
62 {LACP_ACTION_DETACHED, LACP_MUX_STATE_DETACHED}, // event 0 BEGIN
63 {LACP_ACTION_COLLECTING_DISTRIBUTING, LACP_MUX_STATE_COLLECTING_DISTRIBUTING}, // event 1 SELECTED
64 {LACP_ACTION_COLLECTING_DISTRIBUTING, LACP_MUX_STATE_COLLECTING_DISTRIBUTING}, // event 2 STANDBY
65 {LACP_ACTION_ATTACHED, LACP_MUX_STATE_ATTACHED}, // event 3 UNSELECTED
66 {LACP_ACTION_COLLECTING_DISTRIBUTING, LACP_MUX_STATE_COLLECTING_DISTRIBUTING}, // event 4 READY
67 {LACP_ACTION_COLLECTING_DISTRIBUTING, LACP_MUX_STATE_COLLECTING_DISTRIBUTING}, // event 5 SYNC
70 static lacp_fsm_machine_t lacp_mux_fsm_table[] = {
71 {lacp_mux_state_detached},
72 {lacp_mux_state_waiting},
73 {lacp_mux_state_attached},
74 {lacp_mux_state_collecting_distributing},
77 lacp_machine_t lacp_mux_machine = {
83 lacp_detach_mux_from_aggregator (vlib_main_t * vm, slave_if_t * sif)
85 sif->actor.state &= ~LACP_STATE_SYNCHRONIZATION;
91 lacp_attach_mux_to_aggregator (vlib_main_t * vm, slave_if_t * sif)
93 sif->actor.state |= LACP_STATE_SYNCHRONIZATION;
97 lacp_mux_action_detached (void *p1, void *p2)
100 slave_if_t *sif = p2;
101 lacp_main_t *lm = &lacp_main;
103 lacp_detach_mux_from_aggregator (vm, sif);
104 sif->actor.state &= ~LACP_STATE_COLLECTING;
105 bond_disable_collecting_distributing (vm, sif);
106 sif->actor.state &= ~LACP_STATE_DISTRIBUTING;
108 lacp_start_periodic_timer (lm->vlib_main, sif, 0);
110 if (sif->selected == LACP_PORT_SELECTED)
111 lacp_machine_dispatch (&lacp_mux_machine, vm, sif,
112 LACP_MUX_EVENT_SELECTED, &sif->mux_state);
114 if (sif->selected == LACP_PORT_STANDBY)
115 lacp_machine_dispatch (&lacp_mux_machine, vm, sif, LACP_MUX_EVENT_STANDBY,
122 lacp_mux_action_attached (void *p1, void *p2)
124 vlib_main_t *vm = p1;
125 slave_if_t *sif = p2;
126 lacp_main_t *lm = &lacp_main;
128 lacp_attach_mux_to_aggregator (vm, sif);
129 sif->actor.state &= ~LACP_STATE_COLLECTING;
130 bond_disable_collecting_distributing (vm, sif);
131 sif->actor.state &= ~LACP_STATE_DISTRIBUTING;
133 lacp_start_periodic_timer (lm->vlib_main, sif, 0);
135 if ((sif->selected == LACP_PORT_UNSELECTED) ||
136 (sif->selected == LACP_PORT_STANDBY))
137 lacp_machine_dispatch (&lacp_mux_machine, vm, sif,
138 LACP_MUX_EVENT_UNSELECTED, &sif->mux_state);
140 if ((sif->selected == LACP_PORT_SELECTED) &&
141 (sif->partner.state & LACP_STATE_SYNCHRONIZATION))
142 lacp_machine_dispatch (&lacp_mux_machine, vm, sif, LACP_MUX_EVENT_SYNC,
148 lacp_mux_action_waiting (void *p1, void *p2)
150 vlib_main_t *vm = p1;
151 slave_if_t *sif = p2;
152 lacp_main_t *lm = &lacp_main;
154 if (!lacp_timer_is_running (sif->wait_while_timer))
155 lacp_start_wait_while_timer (lm->vlib_main, sif,
156 LACP_AGGREGATE_WAIT_TIME);
158 if ((sif->selected == LACP_PORT_SELECTED) && sif->ready)
159 lacp_machine_dispatch (&lacp_mux_machine, vm, sif,
160 LACP_MUX_EVENT_READY, &sif->mux_state);
162 if (sif->selected == LACP_PORT_UNSELECTED)
163 lacp_machine_dispatch (&lacp_mux_machine, vm, sif,
164 LACP_MUX_EVENT_UNSELECTED, &sif->mux_state);
170 lacp_mux_action_collecting_distributing (void *p1, void *p2)
172 vlib_main_t *vm = p1;
173 slave_if_t *sif = p2;
174 lacp_main_t *lm = &lacp_main;
176 sif->actor.state |= LACP_STATE_SYNCHRONIZATION | LACP_STATE_COLLECTING |
177 LACP_STATE_DISTRIBUTING;
178 bond_enable_collecting_distributing (vm, sif);
180 lacp_start_periodic_timer (lm->vlib_main, sif, 0);
181 if ((sif->selected == LACP_PORT_UNSELECTED) ||
182 (sif->selected == LACP_PORT_STANDBY) ||
183 !(sif->partner.state & LACP_STATE_SYNCHRONIZATION))
184 lacp_machine_dispatch (&lacp_mux_machine, vm, sif,
185 LACP_MUX_EVENT_UNSELECTED, &sif->mux_state);
192 format_mux_event (u8 * s, va_list * args)
194 static lacp_event_struct lacp_mux_event_array[] = {
195 #define _(b, s, n) {.bit = b, .str = #s, },
196 foreach_lacp_mux_event
200 int e = va_arg (*args, int);
201 lacp_event_struct *event_entry = lacp_mux_event_array;
203 if (e >= (sizeof (lacp_mux_event_array) / sizeof (*event_entry)))
204 s = format (s, "Bad event %d", e);
206 s = format (s, "%s", event_entry[e].str);
212 lacp_mux_debug_func (slave_if_t * sif, int event, int state,
213 lacp_fsm_state_t * transition)
215 vlib_worker_thread_t *w = vlib_worker_threads + os_get_thread_index ();
217 ELOG_TYPE_DECLARE (e) =
228 ed = ELOG_TRACK_DATA (&vlib_global_main.elog_main, e, w->elog_track);
230 elog_string (&vlib_global_main.elog_main, "%U-MUX: %U, %U->%U%c",
231 format_vnet_sw_if_index_name, vnet_get_main (),
232 sif->sw_if_index, format_mux_event, event,
233 format_mux_sm_state, state, format_mux_sm_state,
234 transition->next_state, 0);
238 lacp_init_mux_machine (vlib_main_t * vm, slave_if_t * sif)
240 lacp_machine_dispatch (&lacp_mux_machine, vm, sif, LACP_MUX_EVENT_BEGIN,
245 * fd.io coding-style-patch-verification: ON
248 * eval: (c-set-style "gnu")