]> git.proxmox.com Git - mirror_frr.git/commitdiff
vrrpd: initial commit
authorQuentin Young <qlyoung@cumulusnetworks.com>
Mon, 19 Nov 2018 20:51:52 +0000 (20:51 +0000)
committerQuentin Young <qlyoung@cumulusnetworks.com>
Fri, 17 May 2019 00:27:08 +0000 (00:27 +0000)
Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
16 files changed:
Makefile.am
configure.ac
vrrpd/Makefile [new file with mode: 0644]
vrrpd/subdir.am [new file with mode: 0644]
vrrpd/vrrp.c [new file with mode: 0644]
vrrpd/vrrp.h [new file with mode: 0644]
vrrpd/vrrp_main.c [new file with mode: 0644]
vrrpd/vrrp_memory.c [new file with mode: 0644]
vrrpd/vrrp_memory.h [new file with mode: 0644]
vrrpd/vrrp_packet.c [new file with mode: 0644]
vrrpd/vrrp_packet.h [new file with mode: 0644]
vrrpd/vrrp_vty.c [new file with mode: 0644]
vrrpd/vrrp_vty.h [new file with mode: 0644]
vrrpd/vrrp_zebra.c [new file with mode: 0644]
vrrpd/vrrp_zebra.h [new file with mode: 0644]
vtysh/vtysh.h

index 11188ea157d78fb9023bf9f4482ddcc21195d6ff..166ac29d1c7e14013b7cb53f5a1c13b79701807b 100644 (file)
@@ -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
index b7ddf87b43f6631402bf53d3f982cf96c6d3430b..69f489dbc52918218919382d4f0a1e9fdb04e47e 100755 (executable)
@@ -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 (file)
index 0000000..027c6ee
--- /dev/null
@@ -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 (file)
index 0000000..40dee9c
--- /dev/null
@@ -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 (file)
index 0000000..2cc0896
--- /dev/null
@@ -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 (file)
index 0000000..308e3a8
--- /dev/null
@@ -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 (file)
index 0000000..8c73375
--- /dev/null
@@ -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 (file)
index 0000000..4a7c0b7
--- /dev/null
@@ -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 (file)
index 0000000..f57a864
--- /dev/null
@@ -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 (file)
index 0000000..4cbcd77
--- /dev/null
@@ -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 (file)
index 0000000..04116c6
--- /dev/null
@@ -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 (file)
index 0000000..f438c24
--- /dev/null
@@ -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 (file)
index 0000000..2aa47ec
--- /dev/null
@@ -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 (file)
index 0000000..c96f9a5
--- /dev/null
@@ -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 (file)
index 0000000..be6338f
--- /dev/null
@@ -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
index eb69a20b839615837e247f13f2565674533a05a1..50b0ef484416c7d4b9b5e77c3d0864df66bb8f0c 100644 (file)
@@ -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)