Line data Source code
1 : /*
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:
6 : *
7 : * http://www.apache.org/licenses/LICENSE-2.0
8 : *
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.
14 : */
15 :
16 : #define _GNU_SOURCE
17 :
18 : #include <vlib/vlib.h>
19 : #include <vnet/bonding/node.h>
20 : #include <lacp/node.h>
21 :
22 : /*
23 : * LACP State = DETACHED
24 : */
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
32 : };
33 :
34 : /*
35 : * LACP State = WAITING
36 : */
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
44 : };
45 :
46 : /*
47 : * LACP State = ATTACHED
48 : */
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
56 : };
57 :
58 : /*
59 : * LACP State = COLLECTING_DISTRIBUTING
60 : */
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
68 : };
69 :
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},
75 : };
76 :
77 : lacp_machine_t lacp_mux_machine = {
78 : lacp_mux_fsm_table,
79 : lacp_mux_debug_func,
80 : };
81 :
82 : static void
83 27 : lacp_detach_mux_from_aggregator (vlib_main_t * vm, member_if_t * mif)
84 : {
85 27 : mif->actor.state &= ~LACP_STATE_SYNCHRONIZATION;
86 27 : mif->ready = 0;
87 27 : mif->ready_n = 0;
88 27 : }
89 :
90 : static void
91 8 : lacp_attach_mux_to_aggregator (vlib_main_t * vm, member_if_t * mif)
92 : {
93 8 : mif->actor.state |= LACP_STATE_SYNCHRONIZATION;
94 8 : }
95 :
96 : int
97 27 : lacp_mux_action_detached (void *p1, void *p2)
98 : {
99 27 : vlib_main_t *vm = p1;
100 27 : member_if_t *mif = p2;
101 :
102 27 : lacp_detach_mux_from_aggregator (vm, mif);
103 27 : mif->actor.state &= ~LACP_STATE_COLLECTING;
104 27 : bond_disable_collecting_distributing (vm, mif);
105 27 : mif->actor.state &= ~LACP_STATE_DISTRIBUTING;
106 27 : mif->ntt = 1;
107 27 : lacp_start_periodic_timer (vm, mif, 0);
108 :
109 27 : if (mif->selected == LACP_PORT_SELECTED)
110 0 : lacp_machine_dispatch (&lacp_mux_machine, vm, mif,
111 : LACP_MUX_EVENT_SELECTED, &mif->mux_state);
112 :
113 27 : if (mif->selected == LACP_PORT_STANDBY)
114 0 : lacp_machine_dispatch (&lacp_mux_machine, vm, mif, LACP_MUX_EVENT_STANDBY,
115 : &mif->mux_state);
116 :
117 27 : return 0;
118 : }
119 :
120 : int
121 8 : lacp_mux_action_attached (void *p1, void *p2)
122 : {
123 8 : vlib_main_t *vm = p1;
124 8 : member_if_t *mif = p2;
125 :
126 8 : lacp_attach_mux_to_aggregator (vm, mif);
127 8 : mif->actor.state &= ~LACP_STATE_COLLECTING;
128 8 : bond_disable_collecting_distributing (vm, mif);
129 8 : mif->actor.state &= ~LACP_STATE_DISTRIBUTING;
130 8 : mif->ntt = 1;
131 8 : lacp_start_periodic_timer (vm, mif, 0);
132 :
133 8 : if ((mif->selected == LACP_PORT_UNSELECTED) ||
134 8 : (mif->selected == LACP_PORT_STANDBY))
135 0 : lacp_machine_dispatch (&lacp_mux_machine, vm, mif,
136 : LACP_MUX_EVENT_UNSELECTED, &mif->mux_state);
137 :
138 8 : if ((mif->selected == LACP_PORT_SELECTED) &&
139 8 : (mif->partner.state & LACP_STATE_SYNCHRONIZATION))
140 4 : lacp_machine_dispatch (&lacp_mux_machine, vm, mif, LACP_MUX_EVENT_SYNC,
141 : &mif->mux_state);
142 8 : return 0;
143 : }
144 :
145 : int
146 5 : lacp_mux_action_waiting (void *p1, void *p2)
147 : {
148 5 : vlib_main_t *vm = p1;
149 5 : member_if_t *mif = p2;
150 :
151 5 : if (!lacp_timer_is_running (mif->wait_while_timer))
152 5 : lacp_start_wait_while_timer (vm, mif, LACP_AGGREGATE_WAIT_TIME);
153 :
154 5 : if ((mif->selected == LACP_PORT_SELECTED) && mif->ready)
155 3 : lacp_machine_dispatch (&lacp_mux_machine, vm, mif,
156 : LACP_MUX_EVENT_READY, &mif->mux_state);
157 :
158 5 : if (mif->selected == LACP_PORT_UNSELECTED)
159 0 : lacp_machine_dispatch (&lacp_mux_machine, vm, mif,
160 : LACP_MUX_EVENT_UNSELECTED, &mif->mux_state);
161 :
162 5 : return 0;
163 : }
164 :
165 : int
166 12 : lacp_mux_action_collecting_distributing (void *p1, void *p2)
167 : {
168 12 : vlib_main_t *vm = p1;
169 12 : member_if_t *mif = p2;
170 :
171 12 : mif->actor.state |= LACP_STATE_SYNCHRONIZATION | LACP_STATE_COLLECTING |
172 : LACP_STATE_DISTRIBUTING;
173 12 : bond_enable_collecting_distributing (vm, mif);
174 12 : mif->ntt = 1;
175 12 : lacp_start_periodic_timer (vm, mif, 0);
176 12 : if ((mif->selected == LACP_PORT_UNSELECTED) ||
177 12 : (mif->selected == LACP_PORT_STANDBY) ||
178 12 : !(mif->partner.state & LACP_STATE_SYNCHRONIZATION))
179 0 : lacp_machine_dispatch (&lacp_mux_machine, vm, mif,
180 : LACP_MUX_EVENT_UNSELECTED, &mif->mux_state);
181 :
182 :
183 12 : return 0;
184 : }
185 :
186 : static u8 *
187 35 : format_mux_event (u8 * s, va_list * args)
188 : {
189 : static lacp_event_struct lacp_mux_event_array[] = {
190 : #define _(b, s, n) {.bit = b, .str = #s, },
191 : foreach_lacp_mux_event
192 : #undef _
193 : {.str = NULL}
194 : };
195 35 : int e = va_arg (*args, int);
196 35 : lacp_event_struct *event_entry = lacp_mux_event_array;
197 :
198 35 : if (e >= (sizeof (lacp_mux_event_array) / sizeof (*event_entry)))
199 0 : s = format (s, "Bad event %d", e);
200 : else
201 35 : s = format (s, "%s", event_entry[e].str);
202 :
203 35 : return s;
204 : }
205 :
206 : void
207 35 : lacp_mux_debug_func (member_if_t * mif, int event, int state,
208 : lacp_fsm_state_t * transition)
209 : {
210 35 : vlib_worker_thread_t *w = vlib_worker_threads + os_get_thread_index ();
211 : /* *INDENT-OFF* */
212 : ELOG_TYPE_DECLARE (e) =
213 : {
214 : .format = "%s",
215 : .format_args = "T4",
216 : };
217 : /* *INDENT-ON* */
218 : struct
219 : {
220 : u32 event;
221 35 : } *ed = 0;
222 :
223 35 : ed = ELOG_TRACK_DATA (&vlib_global_main.elog_main, e, w->elog_track);
224 35 : ed->event =
225 35 : 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);
230 35 : }
231 :
232 : void
233 11 : lacp_init_mux_machine (vlib_main_t * vm, member_if_t * mif)
234 : {
235 11 : lacp_machine_dispatch (&lacp_mux_machine, vm, mif, LACP_MUX_EVENT_BEGIN,
236 : &mif->mux_state);
237 11 : }
238 :
239 : /*
240 : * fd.io coding-style-patch-verification: ON
241 : *
242 : * Local Variables:
243 : * eval: (c-set-style "gnu")
244 : * End:
245 : */
|