From c23edd740255f0199aaabeaed59aeeff81de9538 Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Tue, 4 Dec 2018 21:28:25 +0000 Subject: [PATCH] vrrpd: config commands, enable ARP * Allow configuring priority * Allow configuring IPv4 addresses * Add show command for vrouters * Fix hash comparison function * Fix ARP packetization bugs * Enable sending of gratuitous ARP Signed-off-by: Quentin Young --- vrrpd/vrrp.c | 51 +++++++++++------- vrrpd/vrrp.h | 49 +++++++++++++++-- vrrpd/vrrp_arp.c | 6 +-- vrrpd/vrrp_vty.c | 134 +++++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 206 insertions(+), 34 deletions(-) diff --git a/vrrpd/vrrp.c b/vrrpd/vrrp.c index 23f144a792..fd0c62cb0d 100644 --- a/vrrpd/vrrp.c +++ b/vrrpd/vrrp.c @@ -58,21 +58,7 @@ static void vrrp_mac_set(struct ethaddr *mac, bool v6, uint8_t vrid) 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, +void vrrp_update_times(struct vrrp_vrouter *vr, uint16_t advertisement_interval, uint16_t master_adver_interval) { vr->advertisement_interval = advertisement_interval; @@ -83,6 +69,25 @@ static void vrrp_update_times(struct vrrp_vrouter *vr, uint16_t advertisement_in vr->master_down_interval /= 256; } +void vrrp_update_priority(struct vrrp_vrouter *vr, uint8_t priority) +{ + if (vr->priority == priority) + return; + + vr->priority = priority; + /* Timers depend on priority value, need to recalculate them */ + vrrp_update_times(vr, vr->advertisement_interval, + vr->master_adver_interval); +} + +void vrrp_add_ip(struct vrrp_vrouter *vr, struct in_addr v4) +{ + struct in_addr *v4_ins = XCALLOC(MTYPE_TMP, sizeof(struct in_addr)); + + *v4_ins = v4; + listnode_add(vr->v4, v4_ins); +} + struct vrrp_vrouter *vrrp_vrouter_create(struct interface *ifp, uint8_t vrid) { struct vrrp_vrouter *vr = @@ -93,7 +98,6 @@ struct vrrp_vrouter *vrrp_vrouter_create(struct interface *ifp, uint8_t vrid) 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; @@ -111,6 +115,17 @@ struct vrrp_vrouter *vrrp_vrouter_create(struct interface *ifp, uint8_t vrid) return vr; } +void vrrp_vrouter_destroy(struct vrrp_vrouter *vr) +{ + if (vr->sock >= 0) + close(vr->sock); + vr->ifp = NULL; + list_delete(&vr->v4); + list_delete(&vr->v6); + hash_release(vrrp_vrouters_hash, vr); + XFREE(MTYPE_TMP, vr); +} + struct vrrp_vrouter *vrrp_lookup(uint8_t vrid) { struct vrrp_vrouter vr; @@ -302,7 +317,7 @@ static int vrrp_startup(struct vrrp_vrouter *vr) if (vr->priority == VRRP_PRIO_MASTER) { vrrp_send_advertisement(vr); - /* vrrp_garp_send(vr); */ + vrrp_garp_send_all(vr); thread_add_timer_msec(master, vrrp_adver_timer_expire, vr, vr->advertisement_interval * 10, @@ -360,7 +375,7 @@ 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; + return vr1->vrid == vr2->vrid; } void vrrp_init(void) diff --git a/vrrpd/vrrp.h b/vrrpd/vrrp.h index f1b93b9242..240144d3b3 100644 --- a/vrrpd/vrrp.h +++ b/vrrpd/vrrp.h @@ -67,9 +67,6 @@ struct vrrp_vrouter { */ struct list *v6; - /* Time between ADVERTISEMENTS (centiseconds) */ - int advint; - /* Whether this VRRP Router is currently the master */ bool is_master; @@ -151,6 +148,52 @@ void vrrp_init(void); */ struct vrrp_vrouter *vrrp_vrouter_create(struct interface *ifp, uint8_t vrid); +/* + * Destroy a VRRP Virtual Router. + */ +void vrrp_vrouter_destroy(struct vrrp_vrouter *vr); + +/* + * 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 + */ +void vrrp_update_times(struct vrrp_vrouter *vr, uint16_t advertisement_interval, + uint16_t master_adver_interval); + +/* + * Change the priority of a VRRP Virtual Router. + * + * Recalculates timers using new priority. + * + * vr + * Virtual Router to change priority of + * + * priority + * New priority + */ +void vrrp_update_priority(struct vrrp_vrouter *vr, uint8_t priority); + +/* + * Add IPv4 address to a VRRP Virtual Router + * + * vr + * Virtual Router to add IPv4 address to + * + * v4 + * Address to add + */ +void vrrp_add_ip(struct vrrp_vrouter *vr, struct in_addr v4); + /* * Find VRRP Virtual Router by Virtual Router ID */ diff --git a/vrrpd/vrrp_arp.c b/vrrpd/vrrp_arp.c index a67af4e104..f917c7ec3a 100644 --- a/vrrpd/vrrp_arp.c +++ b/vrrpd/vrrp_arp.c @@ -93,18 +93,18 @@ static ssize_t vrrp_build_garp(uint8_t *buf, struct interface *ifp, arph->ar_hln = ifp->hw_addr_len; arph->ar_pln = sizeof(struct in_addr); arph->ar_op = htons(ARPOP_REQUEST); - arp_ptr = (uint8_t *)(arph + sizeof(struct arphdr)); + arp_ptr = (uint8_t *)(arph + 1); /* Source MAC: us */ memcpy(arp_ptr, ifp->hw_addr, ifp->hw_addr_len); arp_ptr += ifp->hw_addr_len; /* Source IP: us */ - memcpy(arp_ptr, &v4, sizeof(struct in_addr)); + memcpy(arp_ptr, v4, sizeof(struct in_addr)); arp_ptr += sizeof(struct in_addr); /* Dest MAC: broadcast */ memset(arp_ptr, 0xFF, ETH_ALEN); arp_ptr += ifp->hw_addr_len; /* Dest IP: us */ - memcpy(arp_ptr, &v4, sizeof(struct in_addr)); + memcpy(arp_ptr, v4, sizeof(struct in_addr)); arp_ptr += sizeof(struct in_addr); return arp_ptr - buf; diff --git a/vrrpd/vrrp_vty.c b/vrrpd/vrrp_vty.c index f30aadd626..6c7fc5f194 100644 --- a/vrrpd/vrrp_vty.c +++ b/vrrpd/vrrp_vty.c @@ -22,17 +22,32 @@ #include "command.h" #include "vty.h" #include "if.h" +#include "termtable.h" +#include "prefix.h" #include "vrrp.h" #include "vrrp_vty.h" #include "vrrp_memory.h" -//#ifndef VTYSH_EXTRACT_PL -//#include "vrrp/vrrp_vty_clippy.c" -//#endif +#ifndef VTYSH_EXTRACT_PL +#include "vrrpd/vrrp_vty_clippy.c" +#endif #define VRRP_STR "Virtual Router Redundancy Protocol\n" #define VRRP_VRID_STR "Virtual Router ID\n" +#define VRRP_PRIORITY_STR "Virtual Router Priority\n" +#define VRRP_IP_STR "Virtual Router IPv4 address\n" + +#define VROUTER_GET_VTY(_vty, _vrid, _vr) \ + do { \ + _vr = vrrp_lookup(_vrid); \ + if (!_vr) { \ + vty_out(_vty, \ + "%% Please configure VRRP instance %u\n", \ + (unsigned int)_vrid); \ + return CMD_WARNING_CONFIG_FAILED; \ + } \ + } while (0); DEFUN_NOSH (show_debugging_vrrpd, show_debugging_vrrpd_cmd, @@ -46,19 +61,14 @@ DEFUN_NOSH (show_debugging_vrrpd, return CMD_SUCCESS; } -DEFUN(vrrp_vrid, +DEFPY(vrrp_vrid, vrrp_vrid_cmd, - "[no] vrrp (1-255)", + "[no] vrrp (1-255)$vrid", 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); int ret = vrrp_event(vr, VRRP_EVENT_STARTUP); @@ -70,6 +80,107 @@ DEFUN(vrrp_vrid, return CMD_SUCCESS; } +DEFPY(vrrp_priority, + vrrp_priority_cmd, + "[no] vrrp (1-255)$vrid priority (1-254)", + NO_STR + VRRP_STR + VRRP_VRID_STR + VRRP_PRIORITY_STR + "Priority value\n") +{ + struct vrrp_vrouter *vr; + + VROUTER_GET_VTY(vty, vrid, vr); + vrrp_update_priority(vr, priority); + + return CMD_SUCCESS; +} + +DEFPY(vrrp_ip, + vrrp_ip_cmd, + "[no] vrrp (1-255)$vrid ip A.B.C.D$ip", + NO_STR + VRRP_STR + VRRP_VRID_STR + "Add IP address\n" + VRRP_IP_STR) +{ + struct vrrp_vrouter *vr; + + VROUTER_GET_VTY(vty, vrid, vr); + vrrp_add_ip(vr, ip); + + return CMD_SUCCESS; +} + +DEFPY(vrrp_vrid_show, + vrrp_vrid_show_cmd, + "show vrrp [(1-255)$vrid]", + SHOW_STR + VRRP_STR + VRRP_VRID_STR) +{ + struct vrrp_vrouter *vr; + char ethstr[ETHER_ADDR_STRLEN]; + char ipstr[INET_ADDRSTRLEN]; + const char *stastr; + + VROUTER_GET_VTY(vty, vrid, vr); + + switch (vr->fsm.state) { + case VRRP_STATE_INITIALIZE: + stastr = "Initialize"; + break; + case VRRP_STATE_MASTER: + stastr = "Master"; + break; + case VRRP_STATE_BACKUP: + stastr = "Backup"; + break; + } + + struct ttable *tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]); + + ttable_add_row(tt, "%s|%" PRIu32, "Virtual Router ID", vr->vrid); + prefix_mac2str(&vr->vr_mac_v4, ethstr, sizeof(ethstr)); + ttable_add_row(tt, "%s|%s", "Virtual MAC", ethstr); + ttable_add_row(tt, "%s|%s", "Status", stastr); + ttable_add_row(tt, "%s|%" PRIu8, "Priority", vr->priority); + ttable_add_row(tt, "%s|%s", "Preempt Mode", + vr->preempt_mode ? "Yes" : "No"); + ttable_add_row(tt, "%s|%s", "Accept Mode", + vr->accept_mode ? "Yes" : "No"); + ttable_add_row(tt, "%s|%" PRIu16, "Advertisement Interval", + vr->advertisement_interval); + ttable_add_row(tt, "%s|%" PRIu16, "Master Advertisement Interval", + vr->master_adver_interval); + ttable_add_row(tt, "%s|%" PRIu16, "Skew Time", vr->skew_time); + ttable_add_row(tt, "%s|%" PRIu16, "Master Down Interval", + vr->master_down_interval); + ttable_add_row(tt, "%s|%u", "IPv4 Addresses", vr->v4->count); + + char *table = ttable_dump(tt, "\n"); + vty_out(vty, "\n%s\n", table); + XFREE(MTYPE_TMP, table); + ttable_del(tt); + + /* Dump IPv4 Addresses */ + if (vr->v4->count) { + vty_out(vty, " IPv4 Addresses\n"); + vty_out(vty, " --------------\n"); + struct listnode *ln; + struct in_addr *v4; + for (ALL_LIST_ELEMENTS_RO(vr->v4, ln, v4)) { + inet_ntop(AF_INET, v4, ipstr, sizeof(ipstr)); + vty_out(vty, " %s\n", ipstr); + } + vty_out(vty, "\n"); + } + + return CMD_SUCCESS; +} + static struct cmd_node interface_node = { INTERFACE_NODE, "%s(config-if)# ", 1 @@ -80,5 +191,8 @@ void vrrp_vty_init(void) install_node(&interface_node, NULL); if_cmd_init(); install_element(VIEW_NODE, &show_debugging_vrrpd_cmd); + install_element(VIEW_NODE, &vrrp_vrid_show_cmd); install_element(INTERFACE_NODE, &vrrp_vrid_cmd); + install_element(INTERFACE_NODE, &vrrp_priority_cmd); + install_element(INTERFACE_NODE, &vrrp_ip_cmd); } -- 2.39.5