lacp: convert clib_warning to event logger
[vpp.git] / src / plugins / lacp / mux_machine.c
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 lacp_detach_mux_from_aggregator (vlib_main_t * vm, slave_if_t * sif)
84 {
85   sif->actor.state &= ~LACP_STATE_SYNCHRONIZATION;
86   sif->ready = 0;
87   sif->ready_n = 0;
88 }
89
90 static void
91 lacp_attach_mux_to_aggregator (vlib_main_t * vm, slave_if_t * sif)
92 {
93   sif->actor.state |= LACP_STATE_SYNCHRONIZATION;
94 }
95
96 int
97 lacp_mux_action_detached (void *p1, void *p2)
98 {
99   vlib_main_t *vm = p1;
100   slave_if_t *sif = p2;
101   lacp_main_t *lm = &lacp_main;
102
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;
107   sif->ntt = 1;
108   lacp_start_periodic_timer (lm->vlib_main, sif, 0);
109
110   if (sif->selected == LACP_PORT_SELECTED)
111     lacp_machine_dispatch (&lacp_mux_machine, vm, sif,
112                            LACP_MUX_EVENT_SELECTED, &sif->mux_state);
113
114   if (sif->selected == LACP_PORT_STANDBY)
115     lacp_machine_dispatch (&lacp_mux_machine, vm, sif, LACP_MUX_EVENT_STANDBY,
116                            &sif->mux_state);
117
118   return 0;
119 }
120
121 int
122 lacp_mux_action_attached (void *p1, void *p2)
123 {
124   vlib_main_t *vm = p1;
125   slave_if_t *sif = p2;
126   lacp_main_t *lm = &lacp_main;
127
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;
132   sif->ntt = 1;
133   lacp_start_periodic_timer (lm->vlib_main, sif, 0);
134
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);
139
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,
143                            &sif->mux_state);
144   return 0;
145 }
146
147 int
148 lacp_mux_action_waiting (void *p1, void *p2)
149 {
150   vlib_main_t *vm = p1;
151   slave_if_t *sif = p2;
152   lacp_main_t *lm = &lacp_main;
153
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);
157
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);
161
162   if (sif->selected == LACP_PORT_UNSELECTED)
163     lacp_machine_dispatch (&lacp_mux_machine, vm, sif,
164                            LACP_MUX_EVENT_UNSELECTED, &sif->mux_state);
165
166   return 0;
167 }
168
169 int
170 lacp_mux_action_collecting_distributing (void *p1, void *p2)
171 {
172   vlib_main_t *vm = p1;
173   slave_if_t *sif = p2;
174   lacp_main_t *lm = &lacp_main;
175
176   sif->actor.state |= LACP_STATE_SYNCHRONIZATION | LACP_STATE_COLLECTING |
177     LACP_STATE_DISTRIBUTING;
178   bond_enable_collecting_distributing (vm, sif);
179   sif->ntt = 1;
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);
186
187
188   return 0;
189 }
190
191 static u8 *
192 format_mux_event (u8 * s, va_list * args)
193 {
194   static lacp_event_struct lacp_mux_event_array[] = {
195 #define _(b, s, n) {.bit = b, .str = #s, },
196     foreach_lacp_mux_event
197 #undef _
198     {.str = NULL}
199   };
200   int e = va_arg (*args, int);
201   lacp_event_struct *event_entry = lacp_mux_event_array;
202
203   if (e >= (sizeof (lacp_mux_event_array) / sizeof (*event_entry)))
204     s = format (s, "Bad event %d", e);
205   else
206     s = format (s, "%s", event_entry[e].str);
207
208   return s;
209 }
210
211 void
212 lacp_mux_debug_func (slave_if_t * sif, int event, int state,
213                      lacp_fsm_state_t * transition)
214 {
215   vlib_worker_thread_t *w = vlib_worker_threads + os_get_thread_index ();
216   /* *INDENT-OFF* */
217   ELOG_TYPE_DECLARE (e) =
218     {
219       .format = "%s",
220       .format_args = "T4",
221     };
222   /* *INDENT-ON* */
223   struct
224   {
225     u32 event;
226   } *ed = 0;
227
228   ed = ELOG_TRACK_DATA (&vlib_global_main.elog_main, e, w->elog_track);
229   ed->event =
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);
235 }
236
237 void
238 lacp_init_mux_machine (vlib_main_t * vm, slave_if_t * sif)
239 {
240   lacp_machine_dispatch (&lacp_mux_machine, vm, sif, LACP_MUX_EVENT_BEGIN,
241                          &sif->mux_state);
242 }
243
244 /*
245  * fd.io coding-style-patch-verification: ON
246  *
247  * Local Variables:
248  * eval: (c-set-style "gnu")
249  * End:
250  */