/* * VRRP global definitions and state machine. * Copyright (C) 2018-2019 Cumulus Networks, Inc. * Quentin Young * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program; see the file COPYING; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __VRRP_H__ #define __VRRP_H__ #include #include #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/thread.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_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 shutdown; }; extern struct vrrp_defaults vd; /* threadmaster */ extern struct thread_master *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 thread *t_master_down_timer; struct thread *t_adver_timer; struct thread *t_read; struct thread *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; 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__ */