Download raw body.
carp: embed scope-id when sending NA
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
carp: embed scope-id when sending NA