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