aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/vrrp/vrrp.h
diff options
context:
space:
mode:
authorMatthew Smith <mgsmith@netgate.com>2020-02-11 11:25:32 -0600
committerDave Barach <openvpp@barachs.net>2020-02-13 19:46:30 +0000
commit39e9428b90bc74d1bb15fc17759c8ef6ad712418 (patch)
treede9317a906a7df43bf2140a654d3b7675cab8d86 /src/plugins/vrrp/vrrp.h
parentf75defa7676759fa81ae75e7edd492572c6b8fd6 (diff)
vrrp: add plugin providing vrrp support
Type: feature Add a new plugin to support HA using VRRPv3 (RFC 5798). Change-Id: Iaa2c37e6172f8f41e9165f178f44d481f6e247b9 Signed-off-by: Matthew Smith <mgsmith@netgate.com>
Diffstat (limited to 'src/plugins/vrrp/vrrp.h')
-rw-r--r--src/plugins/vrrp/vrrp.h373
1 files changed, 373 insertions, 0 deletions
diff --git a/src/plugins/vrrp/vrrp.h b/src/plugins/vrrp/vrrp.h
new file mode 100644
index 00000000000..9c636c42802
--- /dev/null
+++ b/src/plugins/vrrp/vrrp.h
@@ -0,0 +1,373 @@
+
+/*
+ * vrrp.h - vrrp plug-in header file
+ *
+ * Copyright 2019-2020 Rubicon Communications, LLC (Netgate)
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ */
+#ifndef __included_vrrp_h__
+#define __included_vrrp_h__
+
+#include <vnet/vnet.h>
+#include <vnet/ip/ip.h>
+#include <vnet/ethernet/ethernet.h>
+
+#include <vppinfra/hash.h>
+#include <vppinfra/error.h>
+
+/* VRRP configuration */
+typedef enum vrrp_vr_flags
+{
+ VRRP_VR_PREEMPT = 0x1,
+ VRRP_VR_ACCEPT = 0x2,
+ VRRP_VR_UNICAST = 0x4,
+ VRRP_VR_IPV6 = 0x8,
+} vrrp_vr_flags_t;
+
+typedef struct vrrp_vr_key
+{
+ u32 sw_if_index;
+ u8 vr_id;
+ u8 is_ipv6;
+} vrrp_vr_key_t;
+
+/* *INDENT-OFF* */
+typedef CLIB_PACKED
+(struct vrrp4_arp_key {
+ union {
+ struct {
+ u32 sw_if_index;
+ ip4_address_t addr;
+ };
+ u64 as_u64;
+ };
+}) vrrp4_arp_key_t;
+/* *INDENT-ON* */
+
+/* *INDENT-OFF* */
+typedef CLIB_PACKED
+(struct vrrp6_nd_key {
+ u32 sw_if_index;
+ ip6_address_t addr;
+}) vrrp6_nd_key_t;
+/* *INDENT-ON* */
+
+typedef struct vrrp_vr_tracking_if
+{
+ u32 sw_if_index;
+ u8 priority;
+} vrrp_vr_tracking_if_t;
+
+typedef struct vrrp_vr_tracking
+{
+ vrrp_vr_tracking_if_t *interfaces;
+ u32 interfaces_dec;
+} vrrp_vr_tracking_t;
+
+typedef struct vrrp_vr_config
+{
+ u32 sw_if_index;
+ u8 vr_id;
+ u8 priority;
+ u16 adv_interval;
+ vrrp_vr_flags_t flags;
+ ip46_address_t *vr_addrs;
+ ip46_address_t *peer_addrs;
+} vrrp_vr_config_t;
+
+#define foreach_vrrp_vr_state \
+_(0, INIT, "Initialize") \
+_(1, BACKUP, "Backup") \
+_(2, MASTER, "Master") \
+_(3, INTF_DOWN, "Interface Down")
+
+/* VRRP runtime data */
+typedef enum vrrp_vr_state
+{
+#define _(v,f,n) VRRP_VR_STATE_##f = v,
+ foreach_vrrp_vr_state
+#undef _
+} vrrp_vr_state_t;
+
+typedef struct vrrp_vr_runtime
+{
+ vrrp_vr_state_t state;
+ u16 master_adv_int;
+ u16 skew;
+ u16 master_down_int;
+ mac_address_t mac;
+ f64 last_sent;
+ u32 timer_index;
+} vrrp_vr_runtime_t;
+
+/* Per-VR data */
+typedef struct vrrp_vr
+{
+ vrrp_vr_config_t config;
+ vrrp_vr_runtime_t runtime;
+ vrrp_vr_tracking_t tracking;
+} vrrp_vr_t;
+
+/* Timers */
+typedef enum vrrp_vr_timer_type
+{
+ VRRP_VR_TIMER_ADV,
+ VRRP_VR_TIMER_MASTER_DOWN,
+} vrrp_vr_timer_type_t;
+
+typedef struct vrrp_vr_timer
+{
+ u32 vr_index;
+ f64 expire_time; /* monotonic, relative to vlib_time_now() */
+ vrrp_vr_timer_type_t type;
+} vrrp_vr_timer_t;
+
+typedef struct
+{
+ /* vectors of vr indices which are configured on this interface
+ * 0 -> ipv4, 1 -> ipv6 */
+ u32 *vr_indices[2];
+
+ /* vector of VR indices which track the state of this interface
+ * 0 -> ipv4, 1*/
+ u32 *tracking_vrs[2];
+
+ /* multicast adjacency indices. 0 -> ipv4, 1 -> ipv6 */
+ adj_index_t mcast_adj_index[2];
+
+ /* number of VRs in master state on sw intf. 0 -> ipv4, 1 -> ipv6 */
+ u8 n_master_vrs[2];
+
+} vrrp_intf_t;
+
+typedef struct
+{
+ /* API message ID base */
+ u16 msg_id_base;
+
+ /* pool of VRs */
+ vrrp_vr_t *vrs;
+
+ /* pool of timers and ordered vector of pool indices */
+ vrrp_vr_timer_t *vr_timers;
+ u32 *pending_timers;
+
+ /* number of running VRs - don't register for VRRP proto if not running */
+ u16 n_vrs_started;
+
+ /* hash mapping a VR key to a pool entry */
+ mhash_t vr_index_by_key;
+
+ /* hashes mapping sw_if_index and address to a vr index */
+ uword *vrrp4_arp_lookup;
+ uword *vrrp6_nd_lookup;
+
+ /* vector of interface data indexed by sw_if_index */
+ vrrp_intf_t *vrrp_intfs;
+
+ /* convenience */
+ vlib_main_t *vlib_main;
+ vnet_main_t *vnet_main;
+ ethernet_main_t *ethernet_main;
+
+ u32 intf_output_node_idx;
+} vrrp_main_t;
+
+extern vrrp_main_t vrrp_main;
+
+extern vlib_node_registration_t vrrp_node;
+extern vlib_node_registration_t vrrp_periodic_node;
+
+/* Periodic function events */
+#define VRRP_EVENT_VR_TIMER_UPDATE 1
+#define VRRP_EVENT_VR_STOP 2
+#define VRRP_EVENT_PERIODIC_ENABLE_DISABLE 3
+
+clib_error_t *vrrp_plugin_api_hookup (vlib_main_t * vm);
+
+int vrrp_vr_add_del (u8 is_add, vrrp_vr_config_t * conf);
+int vrrp_vr_start_stop (u8 is_start, vrrp_vr_key_t * vr_key);
+extern u8 *format_vrrp_vr (u8 * s, va_list * args);
+extern u8 *format_vrrp_vr_key (u8 * s, va_list * args);
+extern u8 *format_vrrp_vr_state (u8 * s, va_list * args);
+extern u8 *format_vrrp_packet_hdr (u8 * s, va_list * args);
+void vrrp_vr_timer_set (vrrp_vr_t * vr, vrrp_vr_timer_type_t type);
+void vrrp_vr_timer_cancel (vrrp_vr_t * vr);
+void vrrp_vr_transition (vrrp_vr_t * vr, vrrp_vr_state_t new_state,
+ void *data);
+int vrrp_vr_set_peers (vrrp_vr_key_t * key, ip46_address_t * peers);
+int vrrp_vr_multicast_group_join (vrrp_vr_t * vr);
+int vrrp_adv_send (vrrp_vr_t * vr, int shutdown);
+int vrrp_garp_or_na_send (vrrp_vr_t * vr);
+u16 vrrp_adv_csum (void *l3_hdr, void *payload, u8 is_ipv6, u16 len);
+int vrrp_vr_tracking_if_add_del (vrrp_vr_t * vr, u32 sw_if_index,
+ u8 priority, u8 is_add);
+int vrrp_vr_tracking_ifs_add_del (vrrp_vr_t * vr,
+ vrrp_vr_tracking_if_t * track_ifs,
+ u8 is_add);
+
+
+always_inline void
+vrrp_vr_skew_compute (vrrp_vr_t * vr)
+{
+ vrrp_vr_config_t *vrc = &vr->config;
+ vrrp_vr_runtime_t *vrt = &vr->runtime;
+
+ vrt->skew = (((256 - vrc->priority) * vrt->master_adv_int) / 256);
+}
+
+always_inline void
+vrrp_vr_master_down_compute (vrrp_vr_t * vr)
+{
+ vrrp_vr_runtime_t *vrt = &vr->runtime;
+
+ vrt->master_down_int = (3 * vrt->master_adv_int) + vrt->skew;
+}
+
+always_inline vrrp_vr_t *
+vrrp_vr_lookup (u32 sw_if_index, u8 vr_id, u8 is_ipv6)
+{
+ vrrp_main_t *vmp = &vrrp_main;
+ vrrp_vr_key_t key = {
+ .sw_if_index = sw_if_index,
+ .vr_id = vr_id,
+ .is_ipv6 = (is_ipv6 != 0),
+ };
+ uword *p;
+
+ p = mhash_get (&vmp->vr_index_by_key, &key);
+ if (p)
+ return pool_elt_at_index (vmp->vrs, p[0]);
+
+ return 0;
+}
+
+always_inline vrrp_vr_t *
+vrrp_vr_lookup_index (u32 vr_index)
+{
+ vrrp_main_t *vmp = &vrrp_main;
+
+ if (pool_is_free_index (vmp->vrs, vr_index))
+ return 0;
+
+ return pool_elt_at_index (vmp->vrs, vr_index);
+}
+
+always_inline u32
+vrrp_vr_lookup_address (u32 sw_if_index, u8 is_ipv6, void *addr)
+{
+ vrrp_main_t *vmp = &vrrp_main;
+ uword *p;
+ vrrp4_arp_key_t key4;
+ vrrp6_nd_key_t key6;
+
+ if (is_ipv6)
+ {
+ key6.sw_if_index = sw_if_index;
+ key6.addr = ((ip6_address_t *) addr)[0];
+ p = hash_get_mem (vmp->vrrp6_nd_lookup, &key6);
+ }
+ else
+ {
+ key4.sw_if_index = sw_if_index;
+ key4.addr = ((ip4_address_t *) addr)[0];
+ p = hash_get (vmp->vrrp4_arp_lookup, key4.as_u64);
+ }
+
+ if (p)
+ return p[0];
+
+ return ~0;
+}
+
+always_inline vrrp_intf_t *
+vrrp_intf_get (u32 sw_if_index)
+{
+ vrrp_main_t *vrm = &vrrp_main;
+
+ if (sw_if_index == ~0)
+ return NULL;
+
+ vec_validate (vrm->vrrp_intfs, sw_if_index);
+ return vec_elt_at_index (vrm->vrrp_intfs, sw_if_index);
+}
+
+always_inline int
+vrrp_intf_num_vrs (u32 sw_if_index, u8 is_ipv6)
+{
+ vrrp_intf_t *intf = vrrp_intf_get (sw_if_index);
+
+ if (intf)
+ return vec_len (intf->vr_indices[is_ipv6]);
+
+ return 0;
+}
+
+always_inline u8
+vrrp_vr_is_ipv6 (vrrp_vr_t * vr)
+{
+ return ((vr->config.flags & VRRP_VR_IPV6) != 0);
+}
+
+always_inline u8
+vrrp_vr_is_unicast (vrrp_vr_t * vr)
+{
+ return ((vr->config.flags & VRRP_VR_UNICAST) != 0);
+}
+
+always_inline u8
+vrrp_vr_is_owner (vrrp_vr_t * vr)
+{
+ return (vr->config.priority == 255);
+}
+
+always_inline u8
+vrrp_vr_n_vr_addrs (vrrp_vr_t * vr)
+{
+ return vec_len (vr->config.vr_addrs);
+}
+
+always_inline u8
+vrrp_vr_n_peer_addrs (vrrp_vr_t * vr)
+{
+ return vec_len (vr->config.peer_addrs);
+}
+
+always_inline u8
+vrrp_vr_accept_mode_enabled (vrrp_vr_t * vr)
+{
+ return ((vr->config.flags & VRRP_VR_ACCEPT) != 0);
+}
+
+always_inline u32
+vrrp_vr_index (vrrp_vr_t * vr)
+{
+ vrrp_main_t *vmp = &vrrp_main;
+
+ return vr - vmp->vrs;
+}
+
+always_inline u8
+vrrp_vr_priority (vrrp_vr_t * vr)
+{
+ u8 rv;
+
+ if (vr->tracking.interfaces_dec < (u32) vr->config.priority)
+ rv = vr->config.priority - vr->tracking.interfaces_dec;
+ else
+ rv = 1;
+
+ return rv;
+}
+
+#endif /* __included_vrrp_h__ */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */