docs: Use newer Ubuntu LTS in tutorial
[vpp.git] / src / plugins / vrrp / vrrp.h
1
2 /*
3  * vrrp.h - vrrp plug-in header file
4  *
5  * Copyright 2019-2020 Rubicon Communications, LLC (Netgate)
6  *
7  * SPDX-License-Identifier: Apache-2.0
8  *
9  */
10 #ifndef __included_vrrp_h__
11 #define __included_vrrp_h__
12
13 #include <vnet/vnet.h>
14 #include <vnet/ip/ip.h>
15 #include <vnet/ethernet/ethernet.h>
16
17 #include <vppinfra/hash.h>
18 #include <vppinfra/error.h>
19
20 /* VRRP configuration */
21 typedef enum vrrp_vr_flags
22 {
23   VRRP_VR_PREEMPT = 0x1,
24   VRRP_VR_ACCEPT = 0x2,
25   VRRP_VR_UNICAST = 0x4,
26   VRRP_VR_IPV6 = 0x8,
27 } vrrp_vr_flags_t;
28
29 typedef struct vrrp_vr_key
30 {
31   u32 sw_if_index;
32   u8 vr_id;
33   u8 is_ipv6;
34 } vrrp_vr_key_t;
35
36 typedef CLIB_PACKED
37 (struct vrrp4_arp_key {
38   union {
39     struct {
40       u32 sw_if_index;
41       ip4_address_t addr;
42     };
43     u64 as_u64;
44   };
45 }) vrrp4_arp_key_t;
46
47 typedef CLIB_PACKED
48 (struct vrrp6_nd_key {
49   u32 sw_if_index;
50   ip6_address_t addr;
51 }) vrrp6_nd_key_t;
52
53 typedef struct vrrp_vr_tracking_if
54 {
55   u32 sw_if_index;
56   u8 priority;
57 } vrrp_vr_tracking_if_t;
58
59 typedef struct vrrp_vr_tracking
60 {
61   vrrp_vr_tracking_if_t *interfaces;
62   u32 interfaces_dec;
63 } vrrp_vr_tracking_t;
64
65 typedef struct vrrp_vr_config
66 {
67   u32 sw_if_index;
68   u8 vr_id;
69   u8 priority;
70   u16 adv_interval;
71   vrrp_vr_flags_t flags;
72   ip46_address_t *vr_addrs;
73   ip46_address_t *peer_addrs;
74 } vrrp_vr_config_t;
75
76 #define foreach_vrrp_vr_state           \
77 _(0, INIT, "Initialize")                \
78 _(1, BACKUP, "Backup")                  \
79 _(2, MASTER, "Master")                  \
80 _(3, INTF_DOWN, "Interface Down")
81
82 /* VRRP runtime data */
83 typedef enum vrrp_vr_state
84 {
85 #define _(v,f,n) VRRP_VR_STATE_##f = v,
86   foreach_vrrp_vr_state
87 #undef _
88 } vrrp_vr_state_t;
89
90 typedef struct vrrp_vr_runtime
91 {
92   vrrp_vr_state_t state;
93   u16 master_adv_int;
94   u16 skew;
95   u16 master_down_int;
96   mac_address_t mac;
97   f64 last_sent;
98   u32 timer_index;
99 } vrrp_vr_runtime_t;
100
101 /* Per-VR data */
102 typedef struct vrrp_vr
103 {
104   vrrp_vr_config_t config;
105   vrrp_vr_runtime_t runtime;
106   vrrp_vr_tracking_t tracking;
107   u32 stat_index;
108 } vrrp_vr_t;
109
110 /* Timers */
111 typedef enum vrrp_vr_timer_type
112 {
113   VRRP_VR_TIMER_ADV,
114   VRRP_VR_TIMER_MASTER_DOWN,
115 } vrrp_vr_timer_type_t;
116
117 typedef struct vrrp_vr_timer
118 {
119   u32 vr_index;
120   f64 expire_time;              /* monotonic, relative to vlib_time_now() */
121   vrrp_vr_timer_type_t type;
122 } vrrp_vr_timer_t;
123
124 typedef struct
125 {
126   /* vectors of vr indices which are configured on this interface
127    * 0 -> ipv4, 1 -> ipv6 */
128   u32 *vr_indices[2];
129
130   /* vector of VR indices which track the state of this interface
131    * 0 -> ipv4, 1*/
132   u32 *tracking_vrs[2];
133
134   /* multicast adjacency indices. 0 -> ipv4, 1 -> ipv6 */
135   adj_index_t mcast_adj_index[2];
136
137   /* number of VRs in master state on sw intf. 0 -> ipv4, 1 -> ipv6 */
138   u8 n_master_vrs[2];
139
140 } vrrp_intf_t;
141
142 typedef struct
143 {
144   /* API message ID base */
145   u16 msg_id_base;
146
147   /* pool of VRs */
148   vrrp_vr_t *vrs;
149
150   /* pool of timers and ordered vector of pool indices */
151   vrrp_vr_timer_t *vr_timers;
152   u32 *pending_timers;
153
154   /* number of running VRs - don't register for VRRP proto if not running */
155   u16 n_vrs_started;
156
157   /* hash mapping a VR key to a pool entry */
158   mhash_t vr_index_by_key;
159
160   /* hashes mapping sw_if_index and address to a vr index */
161   uword *vrrp4_arp_lookup;
162   uword *vrrp6_nd_lookup;
163
164   /* vector of interface data indexed by sw_if_index */
165   vrrp_intf_t *vrrp_intfs;
166
167   /* convenience */
168   vlib_main_t *vlib_main;
169   vnet_main_t *vnet_main;
170   ethernet_main_t *ethernet_main;
171
172   u32 intf_output_node_idx;
173 } vrrp_main_t;
174
175 extern vrrp_main_t vrrp_main;
176
177 extern vlib_node_registration_t vrrp_node;
178 extern vlib_node_registration_t vrrp_periodic_node;
179
180 /* Periodic function events */
181 #define VRRP_EVENT_VR_TIMER_UPDATE 1
182 #define VRRP_EVENT_VR_STOP 2
183 #define VRRP_EVENT_PERIODIC_ENABLE_DISABLE 3
184
185 /* global error counter types */
186 #define foreach_vrrp_err_counter                                              \
187   _ (CHKSUM, 0)                                                               \
188   _ (VERSION, 1)                                                              \
189   _ (VRID, 2)                                                                 \
190   _ (TTL, 3)                                                                  \
191   _ (ADDR_LIST, 4)                                                            \
192   _ (PKT_LEN, 5)
193
194 typedef enum vrrp_err_counter_
195 {
196 #define _(sym, val) VRRP_ERR_COUNTER_##sym = val,
197   foreach_vrrp_err_counter
198 #undef _
199 } vrrp_err_counter_t;
200
201 #define VRRP_ERR_COUNTER_MAX 6
202
203 /* per-instance stats */
204 #define foreach_vrrp_stat_counter                                             \
205   _ (MASTER_TRANS, 0)                                                         \
206   _ (ADV_SENT, 1)                                                             \
207   _ (ADV_RCVD, 2)                                                             \
208   _ (PRIO0_SENT, 3)                                                           \
209   _ (PRIO0_RCVD, 4)
210
211 typedef enum vrrp_stat_counter_
212 {
213 #define _(sym, val) VRRP_STAT_COUNTER_##sym = val,
214   foreach_vrrp_stat_counter
215 #undef _
216 } vrrp_stat_counter_t;
217
218 #define VRRP_STAT_COUNTER_MAX 5
219
220 clib_error_t *vrrp_plugin_api_hookup (vlib_main_t * vm);
221
222 int vrrp_vr_add_del (u8 is_add, vrrp_vr_config_t *conf, index_t *ret_index);
223 int vrrp_vr_update (index_t *vrrp_index, vrrp_vr_config_t *vr_conf);
224 int vrrp_vr_del (index_t vrrp_index);
225 int vrrp_vr_start_stop (u8 is_start, vrrp_vr_key_t * vr_key);
226 extern u8 *format_vrrp_vr (u8 * s, va_list * args);
227 extern u8 *format_vrrp_vr_key (u8 * s, va_list * args);
228 extern u8 *format_vrrp_vr_state (u8 * s, va_list * args);
229 extern u8 *format_vrrp_packet_hdr (u8 * s, va_list * args);
230 void vrrp_vr_timer_set (vrrp_vr_t * vr, vrrp_vr_timer_type_t type);
231 void vrrp_vr_timer_cancel (vrrp_vr_t * vr);
232 void vrrp_vr_transition (vrrp_vr_t * vr, vrrp_vr_state_t new_state,
233                          void *data);
234 int vrrp_vr_set_peers (vrrp_vr_key_t * key, ip46_address_t * peers);
235 int vrrp_vr_multicast_group_join (vrrp_vr_t * vr);
236 int vrrp_adv_send (vrrp_vr_t * vr, int shutdown);
237 int vrrp_garp_or_na_send (vrrp_vr_t * vr);
238 u16 vrrp_adv_csum (void *l3_hdr, void *payload, u8 is_ipv6, u16 len);
239 int vrrp_vr_tracking_if_add_del (vrrp_vr_t * vr, u32 sw_if_index,
240                                  u8 priority, u8 is_add);
241 int vrrp_vr_tracking_ifs_add_del (vrrp_vr_t * vr,
242                                   vrrp_vr_tracking_if_t * track_ifs,
243                                   u8 is_add);
244 void vrrp_vr_event (vrrp_vr_t * vr, vrrp_vr_state_t new_state);
245
246 // stats
247 void vrrp_incr_err_counter (vrrp_err_counter_t err_type);
248 void vrrp_incr_stat_counter (vrrp_stat_counter_t stat_type, u32 stat_index);
249
250 always_inline void
251 vrrp_vr_skew_compute (vrrp_vr_t * vr)
252 {
253   vrrp_vr_config_t *vrc = &vr->config;
254   vrrp_vr_runtime_t *vrt = &vr->runtime;
255
256   vrt->skew = (((256 - vrc->priority) * vrt->master_adv_int) / 256);
257 }
258
259 always_inline void
260 vrrp_vr_master_down_compute (vrrp_vr_t * vr)
261 {
262   vrrp_vr_runtime_t *vrt = &vr->runtime;
263
264   vrt->master_down_int = (3 * vrt->master_adv_int) + vrt->skew;
265 }
266
267 always_inline vrrp_vr_t *
268 vrrp_vr_lookup (u32 sw_if_index, u8 vr_id, u8 is_ipv6)
269 {
270   vrrp_main_t *vmp = &vrrp_main;
271   vrrp_vr_key_t key;
272   uword *p;
273
274   clib_memset (&key, 0, sizeof (key));
275
276   key.sw_if_index = sw_if_index;
277   key.vr_id = vr_id;
278   key.is_ipv6 = (is_ipv6 != 0);
279
280   p = mhash_get (&vmp->vr_index_by_key, &key);
281   if (p)
282     return pool_elt_at_index (vmp->vrs, p[0]);
283
284   return 0;
285 }
286
287 always_inline vrrp_vr_t *
288 vrrp_vr_lookup_index (u32 vr_index)
289 {
290   vrrp_main_t *vmp = &vrrp_main;
291
292   if (pool_is_free_index (vmp->vrs, vr_index))
293     return 0;
294
295   return pool_elt_at_index (vmp->vrs, vr_index);
296 }
297
298 always_inline u32
299 vrrp_vr_lookup_address (u32 sw_if_index, u8 is_ipv6, void *addr)
300 {
301   vrrp_main_t *vmp = &vrrp_main;
302   uword *p;
303   vrrp4_arp_key_t key4;
304   vrrp6_nd_key_t key6;
305
306   if (is_ipv6)
307     {
308       key6.sw_if_index = sw_if_index;
309       key6.addr = ((ip6_address_t *) addr)[0];
310       p = hash_get_mem (vmp->vrrp6_nd_lookup, &key6);
311     }
312   else
313     {
314       key4.sw_if_index = sw_if_index;
315       key4.addr = ((ip4_address_t *) addr)[0];
316       p = hash_get (vmp->vrrp4_arp_lookup, key4.as_u64);
317     }
318
319   if (p)
320     return p[0];
321
322   return ~0;
323 }
324
325 always_inline vrrp_intf_t *
326 vrrp_intf_get (u32 sw_if_index)
327 {
328   vrrp_main_t *vrm = &vrrp_main;
329
330   if (sw_if_index == ~0)
331     return NULL;
332
333   vec_validate (vrm->vrrp_intfs, sw_if_index);
334   return vec_elt_at_index (vrm->vrrp_intfs, sw_if_index);
335 }
336
337 always_inline int
338 vrrp_intf_num_vrs (u32 sw_if_index, u8 is_ipv6)
339 {
340   vrrp_intf_t *intf = vrrp_intf_get (sw_if_index);
341
342   if (intf)
343     return vec_len (intf->vr_indices[is_ipv6]);
344
345   return 0;
346 }
347
348 always_inline u8
349 vrrp_vr_is_ipv6 (vrrp_vr_t * vr)
350 {
351   return ((vr->config.flags & VRRP_VR_IPV6) != 0);
352 }
353
354 always_inline u8
355 vrrp_vr_is_unicast (vrrp_vr_t * vr)
356 {
357   return ((vr->config.flags & VRRP_VR_UNICAST) != 0);
358 }
359
360 always_inline u8
361 vrrp_vr_is_owner (vrrp_vr_t * vr)
362 {
363   return (vr->config.priority == 255);
364 }
365
366 always_inline u8
367 vrrp_vr_n_vr_addrs (vrrp_vr_t * vr)
368 {
369   return vec_len (vr->config.vr_addrs);
370 }
371
372 always_inline u8
373 vrrp_vr_n_peer_addrs (vrrp_vr_t * vr)
374 {
375   return vec_len (vr->config.peer_addrs);
376 }
377
378 always_inline u8
379 vrrp_vr_accept_mode_enabled (vrrp_vr_t * vr)
380 {
381   return ((vr->config.flags & VRRP_VR_ACCEPT) != 0);
382 }
383
384 always_inline u32
385 vrrp_vr_index (vrrp_vr_t * vr)
386 {
387   vrrp_main_t *vmp = &vrrp_main;
388
389   return vr - vmp->vrs;
390 }
391
392 always_inline u8
393 vrrp_vr_priority (vrrp_vr_t * vr)
394 {
395   u8 rv;
396
397   if (vr->tracking.interfaces_dec < (u32) vr->config.priority)
398     rv = vr->config.priority - vr->tracking.interfaces_dec;
399   else
400     rv = 1;
401
402   return rv;
403 }
404
405 #endif /* __included_vrrp_h__ */
406
407 /*
408  * fd.io coding-style-patch-verification: ON
409  *
410  * Local Variables:
411  * eval: (c-set-style "gnu")
412  * End:
413  */