vrrpd: initial commit

Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
This commit is contained in:
Quentin Young 2018-11-19 20:51:52 +00:00
parent db95656d48
commit 5435a2bf61
16 changed files with 1031 additions and 1 deletions

View 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

View file

@ -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])

10
vrrpd/Makefile Normal file
View file

@ -0,0 +1,10 @@
all: ALWAYS
@$(MAKE) -s -C .. vrrp/vrrp
%: ALWAYS
@$(MAKE) -s -C .. vrrp/$@
Makefile:
#nothing
ALWAYS:
.PHONY: ALWAYS makefiles
.SUFFIXES:

32
vrrpd/subdir.am Normal file
View file

@ -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@

351
vrrpd/vrrp.c Normal file
View file

@ -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);
}

162
vrrpd/vrrp.h Normal file
View file

@ -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

151
vrrpd/vrrp_main.c Normal file
View file

@ -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;
}

24
vrrpd/vrrp_memory.c Normal file
View file

@ -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")

27
vrrpd/vrrp_memory.h Normal file
View file

@ -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

50
vrrpd/vrrp_packet.c Normal file
View file

@ -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;
}

49
vrrpd/vrrp_packet.h Normal file
View file

@ -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);

80
vrrpd/vrrp_vty.c Normal file
View file

@ -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);
}

23
vrrpd/vrrp_vty.h Normal file
View file

@ -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

39
vrrpd/vrrp_zebra.c Normal file
View file

@ -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);
}

29
vrrpd/vrrp_zebra.h Normal file
View file

@ -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

View 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)