summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.am3
-rwxr-xr-xconfigure.ac1
-rw-r--r--vrrpd/Makefile10
-rw-r--r--vrrpd/subdir.am32
-rw-r--r--vrrpd/vrrp.c351
-rw-r--r--vrrpd/vrrp.h162
-rw-r--r--vrrpd/vrrp_main.c151
-rw-r--r--vrrpd/vrrp_memory.c24
-rw-r--r--vrrpd/vrrp_memory.h27
-rw-r--r--vrrpd/vrrp_packet.c50
-rw-r--r--vrrpd/vrrp_packet.h49
-rw-r--r--vrrpd/vrrp_vty.c80
-rw-r--r--vrrpd/vrrp_vty.h23
-rw-r--r--vrrpd/vrrp_zebra.c39
-rw-r--r--vrrpd/vrrp_zebra.h29
-rw-r--r--vtysh/vtysh.h1
16 files changed, 1031 insertions, 1 deletions
diff --git a/Makefile.am b/Makefile.am
index 11188ea15..166ac29d1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -147,6 +147,7 @@ include staticd/subdir.am
include bfdd/subdir.am
include yang/subdir.am
include yang/libyang_plugins/subdir.am
+include vrrpd/subdir.am
include vtysh/subdir.am
include tests/subdir.am
@@ -188,7 +189,6 @@ EXTRA_DIST += \
snapcraft/defaults \
snapcraft/helpers \
snapcraft/snap \
- \
babeld/Makefile \
bgpd/Makefile \
bgpd/rfp-example/librfp/Makefile \
@@ -218,6 +218,7 @@ EXTRA_DIST += \
vtysh/Makefile \
watchfrr/Makefile \
zebra/Makefile \
+ vrrpd/Makefile \
# end
noinst_HEADERS += defaults.h
diff --git a/configure.ac b/configure.ac
index b7ddf87b4..69f489dbc 100755
--- a/configure.ac
+++ b/configure.ac
@@ -1602,6 +1602,7 @@ AM_CONDITIONAL([PBRD], [test "${enable_pbrd}" != "no"])
AM_CONDITIONAL([SHARPD], [test "${enable_sharpd}" = "yes"])
AM_CONDITIONAL([STATICD], [test "${enable_staticd}" != "no"])
AM_CONDITIONAL([FABRICD], [test "${enable_fabricd}" != "no"])
+AM_CONDITIONAL([VRRPD], [test "${enable_vrrpd}" != "no"])
if test "${enable_bgp_announce}" = "no";then
AC_DEFINE([DISABLE_BGP_ANNOUNCE], [1], [Disable BGP installation to zebra])
diff --git a/vrrpd/Makefile b/vrrpd/Makefile
new file mode 100644
index 000000000..027c6ee1f
--- /dev/null
+++ b/vrrpd/Makefile
@@ -0,0 +1,10 @@
+all: ALWAYS
+ @$(MAKE) -s -C .. vrrp/vrrp
+%: ALWAYS
+ @$(MAKE) -s -C .. vrrp/$@
+
+Makefile:
+ #nothing
+ALWAYS:
+.PHONY: ALWAYS makefiles
+.SUFFIXES:
diff --git a/vrrpd/subdir.am b/vrrpd/subdir.am
new file mode 100644
index 000000000..40dee9c14
--- /dev/null
+++ b/vrrpd/subdir.am
@@ -0,0 +1,32 @@
+#
+# vrrpd
+#
+
+if VRRPD
+noinst_LIBRARIES += vrrpd/libvrrp.a
+sbin_PROGRAMS += vrrpd/vrrpd
+# dist_examples_DATA += staticd/staticd.conf.sample
+vtysh_scan += $(top_srcdir)/vrrpd/vrrp_vty.c
+man8 += $(MANBUILD)/vrrpd.8
+endif
+
+vrrpd_libvrrp_a_SOURCES = \
+ vrrpd/vrrp_memory.c \
+ vrrpd/vrrp_zebra.c \
+ vrrpd/vrrp_vty.c \
+ vrrpd/vrrp_packet.c \
+ vrrpd/vrrp.c \
+ # end
+
+noinst_HEADERS += \
+ vrrpd/vrrp_memory.h \
+ vrrpd/vrrp_zebra.h \
+ vrrpd/vrrp_vty.h \
+ vrrpd/vrrp.h \
+ # end
+
+vrrpd/vrrp_vty_clippy.c: $(CLIPPY_DEPS)
+vrrpd/vrrp_vty.$(OBJEXT): vrrpd/vrrp_vty_clippy.c
+
+vrrpd_vrrpd_SOURCES = vrrpd/vrrp_main.c
+vrrpd_vrrpd_LDADD = vrrpd/libvrrp.a lib/libfrr.la @LIBCAP@
diff --git a/vrrpd/vrrp.c b/vrrpd/vrrp.c
new file mode 100644
index 000000000..2cc089660
--- /dev/null
+++ b/vrrpd/vrrp.c
@@ -0,0 +1,351 @@
+/*
+ * VRRPD global definitions
+ * Copyright (C) 2018 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
+ */
+#include "memory.h"
+#include "if.h"
+#include "linklist.h"
+#include "prefix.h"
+#include "hash.h"
+#include "vrf.h"
+#include "hook.h"
+
+#include "vrrp.h"
+
+/* Utility functions ------------------------------------------------------- */
+
+/*
+ * Sets an ethaddr to RFC-defined Virtual Router MAC address.
+ *
+ * mac
+ * ethaddr to set
+ *
+ * v6
+ * Whether this is a V6 or V4 Virtual Router MAC
+ *
+ * vrid
+ * Virtual Router Identifier
+ */
+static void vrrp_mac_set(struct ethaddr *mac, bool v6, uint8_t vrid)
+{
+ /*
+ * V4: 00-00-5E-00-01-{VRID}
+ * V6: 00-00-5E-00-02-{VRID}
+ */
+ mac->octet[0] = 0x00;
+ mac->octet[1] = 0x00;
+ mac->octet[2] = 0x5E;
+ mac->octet[3] = 0x00;
+ mac->octet[4] = v6 ? 0x02 : 0x01;
+ mac->octet[5] = vrid;
+}
+
+/*
+ * Sets advertisement_interval and master_adver_interval on a Virtual Router,
+ * then recalculates and sets skew_time and master_down_interval based on these
+ * values.
+ *
+ * vr
+ * Virtual Router to operate on
+ *
+ * advertisement_interval
+ * Advertisement_Interval to set
+ *
+ * master_adver_interval
+ * Master_Adver_Interval to set
+ */
+static void vrrp_update_times(struct vrrp_vrouter *vr, uint16_t advertisement_interval,
+ uint16_t master_adver_interval)
+{
+ vr->advertisement_interval = advertisement_interval;
+ vr->master_adver_interval = master_adver_interval;
+ vr->skew_time = (256 - vr->priority) * vr->master_adver_interval;
+ vr->skew_time /= 256;
+ vr->master_down_interval = (3 * vr->master_adver_interval);
+ vr->master_down_interval /= 256;
+}
+
+struct vrrp_vrouter *vrrp_vrouter_create(struct interface *ifp, uint8_t vrid)
+{
+ struct vrrp_vrouter *vr =
+ XCALLOC(MTYPE_TMP, sizeof(struct vrrp_vrouter));
+
+ vr->sock = -1;
+ vr->ifp = ifp;
+ vr->vrid = vrid;
+ vr->v4 = list_new();
+ vr->v6 = list_new();
+ vr->advint = VRRP_DEFAULT_ADVINT;
+ vr->is_master = false;
+ vr->priority = VRRP_DEFAULT_PRIORITY;
+ vr->advertisement_interval = VRRP_DEFAULT_ADVINT;
+ vr->master_adver_interval = 0;
+ vr->skew_time = 0;
+ vr->master_down_interval = 0;
+ vr->preempt_mode = true;
+ vr->accept_mode = false;
+ vrrp_mac_set(&vr->vr_mac_v4, false, vrid);
+ vrrp_mac_set(&vr->vr_mac_v6, true, vrid);
+ vr->fsm.state = VRRP_STATE_INITIALIZE;
+
+ hash_get(vrrp_vrouters_hash, vr, hash_alloc_intern);
+
+ return vr;
+}
+
+struct vrrp_vrouter *vrrp_lookup(uint8_t vrid)
+{
+ struct vrrp_vrouter vr;
+ vr.vrid = vrid;
+
+ return hash_lookup(vrrp_vrouters_hash, &vr);
+}
+
+/* Network ----------------------------------------------------------------- */
+
+/*
+ * Create and broadcast VRRP ADVERTISEMENT message.
+ *
+ * vr
+ * Virtual Router for which to send ADVERTISEMENT
+ */
+static void vrrp_send_advertisement(struct vrrp_vrouter *vr)
+{
+}
+
+/* FIXME:
+static void vrrp_recv_advertisement(struct thread *thread)
+{
+}
+*/
+
+/*
+ * Create Virtual Router listen socket and join it to the VRRP multicast group.
+ *
+ * The first connected address on the Virtual Router's interface is used as the
+ * interface address.
+ *
+ * vr
+ * Virtual Router for which to create listen socket
+ */
+static int vrrp_socket(struct vrrp_vrouter *vr)
+{
+ struct ip_mreqn req;
+ int ret;
+
+ vr->sock = socket(AF_INET, SOCK_RAW, IPPROTO_VRRP);
+
+ if (vr->sock < 0) {
+ /* FIXME */
+ }
+
+ /* Join the multicast group.*/
+
+ /* FIXME: Use first address on the interface and for imr_interface */
+ struct connected *c = listhead(vr->ifp->connected)->data;
+ struct in_addr v4 = c->address->u.prefix4;
+
+ memset(&req, 0, sizeof(req));
+ req.imr_multiaddr.s_addr = htonl(VRRP_MCAST_GROUP_HEX);
+ req.imr_address = v4;
+ req.imr_ifindex = 0; // FIXME: vr->ifp->ifindex ?
+ ret = setsockopt(vr->sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&req,
+ sizeof(struct ip_mreq));
+ if (ret < 0) {
+ // int err = errno;
+ /* VRRP_LOG(("cant do IP_ADD_MEMBERSHIP errno=%d\n", err)); */
+ return -1;
+ }
+ return 0;
+}
+
+
+/* State machine ----------------------------------------------------------- */
+
+DEFINE_HOOK(vrrp_change_state_hook, (struct vrrp_vrouter *vr, int to), (vr, to));
+
+/*
+ * Handle any necessary actions during state change to MASTER state.
+ *
+ * vr
+ * Virtual Router to operate on
+ */
+static void vrrp_change_state_master(struct vrrp_vrouter *vr)
+{
+}
+
+/*
+ * Handle any necessary actions during state change to BACKUP state.
+ *
+ * vr
+ * Virtual Router to operate on
+ */
+static void vrrp_change_state_backup(struct vrrp_vrouter *vr)
+{
+ /* Uninstall ARP entry for vrouter MAC */
+ /* ... */
+}
+
+/*
+ * Handle any necessary actions during state change to INITIALIZE state.
+ *
+ * This is not called for initial startup, only when transitioning from MASTER
+ * or BACKUP.
+ *
+ * vr
+ * Virtual Router to operate on
+ */
+static void vrrp_change_state_initialize(struct vrrp_vrouter *vr)
+{
+}
+
+void (*vrrp_change_state_handlers[])(struct vrrp_vrouter *vr) = {
+ [VRRP_STATE_MASTER] = vrrp_change_state_master,
+ [VRRP_STATE_BACKUP] = vrrp_change_state_backup,
+ [VRRP_STATE_INITIALIZE] = vrrp_change_state_initialize,
+};
+
+/*
+ * Change Virtual Router FSM position. Handles transitional actions and calls
+ * any subscribers to the state change hook.
+ *
+ * vr
+ * Virtual Router for which to change state
+ *
+ * to
+ * State to change to
+ */
+static void vrrp_change_state(struct vrrp_vrouter *vr, int to)
+{
+ /* Call our handlers, then any subscribers */
+ vrrp_change_state_handlers[to](vr);
+ hook_call(vrrp_change_state_hook, vr, to);
+ vr->fsm.state = to;
+}
+
+/*
+ * Called when Adver_Timer expires.
+ */
+static int vrrp_adver_timer_expire(struct thread *thread)
+{
+ struct vrrp_vrouter *vr = thread->arg;
+
+ if (vr->fsm.state == VRRP_STATE_BACKUP) {
+ vrrp_send_advertisement(vr);
+ /* FIXME: vrrp_send_gratuitous_arp(vr); */
+ } else if (vr->fsm.state == VRRP_STATE_MASTER) {
+
+ } else if (vr->fsm.state == VRRP_STATE_INITIALIZE) {
+ assert(!"FUCK");
+ }
+ return 0;
+}
+
+/*
+ * Called when Master_Down timer expires.
+ */
+static int vrrp_master_down_timer_expire(struct thread *thread)
+{
+ /* struct vrrp_vrouter *vr = thread->arg; */
+
+ return 0;
+}
+
+/*
+ * Event handler for Startup event.
+ *
+ * Creates sockets, sends advertisements and ARP requests, starts timers,
+ * updates state machine.
+ *
+ * vr
+ * Virtual Router on which to apply Startup event
+ */
+static void vrrp_startup(struct vrrp_vrouter *vr)
+{
+ /* Create socket */
+ vrrp_socket(vr);
+
+ /* Schedule listener */
+ /* ... */
+
+ if (vr->priority == VRRP_PRIO_MASTER) {
+ vrrp_send_advertisement(vr);
+ /* FIXME: vrrp_send_gratuitous_arp(vr); */
+
+ thread_add_timer_msec(master, vrrp_adver_timer_expire, vr,
+ vr->advertisement_interval * 10,
+ &vr->t_adver_timer);
+ vrrp_change_state(vr, VRRP_STATE_MASTER);
+ } else {
+ vrrp_update_times(vr, vr->advertisement_interval,
+ vr->advertisement_interval);
+ thread_add_timer_msec(master, vrrp_master_down_timer_expire, vr,
+ vr->master_down_interval * 10,
+ &vr->t_master_down_timer);
+ vrrp_change_state(vr, VRRP_STATE_BACKUP);
+ }
+}
+
+static void vrrp_shutdown(struct vrrp_vrouter *vr)
+{
+ /* NOTHING */
+}
+
+static void (*vrrp_event_handlers[])(struct vrrp_vrouter *vr) = {
+ [VRRP_EVENT_STARTUP] = vrrp_startup,
+ [VRRP_EVENT_SHUTDOWN] = vrrp_shutdown,
+};
+
+/*
+ * Spawn a VRRP FSM event on a Virtual Router.
+ *
+ * vr
+ * Virtual Router on which to spawn event
+ *
+ * event
+ * The event to spawn
+ */
+void vrrp_event(struct vrrp_vrouter *vr, int event)
+{
+ vrrp_event_handlers[event](vr);
+}
+
+
+/* Other ------------------------------------------------------------------- */
+
+static unsigned int vrrp_hash_key(void *arg)
+{
+ struct vrrp_vrouter *vr = arg;
+
+ return vr->vrid;
+}
+
+static bool vrrp_hash_cmp(const void *arg1, const void *arg2)
+{
+ const struct vrrp_vrouter *vr1 = arg1;
+ const struct vrrp_vrouter *vr2 = arg2;
+
+ return vr1->vrid > vr2->vrid;
+}
+
+void vrrp_init(void)
+{
+ vrrp_vrouters_hash = hash_create(&vrrp_hash_key, vrrp_hash_cmp,
+ "VRRP virtual router hash");
+ vrf_init(NULL, NULL, NULL, NULL, NULL);
+}
diff --git a/vrrpd/vrrp.h b/vrrpd/vrrp.h
new file mode 100644
index 000000000..308e3a8e1
--- /dev/null
+++ b/vrrpd/vrrp.h
@@ -0,0 +1,162 @@
+/*
+ * VRRPD global definitions
+ * Copyright (C) 2018 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 <zebra.h>
+#include "linklist.h"
+#include "hash.h"
+#include "if.h"
+#include "thread.h"
+#include "hook.h"
+
+/* Global definitions */
+#define VRRP_DEFAULT_ADVINT 100
+#define VRRP_DEFAULT_PRIORITY 100
+#define VRRP_PRIO_MASTER 255
+#define VRRP_MCAST_GROUP "224.0.0.18"
+#define VRRP_MCAST_GROUP_HEX 0xe0000012
+#define IPPROTO_VRRP 112
+
+/* threadmaster */
+extern struct thread_master *master;
+
+/* Global hash of all Virtual Routers */
+struct hash *vrrp_vrouters_hash;
+
+/*
+ * VRRP Virtual Router
+ */
+struct vrrp_vrouter {
+ /* Socket */
+ int sock;
+
+ /* Interface */
+ struct interface *ifp;
+
+ /* Virtual Router Identifier */
+ uint32_t vrid;
+
+ /* One or more IPv4 addresses associated with this Virtual Router. */
+ struct list *v4;
+
+ /*
+ * One ore more IPv6 addresses associated with this Virtual Router. The
+ * first address must be the Link-Local address associated with the
+ * virtual router.
+ */
+ struct list *v6;
+
+ /* Time between ADVERTISEMENTS (centiseconds) */
+ int advint;
+
+ /* Whether this VRRP Router is currently the master */
+ bool is_master;
+
+ /* Priority */
+ uint8_t priority;
+
+ /*
+ * Time interval between ADVERTISEMENTS (centiseconds). Default is 100
+ * centiseconds (1 second).
+ */
+ uint16_t advertisement_interval;
+ /*
+ * 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;
+
+ /*
+ * 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;
+
+ /*
+ * The MAC address used for the source MAC address in VRRP
+ * advertisements and advertised in ARP responses as the MAC address to
+ * use for IP_Addresses.
+ */
+ struct ethaddr vr_mac_v4;
+ struct ethaddr vr_mac_v6;
+
+ struct thread *t_master_down_timer;
+ struct thread *t_adver_timer;
+
+ struct {
+ int state;
+ } fsm;
+};
+
+/* State machine */
+#define VRRP_STATE_INITIALIZE 1
+#define VRRP_STATE_MASTER 2
+#define VRRP_STATE_BACKUP 3
+#define VRRP_EVENT_STARTUP 1
+#define VRRP_EVENT_SHUTDOWN 2
+
+DECLARE_HOOK(vrrp_change_state_hook, (struct vrrp_vrouter *vr, int to), (vr, to));
+void vrrp_event(struct vrrp_vrouter *vr, int event);
+/* End state machine */
+
+
+/*
+ * Initialize VRRP global datastructures.
+ */
+void vrrp_init(void);
+
+/*
+ * Create and register a new VRRP Virtual Router.
+ */
+struct vrrp_vrouter *vrrp_vrouter_create(struct interface *ifp, uint8_t vrid);
+
+/*
+ * Find VRRP Virtual Router by Virtual Router ID
+ */
+struct vrrp_vrouter *vrrp_lookup(uint8_t vrid);
+
+/*
+ * Trigger VRRP event
+ */
+void vrrp_event(struct vrrp_vrouter *vr, int event);
+
+#endif
diff --git a/vrrpd/vrrp_main.c b/vrrpd/vrrp_main.c
new file mode 100644
index 000000000..8c73375c9
--- /dev/null
+++ b/vrrpd/vrrp_main.c
@@ -0,0 +1,151 @@
+/*
+ * VRRP
+ * Copyright (C) 2018 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
+ */
+#include <zebra.h>
+
+#include <lib/version.h>
+#include "getopt.h"
+#include "thread.h"
+#include "command.h"
+#include "log.h"
+#include "memory.h"
+#include "privs.h"
+#include "sigevent.h"
+#include "libfrr.h"
+#include "vrf.h"
+#include "nexthop.h"
+#include "filter.h"
+
+#include "vrrp.h"
+#include "vrrp_zebra.h"
+#include "vrrp_vty.h"
+
+char backup_config_file[256];
+
+zebra_capabilities_t _caps_p[] = {
+};
+
+struct zebra_privs_t vrrp_privs = {
+#if defined(FRR_USER) && defined(FRR_GROUP)
+ .user = FRR_USER,
+ .group = FRR_GROUP,
+#endif
+#if defined(VTY_GROUP)
+ .vty_group = VTY_GROUP,
+#endif
+ .caps_p = _caps_p,
+ .cap_num_p = array_size(_caps_p),
+ .cap_num_i = 0};
+
+struct option longopts[] = { { 0 } };
+
+/* Master of threads. */
+struct thread_master *master;
+
+/* SIGHUP handler. */
+static void sighup(void)
+{
+ zlog_info("SIGHUP received");
+}
+
+/* SIGINT / SIGTERM handler. */
+static void sigint(void)
+{
+ zlog_notice("Terminating on signal");
+
+ exit(0);
+}
+
+/* SIGUSR1 handler. */
+static void sigusr1(void)
+{
+ zlog_rotate();
+}
+
+struct quagga_signal_t vrrp_signals[] = {
+ {
+ .signal = SIGHUP,
+ .handler = &sighup,
+ },
+ {
+ .signal = SIGUSR1,
+ .handler = &sigusr1,
+ },
+ {
+ .signal = SIGINT,
+ .handler = &sigint,
+ },
+ {
+ .signal = SIGTERM,
+ .handler = &sigint,
+ },
+};
+
+static const struct frr_yang_module_info *vrrp_yang_modules[] = {
+};
+
+#define VRRP_VTY_PORT 2617
+
+FRR_DAEMON_INFO(vrrpd, VRRP, .vty_port = VRRP_VTY_PORT,
+ .proghelp = "Virtual Router Redundancy Protocol",
+ .signals = vrrp_signals,
+ .n_signals = array_size(vrrp_signals),
+ .privs = &vrrp_privs,
+ .yang_modules = vrrp_yang_modules,
+ .n_yang_modules = array_size(vrrp_yang_modules),
+)
+
+int main(int argc, char **argv, char **envp)
+{
+ frr_preinit(&vrrpd_di, argc, argv);
+ frr_opt_add("", longopts, "");
+
+ while (1) {
+ int opt;
+
+ opt = frr_getopt(argc, argv, NULL);
+
+ if (opt == EOF)
+ break;
+
+ switch (opt) {
+ case 0:
+ break;
+ default:
+ frr_help_exit(1);
+ break;
+ }
+ }
+
+ master = frr_init();
+
+ vrrp_zebra_init();
+ vrrp_vty_init();
+ vrrp_init();
+
+ snprintf(backup_config_file, sizeof(backup_config_file),
+ "%s/vrrpd.conf", frr_sysconfdir);
+ vrrpd_di.backup_config_file = backup_config_file;
+
+ frr_config_fork();
+ frr_run(master);
+
+ /* Not reached. */
+ return 0;
+}
diff --git a/vrrpd/vrrp_memory.c b/vrrpd/vrrp_memory.c
new file mode 100644
index 000000000..4a7c0b7e4
--- /dev/null
+++ b/vrrpd/vrrp_memory.c
@@ -0,0 +1,24 @@
+/*
+ * VRRPD memory types
+ * Copyright (C) 2018 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
+ */
+#include <zebra.h>
+#include <memory.h>
+#include "vrrp_memory.h"
+
+DEFINE_MGROUP(VRRP, "vrrpd")
diff --git a/vrrpd/vrrp_memory.h b/vrrpd/vrrp_memory.h
new file mode 100644
index 000000000..f57a86480
--- /dev/null
+++ b/vrrpd/vrrp_memory.h
@@ -0,0 +1,27 @@
+/*
+ * VRRPD memory types
+ * Copyright (C) 2018 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_MEMORY_H__
+#define __VRRP_MEMORY_H__
+
+#include "memory.h"
+
+DECLARE_MGROUP(VRRP)
+
+#endif
diff --git a/vrrpd/vrrp_packet.c b/vrrpd/vrrp_packet.c
new file mode 100644
index 000000000..4cbcd771f
--- /dev/null
+++ b/vrrpd/vrrp_packet.c
@@ -0,0 +1,50 @@
+/*
+ * VRRPD packet crafting
+ * Copyright (C) 2018 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
+ */
+#include <zebra.h>
+
+#include "memory.h"
+#include "ipaddr.h"
+
+#include "vrrp_packet.h"
+
+/*
+ * Builds a VRRP packet.
+ */
+struct vrrp_pkt *vrrp_pkt_build(uint8_t vrid, uint8_t prio,
+ uint16_t max_adver_int, bool v6, uint8_t numip,
+ void **ips)
+{
+ size_t addrsz = v6 ? sizeof(struct in6_addr) : sizeof(struct in_addr);
+ struct vrrp_pkt *pkt =
+ XCALLOC(MTYPE_TMP, sizeof(struct vrrp_pkt) + addrsz * numip);
+
+ pkt->version = VRRP_VERSION;
+ pkt->type = VRRP_TYPE_ADVERTISEMENT;
+ pkt->vrid = vrid;
+ pkt->priority = prio;
+ pkt->rsvd = 0;
+ pkt->max_adver_int = max_adver_int;
+ for (uint8_t i = 0; i < numip; i++)
+ memcpy(&pkt->addrs[i].v4, ips[i], addrsz);
+ /* FIXME */
+ pkt->cksum = 0;
+
+ return pkt;
+}
diff --git a/vrrpd/vrrp_packet.h b/vrrpd/vrrp_packet.h
new file mode 100644
index 000000000..04116c624
--- /dev/null
+++ b/vrrpd/vrrp_packet.h
@@ -0,0 +1,49 @@
+/*
+ * VRRPD packet crafting
+ * Copyright (C) 2018 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
+ */
+#include <zebra.h>
+
+#include "memory.h"
+#include "ipaddr.h"
+#include "prefix.h"
+
+#define VRRP_VERSION 3
+#define VRRP_TYPE_ADVERTISEMENT 1
+
+struct vrrp_pkt {
+ uint8_t version : 4;
+ uint8_t type : 4;
+ uint8_t vrid;
+ uint8_t priority;
+ uint8_t num_ip;
+ uint16_t rsvd : 4;
+ uint16_t max_adver_int : 12;
+ uint16_t cksum;
+ union {
+ struct in_addr v4;
+ struct in6_addr v6;
+ } addrs[];
+} __attribute((packed, aligned(1)));
+
+/*
+ * Builds a VRRP packet.
+ */
+struct vrrp_pkt *vrrp_pkt_build(uint8_t vrid, uint8_t prio,
+ uint16_t max_adver_int, bool v6, uint8_t numip,
+ void **ips);
diff --git a/vrrpd/vrrp_vty.c b/vrrpd/vrrp_vty.c
new file mode 100644
index 000000000..f438c2489
--- /dev/null
+++ b/vrrpd/vrrp_vty.c
@@ -0,0 +1,80 @@
+/*
+ * VRRP commands
+ * Copyright (C) 2018 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
+ */
+#include <zebra.h>
+
+#include "command.h"
+#include "vty.h"
+#include "if.h"
+
+#include "vrrp.h"
+#include "vrrp_vty.h"
+#include "vrrp_memory.h"
+//#ifndef VTYSH_EXTRACT_PL
+//#include "vrrp/vrrp_vty_clippy.c"
+//#endif
+
+
+#define VRRP_STR "Virtual Router Redundancy Protocol\n"
+#define VRRP_VRID_STR "Virtual Router ID\n"
+
+DEFUN_NOSH (show_debugging_vrrpd,
+ show_debugging_vrrpd_cmd,
+ "show debugging [vrrp]",
+ SHOW_STR
+ DEBUG_STR
+ "VRRP information\n")
+{
+ vty_out(vty, "VRRP debugging status\n");
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(vrrp_vrid,
+ vrrp_vrid_cmd,
+ "[no] vrrp (1-255)",
+ NO_STR
+ VRRP_STR
+ VRRP_VRID_STR)
+{
+ VTY_DECLVAR_CONTEXT(interface, ifp);
+ int idx = 0;
+ uint8_t vrid;
+
+ argv_find(argv, argc, "(1-255)", &idx);
+ vrid = strtoul(argv[idx]->arg, NULL, 10);
+
+ struct vrrp_vrouter *vr = vrrp_vrouter_create(ifp, vrid);
+ vrrp_event(vr, VRRP_EVENT_STARTUP);
+
+ return CMD_SUCCESS;
+}
+
+static struct cmd_node interface_node = {
+ INTERFACE_NODE,
+ "%s(config-if)# ", 1
+};
+
+void vrrp_vty_init(void)
+{
+ install_node(&interface_node, NULL);
+ if_cmd_init();
+ install_element(VIEW_NODE, &show_debugging_vrrpd_cmd);
+ install_element(INTERFACE_NODE, &vrrp_vrid_cmd);
+}
diff --git a/vrrpd/vrrp_vty.h b/vrrpd/vrrp_vty.h
new file mode 100644
index 000000000..2aa47ec20
--- /dev/null
+++ b/vrrpd/vrrp_vty.h
@@ -0,0 +1,23 @@
+/*
+ * VRRP commands
+ * Copyright (C) 2018 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_VTY_H__
+#define __VRRP_VTY_H__
+
+void vrrp_vty_init(void);
+#endif
diff --git a/vrrpd/vrrp_zebra.c b/vrrpd/vrrp_zebra.c
new file mode 100644
index 000000000..c96f9a564
--- /dev/null
+++ b/vrrpd/vrrp_zebra.c
@@ -0,0 +1,39 @@
+/*
+ * Zebra interfacing
+ * Copyright (C) 2018 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
+ */
+#include <zebra.h>
+
+#include "zclient.h"
+#include "thread.h"
+
+#include "vrrp_zebra.h"
+
+/* Zebra structure to hold current status. */
+struct thread_master *master;
+struct zclient *zclient;
+
+void vrrp_zebra_init(void)
+{
+ struct zclient_options opt = { .receive_notify = true };
+
+ zclient = zclient_new(master, &opt);
+
+ zclient_init(zclient, 0, 0, &vrrp_privs);
+}
+
diff --git a/vrrpd/vrrp_zebra.h b/vrrpd/vrrp_zebra.h
new file mode 100644
index 000000000..be6338f17
--- /dev/null
+++ b/vrrpd/vrrp_zebra.h
@@ -0,0 +1,29 @@
+/*
+ * Zebra interfacing
+ * Copyright (C) 2018 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_ZEBRA_H__
+#define __VRRP_ZEBRA_H__
+
+#include "zclient.h"
+#include "thread.h"
+
+extern struct thread_master *master;
+extern struct zebra_privs_t vrrp_privs;
+extern void vrrp_zebra_init(void);
+#endif
diff --git a/vtysh/vtysh.h b/vtysh/vtysh.h
index eb69a20b8..50b0ef484 100644
--- a/vtysh/vtysh.h
+++ b/vtysh/vtysh.h
@@ -42,6 +42,7 @@ DECLARE_MGROUP(MVTYSH)
#define VTYSH_STATICD 0x08000
#define VTYSH_BFDD 0x10000
#define VTYSH_FABRICD 0x20000
+#define VTYSH_VRRPD 0x40000
#define VTYSH_WAS_ACTIVE (-2)