From owner-svn-src-all@freebsd.org Sat Sep 5 14:14:05 2015 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 01F819CAE35; Sat, 5 Sep 2015 14:14:05 +0000 (UTC) (envelope-from melifaro@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id E5EBA842; Sat, 5 Sep 2015 14:14:04 +0000 (UTC) (envelope-from melifaro@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.70]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id t85EE4vB084923; Sat, 5 Sep 2015 14:14:04 GMT (envelope-from melifaro@FreeBSD.org) Received: (from melifaro@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id t85EE3Qu084919; Sat, 5 Sep 2015 14:14:03 GMT (envelope-from melifaro@FreeBSD.org) Message-Id: <201509051414.t85EE3Qu084919@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: melifaro set sender to melifaro@FreeBSD.org using -f From: "Alexander V. Chernikov" Date: Sat, 5 Sep 2015 14:14:03 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r287484 - in head/sys: netinet netinet6 X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 05 Sep 2015 14:14:05 -0000 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]); }