summaryrefslogtreecommitdiffstats
path: root/vrrpd/vrrp.h
blob: 0ac9b1f49c1a0ec9fb95bf136dd26263ecc43833 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * VRRP global definitions and state machine.
 * Copyright (C) 2018-2019 Cumulus Networks, Inc.
 * Quentin Young
 */
#ifndef __VRRP_H__
#define __VRRP_H__

#include <zebra.h>
#include <netinet/ip.h>

#include "lib/memory.h"
#include "lib/hash.h"
#include "lib/hook.h"
#include "lib/if.h"
#include "lib/linklist.h"
#include "lib/northbound.h"
#include "lib/privs.h"
#include "lib/stream.h"
#include "lib/frrevent.h"
#include "lib/vty.h"

/* Global definitions */
#define VRRP_RADV_INT 16
#define VRRP_PRIO_MASTER 255
#define VRRP_MCASTV4_GROUP_STR "224.0.0.18"
#define VRRP_MCASTV6_GROUP_STR "ff02:0:0:0:0:0:0:12"
#define VRRP_MCASTV4_GROUP 0xe0000012
#define VRRP_MCASTV6_GROUP 0xff020000000000000000000000000012
#define IPPROTO_VRRP 112

#define VRRP_LOGPFX_VRID "[VRID %u] "
#define VRRP_LOGPFX_FAM "[%s] "

/* Default defaults */
#define VRRP_XPATH_FULL "/frr-interface:lib/interface/frr-vrrpd:vrrp/vrrp-group"
#define VRRP_XPATH "./frr-vrrpd:vrrp/vrrp-group"
#define VRRP_DEFAULT_PRIORITY 100
#define VRRP_DEFAULT_ADVINT 100
#define VRRP_DEFAULT_PREEMPT true
#define VRRP_DEFAULT_ACCEPT true
#define VRRP_DEFAULT_CHECKSUM_WITH_IPV4_PSEUDOHEADER true
#define VRRP_DEFAULT_SHUTDOWN false

/* User compatibility constant */
#define CS2MS 10

DECLARE_MGROUP(VRRPD);

/* Northbound */
extern const struct frr_yang_module_info frr_vrrpd_info;

/* Configured defaults */
struct vrrp_defaults {
	uint8_t version;
	uint8_t priority;
	uint16_t advertisement_interval;
	bool preempt_mode;
	bool accept_mode;
	bool checksum_with_ipv4_pseudoheader;
	bool shutdown;
};

extern struct vrrp_defaults vd;

/* threadmaster */
extern struct event_loop *master;

/* privileges */
extern struct zebra_privs_t vrrp_privs;

/* Global hash of all Virtual Routers */
extern struct hash *vrrp_vrouters_hash;

/*
 * VRRP Router.
 *
 * This struct contains all state for a particular VRRP Router operating
 * in a Virtual Router for either IPv4 or IPv6.
 */
struct vrrp_router {
	/*
	 * Whether this VRRP Router is active.
	 */
	bool is_active;

	/* Whether we are the address owner */
	bool is_owner;

	/* Rx socket: Rx from parent of mvl_ifp */
	int sock_rx;
	/* Tx socket; Tx from mvl_ifp */
	int sock_tx;

	/* macvlan interface */
	struct interface *mvl_ifp;

	/* Source address for advertisements */
	struct ipaddr src;

	/* Socket read buffer */
	uint8_t ibuf[IP_MAXPACKET];

	/*
	 * Address family of this Virtual Router.
	 * Either AF_INET or AF_INET6.
	 */
	int family;

	/*
	 * Virtual Router this VRRP Router is participating in.
	 */
	struct vrrp_vrouter *vr;

	/*
	 * One or more IPvX addresses associated with this Virtual
	 * Router. The first address must be the "primary" address this
	 * Virtual Router is backing up in the case of IPv4. In the case of
	 * IPv6 it must be the link-local address of vr->ifp.
	 *
	 * Type: struct ipaddr *
	 */
	struct list *addrs;

	/*
	 * This flag says whether we are waiting on an interface up
	 * notification from Zebra before we send an ADVERTISEMENT.
	 */
	bool advert_pending;

	/*
	 * If this is an IPv4 VRRP router, this flag says whether we are
	 * waiting on an interface up notification from Zebra before we send
	 * gratuitous ARP packets for all our addresses. Should never be true
	 * if family == AF_INET6.
	 */
	bool garp_pending;
	/*
	 * If this is an IPv6 VRRP router, this flag says whether we are
	 * waiting on an interface up notification from Zebra before we send
	 * Unsolicited Neighbor Advertisement packets for all our addresses.
	 * Should never be true if family == AF_INET.
	 */
	bool ndisc_pending;

	/*
	 * Effective priority
	 *    => vr->priority if we are Backup
	 *    => 255 if we are Master
	 */
	uint8_t priority;

	/*
	 * Advertisement interval contained in ADVERTISEMENTS received from the
	 * Master (centiseconds)
	 */
	uint16_t master_adver_interval;

	/*
	 * Time to skew Master_Down_Interval in centiseconds. Calculated as:
	 * (((256 - priority) * Master_Adver_Interval) / 256)
	 */
	uint16_t skew_time;

	/*
	 * Time interval for Backup to declare Master down (centiseconds).
	 * Calculated as:
	 * (3 * Master_Adver_Interval) + Skew_time
	 */
	uint16_t master_down_interval;

	/*
	 * The MAC address used for the source MAC address in VRRP
	 * advertisements, advertised in ARP requests/responses, and advertised
	 * in ND Neighbor Advertisements.
	 */
	struct ethaddr vmac;

	struct {
		int state;
	} fsm;

	struct {
		/* Total number of advertisements sent and received */
		uint32_t adver_tx_cnt;
		uint32_t adver_rx_cnt;
		/* Total number of gratuitous ARPs sent */
		uint32_t garp_tx_cnt;
		/* Total number of unsolicited Neighbor Advertisements sent */
		uint32_t una_tx_cnt;
		/* Total number of state transitions */
		uint32_t trans_cnt;
	} stats;

	struct event *t_master_down_timer;
	struct event *t_adver_timer;
	struct event *t_read;
	struct event *t_write;
};

/*
 * VRRP Virtual Router.
 *
 * This struct contains all state and configuration for a given Virtual Router
 * Identifier on a given interface, both v4 and v6.
 *
 * RFC5798 s. 1 states:
 *    "Within a VRRP router, the virtual routers in each of the IPv4 and IPv6
 *    address families are a domain unto themselves and do not overlap."
 *
 * This implementation has chosen the tuple (interface, VRID) as the key for a
 * particular VRRP Router, and the rest of the program is designed around this
 * assumption. Additionally, base protocol configuration parameters such as the
 * advertisement interval and (configured) priority are shared between v4 and
 * v6 instances. This corresponds to the choice made by other industrial
 * implementations.
 */
struct vrrp_vrouter {
	/* Whether this instance was automatically configured */
	bool autoconf;

	/* Whether this VRRP router is in administrative shutdown */
	bool shutdown;

	/* Interface */
	struct interface *ifp;

	/* Version */
	uint8_t version;

	/* Virtual Router Identifier */
	uint32_t vrid;

	/* Configured priority */
	uint8_t priority;

	/*
	 * Time interval between ADVERTISEMENTS (centiseconds). Default is 100
	 * centiseconds (1 second).
	 */
	uint16_t advertisement_interval;

	/*
	 * Controls whether a (starting or restarting) higher-priority Backup
	 * router preempts a lower-priority Master router. Values are True to
	 * allow preemption and False to prohibit preemption. Default is True.
	 */
	bool preempt_mode;

	/*
	 * Controls whether a virtual router in Master state will accept
	 * packets addressed to the address owner's IPvX address as its own if
	 * it is not the IPvX address owner. The default is False.
	 */
	bool accept_mode;

	/*
	 * Indicates whether this router computes and accepts VRRPv3 checksums
	 * without pseudoheader, for device interoperability.
	 *
	 * This option should only affect IPv4 virtual routers.
	 */
	bool checksum_with_ipv4_pseudoheader;

	struct vrrp_router *v4;
	struct vrrp_router *v6;
};

/*
 * Initialize VRRP global datastructures.
 */
void vrrp_init(void);

/*
 * Destroy all VRRP instances and gracefully shutdown.
 *
 * For instances in Master state, VRRP advertisements with 0 priority will be
 * sent if possible to notify Backup routers that we are going away.
 */
void vrrp_fini(void);


/* Creation and destruction ------------------------------------------------ */

/*
 * Create and register a new VRRP Virtual Router.
 *
 * ifp
 *    Base interface to configure VRRP on
 *
 * vrid
 *    Virtual Router Identifier
 */
struct vrrp_vrouter *vrrp_vrouter_create(struct interface *ifp, uint8_t vrid,
					 uint8_t version);

/*
 * Destroy a VRRP Virtual Router, freeing all its resources.
 *
 * If there are any running VRRP instances, these are stopped and destroyed.
 */
void vrrp_vrouter_destroy(struct vrrp_vrouter *vr);


/* Configuration controllers ----------------------------------------------- */

/*
 * Check if a Virtual Router ought to be started, and if so, start it.
 *
 * vr
 *    Virtual Router to checkstart
 */
void vrrp_check_start(struct vrrp_vrouter *vr);

/*
 * Change the configured priority of a VRRP Virtual Router.
 *
 * Note that this only changes the configured priority of the Virtual Router.
 * The currently effective priority will not be changed; to change the
 * effective priority, the Virtual Router must be restarted by issuing a
 * VRRP_EVENT_SHUTDOWN followed by a VRRP_EVENT_STARTUP.
 *
 * vr
 *    Virtual Router to change priority of
 *
 * priority
 *    New priority
 */
void vrrp_set_priority(struct vrrp_vrouter *vr, uint8_t priority);

/*
 * Set Advertisement Interval on this Virtual Router.
 *
 * vr
 *    Virtual Router to change priority of
 *
 * advertisement_interval
 *    New advertisement interval
 */
void vrrp_set_advertisement_interval(struct vrrp_vrouter *vr,
				     uint16_t advertisement_interval);

/*
 * Add an IPvX address to a VRRP Virtual Router.
 *
 * vr
 *    Virtual Router to add IPvx address to
 *
 * ip
 *    Address to add
 *
 * activate
 *    Whether to automatically start the VRRP router if this is the first IP
 *    address added.
 *
 * Returns:
 *    -1 on error
 *     0 otherwise
 */
int vrrp_add_ip(struct vrrp_vrouter *vr, struct ipaddr *ip);

/*
 * Add an IPv4 address to a VRRP Virtual Router.
 *
 * vr
 *    Virtual Router to add IPv4 address to
 *
 * v4
 *    Address to add
 *
 * activate
 *    Whether to automatically start the VRRP router if this is the first IP
 *    address added.
 *
 * Returns:
 *    -1 on error
 *     0 otherwise
 */
int vrrp_add_ipv4(struct vrrp_vrouter *vr, struct in_addr v4);

/*
 * Add an IPv6 address to a VRRP Virtual Router.
 *
 * vr
 *    Virtual Router to add IPv6 address to
 *
 * v6
 *    Address to add
 *
 * activate
 *    Whether to automatically start the VRRP router if this is the first IP
 *    address added.
 *
 * Returns:
 *    -1 on error
 *     0 otherwise
 */
int vrrp_add_ipv6(struct vrrp_vrouter *vr, struct in6_addr v6);

/*
 * Remove an IP address from a VRRP Virtual Router.
 *
 * vr
 *    Virtual Router to remove IP address from
 *
 * ip
 *    Address to remove
 *
 * deactivate
 *    Whether to automatically stop the VRRP router if removing v4 would leave
 *    us with an empty address list. If this is not true and ip is the only IP
 *    address backed up by this virtual router, this function will not remove
 *    the address and return failure.
 *
 * Returns:
 *    -1 on error
 *     0 otherwise
 */
int vrrp_del_ip(struct vrrp_vrouter *vr, struct ipaddr *ip);

/*
 * Remove an IPv4 address from a VRRP Virtual Router.
 *
 * vr
 *    Virtual Router to remove IPv4 address from
 *
 * v4
 *    Address to remove
 *
 * deactivate
 *    Whether to automatically stop the VRRP router if removing v4 would leave
 *    us with an empty address list. If this is not true and v4 is the only
 *    IPv4 address backed up by this virtual router, this function will not
 *    remove the address and return failure.
 *
 * Returns:
 *    -1 on error
 *     0 otherwise
 */
int vrrp_del_ipv4(struct vrrp_vrouter *vr, struct in_addr v4);

/*
 * Remove an IPv6 address from a VRRP Virtual Router.
 *
 * vr
 *    Virtual Router to remove IPv6 address from
 *
 * v6
 *    Address to remove
 *
 * deactivate
 *    Whether to automatically stop the VRRP router if removing v5 would leave
 *    us with an empty address list. If this is not true and v4 is the only
 *    IPv6 address backed up by this virtual router, this function will not
 *    remove the address and return failure.
 *
 * Returns:
 *    -1 on error
 *     0 otherwise
 */
int vrrp_del_ipv6(struct vrrp_vrouter *vr, struct in6_addr v6);

/* State machine ----------------------------------------------------------- */

#define VRRP_STATE_INITIALIZE 0
#define VRRP_STATE_MASTER 1
#define VRRP_STATE_BACKUP 2
#define VRRP_EVENT_STARTUP 0
#define VRRP_EVENT_SHUTDOWN 1

extern const char *const vrrp_state_names[3];

/*
 * This hook called whenever the state of a Virtual Router changes, after the
 * specific internal state handlers have run.
 *
 * Use this if you need to react to state changes to perform non-critical
 * tasks. Critical tasks should go in the internal state change handlers.
 */
DECLARE_HOOK(vrrp_change_state_hook, (struct vrrp_router *r, int to), (r, to));

/*
 * Trigger a VRRP event on a given Virtual Router..
 *
 * vr
 *    Virtual Router to operate on
 *
 * event
 *    Event to kick off. All event related processing will have completed upon
 *    return of this function.
 *
 * Returns:
 *    < 0 if the event created an error
 *      0 otherwise
 */
int vrrp_event(struct vrrp_router *r, int event);

/* Autoconfig -------------------------------------------------------------- */

/*
 * Search for and automatically configure VRRP instances on interfaces.
 *
 * ifp
 *    Interface to autoconfig. If it is a macvlan interface and has a VRRP MAC,
 *    a VRRP instance corresponding to VMAC assigned to macvlan will be created
 *    on the parent interface and all addresses on the macvlan interface except
 *    the v6 link local will be configured as VRRP addresses. If NULL, this
 *    treatment will be applied to all existing interfaces matching the above
 *    criterion.
 *
 * Returns:
 *    -1 on failure
 *     0 otherwise
 */
int vrrp_autoconfig(void);

/*
 * Enable autoconfiguration.
 *
 * Calling this function will cause vrrpd to automatically configure VRRP
 * instances on existing compatible macvlan interfaces. These instances will
 * react to interface up/down and address add/delete events to keep themselves
 * in sync with the available interfaces.
 *
 * version
 *    VRRP version to use for autoconfigured instances. Must be 2 or 3.
 */
void vrrp_autoconfig_on(int version);

/*
 * Disable autoconfiguration.
 *
 * Calling this function will delete all existing autoconfigured VRRP instances.
 */
void vrrp_autoconfig_off(void);

/* Interface Tracking ------------------------------------------------------ */

void vrrp_if_add(struct interface *ifp);
void vrrp_if_del(struct interface *ifp);
void vrrp_if_up(struct interface *ifp);
void vrrp_if_down(struct interface *ifp);
void vrrp_if_address_add(struct interface *ifp);
void vrrp_if_address_del(struct interface *ifp);

/* Other ------------------------------------------------------------------- */

/*
 * Write global level configuration to vty.
 *
 * vty
 *    vty to write config to
 *
 * Returns:
 *    # of lines written
 */
int vrrp_config_write_global(struct vty *vty);

/*
 * Find VRRP Virtual Router by Virtual Router ID
 */
struct vrrp_vrouter *vrrp_lookup(const struct interface *ifp, uint8_t vrid);

#endif /* __VRRP_H__ */