Date: Sat, 5 Sep 2015 14:14:03 +0000 (UTC) From: "Alexander V. Chernikov" <melifaro@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r287484 - in head/sys: netinet netinet6 Message-ID: <201509051414.t85EE3Qu084919@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: melifaro Date: Sat Sep 5 14:14:03 2015 New Revision: 287484 URL: https://svnweb.freebsd.org/changeset/base/287484 Log: Do not pass lle to nd6_ns_output(). Use newly-added nd6_llinfo_get_holdsrc() to extract desired IPv6 source from holdchain and pass it to the nd6_ns_output(). Modified: head/sys/netinet/toecore.c head/sys/netinet6/nd6.c head/sys/netinet6/nd6.h head/sys/netinet6/nd6_nbr.c Modified: head/sys/netinet/toecore.c ============================================================================== --- head/sys/netinet/toecore.c Sat Sep 5 12:28:18 2015 (r287483) +++ head/sys/netinet/toecore.c Sat Sep 5 14:14:03 2015 (r287484) @@ -482,7 +482,7 @@ restart: (long)ND_IFINFO(ifp)->retrans * hz / 1000); LLE_WUNLOCK(lle); - nd6_ns_output(ifp, NULL, &sin6->sin6_addr, NULL, 0); + nd6_ns_output(ifp, NULL, NULL, &sin6->sin6_addr, 0); return (EWOULDBLOCK); } else { Modified: head/sys/netinet6/nd6.c ============================================================================== --- head/sys/netinet6/nd6.c Sat Sep 5 12:28:18 2015 (r287483) +++ head/sys/netinet6/nd6.c Sat Sep 5 14:14:03 2015 (r287484) @@ -510,6 +510,34 @@ nd6_llinfo_settimer_locked(struct llentr LLE_REMREF(ln); } +/* +* Gets source address of the first packet in hold queue +* and stores it in @src. +* Returns pointer to @src (if hold queue is not empty) or NULL. +* +*/ +static struct in6_addr * +nd6_llinfo_get_holdsrc(struct llentry *ln, struct in6_addr *src) +{ + struct ip6_hdr hdr; + struct mbuf *m; + + if (ln->la_hold == NULL) + return (NULL); + + /* + * assume every packet in la_hold has the same IP header + */ + m = ln->la_hold; + if (sizeof(hdr) < m->m_len) + return (NULL); + + m_copydata(m, 0, sizeof(hdr), (caddr_t)&hdr); + *src = hdr.ip6_src; + + return (src); +} + void nd6_llinfo_settimer(struct llentry *ln, long tick) { @@ -523,9 +551,10 @@ static void nd6_llinfo_timer(void *arg) { struct llentry *ln; - struct in6_addr *dst; + struct in6_addr *dst, *pdst, *psrc, src; struct ifnet *ifp; struct nd_ifinfo *ndi = NULL; + int send_ns; KASSERT(arg != NULL, ("%s: arg NULL", __func__)); ln = (struct llentry *)arg; @@ -552,6 +581,10 @@ nd6_llinfo_timer(void *arg) } ifp = ln->lle_tbl->llt_ifp; CURVNET_SET(ifp->if_vnet); + ndi = ND_IFINFO(ifp); + send_ns = 0; + dst = &ln->r_l3addr.addr6; + pdst = dst; if (ln->ln_ntick > 0) { if (ln->ln_ntick > INT_MAX) { @@ -564,8 +597,6 @@ nd6_llinfo_timer(void *arg) goto done; } - ndi = ND_IFINFO(ifp); - dst = &ln->r_l3addr.addr6; if (ln->la_flags & LLE_STATIC) { goto done; } @@ -580,10 +611,9 @@ nd6_llinfo_timer(void *arg) case ND6_LLINFO_INCOMPLETE: if (ln->la_asked < V_nd6_mmaxtries) { ln->la_asked++; - nd6_llinfo_settimer_locked(ln, (long)ndi->retrans * hz / 1000); - LLE_WUNLOCK(ln); - nd6_ns_output(ifp, NULL, dst, ln, NULL); - LLE_WLOCK(ln); + send_ns = 1; + /* Send NS to multicast address */ + pdst = NULL; } else { struct mbuf *m = ln->la_hold; if (m) { @@ -627,10 +657,7 @@ nd6_llinfo_timer(void *arg) /* We need NUD */ ln->la_asked = 1; ln->ln_state = ND6_LLINFO_PROBE; - nd6_llinfo_settimer_locked(ln, (long)ndi->retrans * hz / 1000); - LLE_WUNLOCK(ln); - nd6_ns_output(ifp, dst, dst, ln, NULL); - LLE_WLOCK(ln); + send_ns = 1; } else { ln->ln_state = ND6_LLINFO_STALE; /* XXX */ nd6_llinfo_settimer_locked(ln, (long)V_nd6_gctimer * hz); @@ -639,10 +666,7 @@ nd6_llinfo_timer(void *arg) case ND6_LLINFO_PROBE: if (ln->la_asked < V_nd6_umaxtries) { ln->la_asked++; - nd6_llinfo_settimer_locked(ln, (long)ndi->retrans * hz / 1000); - LLE_WUNLOCK(ln); - nd6_ns_output(ifp, dst, dst, ln, NULL); - LLE_WLOCK(ln); + send_ns = 1; } else { EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_EXPIRED); (void)nd6_free(ln, 0); @@ -654,6 +678,14 @@ nd6_llinfo_timer(void *arg) __func__, ln->ln_state); } done: + if (send_ns != 0) { + nd6_llinfo_settimer_locked(ln, (long)ndi->retrans * hz / 1000); + psrc = nd6_llinfo_get_holdsrc(ln, &src); + LLE_FREE_LOCKED(ln); + ln = NULL; + nd6_ns_output(ifp, psrc, pdst, dst, NULL); + } + if (ln != NULL) LLE_FREE_LOCKED(ln); CURVNET_RESTORE(); @@ -2170,12 +2202,14 @@ nd6_output_lle(struct ifnet *ifp, struct * INCOMPLETE state, send the first solicitation. */ if (!ND6_LLINFO_PERMANENT(lle) && lle->la_asked == 0) { + struct in6_addr src, *psrc; lle->la_asked++; nd6_llinfo_settimer_locked(lle, (long)ND_IFINFO(ifp)->retrans * hz / 1000); + psrc = nd6_llinfo_get_holdsrc(lle, &src); LLE_WUNLOCK(lle); - nd6_ns_output(ifp, NULL, &dst->sin6_addr, lle, NULL); + nd6_ns_output(ifp, psrc, NULL, &dst->sin6_addr, NULL); } else { /* We did the lookup so we need to do the unlock here. */ LLE_WUNLOCK(lle); Modified: head/sys/netinet6/nd6.h ============================================================================== --- head/sys/netinet6/nd6.h Sat Sep 5 12:28:18 2015 (r287483) +++ head/sys/netinet6/nd6.h Sat Sep 5 14:14:03 2015 (r287484) @@ -437,7 +437,7 @@ void nd6_na_output(struct ifnet *, const const struct in6_addr *, u_long, int, struct sockaddr *); void nd6_ns_input(struct mbuf *, int, int); void nd6_ns_output(struct ifnet *, const struct in6_addr *, - const struct in6_addr *, struct llentry *, uint8_t *); + const struct in6_addr *, const struct in6_addr *, uint8_t *); caddr_t nd6_ifptomac(struct ifnet *); void nd6_dad_init(void); void nd6_dad_start(struct ifaddr *, int); Modified: head/sys/netinet6/nd6_nbr.c ============================================================================== --- head/sys/netinet6/nd6_nbr.c Sat Sep 5 12:28:18 2015 (r287483) +++ head/sys/netinet6/nd6_nbr.c Sat Sep 5 14:14:03 2015 (r287484) @@ -95,7 +95,7 @@ static void nd6_dad_na_input(struct ifad static void nd6_na_output_fib(struct ifnet *, const struct in6_addr *, const struct in6_addr *, u_long, int, struct sockaddr *, u_int); static void nd6_ns_output_fib(struct ifnet *, const struct in6_addr *, - const struct in6_addr *, struct llentry *, uint8_t *, u_int); + const struct in6_addr *, const struct in6_addr *, uint8_t *, u_int); static VNET_DEFINE(int, dad_enhanced) = 1; #define V_dad_enhanced VNET(dad_enhanced) @@ -396,9 +396,9 @@ nd6_ns_input(struct mbuf *m, int off, in * the value (length is ND_OPT_NONCE_LEN) is used as a random nonce. */ static void -nd6_ns_output_fib(struct ifnet *ifp, const struct in6_addr *daddr6, - const struct in6_addr *taddr6, struct llentry *ln, uint8_t *nonce, - u_int fibnum) +nd6_ns_output_fib(struct ifnet *ifp, const struct in6_addr *saddr6, + const struct in6_addr *daddr6, const struct in6_addr *taddr6, + uint8_t *nonce, u_int fibnum) { struct mbuf *m; struct m_tag *mtag; @@ -462,7 +462,7 @@ nd6_ns_output_fib(struct ifnet *ifp, con goto bad; } if (nonce == NULL) { - struct ifaddr *ifa; + struct ifaddr *ifa = NULL; /* * RFC2461 7.2.2: @@ -474,35 +474,15 @@ nd6_ns_output_fib(struct ifnet *ifp, con * interface should be used." * * We use the source address for the prompting packet - * (saddr6), if: - * - saddr6 is given from the caller (by giving "ln"), and - * - saddr6 belongs to the outgoing interface. + * (saddr6), if saddr6 belongs to the outgoing interface. * Otherwise, we perform the source address selection as usual. */ - struct in6_addr *hsrc; - hsrc = NULL; - if (ln != NULL) { - LLE_RLOCK(ln); - if (ln->la_hold != NULL) { - struct ip6_hdr *hip6; /* hold ip6 */ - - /* - * assuming every packet in la_hold has the same IP - * header - */ - hip6 = mtod(ln->la_hold, struct ip6_hdr *); - /* XXX pullup? */ - if (sizeof(*hip6) < ln->la_hold->m_len) { - ip6->ip6_src = hip6->ip6_src; - hsrc = &hip6->ip6_src; - } - } - LLE_RUNLOCK(ln); - } - if (hsrc && (ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, - hsrc)) != NULL) { + if (saddr6 != NULL) + ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, saddr6); + if (ifa != NULL) { /* ip6_src set already. */ + ip6->ip6_src = *saddr6; ifa_free(ifa); } else { int error; @@ -626,11 +606,11 @@ nd6_ns_output_fib(struct ifnet *ifp, con #ifndef BURN_BRIDGES void -nd6_ns_output(struct ifnet *ifp, const struct in6_addr *daddr6, - const struct in6_addr *taddr6, struct llentry *ln, uint8_t *nonce) +nd6_ns_output(struct ifnet *ifp, const struct in6_addr *saddr6, + const struct in6_addr *daddr6, const struct in6_addr *taddr6,uint8_t *nonce) { - nd6_ns_output_fib(ifp, daddr6, taddr6, ln, nonce, RT_DEFAULT_FIB); + nd6_ns_output_fib(ifp, saddr6, daddr6, taddr6, nonce, RT_DEFAULT_FIB); } #endif /* @@ -1581,7 +1561,7 @@ nd6_dad_ns_output(struct dadq *dp, struc * should work well in almost all cases. */ } - nd6_ns_output(ifp, NULL, &ia->ia_addr.sin6_addr, NULL, + nd6_ns_output(ifp, NULL, NULL, &ia->ia_addr.sin6_addr, (uint8_t *)&dp->dad_nonce[0]); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201509051414.t85EE3Qu084919>