From dac42f2ef5969a4f5378ddaeede31500f0fdeff9 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 30 Jun 2021 10:25:43 -0400 Subject: [PATCH] bgpd: Ensure v6 LL address is available before establishing peering There are startup situations where we will attempt to connect to a remote peer before bgp has received the v6 LL address. If we do not have this address we must not allow the connection to come up until we have one available to use in those situations where we must have a v6 LL address. Signed-off-by: Donald Sharp --- bgpd/bgp_zebra.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 5d3176537bb2..ec71e17034d3 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -683,7 +683,7 @@ static int if_get_ipv6_global(struct interface *ifp, struct in6_addr *addr) return 0; } -static int if_get_ipv6_local(struct interface *ifp, struct in6_addr *addr) +static bool if_get_ipv6_local(struct interface *ifp, struct in6_addr *addr) { struct listnode *cnode; struct connected *connected; @@ -695,10 +695,10 @@ static int if_get_ipv6_local(struct interface *ifp, struct in6_addr *addr) if (cp->family == AF_INET6) if (IN6_IS_ADDR_LINKLOCAL(&cp->u.prefix6)) { memcpy(addr, &cp->u.prefix6, IPV6_MAX_BYTELEN); - return 1; + return true; } } - return 0; + return false; } static int if_get_ipv4_address(struct interface *ifp, struct in_addr *addr) @@ -724,6 +724,7 @@ bool bgp_zebra_nexthop_set(union sockunion *local, union sockunion *remote, { int ret = 0; struct interface *ifp = NULL; + bool v6_ll_avail = true; memset(nexthop, 0, sizeof(struct bgp_nexthop)); @@ -793,12 +794,20 @@ bool bgp_zebra_nexthop_set(union sockunion *local, union sockunion *remote, * route-map to * specify the global IPv6 nexthop. */ - if_get_ipv6_local(ifp, &nexthop->v6_global); + v6_ll_avail = + if_get_ipv6_local(ifp, &nexthop->v6_global); memcpy(&nexthop->v6_local, &nexthop->v6_global, IPV6_MAX_BYTELEN); } else - if_get_ipv6_local(ifp, &nexthop->v6_local); + v6_ll_avail = + if_get_ipv6_local(ifp, &nexthop->v6_local); + /* + * If we are a v4 connection and we are not doing unnumbered + * not having a v6 LL address is ok + */ + if (!v6_ll_avail && !peer->conf_if) + v6_ll_avail = true; if (if_lookup_by_ipv4(&remote->sin.sin_addr, peer->bgp->vrf_id)) peer->shared_network = 1; else @@ -824,7 +833,8 @@ bool bgp_zebra_nexthop_set(union sockunion *local, union sockunion *remote, remote->sin6.sin6_scope_id, peer->bgp->vrf_id); if (direct) - if_get_ipv6_local(ifp, &nexthop->v6_local); + v6_ll_avail = if_get_ipv6_local( + ifp, &nexthop->v6_local); } else /* Link-local address. */ { @@ -871,7 +881,7 @@ bool bgp_zebra_nexthop_set(union sockunion *local, union sockunion *remote, /* If we have identified the local interface, there is no error for now. */ - return true; + return v6_ll_avail; } static struct in6_addr *