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