From 5435a2bf61c4179e8b69af5d3a808b42f5387177 Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Mon, 19 Nov 2018 20:51:52 +0000 Subject: [PATCH] vrrpd: initial commit Signed-off-by: Quentin Young --- Makefile.am | 3 +- configure.ac | 1 + vrrpd/Makefile | 10 ++ vrrpd/subdir.am | 32 ++++ vrrpd/vrrp.c | 351 ++++++++++++++++++++++++++++++++++++++++++++ vrrpd/vrrp.h | 162 ++++++++++++++++++++ vrrpd/vrrp_main.c | 151 +++++++++++++++++++ vrrpd/vrrp_memory.c | 24 +++ vrrpd/vrrp_memory.h | 27 ++++ vrrpd/vrrp_packet.c | 50 +++++++ vrrpd/vrrp_packet.h | 49 +++++++ vrrpd/vrrp_vty.c | 80 ++++++++++ vrrpd/vrrp_vty.h | 23 +++ vrrpd/vrrp_zebra.c | 39 +++++ vrrpd/vrrp_zebra.h | 29 ++++ vtysh/vtysh.h | 1 + 16 files changed, 1031 insertions(+), 1 deletion(-) create mode 100644 vrrpd/Makefile create mode 100644 vrrpd/subdir.am create mode 100644 vrrpd/vrrp.c create mode 100644 vrrpd/vrrp.h create mode 100644 vrrpd/vrrp_main.c create mode 100644 vrrpd/vrrp_memory.c create mode 100644 vrrpd/vrrp_memory.h create mode 100644 vrrpd/vrrp_packet.c create mode 100644 vrrpd/vrrp_packet.h create mode 100644 vrrpd/vrrp_vty.c create mode 100644 vrrpd/vrrp_vty.h create mode 100644 vrrpd/vrrp_zebra.c create mode 100644 vrrpd/vrrp_zebra.h 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 +#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 + +#include +#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 +#include +#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 + +#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 + +#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 + +#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 + +#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) -- 2.39.2