From: Quentin Young Date: Thu, 14 Feb 2019 22:28:51 +0000 (+0000) Subject: vrrpd: interface tracking X-Git-Tag: base_7.2~330^2~76 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=6e93585e6f4f837e3f1912e1877b72d7ca7544f9;p=mirror%2Ffrr.git vrrpd: interface tracking * Dynamically bind interfaces when they become available * Automatically start VRRP sessions when their interfaces are added or come up * Automatically shut down VRRP sessions when their interfaces are deleted or go down * Automatically unbind interfaces when they are deleted Signed-off-by: Quentin Young --- diff --git a/vrrpd/vrrp.c b/vrrpd/vrrp.c index bb24bc9510..bf4f0f1ec9 100644 --- a/vrrpd/vrrp.c +++ b/vrrpd/vrrp.c @@ -128,8 +128,146 @@ static bool vrrp_is_owner(struct interface *ifp, struct ipaddr *addr) return !!connected_lookup_prefix_exact(ifp, &p); } +/* + * Whether an interface has a MAC address that matches the VRRP RFC. + * + * ifp + * Interface to check + * + * Returns: + * Whether the interface has a VRRP mac or not + */ +static bool vrrp_ifp_has_vrrp_mac(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); +} + +/* + * Lookup a Virtual Router instance given a macvlan subinterface. + * + * The VRID is extracted from the interface MAC and the 2-tuple (iface, vrid) + * is used to look up any existing instances that match the interface. It does + * not matter whether the instance is already bound to the interface or not. + * + * mvl_ifp + * Interface pointer to use to lookup. Should be a macvlan device. + * + * Returns: + * Virtual Router, if found + * NULL otherwise + */ +static struct vrrp_vrouter *vrrp_lookup_by_if_mvl(struct interface *mvl_ifp) +{ + struct interface *p; + + if (!mvl_ifp || !mvl_ifp->link_ifindex + || !vrrp_ifp_has_vrrp_mac(mvl_ifp)) + return NULL; + + p = if_lookup_by_index(mvl_ifp->link_ifindex, VRF_DEFAULT); + uint8_t vrid = mvl_ifp->hw_addr[5]; + + return vrrp_lookup(p, vrid); +} + +/* + * Lookup the Virtual Router instances configured on a particular interface. + * + * ifp + * Interface pointer to use to lookup. Should not be a macvlan device. + * + * Returns: + * List of virtual routers found + */ +static struct list *vrrp_lookup_by_if(struct interface *ifp) +{ + struct list *l = hash_to_list(vrrp_vrouters_hash); + struct listnode *ln, *nn; + struct vrrp_vrouter *vr; + + for (ALL_LIST_ELEMENTS(l, ln, nn, vr)) + if (vr->ifp != ifp) + list_delete_node(l, ln); + + return l; +} + +/* + * Lookup any Virtual Router instances associated with a particular interface. + * This is a combination of the results from vrrp_lookup_by_if_mvl and + * vrrp_lookup_by_if. + * + * Suppose the system interface list looks like the following: + * + * eth0 + * \- eth0-v0 00:00:5e:00:01:01 + * \- eth0-v1 00:00:5e:00:02:01 + * \- eth0-v2 00:00:5e:00:01:0a + * + * Passing eth0-v2 to this function will give you the VRRP instance configured + * on eth0 with VRID 10. Passing eth0-v0 or eth0-v1 will give you the VRRP + * instance configured on eth0 with VRID 1. Passing eth0 will give you both. + * + * ifp + * Interface pointer to use to lookup. Can be any interface. + * + * Returns: + * List of virtual routers found + */ +static struct list *vrrp_lookup_by_if_any(struct interface *ifp) +{ + struct vrrp_vrouter *vr; + struct list *vrs; + + vr = vrrp_lookup_by_if_mvl(ifp); + vrs = vr ? list_new() : vrrp_lookup_by_if(ifp); + + if (vr) + listnode_add(vrs, vr); + + return vrs; +} + /* Configuration controllers ----------------------------------------------- */ +void vrrp_check_start(struct vrrp_vrouter *vr) +{ + struct vrrp_router *r; + bool start; + + if (vr->shutdown || vr->ifp == NULL) + return; + + r = vr->v4; + start = r->fsm.state == VRRP_STATE_INITIALIZE; + start = start && (vr->ifp != NULL); + start = start && (CHECK_FLAG(vr->ifp->flags, IFF_UP)); + start = start && vr->ifp->connected->count > 0; + start = start && (r->mvl_ifp != NULL); + start = start && (CHECK_FLAG(r->mvl_ifp->flags, IFF_UP)); + start = start && r->addrs->count > 0; + if (start) + vrrp_event(r, VRRP_EVENT_STARTUP); + + r = vr->v6; + start = r->fsm.state == VRRP_STATE_INITIALIZE; + start = start && (vr->ifp != NULL); + start = start && (CHECK_FLAG(vr->ifp->flags, IFF_UP)); + start = start && vr->ifp->connected->count; + start = start && (r->mvl_ifp != NULL); + start = start && (CHECK_FLAG(r->mvl_ifp->flags, IFF_UP)); + start = start && (r->mvl_ifp->connected->count > 0); + start = start && r->addrs->count > 0; + if (start) + vrrp_event(r, VRRP_EVENT_STARTUP); +} + void vrrp_set_priority(struct vrrp_vrouter *vr, uint8_t priority) { vr->priority = priority; @@ -161,7 +299,7 @@ static bool vrrp_has_ip(struct vrrp_vrouter *vr, struct ipaddr *ip) return false; } -int vrrp_add_ip(struct vrrp_router *r, struct ipaddr *ip, bool activate) +int vrrp_add_ip(struct vrrp_router *r, struct ipaddr *ip) { int af = (ip->ipa_type == IPADDR_V6) ? AF_INET6 : AF_INET; @@ -185,15 +323,7 @@ int vrrp_add_ip(struct vrrp_router *r, struct ipaddr *ip, bool activate) *new = *ip; listnode_add(r->addrs, new); - bool do_activate = (activate && r->fsm.state == VRRP_STATE_INITIALIZE); - int ret = 0; - - if (do_activate) { - ret = vrrp_event(r, VRRP_EVENT_STARTUP); - if (ret) - listnode_delete(r->addrs, new); - } - else if (r->fsm.state == VRRP_STATE_MASTER) { + if (r->fsm.state == VRRP_STATE_MASTER) { switch (r->family) { case AF_INET: vrrp_garp_send(r, &new->ipaddr_v4); @@ -204,26 +334,26 @@ int vrrp_add_ip(struct vrrp_router *r, struct ipaddr *ip, bool activate) } } - return ret; + return 0; } -int vrrp_add_ipv4(struct vrrp_vrouter *vr, struct in_addr v4, bool activate) +int vrrp_add_ipv4(struct vrrp_vrouter *vr, struct in_addr v4) { struct ipaddr ip; ip.ipa_type = IPADDR_V4; ip.ipaddr_v4 = v4; - return vrrp_add_ip(vr->v4, &ip, activate); + return vrrp_add_ip(vr->v4, &ip); } -int vrrp_add_ipv6(struct vrrp_vrouter *vr, struct in6_addr v6, bool activate) +int vrrp_add_ipv6(struct vrrp_vrouter *vr, struct in6_addr v6) { struct ipaddr ip; ip.ipa_type = IPADDR_V6; ip.ipaddr_v6 = v6; - return vrrp_add_ip(vr->v6, &ip, activate); + return vrrp_add_ip(vr->v6, &ip); } -int vrrp_del_ip(struct vrrp_router *r, struct ipaddr *ip, bool deactivate) +int vrrp_del_ip(struct vrrp_router *r, struct ipaddr *ip) { struct listnode *ln, *nn; struct ipaddr *iter; @@ -232,37 +362,36 @@ int vrrp_del_ip(struct vrrp_router *r, struct ipaddr *ip, bool deactivate) if (!vrrp_has_ip(r->vr, ip)) return 0; - if (deactivate && r->addrs->count == 1 - && r->fsm.state != VRRP_STATE_INITIALIZE) - ret = vrrp_event(r, VRRP_EVENT_SHUTDOWN); + for (ALL_LIST_ELEMENTS(r->addrs, ln, nn, iter)) + if (!memcmp(&iter->ip, &ip->ip, IPADDRSZ(ip))) + list_delete_node(r->addrs, ln); /* - * Don't delete IP if we failed to deactivate, otherwise we'll run into - * issues later trying to build a VRRP advertisement with no IPs + * NB: Deleting the last address and then issuing a shutdown will cause + * transmission of a priority 0 VRRP Advertisement - as per the RFC - + * but it will have no addresses. This is not forbidden in the RFC but + * might confuse other implementations. */ - if (ret == 0) { - for (ALL_LIST_ELEMENTS(r->addrs, ln, nn, iter)) - if (!memcmp(&iter->ip, &ip->ip, IPADDRSZ(ip))) - list_delete_node(r->addrs, ln); - } + if (r->addrs->count == 0 && r->fsm.state != VRRP_STATE_INITIALIZE) + ret = vrrp_event(r, VRRP_EVENT_SHUTDOWN); return ret; } -int vrrp_del_ipv6(struct vrrp_vrouter *vr, struct in6_addr v6, bool deactivate) +int vrrp_del_ipv6(struct vrrp_vrouter *vr, struct in6_addr v6) { struct ipaddr ip; ip.ipa_type = IPADDR_V6; ip.ipaddr_v6 = v6; - return vrrp_del_ip(vr->v6, &ip, deactivate); + return vrrp_del_ip(vr->v6, &ip); } -int vrrp_del_ipv4(struct vrrp_vrouter *vr, struct in_addr v4, bool deactivate) +int vrrp_del_ipv4(struct vrrp_vrouter *vr, struct in_addr v4) { struct ipaddr ip; ip.ipa_type = IPADDR_V4; ip.ipaddr_v4 = v4; - return vrrp_del_ip(vr->v4, &ip, deactivate); + return vrrp_del_ip(vr->v4, &ip); } @@ -1363,7 +1492,7 @@ static void vrrp_autoconfig_autoaddrupdate(struct vrrp_vrouter *vr) DEBUGD(&vrrp_dbg_auto, VRRP_LOGPFX VRRP_LOGPFX_VRID "Adding %s", vr->vrid, ipbuf); - vrrp_add_ipv4(vr, c->address->u.prefix4, true); + vrrp_add_ipv4(vr, c->address->u.prefix4); } } @@ -1380,10 +1509,12 @@ static void vrrp_autoconfig_autoaddrupdate(struct vrrp_vrouter *vr) DEBUGD(&vrrp_dbg_auto, VRRP_LOGPFX VRRP_LOGPFX_VRID "Adding %s", vr->vrid, ipbuf); - vrrp_add_ipv6(vr, c->address->u.prefix6, true); + vrrp_add_ipv6(vr, c->address->u.prefix6); } } + vrrp_check_start(vr); + if (vr->v4->addrs->count == 0 && vr->v4->fsm.state != VRRP_STATE_INITIALIZE) { DEBUGD(&vrrp_dbg_auto, @@ -1436,32 +1567,21 @@ vrrp_autoconfig_autocreate(struct interface *mvl_ifp) return vr; } -static bool vrrp_ifp_has_vrrp_mac(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); -} - -static struct vrrp_vrouter *vrrp_lookup_by_mvlif(struct interface *mvl_ifp) -{ - struct interface *p; - - if (!mvl_ifp || !mvl_ifp->link_ifindex - || !vrrp_ifp_has_vrrp_mac(mvl_ifp)) - return NULL; - - p = if_lookup_by_index(mvl_ifp->link_ifindex, VRF_DEFAULT); - uint8_t vrid = mvl_ifp->hw_addr[5]; - - return vrrp_lookup(p, vrid); -} - -int vrrp_autoconfig_if_add(struct interface *ifp) +/* + * Callback to notify autoconfig of interface add. + * + * If the interface is a VRRP-compatible device, and there is no existing VRRP + * router running on it, one is created. All addresses on the interface are + * added to the router. + * + * ifp + * Interface to operate on + * + * Returns: + * -1 on failure + * 0 otherwise + */ +static int vrrp_autoconfig_if_add(struct interface *ifp) { bool created = false; struct vrrp_vrouter *vr; @@ -1472,7 +1592,7 @@ int vrrp_autoconfig_if_add(struct interface *ifp) if (!ifp || !ifp->link_ifindex || !vrrp_ifp_has_vrrp_mac(ifp)) return -1; - vr = vrrp_lookup_by_mvlif(ifp); + vr = vrrp_lookup_by_if_mvl(ifp); if (!vr) { vr = vrrp_autoconfig_autocreate(ifp); @@ -1485,66 +1605,73 @@ int vrrp_autoconfig_if_add(struct interface *ifp) if (vr->autoconf == false) return 0; else if (!created) { - vrrp_attach_interface(vr->v4); - vrrp_attach_interface(vr->v6); vrrp_autoconfig_autoaddrupdate(vr); } return 0; } -int vrrp_autoconfig_if_del(struct interface *ifp) +/* + * Callback to notify autoconfig of interface delete. + * + * If the interface is a VRRP-compatible device, and a VRRP router is running + * on it, and that VRRP router was automatically configured, it will be + * deleted. If that was the last router for the corresponding VRID (i.e., if + * this interface was a v4 VRRP interface and no v6 router is configured for + * the same VRID) then the entire virtual router is deleted. + * + * ifp + * Interface to operate on + * + * Returns: + * -1 on failure + * 0 otherwise + */ +static int vrrp_autoconfig_if_del(struct interface *ifp) { if (!vrrp_autoconfig_is_on) return 0; - struct vrrp_vrouter *vr = vrrp_lookup_by_mvlif(ifp); - - if (!vr) - return 0; + struct vrrp_vrouter *vr; + struct listnode *ln; + struct list *vrs; - if (vr && vr->autoconf == false) - return 0; + vrs = vrrp_lookup_by_if_any(ifp); - if (vr && vr->v4->mvl_ifp == ifp) { - if (vr->v4->fsm.state != VRRP_STATE_INITIALIZE) { + for (ALL_LIST_ELEMENTS_RO(vrs, ln, vr)) + if (vr->autoconf + && (!vr->ifp || (!vr->v4->mvl_ifp && !vr->v6->mvl_ifp))) { DEBUGD(&vrrp_dbg_auto, VRRP_LOGPFX VRRP_LOGPFX_VRID - "Interface %s deleted; shutting down IPv4 VRRP router", - vr->vrid, ifp->name); - vrrp_event(vr->v4, VRRP_EVENT_SHUTDOWN); - } - vr->v4->mvl_ifp = NULL; - } - if (vr && vr->v6->mvl_ifp == ifp) { - if (vr->v6->fsm.state != VRRP_STATE_INITIALIZE) { - DEBUGD(&vrrp_dbg_auto, - VRRP_LOGPFX VRRP_LOGPFX_VRID - "Interface %s deleted; shutting down IPv6 VRRP router", - vr->vrid, ifp->name); - vrrp_event(vr->v6, VRRP_EVENT_SHUTDOWN); + "All VRRP interfaces for instance deleted; destroying autoconfigured VRRP router", + vr->vrid); + vrrp_vrouter_destroy(vr); } - vr->v6->mvl_ifp = NULL; - } - if (vr->v4->mvl_ifp == NULL && vr->v6->mvl_ifp == NULL) { - DEBUGD(&vrrp_dbg_auto, - VRRP_LOGPFX VRRP_LOGPFX_VRID - "All VRRP interfaces for instance deleted; destroying autoconfigured VRRP router", - vr->vrid); - vrrp_vrouter_destroy(vr); - vr = NULL; - } + list_delete(&vrs); return 0; } -int vrrp_autoconfig_if_up(struct interface *ifp) +/* + * Callback to notify autoconfig of interface up. + * + * Roughly equivalent to vrrp_autoconfig_if_add, except that addresses are + * refreshed if an autoconfigured virtual router already exists. + * + * ifp + * Interface to operate on + * + * Returns: + * -1 on failure + * 0 otherwise + */ +static int vrrp_autoconfig_if_up(struct interface *ifp) { if (!vrrp_autoconfig_is_on) return 0; - struct vrrp_vrouter *vr = vrrp_lookup_by_mvlif(ifp); + struct vrrp_vrouter *vr = vrrp_lookup_by_if_mvl(ifp); if (vr && !vr->autoconf) return 0; @@ -1554,14 +1681,27 @@ int vrrp_autoconfig_if_up(struct interface *ifp) return 0; } - vrrp_attach_interface(vr->v4); - vrrp_attach_interface(vr->v6); vrrp_autoconfig_autoaddrupdate(vr); return 0; } -int vrrp_autoconfig_if_down(struct interface *ifp) +/* + * Callback to notify autoconfig of interface down. + * + * Does nothing. An interface down event is accompanied by address deletion + * events for all the addresses on the interface; if an autoconfigured VRRP + * router exists on this interface, then it will have all its addresses deleted + * and end up in Initialize. + * + * ifp + * Interface to operate on + * + * Returns: + * -1 on failure + * 0 otherwise + */ +static int vrrp_autoconfig_if_down(struct interface *ifp) { if (!vrrp_autoconfig_is_on) return 0; @@ -1569,12 +1709,27 @@ int vrrp_autoconfig_if_down(struct interface *ifp) return 0; } -int vrrp_autoconfig_if_address_add(struct interface *ifp) +/* + * Callback to notify autoconfig of a new interface address. + * + * If a VRRP router exists on this interface, its address list is updated to + * match the new address list. If no addresses remain, a Shutdown event is + * issued to the VRRP router. + * + * ifp + * Interface to operate on + * + * Returns: + * -1 on failure + * 0 otherwise + * + */ +static int vrrp_autoconfig_if_address_add(struct interface *ifp) { if (!vrrp_autoconfig_is_on) return 0; - struct vrrp_vrouter *vr = vrrp_lookup_by_mvlif(ifp); + struct vrrp_vrouter *vr = vrrp_lookup_by_if_mvl(ifp); if (vr && vr->autoconf) vrrp_autoconfig_autoaddrupdate(vr); @@ -1582,12 +1737,27 @@ int vrrp_autoconfig_if_address_add(struct interface *ifp) return 0; } -int vrrp_autoconfig_if_address_del(struct interface *ifp) +/* + * Callback to notify autoconfig of a removed interface address. + * + * If a VRRP router exists on this interface, its address list is updated to + * match the new address list. If no addresses remain, a Shutdown event is + * issued to the VRRP router. + * + * ifp + * Interface to operate on + * + * Returns: + * -1 on failure + * 0 otherwise + * + */ +static int vrrp_autoconfig_if_address_del(struct interface *ifp) { if (!vrrp_autoconfig_is_on) return 0; - struct vrrp_vrouter *vr = vrrp_lookup_by_mvlif(ifp); + struct vrrp_vrouter *vr = vrrp_lookup_by_if_mvl(ifp); if (vr && vr->autoconf) vrrp_autoconfig_autoaddrupdate(vr); @@ -1633,6 +1803,142 @@ void vrrp_autoconfig_off(void) list_delete(&ll); } +/* Interface tracking ------------------------------------------------------ */ + +/* + * Bind any pending interfaces. + * + * mvl_ifp + * macvlan interface that some VRRP instances might want to bind to + */ +static void vrrp_bind_pending(struct interface *mvl_ifp) +{ + struct vrrp_vrouter *vr; + + vr = vrrp_lookup_by_if_mvl(mvl_ifp); + + if (vr) { + if (mvl_ifp->hw_addr[4] == 0x01 && !vr->v4->mvl_ifp) + vrrp_attach_interface(vr->v4); + else if (mvl_ifp->hw_addr[4] == 0x02 && !vr->v6->mvl_ifp) + vrrp_attach_interface(vr->v6); + } +} + +void vrrp_if_up(struct interface *ifp) +{ + struct vrrp_vrouter *vr; + struct listnode *ln; + struct list *vrs; + + vrrp_bind_pending(ifp); + + vrs = vrrp_lookup_by_if_any(ifp); + + for (ALL_LIST_ELEMENTS_RO(vrs, ln, vr)) + vrrp_check_start(vr); + + list_delete(&vrs); + + vrrp_autoconfig_if_up(ifp); +} + +void vrrp_if_down(struct interface *ifp) +{ + struct vrrp_vrouter *vr; + struct listnode *ln; + struct list *vrs; + + vrs = vrrp_lookup_by_if_any(ifp); + + for (ALL_LIST_ELEMENTS_RO(vrs, ln, vr)) { + if (vr->v4->mvl_ifp == ifp || vr->ifp == ifp) { + if (vr->v4->fsm.state != VRRP_STATE_INITIALIZE) { + DEBUGD(&vrrp_dbg_auto, + VRRP_LOGPFX VRRP_LOGPFX_VRID + "Interface %s down; shutting down IPv4 VRRP router", + vr->vrid, ifp->name); + vrrp_event(vr->v4, VRRP_EVENT_SHUTDOWN); + } + } + + if (vr->v6->mvl_ifp == ifp || vr->ifp == ifp) { + if (vr->v6->fsm.state != VRRP_STATE_INITIALIZE) { + DEBUGD(&vrrp_dbg_auto, + VRRP_LOGPFX VRRP_LOGPFX_VRID + "Interface %s down; shutting down IPv6 VRRP router", + vr->vrid, ifp->name); + vrrp_event(vr->v6, VRRP_EVENT_SHUTDOWN); + } + } + } + + list_delete(&vrs); + + vrrp_autoconfig_if_down(ifp); +} + +void vrrp_if_add(struct interface *ifp) +{ + vrrp_bind_pending(ifp); + + /* thanks, zebra */ + if (CHECK_FLAG(ifp->flags, IFF_UP)) + vrrp_if_up(ifp); + + vrrp_autoconfig_if_add(ifp); +} + +void vrrp_if_del(struct interface *ifp) +{ + struct listnode *ln; + struct vrrp_vrouter *vr; + struct list *vrs = vrrp_lookup_by_if_any(ifp); + + vrrp_if_down(ifp); + + for (ALL_LIST_ELEMENTS_RO(vrs, ln, vr)) { + if (vr->ifp == ifp) + vr->ifp = NULL; + else if (vr->v4->mvl_ifp == ifp) + vr->v4->mvl_ifp = NULL; + else if (vr->v6->mvl_ifp == ifp) + vr->v6->mvl_ifp = NULL; + } + + list_delete(&vrs); + + vrrp_autoconfig_if_del(ifp); +} + +void vrrp_if_address_add(struct interface *ifp) +{ + struct vrrp_vrouter *vr; + struct listnode *ln; + struct list *vrs; + + /* + * We have to do a wide search here, because we need to know when a v6 + * macvlan device gets a new address. This is because the macvlan link + * local is used as the source address for v6 advertisements, and hence + * "do I have a link local" constitutes an activation condition for v6 + * virtual routers. + */ + vrs = vrrp_lookup_by_if_any(ifp); + + for (ALL_LIST_ELEMENTS_RO(vrs, ln, vr)) + vrrp_check_start(vr); + + list_delete(&vrs); + + vrrp_autoconfig_if_address_add(ifp); +} + +void vrrp_if_address_del(struct interface *ifp) +{ + vrrp_autoconfig_if_address_del(ifp); +} + /* Other ------------------------------------------------------------------- */ int vrrp_config_write_interface(struct vty *vty) diff --git a/vrrpd/vrrp.h b/vrrpd/vrrp.h index eabb23fe75..45f4e4ecb7 100644 --- a/vrrpd/vrrp.h +++ b/vrrpd/vrrp.h @@ -168,6 +168,9 @@ struct vrrp_vrouter { /* Whether this instance was automatically configured */ bool autoconf; + /* Whether this VRRP router is in administrative shutdown */ + bool shutdown; + /* Interface */ struct interface *ifp; @@ -234,6 +237,14 @@ void vrrp_vrouter_destroy(struct vrrp_vrouter *vr); /* Configuration controllers ----------------------------------------------- */ +/* + * Check if a Virtual Router ought to be started, and if so, start it. + * + * vr + * Virtual Router to checkstart + */ +void vrrp_check_start(struct vrrp_vrouter *vr); + /* * Change the configured priority of a VRRP Virtual Router. * @@ -279,7 +290,7 @@ void vrrp_set_advertisement_interval(struct vrrp_vrouter *vr, * -1 on error * 0 otherwise */ -int vrrp_add_ip(struct vrrp_router *r, struct ipaddr *ip, bool activate); +int vrrp_add_ip(struct vrrp_router *r, struct ipaddr *ip); /* * Add an IPv4 address to a VRRP Virtual Router. @@ -298,7 +309,7 @@ int vrrp_add_ip(struct vrrp_router *r, struct ipaddr *ip, bool activate); * -1 on error * 0 otherwise */ -int vrrp_add_ipv4(struct vrrp_vrouter *vr, struct in_addr v4, bool activate); +int vrrp_add_ipv4(struct vrrp_vrouter *vr, struct in_addr v4); /* * Add an IPv6 address to a VRRP Virtual Router. @@ -317,7 +328,7 @@ int vrrp_add_ipv4(struct vrrp_vrouter *vr, struct in_addr v4, bool activate); * -1 on error * 0 otherwise */ -int vrrp_add_ipv6(struct vrrp_vrouter *vr, struct in6_addr v6, bool activate); +int vrrp_add_ipv6(struct vrrp_vrouter *vr, struct in6_addr v6); /* * Remove an IP address from a VRRP Virtual Router. @@ -338,7 +349,7 @@ int vrrp_add_ipv6(struct vrrp_vrouter *vr, struct in6_addr v6, bool activate); * -1 on error * 0 otherwise */ -int vrrp_del_ip(struct vrrp_router *r, struct ipaddr *ip, bool deactivate); +int vrrp_del_ip(struct vrrp_router *r, struct ipaddr *ip); /* * Remove an IPv4 address from a VRRP Virtual Router. @@ -359,7 +370,7 @@ int vrrp_del_ip(struct vrrp_router *r, struct ipaddr *ip, bool deactivate); * -1 on error * 0 otherwise */ -int vrrp_del_ipv4(struct vrrp_vrouter *vr, struct in_addr v4, bool deactivate); +int vrrp_del_ipv4(struct vrrp_vrouter *vr, struct in_addr v4); /* * Remove an IPv6 address from a VRRP Virtual Router. @@ -380,7 +391,7 @@ int vrrp_del_ipv4(struct vrrp_vrouter *vr, struct in_addr v4, bool deactivate); * -1 on error * 0 otherwise */ -int vrrp_del_ipv6(struct vrrp_vrouter *vr, struct in6_addr v6, bool deactivate); +int vrrp_del_ipv6(struct vrrp_vrouter *vr, struct in6_addr v6); /* State machine ----------------------------------------------------------- */ @@ -457,105 +468,14 @@ void vrrp_autoconfig_on(int version); */ void vrrp_autoconfig_off(void); -/* - * Callback to notify autoconfig of interface add. - * - * If the interface is a VRRP-compatible device, and there is no existing VRRP - * router running on it, one is created. All addresses on the interface are - * added to the router. - * - * ifp - * Interface to operate on - * - * Returns: - * -1 on failure - * 0 otherwise - */ -int vrrp_autoconfig_if_add(struct interface *ifp); - -/* - * Callback to notify autoconfig of interface delete. - * - * If the interface is a VRRP-compatible device, and a VRRP router is running - * on it, and that VRRP router was automatically configured, it will be - * deleted. If that was the last router for the corresponding VRID (i.e., if - * this interface was a v4 VRRP interface and no v6 router is configured for - * the same VRID) then the entire virtual router is deleted. - * - * ifp - * Interface to operate on - * - * Returns: - * -1 on failure - * 0 otherwise - */ -int vrrp_autoconfig_if_del(struct interface *ifp); - -/* - * Callback to notify autoconfig of interface up. - * - * Roughly equivalent to vrrp_autoconfig_if_add, except that addresses are - * refreshed if an autoconfigured virtual router already exists. - * - * ifp - * Interface to operate on - * - * Returns: - * -1 on failure - * 0 otherwise - */ -int vrrp_autoconfig_if_up(struct interface *ifp); - -/* - * Callback to notify autoconfig of interface down. - * - * Does nothing. An interface down event is accompanied by address deletion - * events for all the addresses on the interface; if an autoconfigured VRRP - * router exists on this interface, then it will have all its addresses deleted - * and end up in Initialize. - * - * ifp - * Interface to operate on - * - * Returns: - * -1 on failure - * 0 otherwise - */ -int vrrp_autoconfig_if_down(struct interface *ifp); +/* Interface Tracking ------------------------------------------------------ */ -/* - * Callback to notify autoconfig of a new interface address. - * - * If a VRRP router exists on this interface, its address list is updated to - * match the new address list. If no addresses remain, a Shutdown event is - * issued to the VRRP router. - * - * ifp - * Interface to operate on - * - * Returns: - * -1 on failure - * 0 otherwise - * - */ -int vrrp_autoconfig_if_address_add(struct interface *ifp); - -/* - * Callback to notify autoconfig of a removed interface address. - * - * If a VRRP router exists on this interface, its address list is updated to - * match the new address list. If no addresses remain, a Shutdown event is - * issued to the VRRP router. - * - * ifp - * Interface to operate on - * - * Returns: - * -1 on failure - * 0 otherwise - * - */ -int vrrp_autoconfig_if_address_del(struct interface *ifp); +void vrrp_if_add(struct interface *ifp); +void vrrp_if_del(struct interface *ifp); +void vrrp_if_up(struct interface *ifp); +void vrrp_if_down(struct interface *ifp); +void vrrp_if_address_add(struct interface *ifp); +void vrrp_if_address_del(struct interface *ifp); /* Other ------------------------------------------------------------------- */ diff --git a/vrrpd/vrrp_vty.c b/vrrpd/vrrp_vty.c index eacf4a14c3..4f1d5dfa08 100644 --- a/vrrpd/vrrp_vty.c +++ b/vrrpd/vrrp_vty.c @@ -146,12 +146,14 @@ DEFPY(vrrp_ip, if (no) { int oldstate = vr->v4->fsm.state; - failed = vrrp_del_ipv4(vr, ip, true); + failed = vrrp_del_ipv4(vr, ip); + vrrp_check_start(vr); deactivated = (vr->v4->fsm.state == VRRP_STATE_INITIALIZE && oldstate != VRRP_STATE_INITIALIZE); } else { int oldstate = vr->v4->fsm.state; - failed = vrrp_add_ipv4(vr, ip, true); + failed = vrrp_add_ipv4(vr, ip); + vrrp_check_start(vr); activated = (vr->v4->fsm.state != VRRP_STATE_INITIALIZE && oldstate == VRRP_STATE_INITIALIZE); } @@ -203,12 +205,12 @@ DEFPY(vrrp_ip6, if (no) { int oldstate = vr->v6->fsm.state; - failed = vrrp_del_ipv6(vr, ipv6, true); + failed = vrrp_del_ipv6(vr, ipv6); deactivated = (vr->v6->fsm.state == VRRP_STATE_INITIALIZE && oldstate != VRRP_STATE_INITIALIZE); } else { int oldstate = vr->v6->fsm.state; - failed = vrrp_add_ipv6(vr, ipv6, true); + failed = vrrp_add_ipv6(vr, ipv6); activated = (vr->v6->fsm.state != VRRP_STATE_INITIALIZE && oldstate == VRRP_STATE_INITIALIZE); } diff --git a/vrrpd/vrrp_zebra.c b/vrrpd/vrrp_zebra.c index a4e1158010..1baeb41ba4 100644 --- a/vrrpd/vrrp_zebra.c +++ b/vrrpd/vrrp_zebra.c @@ -61,7 +61,7 @@ static int vrrp_zebra_if_add(int command, struct zclient *zclient, if (!ifp) return 0; - vrrp_autoconfig_if_add(ifp); + vrrp_if_add(ifp); return 0; } @@ -75,7 +75,7 @@ static int vrrp_zebra_if_del(int command, struct zclient *zclient, if (!ifp) return 0; - vrrp_autoconfig_if_del(ifp); + vrrp_if_del(ifp); #if 0 if (VRRP_DEBUG_ZEBRA) { @@ -104,7 +104,7 @@ static int vrrp_zebra_if_state_up(int command, struct zclient *zclient, if (!ifp) return 0; - vrrp_autoconfig_if_up(ifp); + vrrp_if_up(ifp); #if 0 if (VRRP_DEBUG_ZEBRA) { @@ -132,7 +132,7 @@ static int vrrp_zebra_if_state_down(int command, struct zclient *zclient, if (!ifp) return 0; - vrrp_autoconfig_if_down(ifp); + vrrp_if_down(ifp); #if 0 if (VRRP_DEBUG_ZEBRA) { @@ -189,7 +189,7 @@ static int vrrp_zebra_if_address_add(int command, struct zclient *zclient, if (!c) return 0; - vrrp_autoconfig_if_address_add(c->ifp); + vrrp_if_address_add(c->ifp); #if 0 if (VRRP_DEBUG_ZEBRA) { @@ -225,7 +225,7 @@ static int vrrp_zebra_if_address_del(int command, struct zclient *client, if (!c) return 0; - vrrp_autoconfig_if_address_del(c->ifp); + vrrp_if_address_del(c->ifp); return 0; }