blob: ae811a12a64a72c545a44c3719fefc548372ac43 [file] [log] [blame]
Steven9cd2d7a2017-12-20 12:43:01 -08001/*
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#ifndef __included_vnet_bonding_node_h__
16#define __included_vnet_bonding_node_h__
17
18#include <vlib/vlib.h>
19#include <vlib/unix/unix.h>
20#include <vppinfra/format.h>
21#include <vppinfra/hash.h>
22#include <vnet/ethernet/ethernet.h>
23#include <vnet/interface.h>
24
25#define LACP_FAST_PERIODIC_TIMER 1.0
26#define LACP_SHORT_TIMOUT_TIME (LACP_FAST_PERIODIC_TIMER * 3)
27#define LACP_SLOW_PERIODIC_TIMER 30.0
28#define LACP_LONG_TIMOUT_TIME (LACP_SLOW_PERIODIC_TIMER * 3)
29
30#ifndef MIN
31#define MIN(x,y) (((x)<(y))?(x):(y))
32#endif
33
34#define foreach_bond_mode \
35 _ (1, ROUND_ROBIN, "round-robin") \
36 _ (2, ACTIVE_BACKUP, "active-backup") \
37 _ (3, XOR, "xor") \
38 _ (4, BROADCAST, "broadcast") \
39 _ (5, LACP, "lacp")
40
41typedef enum
42{
43#define _(v, f, s) BOND_MODE_##f = v,
44 foreach_bond_mode
45#undef _
46} bond_mode_t;
47
48/* configurable load-balances */
49#define foreach_bond_lb \
50 _ (2, L23, "l23", l23) \
51 _ (1, l34 , "l34", l34) \
52 _ (0, L2, "l2", l2)
53
54/* load-balance functions implemented in bond-output */
55#define foreach_bond_lb_algo \
56 _ (0, L2, "l2", l2) \
57 _ (1, l34 , "l34", l34) \
58 _ (2, L23, "l23", l23) \
59 _ (3, RR, "round-robin", round_robin) \
60 _ (4, BC, "broadcast", broadcast) \
61 _ (5, AB, "active-backup", active_backup)
62
63typedef enum
64{
65#define _(v, f, s, p) BOND_LB_##f = v,
66 foreach_bond_lb_algo
67#undef _
68} bond_load_balance_t;
69
70typedef struct
71{
72 u8 hw_addr_set;
73 u8 hw_addr[6];
74 u8 mode;
75 u8 lb;
76 /* return */
77 u32 sw_if_index;
78 int rv;
79 clib_error_t *error;
80} bond_create_if_args_t;
81
82typedef struct
83{
84 /* slave's sw_if_index */
85 u32 slave;
86 /* bond's sw_if_index */
87 u32 group;
88 u8 is_passive;
89 u8 is_long_timeout;
90 /* return */
91 int rv;
92 clib_error_t *error;
93} bond_enslave_args_t;
94
95typedef struct
96{
97 u32 slave;
98 /* return */
99 int rv;
100 clib_error_t *error;
101} bond_detach_slave_args_t;
102
103/** BOND interface details struct */
104typedef struct
105{
106 u32 sw_if_index;
107 u8 interface_name[64];
108 u8 mode;
109 u8 lb;
110 u32 active_slaves;
111 u32 slaves;
112} bond_interface_details_t;
113
114/** slave interface details struct */
115typedef struct
116{
117 u32 sw_if_index;
118 u8 interface_name[64];
119 u8 is_passive;
120 u8 is_long_timeout;
121 u32 active_slaves;
122} slave_interface_details_t;
123
124typedef CLIB_PACKED (struct
125 {
126 u16 system_priority;
127 u8 system[6];
128 u16 key; u16 port_priority; u16 port_number;
129 u8 state;
130 }) lacp_port_info_t;
131
132typedef struct
133{
Stevena005e7f2018-03-22 17:46:58 -0700134 vlib_frame_t **frame;
135
136} bond_if_per_thread_t;
137
138typedef struct
139{
Steven9cd2d7a2017-12-20 12:43:01 -0800140 u8 admin_up;
141 u8 mode;
142 u8 lb;
143
144 /* the last slave index for the rr lb */
145 u32 lb_rr_last_index;
146
147 u32 dev_instance;
148 u32 hw_if_index;
149 u32 sw_if_index;
150
151 /* Configured slaves */
152 u32 *slaves;
153
154 /* Slaves that are in DISTRIBUTING state */
155 u32 *active_slaves;
156
157 /* rapidly find an active slave */
158 uword *active_slave_by_sw_if_index;
159
160 lacp_port_info_t partner;
161 lacp_port_info_t actor;
162 u8 individual_aggregator;
163
164 u32 group;
165 uword *port_number_bitmap;
166 u8 use_custom_mac;
167 u8 hw_address[6];
Stevena005e7f2018-03-22 17:46:58 -0700168
169 clib_spinlock_t lockp;
170 bond_if_per_thread_t *per_thread_info;
Steven9cd2d7a2017-12-20 12:43:01 -0800171} bond_if_t;
172
173typedef struct
174{
175 u8 persistent_hw_address[6];
176
177 /* neighbor's vlib software interface index */
178 u32 sw_if_index;
179
180 /* Neighbor time-to-live (usually 3s) */
181 f32 ttl_in_seconds;
182
183 /* 1 = interface is configured with long timeout (60s) */
184 u8 is_long_timeout;
185
186 /* 1 = debug is on; 0 = debug is off */
187 u8 debug;
188
189 /* tx packet template id for this neighbor */
190 u8 packet_template_index;
191
192 /* Info we actually keep about each neighbor */
193
194 /* Jenkins hash optimization: avoid tlv scan, send short keepalive msg */
195 u8 last_packet_signature_valid;
196 uword last_packet_signature;
197
198 /* last received lacp packet, for the J-hash optimization */
199 u8 *last_rx_pkt;
200
201 /* last marker packet */
202 u8 *last_marker_pkt;
203
204 /* neighbor vlib hw_if_index */
205 u32 hw_if_index;
206
207 /* actor does not initiate the protocol exchange */
208 u8 is_passive;
209
210 /* Partner port information */
211 lacp_port_info_t partner;
212 lacp_port_info_t partner_admin;;
213
214 /* Partner port information */
215 lacp_port_info_t actor;
216 lacp_port_info_t actor_admin;
217
218 /* Need To Transmit flag */
219 u8 ntt;
220
221 /* Link has been established and Aggregate Port is operable */
222 u8 port_enabled;
223
224 /* Initialization or reinitialization of the lacp protocol entity */
225 u8 begin;
226
227 /* Aggregation Port is operating the lacp */
228 u8 lacp_enabled;
229
230 /* MUX to indicate to the Selection Logic wait_while_timer expired */
231 u8 ready_n;
232
233 /* Selection Logic indicates al Aggregation Ports attached */
234 u8 ready;
235
236 /* Selection Logic selected an Aggregator */
237 int selected;
238
239 /* RX machine indicates an Aggregation Port in PORT_DISABLED state */
240 u8 port_moved;
241
242 /* timer used to detect whether received protocol information has expired */
243 f64 current_while_timer;
244
245 /* timer used to detect actor churn states */
246 f64 actor_churn_timer;
247
248 /* time last lacpdu was sent */
249 f64 last_lacpdu_time;
250
251 /* timer used to generate periodic transmission */
252 f64 periodic_timer;
253
254 /* timer used to detect partner churn states */
255 f64 partner_churn_timer;
256
257 /* provides hysteresis before performing an aggregation change */
258 f64 wait_while_timer;
259
260 /* Implemention variables, not in the spec */
261 int rx_state;
262 int tx_state;
263 int mux_state;
264 int ptx_state;
265
266 /* actor admin key */
267 u32 group;
268
269 u32 marker_tx_id;
270
271 u32 bif_dev_instance;
272
273 u8 loopback_port;
274
275 /* bond mode */
276 u8 mode;
277
278 clib_spinlock_t lockp;
279} slave_if_t;
280
281typedef void (*lacp_enable_disable_func) (vlib_main_t * vm, bond_if_t * bif,
282 slave_if_t * sif, u8 enable);
283
284typedef struct
285{
286 /* pool of bonding interfaces */
287 bond_if_t *interfaces;
288
289 /* pool of lacp neighbors */
290 slave_if_t *neighbors;
291
292 /* rapidly find a neighbor by vlib software interface index */
293 uword *neighbor_by_sw_if_index;
294
295 /* rapidly find a bond by vlib software interface index */
296 uword *bond_by_sw_if_index;
297
298 /* convenience variables */
299 vlib_main_t *vlib_main;
300 vnet_main_t *vnet_main;
301
302 /* lacp plugin is loaded */
303 u8 lacp_plugin_loaded;
304
305 lacp_enable_disable_func lacp_enable_disable;
306} bond_main_t;
307
308/* bond packet trace capture */
309typedef struct
310{
311 ethernet_header_t ethernet;
312 u32 sw_if_index;
313 u32 bond_sw_if_index;
314} bond_packet_trace_t;
315
316typedef u32 (*load_balance_func) (vlib_main_t * vm,
317 vlib_node_runtime_t * node, bond_if_t * bif,
318 vlib_buffer_t * b0);
319
320typedef struct
321{
322 load_balance_func load_balance;
323} bond_load_balance_func_t;
324
325extern vlib_node_registration_t bond_input_node;
326extern vnet_device_class_t bond_dev_class;
327extern bond_main_t bond_main;
328
329void bond_disable_collecting_distributing (vlib_main_t * vm,
330 slave_if_t * sif);
331void bond_enable_collecting_distributing (vlib_main_t * vm, slave_if_t * sif);
332u8 *format_bond_interface_name (u8 * s, va_list * args);
333
334void bond_create_if (vlib_main_t * vm, bond_create_if_args_t * args);
335int bond_delete_if (vlib_main_t * vm, u32 sw_if_index);
336void bond_enslave (vlib_main_t * vm, bond_enslave_args_t * args);
337void bond_detach_slave (vlib_main_t * vm, bond_detach_slave_args_t * args);
338int bond_dump_ifs (bond_interface_details_t ** out_bondids);
339int bond_dump_slave_ifs (slave_interface_details_t ** out_slaveids,
340 u32 bond_sw_if_index);
341
342static inline uword
343unformat_bond_mode (unformat_input_t * input, va_list * args)
344{
345 u8 *r = va_arg (*args, u8 *);
346
347 if (0);
348#define _(v, f, s) else if (unformat (input, s)) *r = BOND_MODE_##f;
349 foreach_bond_mode
350#undef _
351 else
352 return 0;
353
354 return 1;
355}
356
357static inline u8 *
358format_bond_mode (u8 * s, va_list * args)
359{
360 u32 i = va_arg (*args, u32);
361 u8 *t = 0;
362
363 switch (i)
364 {
365#define _(v, f, s) case BOND_MODE_##f: t = (u8 *) s; break;
366 foreach_bond_mode
367#undef _
368 default:
369 return format (s, "unknown");
370 }
371 return format (s, "%s", t);
372}
373
374static inline uword
375unformat_bond_load_balance (unformat_input_t * input, va_list * args)
376{
377 u8 *r = va_arg (*args, u8 *);
378
379 if (0);
380#define _(v, f, s, p) else if (unformat (input, s)) *r = BOND_LB_##f;
381 foreach_bond_lb
382#undef _
383 else
384 return 0;
385
386 return 1;
387}
388
389static inline u8 *
390format_bond_load_balance (u8 * s, va_list * args)
391{
392 u32 i = va_arg (*args, u32);
393 u8 *t = 0;
394
395 switch (i)
396 {
397#define _(v, f, s, p) case BOND_LB_##f: t = (u8 *) s; break;
398 foreach_bond_lb_algo
399#undef _
400 default:
401 return format (s, "unknown");
402 }
403 return format (s, "%s", t);
404}
405
406static inline void
407bond_register_callback (lacp_enable_disable_func func)
408{
409 bond_main_t *bm = &bond_main;
410
411 bm->lacp_plugin_loaded = 1;
412 bm->lacp_enable_disable = func;
413}
414
415static inline bond_if_t *
416bond_get_master_by_sw_if_index (u32 sw_if_index)
417{
418 bond_main_t *bm = &bond_main;
419 uword *p;
420
421 p = hash_get (bm->bond_by_sw_if_index, sw_if_index);
422 if (!p)
423 {
424 return 0;
425 }
426 return pool_elt_at_index (bm->interfaces, p[0]);
427}
428
429static inline bond_if_t *
430bond_get_master_by_dev_instance (u32 dev_instance)
431{
432 bond_main_t *bm = &bond_main;
433
434 return pool_elt_at_index (bm->interfaces, dev_instance);
435}
436
437static inline slave_if_t *
438bond_get_slave_by_sw_if_index (u32 sw_if_index)
439{
440 bond_main_t *bm = &bond_main;
441 slave_if_t *sif = 0;
442 uword *p;
443
444 p = hash_get (bm->neighbor_by_sw_if_index, sw_if_index);
445 if (p)
446 {
447 sif = pool_elt_at_index (bm->neighbors, p[0]);
448 }
449 return sif;
450}
451
452#endif /* __included_vnet_bonding_node_h__ */
453
454/*
455 * fd.io coding-style-patch-verification: ON
456 *
457 * Local Variables:
458 * eval: (c-set-style "gnu")
459 * End:
460 */