diff options
author | Donald Sharp <sharpd@cumulusnetworks.com> | 2021-07-13 15:40:13 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-07-13 15:40:13 +0200 |
commit | 802a83935f57ec9162bbfae61bb5b6231aaf6681 (patch) | |
tree | e99e81fd34234442adc39bc213ba36f4aa8a3377 /ospf6d/ospf6_interface.c | |
parent | Merge pull request #9036 from donaldsharp/hash_cmp_stuff (diff) | |
parent | ospf6d: fix freebsd mcast group issues (diff) | |
download | frr-802a83935f57ec9162bbfae61bb5b6231aaf6681.tar.xz frr-802a83935f57ec9162bbfae61bb5b6231aaf6681.zip |
Merge pull request #9037 from idryzhov/ospf6-freebsd
ospf6d: fix freebsd mcast group issues
Diffstat (limited to 'ospf6d/ospf6_interface.c')
-rw-r--r-- | ospf6d/ospf6_interface.c | 59 |
1 files changed, 48 insertions, 11 deletions
diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c index 92c88623a..b52d6af90 100644 --- a/ospf6d/ospf6_interface.c +++ b/ospf6d/ospf6_interface.c @@ -680,6 +680,43 @@ static uint8_t dr_election(struct ospf6_interface *oi) return next_state; } +#ifdef __FreeBSD__ + +#include <ifaddrs.h> + +static bool ifmaddr_check(ifindex_t ifindex, struct in6_addr *addr) +{ + struct ifmaddrs *ifmap, *ifma; + struct sockaddr_dl *sdl; + struct sockaddr_in6 *sin6; + bool found = false; + + if (getifmaddrs(&ifmap) != 0) + return false; + + for (ifma = ifmap; ifma; ifma = ifma->ifma_next) { + if (ifma->ifma_name == NULL || ifma->ifma_addr == NULL) + continue; + if (ifma->ifma_name->sa_family != AF_LINK) + continue; + if (ifma->ifma_addr->sa_family != AF_INET6) + continue; + sdl = (struct sockaddr_dl *)ifma->ifma_name; + sin6 = (struct sockaddr_in6 *)ifma->ifma_addr; + if (sdl->sdl_index == ifindex + && memcmp(&sin6->sin6_addr, addr, IPV6_MAX_BYTELEN) == 0) { + found = true; + break; + } + } + + if (ifmap) + freeifmaddrs(ifmap); + + return found; +} + +#endif /* __FreeBSD__ */ /* Interface State Machine */ int interface_up(struct thread *thread) @@ -693,11 +730,7 @@ int interface_up(struct thread *thread) if (!oi->type_cfg) oi->type = ospf6_default_iftype(oi->interface); - /* - * Remove old pointer. If this thread wasn't a timer this - * operation won't make a difference, because it is already NULL. - */ - oi->thread_sso = NULL; + thread_cancel(&oi->thread_sso); if (IS_OSPF6_DEBUG_INTERFACE) zlog_debug("Interface Event %s: [InterfaceUp]", @@ -740,13 +773,17 @@ int interface_up(struct thread *thread) #ifdef __FreeBSD__ /* - * XXX: Schedule IPv6 group join for later, otherwise we might - * lose the multicast group registration caused by IPv6 group - * leave race. + * There's a delay in FreeBSD between issuing a command to leave a + * multicast group and an actual leave. If we execute "no router ospf6" + * and "router ospf6" fast enough, we can end up in a situation when OS + * performs the leave later than it performs the join and the interface + * remains without a multicast group. We have to do the join only after + * the interface actually left the group. */ - if (oi->sso_try_cnt == 0) { - oi->sso_try_cnt++; - zlog_info("Scheduling %s for sso", oi->interface->name); + if (ifmaddr_check(oi->interface->ifindex, &allspfrouters6)) { + zlog_info( + "Interface %s is still in all routers group, rescheduling for SSO", + oi->interface->name); thread_add_timer(master, interface_up, oi, OSPF6_INTERFACE_SSO_RETRY_INT, &oi->thread_sso); |