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 <vnet/bonding/node.h>
19 : #include <lacp/node.h>
20 :
21 : /*
22 : * LACP State = NO_PERIODIC
23 : */
24 : static lacp_fsm_state_t lacp_ptx_state_no_periodic[] = {
25 : {LACP_ACTION_NO_PERIODIC, LACP_PTX_STATE_NO_PERIODIC}, // event 0 NO_PERIODIC
26 : {LACP_ACTION_SLOW_PERIODIC, LACP_PTX_STATE_SLOW_PERIODIC}, // event 1 LONG_TIMEOUT
27 : {LACP_ACTION_NO_PERIODIC, LACP_PTX_STATE_NO_PERIODIC}, // event 2 TIMER_EXPIRED
28 : {LACP_ACTION_FAST_PERIODIC, LACP_PTX_STATE_FAST_PERIODIC}, // event 3 SHORT_TIMEOUT
29 : };
30 :
31 : /*
32 : * LACP State = FAST_PERIODIC
33 : */
34 : static lacp_fsm_state_t lacp_ptx_state_fast_periodic[] = {
35 : {LACP_ACTION_NO_PERIODIC, LACP_PTX_STATE_NO_PERIODIC}, // event 0 NO_PERIODIC
36 : {LACP_ACTION_SLOW_PERIODIC, LACP_PTX_STATE_SLOW_PERIODIC}, // event 1 LONG_TIMEOUT
37 : {LACP_ACTION_TIMER_EXPIRED, LACP_PTX_STATE_PERIODIC_TX}, // event 2 TIMER_EXPIRED
38 : {LACP_ACTION_FAST_PERIODIC, LACP_PTX_STATE_FAST_PERIODIC}, // event 3 SHORT_TIMEOUT
39 : };
40 :
41 : /*
42 : * LACP State = SLOW_PERIODIC
43 : */
44 : static lacp_fsm_state_t lacp_ptx_state_slow_periodic[] = {
45 : {LACP_ACTION_NO_PERIODIC, LACP_PTX_STATE_NO_PERIODIC}, // event 0 NO_PERIODIC
46 : {LACP_ACTION_SLOW_PERIODIC, LACP_PTX_STATE_SLOW_PERIODIC}, // event 1 LONG_TIMEOUT
47 : {LACP_ACTION_TIMER_EXPIRED, LACP_PTX_STATE_PERIODIC_TX}, // event 2 TIMER_EXPIRED
48 : {LACP_ACTION_FAST_PERIODIC, LACP_PTX_STATE_FAST_PERIODIC}, // event 3 SHORT_TIMEOUT
49 : };
50 :
51 : /*
52 : * LACP State = PERIODIC_TX
53 : */
54 : static lacp_fsm_state_t lacp_ptx_state_periodic_tx[] = {
55 : {LACP_ACTION_NO_PERIODIC, LACP_PTX_STATE_NO_PERIODIC}, // event 0 NO_PERIODIC
56 : {LACP_NOACTION, LACP_PTX_STATE_PERIODIC_TX}, // event 1 LONG_TIMEOUT
57 : {LACP_ACTION_TIMER_EXPIRED, LACP_PTX_STATE_PERIODIC_TX}, // event 2 TIMER_EXPIRED
58 : {LACP_NOACTION, LACP_PTX_STATE_PERIODIC_TX}, // event 3 SHORT_TIMEOUT
59 : };
60 :
61 :
62 : static lacp_fsm_machine_t lacp_ptx_fsm_table[] = {
63 : {lacp_ptx_state_no_periodic},
64 : {lacp_ptx_state_fast_periodic},
65 : {lacp_ptx_state_slow_periodic},
66 : {lacp_ptx_state_periodic_tx},
67 : };
68 :
69 : lacp_machine_t lacp_ptx_machine = {
70 : lacp_ptx_fsm_table,
71 : lacp_ptx_debug_func,
72 : };
73 :
74 : int
75 13 : lacp_ptx_action_no_periodic (void *p1, void *p2)
76 : {
77 13 : vlib_main_t *vm = p1;
78 13 : member_if_t *mif = p2;
79 :
80 13 : lacp_stop_timer (&mif->periodic_timer);
81 13 : lacp_ptx_post_short_timeout_event (vm, mif);
82 13 : return 0;
83 : }
84 :
85 : int
86 9 : lacp_ptx_action_slow_periodic (void *p1, void *p2)
87 : {
88 9 : vlib_main_t *vm = p1;
89 9 : member_if_t *mif = p2;
90 : u8 timer_expired;
91 :
92 9 : if (!(mif->partner.state & LACP_STATE_LACP_ACTIVITY) &&
93 9 : !(mif->actor.state & LACP_STATE_LACP_ACTIVITY))
94 0 : lacp_machine_dispatch (&lacp_ptx_machine, vm, mif,
95 : LACP_PTX_EVENT_NO_PERIODIC, &mif->ptx_state);
96 : else
97 : {
98 18 : if (lacp_timer_is_running (mif->periodic_timer) &&
99 9 : lacp_timer_is_expired (vm, mif->periodic_timer))
100 0 : timer_expired = 1;
101 : else
102 9 : timer_expired = 0;
103 :
104 9 : lacp_schedule_periodic_timer (vm, mif);
105 :
106 9 : if (timer_expired || (mif->partner.state & LACP_STATE_LACP_TIMEOUT))
107 0 : lacp_machine_dispatch (&lacp_ptx_machine, vm, mif,
108 : LACP_PTX_EVENT_TIMER_EXPIRED, &mif->ptx_state);
109 : }
110 :
111 9 : return 0;
112 : }
113 :
114 : int
115 20 : lacp_ptx_action_fast_periodic (void *p1, void *p2)
116 : {
117 20 : vlib_main_t *vm = p1;
118 20 : member_if_t *mif = p2;
119 : u8 timer_expired;
120 :
121 20 : if (!(mif->partner.state & LACP_STATE_LACP_ACTIVITY) &&
122 20 : !(mif->actor.state & LACP_STATE_LACP_ACTIVITY))
123 0 : lacp_machine_dispatch (&lacp_ptx_machine, vm, mif,
124 : LACP_PTX_EVENT_NO_PERIODIC, &mif->ptx_state);
125 : else
126 : {
127 29 : if (lacp_timer_is_running (mif->periodic_timer) &&
128 9 : lacp_timer_is_expired (vm, mif->periodic_timer))
129 9 : timer_expired = 1;
130 : else
131 11 : timer_expired = 0;
132 :
133 20 : lacp_start_periodic_timer (vm, mif, LACP_FAST_PERIODIC_TIMER);
134 :
135 20 : if (timer_expired)
136 9 : lacp_machine_dispatch (&lacp_ptx_machine, vm, mif,
137 : LACP_PTX_EVENT_TIMER_EXPIRED, &mif->ptx_state);
138 :
139 20 : if (!(mif->partner.state & LACP_STATE_LACP_TIMEOUT))
140 9 : lacp_machine_dispatch (&lacp_ptx_machine, vm, mif,
141 : LACP_PTX_EVENT_LONG_TIMEOUT, &mif->ptx_state);
142 : }
143 :
144 20 : return 0;
145 : }
146 :
147 : int
148 33 : lacp_ptx_action_timer_expired (void *p1, void *p2)
149 : {
150 33 : vlib_main_t *vm = p1;
151 33 : member_if_t *mif = p2;
152 :
153 33 : if (!(mif->partner.state & LACP_STATE_LACP_ACTIVITY) &&
154 11 : !(mif->actor.state & LACP_STATE_LACP_ACTIVITY))
155 0 : lacp_machine_dispatch (&lacp_ptx_machine, vm, mif,
156 : LACP_PTX_EVENT_NO_PERIODIC, &mif->ptx_state);
157 : else
158 : {
159 33 : mif->ntt = 1;
160 33 : lacp_machine_dispatch (&lacp_tx_machine, vm, mif, LACP_TX_EVENT_NTT,
161 : &mif->tx_state);
162 33 : if (mif->partner.state & LACP_STATE_LACP_TIMEOUT)
163 33 : lacp_machine_dispatch (&lacp_ptx_machine, vm, mif,
164 : LACP_PTX_EVENT_SHORT_TIMEOUT, &mif->ptx_state);
165 : else
166 0 : lacp_machine_dispatch (&lacp_ptx_machine, vm, mif,
167 : LACP_PTX_EVENT_LONG_TIMEOUT, &mif->ptx_state);
168 : }
169 :
170 33 : return 0;
171 : }
172 :
173 : static u8 *
174 70 : format_ptx_event (u8 * s, va_list * args)
175 : {
176 : static lacp_event_struct lacp_ptx_event_array[] = {
177 : #define _(b, s, n) {.bit = b, .str = #s, },
178 : foreach_lacp_ptx_event
179 : #undef _
180 : {.str = NULL}
181 : };
182 70 : int e = va_arg (*args, int);
183 70 : lacp_event_struct *event_entry = lacp_ptx_event_array;
184 :
185 70 : if (e >= (sizeof (lacp_ptx_event_array) / sizeof (*event_entry)))
186 0 : s = format (s, "Bad event %d", e);
187 : else
188 70 : s = format (s, "%s", event_entry[e].str);
189 :
190 70 : return s;
191 : }
192 :
193 : void
194 70 : lacp_ptx_debug_func (member_if_t * mif, int event, int state,
195 : lacp_fsm_state_t * transition)
196 : {
197 70 : vlib_worker_thread_t *w = vlib_worker_threads + os_get_thread_index ();
198 : /* *INDENT-OFF* */
199 : ELOG_TYPE_DECLARE (e) =
200 : {
201 : .format = "%s",
202 : .format_args = "T4",
203 : };
204 : /* *INDENT-ON* */
205 : struct
206 : {
207 : u32 event;
208 70 : } *ed = 0;
209 :
210 70 : ed = ELOG_TRACK_DATA (&vlib_global_main.elog_main, e, w->elog_track);
211 70 : ed->event =
212 70 : elog_string (&vlib_global_main.elog_main, "%U-PTX: %U, %U->%U%c",
213 : format_vnet_sw_if_index_name, vnet_get_main (),
214 : mif->sw_if_index, format_ptx_event, event,
215 : format_ptx_sm_state, state, format_ptx_sm_state,
216 : transition->next_state, 0);
217 70 : }
218 :
219 : void
220 11 : lacp_init_ptx_machine (vlib_main_t * vm, member_if_t * mif)
221 : {
222 11 : lacp_machine_dispatch (&lacp_ptx_machine, vm, mif,
223 : LACP_PTX_EVENT_NO_PERIODIC, &mif->ptx_state);
224 11 : }
225 :
226 : /*
227 : * fd.io coding-style-patch-verification: ON
228 : *
229 : * Local Variables:
230 : * eval: (c-set-style "gnu")
231 : * End:
232 : */
|