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, member_if_t * mif)
85 mif->actor.state &= ~LACP_STATE_SYNCHRONIZATION;
91 lacp_attach_mux_to_aggregator (vlib_main_t * vm, member_if_t * mif)
93 mif->actor.state |= LACP_STATE_SYNCHRONIZATION;
97 lacp_mux_action_detached (void *p1, void *p2)
100 member_if_t *mif = p2;
102 lacp_detach_mux_from_aggregator (vm, mif);
103 mif->actor.state &= ~LACP_STATE_COLLECTING;
104 bond_disable_collecting_distributing (vm, mif);
105 mif->actor.state &= ~LACP_STATE_DISTRIBUTING;
107 lacp_start_periodic_timer (vm, mif, 0);
109 if (mif->selected == LACP_PORT_SELECTED)
110 lacp_machine_dispatch (&lacp_mux_machine, vm, mif,
111 LACP_MUX_EVENT_SELECTED, &mif->mux_state);
113 if (mif->selected == LACP_PORT_STANDBY)
114 lacp_machine_dispatch (&lacp_mux_machine, vm, mif, LACP_MUX_EVENT_STANDBY,
121 lacp_mux_action_attached (void *p1, void *p2)
123 vlib_main_t *vm = p1;
124 member_if_t *mif = p2;
126 lacp_attach_mux_to_aggregator (vm, mif);
127 mif->actor.state &= ~LACP_STATE_COLLECTING;
128 bond_disable_collecting_distributing (vm, mif);
129 mif->actor.state &= ~LACP_STATE_DISTRIBUTING;
131 lacp_start_periodic_timer (vm, mif, 0);
133 if ((mif->selected == LACP_PORT_UNSELECTED) ||
134 (mif->selected == LACP_PORT_STANDBY))
135 lacp_machine_dispatch (&lacp_mux_machine, vm, mif,
136 LACP_MUX_EVENT_UNSELECTED, &mif->mux_state);
138 if ((mif->selected == LACP_PORT_SELECTED) &&
139 (mif->partner.state & LACP_STATE_SYNCHRONIZATION))
140 lacp_machine_dispatch (&lacp_mux_machine, vm, mif, LACP_MUX_EVENT_SYNC,
146 lacp_mux_action_waiting (void *p1, void *p2)
148 vlib_main_t *vm = p1;
149 member_if_t *mif = p2;
151 if (!lacp_timer_is_running (mif->wait_while_timer))
152 lacp_start_wait_while_timer (vm, mif, LACP_AGGREGATE_WAIT_TIME);
154 if ((mif->selected == LACP_PORT_SELECTED) && mif->ready)
155 lacp_machine_dispatch (&lacp_mux_machine, vm, mif,
156 LACP_MUX_EVENT_READY, &mif->mux_state);
158 if (mif->selected == LACP_PORT_UNSELECTED)
159 lacp_machine_dispatch (&lacp_mux_machine, vm, mif,
160 LACP_MUX_EVENT_UNSELECTED, &mif->mux_state);
166 lacp_mux_action_collecting_distributing (void *p1, void *p2)
168 vlib_main_t *vm = p1;
169 member_if_t *mif = p2;
171 mif->actor.state |= LACP_STATE_SYNCHRONIZATION | LACP_STATE_COLLECTING |
172 LACP_STATE_DISTRIBUTING;
173 bond_enable_collecting_distributing (vm, mif);
175 lacp_start_periodic_timer (vm, mif, 0);
176 if ((mif->selected == LACP_PORT_UNSELECTED) ||
177 (mif->selected == LACP_PORT_STANDBY) ||
178 !(mif->partner.state & LACP_STATE_SYNCHRONIZATION))
179 lacp_machine_dispatch (&lacp_mux_machine, vm, mif,
180 LACP_MUX_EVENT_UNSELECTED, &mif->mux_state);
187 format_mux_event (u8 * s, va_list * args)
189 static lacp_event_struct lacp_mux_event_array[] = {
190 #define _(b, s, n) {.bit = b, .str = #s, },
191 foreach_lacp_mux_event
195 int e = va_arg (*args, int);
196 lacp_event_struct *event_entry = lacp_mux_event_array;
198 if (e >= (sizeof (lacp_mux_event_array) / sizeof (*event_entry)))
199 s = format (s, "Bad event %d", e);
201 s = format (s, "%s", event_entry[e].str);
207 lacp_mux_debug_func (member_if_t * mif, int event, int state,
208 lacp_fsm_state_t * transition)
210 vlib_worker_thread_t *w = vlib_worker_threads + os_get_thread_index ();
212 ELOG_TYPE_DECLARE (e) =
223 ed = ELOG_TRACK_DATA (&vlib_global_main.elog_main, e, w->elog_track);
225 elog_string (&vlib_global_main.elog_main, "%U-MUX: %U, %U->%U%c",
226 format_vnet_sw_if_index_name, vnet_get_main (),
227 mif->sw_if_index, format_mux_event, event,
228 format_mux_sm_state, state, format_mux_sm_state,
229 transition->next_state, 0);
233 lacp_init_mux_machine (vlib_main_t * vm, member_if_t * mif)
235 lacp_machine_dispatch (&lacp_mux_machine, vm, mif, LACP_MUX_EVENT_BEGIN,
240 * fd.io coding-style-patch-verification: ON
243 * eval: (c-set-style "gnu")