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