diff options
author | Quentin Young <qlyoung@cumulusnetworks.com> | 2019-02-28 19:25:39 +0100 |
---|---|---|
committer | Quentin Young <qlyoung@cumulusnetworks.com> | 2019-05-17 02:27:08 +0200 |
commit | ac1429b9ef8da6d5d8744be7f6cc7f284d5b9b5a (patch) | |
tree | 2dc93b9c7a4dd11853ef1e954e9bb63126c74950 /vrrpd | |
parent | vrrpd: set autoconfed VRRP ifaces protodown off (diff) | |
download | frr-ac1429b9ef8da6d5d8744be7f6cc7f284d5b9b5a.tar.xz frr-ac1429b9ef8da6d5d8744be7f6cc7f284d5b9b5a.zip |
vrrpd: only update one vrrp_router list at a time
When using an autoconfigured VRRP instance, when an interface address
was added or deleted we were trying to update the address list for both
v4 and v6 vrrp_router's which sometimes would cause all the addresses to
get deleted off of one of them and result in an automatic shutdown.
Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
Diffstat (limited to 'vrrpd')
-rw-r--r-- | vrrpd/vrrp.c | 99 |
1 files changed, 45 insertions, 54 deletions
diff --git a/vrrpd/vrrp.c b/vrrpd/vrrp.c index 44885f2e5..58a046fef 100644 --- a/vrrpd/vrrp.c +++ b/vrrpd/vrrp.c @@ -1529,65 +1529,44 @@ int vrrp_event(struct vrrp_router *r, int event) * vr * VRRP router to act on */ -static void vrrp_autoconfig_autoaddrupdate(struct vrrp_vrouter *vr) +static void vrrp_autoconfig_autoaddrupdate(struct vrrp_router *r) { - list_delete_all_node(vr->v4->addrs); - list_delete_all_node(vr->v6->addrs); - struct listnode *ln; struct connected *c = NULL; + bool is_v6_ll; char ipbuf[INET6_ADDRSTRLEN]; - if (vr->v4->mvl_ifp) { - DEBUGD(&vrrp_dbg_auto, - VRRP_LOGPFX VRRP_LOGPFX_VRID - "Setting IPv4 Virtual IP list to match IPv4 addresses on %s", - vr->vrid, vr->v4->mvl_ifp->name); - for (ALL_LIST_ELEMENTS_RO(vr->v4->mvl_ifp->connected, ln, c)) - if (c->address->family == AF_INET) { - inet_ntop(AF_INET, &c->address->u.prefix4, - ipbuf, sizeof(ipbuf)); - DEBUGD(&vrrp_dbg_auto, - VRRP_LOGPFX VRRP_LOGPFX_VRID "Adding %s", - vr->vrid, ipbuf); - vrrp_add_ipv4(vr, c->address->u.prefix4); - } - } + if (!r->mvl_ifp) + return; - if (vr->v6->mvl_ifp) { - DEBUGD(&vrrp_dbg_auto, - VRRP_LOGPFX VRRP_LOGPFX_VRID - "Setting IPv6 Virtual IP list to match IPv6 addresses on %s", - vr->vrid, vr->v6->mvl_ifp->name); - for (ALL_LIST_ELEMENTS_RO(vr->v6->mvl_ifp->connected, ln, c)) - if (c->address->family == AF_INET6 - && !IN6_IS_ADDR_LINKLOCAL(&c->address->u.prefix6)) { - inet_ntop(AF_INET6, &c->address->u.prefix6, - ipbuf, sizeof(ipbuf)); - DEBUGD(&vrrp_dbg_auto, - VRRP_LOGPFX VRRP_LOGPFX_VRID "Adding %s", - vr->vrid, ipbuf); - vrrp_add_ipv6(vr, c->address->u.prefix6); - } + DEBUGD(&vrrp_dbg_auto, + VRRP_LOGPFX VRRP_LOGPFX_VRID + "Setting %s Virtual IP list to match IPv4 addresses on %s", + r->vr->vrid, family2str(r->family), r->mvl_ifp->name); + for (ALL_LIST_ELEMENTS_RO(r->mvl_ifp->connected, ln, c)) { + is_v6_ll = (c->address->family == AF_INET6 + && IN6_IS_ADDR_LINKLOCAL(&c->address->u.prefix6)); + if (c->address->family == r->family && !is_v6_ll) { + inet_ntop(r->family, &c->address->u.prefix, ipbuf, + sizeof(ipbuf)); + DEBUGD(&vrrp_dbg_auto, + VRRP_LOGPFX VRRP_LOGPFX_VRID "Adding %s", + r->vr->vrid, ipbuf); + if (r->family == AF_INET) + vrrp_add_ipv4(r->vr, c->address->u.prefix4); + else + vrrp_add_ipv6(r->vr, c->address->u.prefix6); + } } - vrrp_check_start(vr); + vrrp_check_start(r->vr); - if (vr->v4->addrs->count == 0 - && vr->v4->fsm.state != VRRP_STATE_INITIALIZE) { - DEBUGD(&vrrp_dbg_auto, - VRRP_LOGPFX VRRP_LOGPFX_VRID - "IPv4 Virtual IP list is empty; shutting down", - vr->vrid); - vrrp_event(vr->v4, VRRP_EVENT_SHUTDOWN); - } - if (vr->v6->addrs->count == 0 - && vr->v6->fsm.state != VRRP_STATE_INITIALIZE) { + if (r->addrs->count == 0 && r->fsm.state != VRRP_STATE_INITIALIZE) { DEBUGD(&vrrp_dbg_auto, VRRP_LOGPFX VRRP_LOGPFX_VRID - "IPv6 Virtual IP list is empty; shutting down", - vr->vrid); - vrrp_event(vr->v6, VRRP_EVENT_SHUTDOWN); + "%s Virtual IP list is empty; shutting down", + r->vr->vrid, family2str(r->family)); + vrrp_event(r, VRRP_EVENT_SHUTDOWN); } } @@ -1618,7 +1597,8 @@ vrrp_autoconfig_autocreate(struct interface *mvl_ifp) return NULL; } - vrrp_autoconfig_autoaddrupdate(vr); + vrrp_autoconfig_autoaddrupdate(vr->v4); + vrrp_autoconfig_autoaddrupdate(vr->v6); vr->autoconf = true; @@ -1666,7 +1646,10 @@ static int vrrp_autoconfig_if_add(struct interface *ifp) if (vr->autoconf == false) return 0; else if (!created) { - vrrp_autoconfig_autoaddrupdate(vr); + if (vr->v4->mvl_ifp == ifp) + vrrp_autoconfig_autoaddrupdate(vr->v4); + else if (vr->v6->mvl_ifp == ifp) + vrrp_autoconfig_autoaddrupdate(vr->v6); } return 0; @@ -1790,8 +1773,12 @@ static int vrrp_autoconfig_if_address_add(struct interface *ifp) struct vrrp_vrouter *vr = vrrp_lookup_by_if_mvl(ifp); - if (vr && vr->autoconf) - vrrp_autoconfig_autoaddrupdate(vr); + if (vr && vr->autoconf) { + if (vr->v4->mvl_ifp == ifp) + vrrp_autoconfig_autoaddrupdate(vr->v4); + else if (vr->v6->mvl_ifp == ifp) + vrrp_autoconfig_autoaddrupdate(vr->v6); + } return 0; } @@ -1818,8 +1805,12 @@ static int vrrp_autoconfig_if_address_del(struct interface *ifp) struct vrrp_vrouter *vr = vrrp_lookup_by_if_mvl(ifp); - if (vr && vr->autoconf) - vrrp_autoconfig_autoaddrupdate(vr); + if (vr && vr->autoconf) { + if (vr->v4->mvl_ifp == ifp) + vrrp_autoconfig_autoaddrupdate(vr->v4); + else if (vr->v6->mvl_ifp == ifp) + vrrp_autoconfig_autoaddrupdate(vr->v6); + } return 0; } |