diff options
author | Quentin Young <qlyoung@cumulusnetworks.com> | 2019-02-08 00:48:49 +0100 |
---|---|---|
committer | Quentin Young <qlyoung@cumulusnetworks.com> | 2019-05-17 02:27:08 +0200 |
commit | 53e60e5c5819ea3a602d1bd60b50b0b30caf7702 (patch) | |
tree | bcbf644e60899329c024416485d8b165c150795a | |
parent | vrrpd: add cli for preempt mode (diff) | |
download | frr-53e60e5c5819ea3a602d1bd60b50b0b30caf7702.tar.xz frr-53e60e5c5819ea3a602d1bd60b50b0b30caf7702.zip |
vrrpd: autoconfig support
Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
-rw-r--r-- | lib/if.h | 4 | ||||
-rw-r--r-- | lib/zclient.c | 3 | ||||
-rw-r--r-- | vrrpd/vrrp.c | 76 | ||||
-rw-r--r-- | vrrpd/vrrp.h | 38 | ||||
-rw-r--r-- | vrrpd/vrrp_vty.c | 21 | ||||
-rw-r--r-- | vrrpd/vrrp_zebra.c | 3 | ||||
-rw-r--r-- | zebra/zapi_msg.c | 2 |
7 files changed, 139 insertions, 8 deletions
@@ -225,6 +225,10 @@ struct interface { not work as expected. */ ifindex_t ifindex; + /* + * ifindex of parent interface, if any + */ + ifindex_t link_ifindex; #define IFINDEX_INTERNAL 0 /* Zebra internal interface status */ diff --git a/lib/zclient.c b/lib/zclient.c index 6647a1ab1..0972590ca 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -1400,6 +1400,8 @@ stream_failure: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | bandwidth | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | parent ifindex | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Link Layer Type | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Harware Address Length | @@ -1580,6 +1582,7 @@ void zebra_interface_if_set_value(struct stream *s, struct interface *ifp) ifp->mtu = stream_getl(s); ifp->mtu6 = stream_getl(s); ifp->bandwidth = stream_getl(s); + ifp->link_ifindex = stream_getl(s); ifp->ll_type = stream_getl(s); ifp->hw_addr_len = stream_getl(s); if (ifp->hw_addr_len) diff --git a/vrrpd/vrrp.c b/vrrpd/vrrp.c index 265cce33f..bf804abb3 100644 --- a/vrrpd/vrrp.c +++ b/vrrpd/vrrp.c @@ -1297,6 +1297,81 @@ int vrrp_event(struct vrrp_router *r, int event) /* Other ------------------------------------------------------------------- */ +static struct vrrp_vrouter * +vrrp_autoconfig_autocreate(struct interface *mvl_ifp) +{ + struct interface *p; + struct vrrp_vrouter *vr; + + p = if_lookup_by_index(mvl_ifp->link_ifindex, VRF_DEFAULT); + uint8_t vrid = mvl_ifp->hw_addr[5]; + + zlog_info(VRRP_LOGPFX "Autoconfiguring VRRP on %s", p->name); + + /* If it already exists, skip it */ + vr = vrrp_lookup(p, vrid); + if (vr) { + zlog_info(VRRP_LOGPFX "VRRP instance %" PRIu8 + "already configured on %s", + vrid, p->name); + return vr; + } + + /* create a new one */ + vr = vrrp_vrouter_create(p, vrid, vrrp_autoconfig_version); + + if (!vr) + return NULL; + + /* add connected addresses as vips */ + struct listnode *ln; + struct connected *c = NULL; + for (ALL_LIST_ELEMENTS_RO(mvl_ifp->connected, ln, c)) + if (c->address->family == AF_INET) + vrrp_add_ipv4(vr, c->address->u.prefix4, false); + else if (c->address->family == AF_INET6) { + if (!IN6_IS_ADDR_LINKLOCAL(&c->address->u.prefix6)) + vrrp_add_ipv6(vr, c->address->u.prefix6, false); + } + + if (vr->v4->addrs->count) + vrrp_event(vr->v4, VRRP_EVENT_STARTUP); + if (vr->v6->addrs->count) + vrrp_event(vr->v6, VRRP_EVENT_STARTUP); + + vr->autoconf = true; + + return vr; +} + +static bool vrrp_ifp_is_mvl(struct interface *ifp) +{ + struct ethaddr vmac4; + struct ethaddr vmac6; + vrrp_mac_set(&vmac4, 0, 0x00); + vrrp_mac_set(&vmac6, 1, 0x00); + + return !memcmp(ifp->hw_addr, vmac4.octet, sizeof(vmac4.octet) - 1) + || !memcmp(ifp->hw_addr, vmac6.octet, sizeof(vmac6.octet) - 1); +} + +int vrrp_autoconfig(struct interface *ifp) +{ + if (ifp && vrrp_ifp_is_mvl(ifp)) { + vrrp_autoconfig_autocreate(ifp); + return 0; + } + + /* Loop through interfaces, looking for compatible macvlan devices. */ + struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); + + FOR_ALL_INTERFACES (vrf, ifp) + if (vrrp_ifp_is_mvl(ifp)) + vrrp_autoconfig_autocreate(ifp); + + return 0; +} + static unsigned int vrrp_hash_key(void *arg) { struct vrrp_vrouter *vr = arg; @@ -1323,6 +1398,7 @@ static bool vrrp_hash_cmp(const void *arg1, const void *arg2) void vrrp_init(void) { + vrrp_autoconfig_version = 3; 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 index 0df588b22..57ec55eea 100644 --- a/vrrpd/vrrp.h +++ b/vrrpd/vrrp.h @@ -53,13 +53,17 @@ extern struct zebra_privs_t vrrp_privs; /* Global hash of all Virtual Routers */ struct hash *vrrp_vrouters_hash; -/* - * VRRP Router. - * - * This struct contains all state for a particular VRRP Router operating in a - * Virtual Router for either IPv4 or IPv6. - */ -struct vrrp_router { +/* Whether to automatically configure VRRP instances */ +static bool vrrp_autoconfig_on; +static int vrrp_autoconfig_version; + + /* + * VRRP Router. + * + * This struct contains all state for a particular VRRP Router operating + * in a Virtual Router for either IPv4 or IPv6. + */ + struct vrrp_router { /* * Whether this VRRP Router is active. */ @@ -164,6 +168,9 @@ struct vrrp_router { * implementations. */ struct vrrp_vrouter { + /* Whether this instance was automatically configured */ + bool autoconf; + /* Interface */ struct interface *ifp; @@ -418,6 +425,23 @@ int vrrp_event(struct vrrp_router *r, int event); /* Other ------------------------------------------------------------------- */ /* + * Search for and automatically configure VRRP instances on interfaces. + * + * ifp + * Interface to autoconfig. If it is a macvlan interface and has a VRRP MAC, + * a VRRP instance corresponding to VMAC assigned to macvlan will be created + * on the parent interface and all addresses on the macvlan interface except + * the v6 link local will be configured as VRRP addresses. If NULL, this + * treatment will be applied to all existing interfaces matching the above + * criterion. + * + * Returns: + * -1 on failure + * 0 otherwise + */ +int vrrp_autoconfig(struct interface *ifp); + +/* * Find VRRP Virtual Router by Virtual Router ID */ struct vrrp_vrouter *vrrp_lookup(struct interface *ifp, uint8_t vrid); diff --git a/vrrpd/vrrp_vty.c b/vrrpd/vrrp_vty.c index 70711d12a..c73e5cb55 100644 --- a/vrrpd/vrrp_vty.c +++ b/vrrpd/vrrp_vty.c @@ -287,6 +287,26 @@ DEFPY(vrrp_preempt, return CMD_SUCCESS; } +DEFPY(vrrp_autoconf, + vrrp_autoconf_cmd, + "[no] vrrp autoconfig [version (2-3)]", + NO_STR + VRRP_STR + "Automatically set up VRRP instances on VRRP-compatible interfaces\n" + "Version for automatically configured instances\n" + VRRP_VERSION_STR) +{ + vrrp_autoconfig_on = !no; + version = version ? version : 3; + + if (vrrp_autoconfig_on) + vrrp_autoconfig(NULL); + + vrrp_autoconfig_version = !no ? version : vrrp_autoconfig_version; + + return CMD_SUCCESS; +} + static void vrrp_show(struct vty *vty, struct vrrp_vrouter *vr) { char ethstr4[ETHER_ADDR_STRLEN]; @@ -401,6 +421,7 @@ void vrrp_vty_init(void) if_cmd_init(); install_element(VIEW_NODE, &show_debugging_vrrpd_cmd); install_element(VIEW_NODE, &vrrp_vrid_show_cmd); + install_element(CONFIG_NODE, &vrrp_autoconf_cmd); install_element(INTERFACE_NODE, &vrrp_vrid_cmd); install_element(INTERFACE_NODE, &vrrp_priority_cmd); install_element(INTERFACE_NODE, &vrrp_advertisement_interval_cmd); diff --git a/vrrpd/vrrp_zebra.c b/vrrpd/vrrp_zebra.c index c41915cbd..e7967f932 100644 --- a/vrrpd/vrrp_zebra.c +++ b/vrrpd/vrrp_zebra.c @@ -61,7 +61,8 @@ static int vrrp_zebra_if_add(int command, struct zclient *zclient, if (!ifp) return 0; - /* FIXME: handle subinterface creation here */ + if (vrrp_autoconfig_on) + vrrp_autoconfig(ifp); return 0; } diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index a49733170..ca371186b 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -71,6 +71,7 @@ static void zserv_encode_interface(struct stream *s, struct interface *ifp) { /* Interface information. */ + struct zebra_if *zif = ifp->info; stream_put(s, ifp->name, INTERFACE_NAMSIZ); stream_putl(s, ifp->ifindex); stream_putc(s, ifp->status); @@ -82,6 +83,7 @@ static void zserv_encode_interface(struct stream *s, struct interface *ifp) stream_putl(s, ifp->mtu); stream_putl(s, ifp->mtu6); stream_putl(s, ifp->bandwidth); + stream_putl(s, zif->link_ifindex); stream_putl(s, ifp->ll_type); stream_putl(s, ifp->hw_addr_len); if (ifp->hw_addr_len) |