From: Florian Obser Subject: Re: carp: embed scope-id when sending NA To: YASUOKA Masahiko Cc: tech@openbsd.org Date: Thu, 05 Dec 2024 18:36:34 +0100 This reads OK to me. (I don't have a carp setup at the moment). On 2024-12-05 12:26 +09, YASUOKA Masahiko wrote: > Hi, > > My colleague noticed that all unsolicited NAs when carp becomes master > are ignored by the received hosts. This is because the source address > is ::1. > > 20:32:08.676523 00:50:56:xx:xx:xx 33:33:00:00:00:01 86dd 86: ::1 > ff02::1: icmp6: neighbor adv: tgt is xxxx:xxxx:bb5e:1823::1:250 > > We must embed a scope-id to the destination when calling > nd6_na_output(). Also the route the "ff02:1" is not RTF_UP at that > time. We need to wait until if state change task is completed. > > > comments? ok? > > Embed scope-id when sending NA. Also, do it when the link state is > up because the route entry to the mutlicast is not ready yet when the > carp becomes master. > > Index: sys/netinet/ip_carp.c > =================================================================== > RCS file: /disk/cvs/openbsd/src/sys/netinet/ip_carp.c,v > diff -u -p -r1.363 ip_carp.c > --- sys/netinet/ip_carp.c 14 Jul 2024 18:53:39 -0000 1.363 > +++ sys/netinet/ip_carp.c 5 Dec 2024 03:19:34 -0000 > @@ -138,6 +138,7 @@ struct carp_softc { > struct ip_moptions sc_imo; > #ifdef INET6 > struct ip6_moptions sc_im6o; > + struct task sc_itask; > #endif /* INET6 */ > > SRPL_ENTRY(carp_softc) sc_list; > @@ -171,6 +172,9 @@ struct carp_softc { > u_int32_t sc_lsmask; /* load sharing mask */ > int sc_lscount; /* # load sharing interfaces (max 32) */ > int sc_delayed_arp; /* delayed ARP request countdown */ > +#ifdef INET6 > + int sc_send_na; /* send NA when link state up */ > +#endif /* INET6 */ > int sc_realmac; /* using real mac */ > > struct in_addr sc_peer; > @@ -250,6 +254,7 @@ int carp_join_multicast(struct carp_soft > void carp_send_na(struct carp_softc *); > int carp_set_addr6(struct carp_softc *, struct sockaddr_in6 *); > int carp_join_multicast6(struct carp_softc *); > +void carp_if_linkstate(void *); > #endif > int carp_clone_create(struct if_clone *, int); > int carp_clone_destroy(struct ifnet *); > @@ -811,6 +816,9 @@ carp_clone_create(struct if_clone *ifc, > task_set(&sc->sc_atask, carp_addr_updated, sc); > task_set(&sc->sc_ltask, carp_carpdev_state, sc); > task_set(&sc->sc_dtask, carpdetach, sc); > +#ifdef INET6 > + task_set(&sc->sc_itask, carp_if_linkstate, sc); > +#endif /* INET6 */ > > sc->sc_suppress = 0; > sc->sc_advbase = CARP_DFLTINTV; > @@ -843,6 +851,9 @@ carp_clone_create(struct if_clone *ifc, > > /* Hook carp_addr_updated to cope with address and route changes. */ > if_addrhook_add(&sc->sc_if, &sc->sc_atask); > +#ifdef INET6 > + if_linkstatehook_add(&sc->sc_if, &sc->sc_itask); > +#endif /* INET6 */ > > return (0); > } > @@ -894,6 +905,9 @@ carp_clone_destroy(struct ifnet *ifp) > struct carp_softc *sc = ifp->if_softc; > > if_addrhook_del(&sc->sc_if, &sc->sc_atask); > +#ifdef INET6 > + if_linkstatehook_del(&sc->sc_if, &sc->sc_itask); > +#endif /* INET6 */ > > NET_LOCK(); > carpdetach(sc); > @@ -1285,13 +1299,13 @@ void > carp_send_na(struct carp_softc *sc) > { > struct ifaddr *ifa; > - struct in6_addr *in6; > - static struct in6_addr mcast = IN6ADDR_LINKLOCAL_ALLNODES_INIT; > + struct in6_addr *in6, mcast = IN6ADDR_LINKLOCAL_ALLNODES_INIT; > int i_am_router = (atomic_load_int(&ip6_forwarding) != 0); > int flags = ND_NA_FLAG_OVERRIDE; > > if (i_am_router) > flags |= ND_NA_FLAG_ROUTER; > + mcast.s6_addr16[1] = htons(sc->sc_if.if_index); > > TAILQ_FOREACH(ifa, &sc->sc_if.if_addrlist, ifa_list) { > > @@ -1534,7 +1548,8 @@ carp_master_down(struct carp_vhost_entry > /* Schedule a delayed ARP to deal w/ some L3 switches */ > sc->sc_delayed_arp = 2; > #ifdef INET6 > - carp_send_na(sc); > + /* routing entry is not ready yet. do it later */ > + sc->sc_send_na = 1; > #endif /* INET6 */ > } > carp_setrun(vhe, 0); > @@ -1955,6 +1970,17 @@ carp_join_multicast6(struct carp_softc * > return (0); > } > > +void > +carp_if_linkstate(void *v) > +{ > + struct carp_softc *sc = v; > + > + if (sc->sc_send_na) { > + if (sc->sc_if.if_link_state == LINK_STATE_UP) > + carp_send_na(sc); > + sc->sc_send_na = 0; > + } > +} > #endif /* INET6 */ > > int > -- In my defence, I have been left unsupervised.