From owner-svn-src-user@FreeBSD.ORG Tue Dec 9 04:54:17 2008 Return-Path: Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id D1921106564A; Tue, 9 Dec 2008 04:54:17 +0000 (UTC) (envelope-from kmacy@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id BF51F8FC13; Tue, 9 Dec 2008 04:54:17 +0000 (UTC) (envelope-from kmacy@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id mB94sHur080438; Tue, 9 Dec 2008 04:54:17 GMT (envelope-from kmacy@svn.freebsd.org) Received: (from kmacy@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id mB94sHgZ080428; Tue, 9 Dec 2008 04:54:17 GMT (envelope-from kmacy@svn.freebsd.org) Message-Id: <200812090454.mB94sHgZ080428@svn.freebsd.org> From: Kip Macy Date: Tue, 9 Dec 2008 04:54:17 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r185785 - in user/kmacy/head_arpv2/sys: net netinet netinet6 X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 09 Dec 2008 04:54:18 -0000 Author: kmacy Date: Tue Dec 9 04:54:17 2008 New Revision: 185785 URL: http://svn.freebsd.org/changeset/base/185785 Log: - remove a number of cases of IF_AFDATA_LOCK recursion - implement LLE_EXCLUSIVE - implement LLE_FREE Modified: user/kmacy/head_arpv2/sys/net/if_llatbl.c user/kmacy/head_arpv2/sys/net/if_llatbl.h user/kmacy/head_arpv2/sys/net/if_var.h user/kmacy/head_arpv2/sys/netinet/if_ether.c user/kmacy/head_arpv2/sys/netinet/in.c user/kmacy/head_arpv2/sys/netinet/ip_output.c user/kmacy/head_arpv2/sys/netinet6/icmp6.c user/kmacy/head_arpv2/sys/netinet6/in6.c user/kmacy/head_arpv2/sys/netinet6/nd6.c user/kmacy/head_arpv2/sys/netinet6/nd6_nbr.c Modified: user/kmacy/head_arpv2/sys/net/if_llatbl.c ============================================================================== --- user/kmacy/head_arpv2/sys/net/if_llatbl.c Tue Dec 9 04:30:47 2008 (r185784) +++ user/kmacy/head_arpv2/sys/net/if_llatbl.c Tue Dec 9 04:54:17 2008 (r185785) @@ -213,10 +213,10 @@ lla_rt_output(struct rt_msghdr *rtm, str log(LOG_INFO, "%s: RTM_ADD publish " "(proxy only) is invalid\n", __func__); - rtfree(rt); + RTFREE(rt); return EINVAL; } - rtfree(rt); + RTFREE(rt); flags |= LLE_PROXY; } Modified: user/kmacy/head_arpv2/sys/net/if_llatbl.h ============================================================================== --- user/kmacy/head_arpv2/sys/net/if_llatbl.h Tue Dec 9 04:30:47 2008 (r185784) +++ user/kmacy/head_arpv2/sys/net/if_llatbl.h Tue Dec 9 04:54:17 2008 (r185785) @@ -77,6 +77,7 @@ struct llentry { #define LLE_WUNLOCK(lle) rw_wunlock(&(lle)->lle_lock) #define LLE_RUNLOCK(lle) rw_runlock(&(lle)->lle_lock) #define LLE_DOWNGRADE(lle) rw_downgrade(&(lle)->lle_lock) +#define LLE_TRY_UPGRADE(lle) rw_try_upgrade(&(lle)->lle_lock) #define LLE_LOCK_INIT(lle) rw_init_flags(&(lle)->lle_lock, "lle", RW_DUPOK) #define LLE_WLOCK_ASSERT(lle) rw_assert(&(lle)->lle_lock, RA_WLOCKED) @@ -105,6 +106,18 @@ struct llentry { lle = 0; \ } while (0) +#define LLE_FREE(lle) do { \ + LLE_WLOCK(lle); \ + if ((lle)->lle_refcnt <= 1) \ + (lle)->lle_tbl->llt_free((lle)->lle_tbl, (lle));\ + else { \ + (lle)->lle_refcnt--; \ + LLE_WUNLOCK(lle); \ + } \ + /* guard against invalid refs */ \ + lle = 0; \ +} while (0) + #define ln_timer_ch lle_timer.ln_timer_ch #define la_timer lle_timer.la_timer Modified: user/kmacy/head_arpv2/sys/net/if_var.h ============================================================================== --- user/kmacy/head_arpv2/sys/net/if_var.h Tue Dec 9 04:30:47 2008 (r185784) +++ user/kmacy/head_arpv2/sys/net/if_var.h Tue Dec 9 04:54:17 2008 (r185785) @@ -359,13 +359,15 @@ typedef void (*group_change_event_handle EVENTHANDLER_DECLARE(group_change_event, group_change_event_handler_t); #define IF_AFDATA_LOCK_INIT(ifp) \ - mtx_init(&(ifp)->if_afdata_mtx, "if_afdata", NULL, \ - (MTX_DEF | MTX_RECURSE)) + mtx_init(&(ifp)->if_afdata_mtx, "if_afdata", NULL, MTX_DEF) #define IF_AFDATA_LOCK(ifp) mtx_lock(&(ifp)->if_afdata_mtx) #define IF_AFDATA_TRYLOCK(ifp) mtx_trylock(&(ifp)->if_afdata_mtx) #define IF_AFDATA_UNLOCK(ifp) mtx_unlock(&(ifp)->if_afdata_mtx) #define IF_AFDATA_DESTROY(ifp) mtx_destroy(&(ifp)->if_afdata_mtx) +#define IF_AFDATA_LOCK_ASSERT(ifp) mtx_assert(&(ifp)->if_afdata_mtx, MA_OWNED) +#define IF_AFDATA_UNLOCK_ASSERT(ifp) mtx_assert(&(ifp)->if_afdata_mtx, MA_NOTOWNED) + #define IFF_LOCKGIANT(ifp) do { \ if ((ifp)->if_flags & IFF_NEEDSGIANT) \ mtx_lock(&Giant); \ Modified: user/kmacy/head_arpv2/sys/netinet/if_ether.c ============================================================================== --- user/kmacy/head_arpv2/sys/netinet/if_ether.c Tue Dec 9 04:30:47 2008 (r185784) +++ user/kmacy/head_arpv2/sys/netinet/if_ether.c Tue Dec 9 04:54:17 2008 (r185785) @@ -156,15 +156,22 @@ arptimer(void *arg) return; } ifp = lle->lle_tbl->llt_ifp; - IF_AFDATA_LOCK(ifp); if ((lle->la_flags & LLE_DELETED) || (time_second >= lle->la_expire)) { + printf("deleting entry\n"); + + IF_AFDATA_LOCK(ifp); if (!callout_pending(&lle->la_timer) && (callout_active(&lle->la_timer))) { (void)llentry_free(lle); } + IF_AFDATA_UNLOCK(ifp); + } else { + /* + * Still valid, just drop our reference + */ + LLE_FREE(lle); } - IF_AFDATA_UNLOCK(ifp); } @@ -251,6 +258,7 @@ arpresolve(struct ifnet *ifp, struct rte u_int flags; int error; + log(LOG_DEBUG, "arpesolve called\n"); *lle = NULL; if (m != NULL) { if (m->m_flags & M_BCAST) { @@ -280,11 +288,12 @@ arpresolve(struct ifnet *ifp, struct rte "arpresolve: can't allocate llinfo for %s\n", inet_ntoa(SIN(dst)->sin_addr)); m_freem(m); + log(LOG_DEBUG, "arpesolve: lla_lookup fail\n"); return (EINVAL); } - if (la->la_flags & LLE_VALID && - (la->la_flags & LLE_STATIC || la->la_expire > time_uptime)) { + if ((la->la_flags & LLE_VALID) && + ((la->la_flags & LLE_STATIC) || (la->la_expire > time_uptime))) { bcopy(&la->ll_addr, desten, ifp->if_addrlen); /* * If entry has an expiry time and it is approaching, @@ -297,12 +306,18 @@ arpresolve(struct ifnet *ifp, struct rte &SIN(dst)->sin_addr, IF_LLADDR(ifp)); la->la_preempt--; - } + } + log(LOG_DEBUG, "arpresolve: success\n"); + *lle = la; error = 0; goto done; - } - + } else + log(LOG_DEBUG, + "la=%p valid=%d static=%d expire=%ld uptime=%ld\n", la, + !!(la->la_flags & LLE_VALID), !!(la->la_flags & LLE_STATIC), + la->la_expire, time_uptime); + if (la->la_flags & LLE_STATIC) { /* should not happen! */ log(LOG_DEBUG, "arpresolve: ouch, empty static llinfo for %s\n", inet_ntoa(SIN(dst)->sin_addr)); @@ -319,7 +334,8 @@ arpresolve(struct ifnet *ifp, struct rte if (la->la_hold) m_freem(la->la_hold); la->la_hold = m; - LLE_DOWNGRADE(la); + if (!(la->la_asked == 0 || la->la_expire != time_uptime)) + LLE_DOWNGRADE(la); } /* * Return EWOULDBLOCK if we have tried less than arp_maxtries. It @@ -334,12 +350,17 @@ arpresolve(struct ifnet *ifp, struct rte (rt0->rt_flags & RTF_GATEWAY) ? EHOSTDOWN : EHOSTUNREACH; if (la->la_asked == 0 || la->la_expire != time_uptime) { + log(LOG_DEBUG, + "arpresolve: kicking off new resolve expire=%ld\n", + la->la_expire); + LLE_ADDREF(la); la->la_expire = time_uptime; callout_reset(&la->la_timer, hz, arptimer, la); la->la_asked++; - + LLE_WUNLOCK(la); arprequest(ifp, NULL, &SIN(dst)->sin_addr, IF_LLADDR(ifp)); + return (error); } done: @@ -435,6 +456,7 @@ in_arpinput(struct mbuf *m) struct in_addr isaddr, itaddr, myaddr; u_int8_t *enaddr = NULL; int op, flags; + struct mbuf *m0; /* , rif_len; */ @@ -529,6 +551,7 @@ in_arpinput(struct mbuf *m) if (!bridged || (ia = TAILQ_FIRST(&V_in_ifaddrhead)) == NULL) goto drop; match: + log(LOG_DEBUG,"in_arpinput: match\n"); if (!enaddr) enaddr = (u_int8_t *)IF_LLADDR(ifp); myaddr = ia->ia_addr.sin_addr; @@ -567,12 +590,13 @@ match: la = lla_lookup(LLTABLE(ifp), flags, (struct sockaddr *)&sin); IF_AFDATA_UNLOCK(ifp); if (la != NULL) { + log(LOG_DEBUG, "in_arpinput: la found\n"); /* the following is not an error when doing bridging */ if (!bridged && la->lle_tbl->llt_ifp != ifp #ifdef DEV_CARP && (ifp->if_type != IFT_CARP || !carp_match) #endif - ) { + ) { if (log_arp_wrong_iface) log(LOG_ERR, "arp: %s is on %s " "but got reply from %*D on %s\n", @@ -582,9 +606,9 @@ match: ifp->if_xname); goto reply; } - - if (la->la_flags & LLE_VALID && + if ((la->la_flags & LLE_VALID) && bcmp(ar_sha(ah), &la->ll_addr, ifp->if_addrlen)) { + log(LOG_DEBUG, "LLE_VALID and match\n"); if (la->la_flags & LLE_STATIC) { log(LOG_ERR, "arp: %*D attempts to modify permanent " @@ -603,6 +627,7 @@ match: ifp->if_xname); } } + if (ifp->if_addrlen != ah->ar_hln) { log(LOG_WARNING, "arp from %*D: addr len: new %d, i/f %d (ignored)", @@ -613,6 +638,7 @@ match: (void)memcpy(&la->ll_addr, ar_sha(ah), ifp->if_addrlen); la->la_flags |= LLE_VALID; + log(LOG_DEBUG, "in_arpinput: la=%p valid set\n", la); if (!(la->la_flags & LLE_STATIC)) { la->la_expire = time_uptime + arpt_keep; callout_reset(&la->la_timer, hz * V_arpt_keep, @@ -621,8 +647,13 @@ match: la->la_asked = 0; la->la_preempt = V_arp_maxtries; if (la->la_hold) { - (*ifp->if_output)(ifp, la->la_hold, L3_ADDR(la), NULL); + m0 = la->la_hold; la->la_hold = 0; + memcpy(&sa, L3_ADDR(la), sizeof(sa)); + LLE_WUNLOCK(la); + + (*ifp->if_output)(ifp, m0, &sa, NULL); + return; } } reply: @@ -639,7 +670,6 @@ reply: goto drop; sin.sin_addr = itaddr; - /* XXX MRT use table 0 for arp reply */ rt = in_rtalloc1((struct sockaddr *)&sin, 0, 0UL, 0); if (!rt) @@ -650,12 +680,12 @@ reply: * over who claims what Ether address. */ if (rt->rt_ifp == ifp) { - rtfree(rt); + RTFREE(rt); goto drop; } (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln); (void)memcpy(ar_sha(ah), enaddr, ah->ar_hln); - rtfree(rt); + RTFREE(rt); /* * Also check that the node which sent the ARP packet @@ -674,10 +704,10 @@ reply: " from %s via %s, expecting %s\n", inet_ntoa(isaddr), ifp->if_xname, rt->rt_ifp->if_xname); - rtfree(rt); + RTFREE(rt); goto drop; } - rtfree(rt); + RTFREE(rt); #ifdef DEBUG_PROXY printf("arp: proxying for %s\n", Modified: user/kmacy/head_arpv2/sys/netinet/in.c ============================================================================== --- user/kmacy/head_arpv2/sys/netinet/in.c Tue Dec 9 04:30:47 2008 (r185784) +++ user/kmacy/head_arpv2/sys/netinet/in.c Tue Dec 9 04:54:17 2008 (r185785) @@ -1077,10 +1077,10 @@ in_lltable_rtcheck(struct ifnet *ifp, co log(LOG_INFO, "IPv4 address: \"%s\" is not on the network\n", inet_ntoa(((const struct sockaddr_in *)l3addr)->sin_addr)); if (rt != NULL) - rtfree(rt); - return EINVAL; + RTFREE_LOCKED(rt); + return (EINVAL); } - rtfree(rt); + RTFREE_LOCKED(rt); return 0; } @@ -1110,17 +1110,14 @@ in_lltable_lookup(struct lltable *llt, u break; } - if (lle != NULL ) { - if (flags & LLE_DELETE) { - LLE_WLOCK(lle); - lle->la_flags = LLE_DELETED; - LLE_WUNLOCK(lle); + if ((lle != NULL) && (flags & LLE_DELETE)) { + LLE_WLOCK(lle); + lle->la_flags = LLE_DELETED; + LLE_WUNLOCK(lle); #ifdef INVARIANTS - log(LOG_INFO, "ifaddr cache = %p is deleted\n", lle); + log(LOG_INFO, "ifaddr cache = %p is deleted\n", lle); #endif - lle = NULL; - } else - LLE_RLOCK(lle); + lle = NULL; } else { #ifdef INVARIANTS if (flags & LLE_DELETE) @@ -1150,9 +1147,14 @@ in_lltable_lookup(struct lltable *llt, u lle->lle_tbl = llt; lle->lle_head = lleh; - LLE_RLOCK(lle); LIST_INSERT_HEAD(lleh, lle, lle_next); } + if (lle) { + if (flags & LLE_EXCLUSIVE) + LLE_WLOCK(lle); + else + LLE_RLOCK(lle); + } done: return (lle); } Modified: user/kmacy/head_arpv2/sys/netinet/ip_output.c ============================================================================== --- user/kmacy/head_arpv2/sys/netinet/ip_output.c Tue Dec 9 04:30:47 2008 (r185784) +++ user/kmacy/head_arpv2/sys/netinet/ip_output.c Tue Dec 9 04:54:17 2008 (r185785) @@ -567,11 +567,8 @@ passout: * to avoid confusing lower layers. */ m->m_flags &= ~(M_PROTOFLAGS); - - IF_AFDATA_LOCK(ifp); error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst, ro->ro_rt); - IF_AFDATA_UNLOCK(ifp); goto done; } @@ -604,10 +601,8 @@ passout: */ m->m_flags &= ~(M_PROTOFLAGS); - IF_AFDATA_LOCK(ifp); error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst, ro->ro_rt); - IF_AFDATA_UNLOCK(ifp); } else m_freem(m); } Modified: user/kmacy/head_arpv2/sys/netinet6/icmp6.c ============================================================================== --- user/kmacy/head_arpv2/sys/netinet6/icmp6.c Tue Dec 9 04:30:47 2008 (r185784) +++ user/kmacy/head_arpv2/sys/netinet6/icmp6.c Tue Dec 9 04:54:17 2008 (r185785) @@ -2583,17 +2583,16 @@ icmp6_redirect_output(struct mbuf *m0, s IF_AFDATA_LOCK(ifp); ln = nd6_lookup(router_ll6, 0, ifp); - if (!ln) { - IF_AFDATA_UNLOCK(ifp); + IF_AFDATA_UNLOCK(ifp); + if (!ln) goto nolladdropt; - } + len = sizeof(*nd_opt) + ifp->if_addrlen; len = (len + 7) & ~7; /* round by 8 */ /* safety check */ - if (len + (p - (u_char *)ip6) > maxlen) { - IF_AFDATA_UNLOCK(ifp); + if (len + (p - (u_char *)ip6) > maxlen) goto nolladdropt; - } + if (ln->la_flags & LLE_VALID) { nd_opt = (struct nd_opt_hdr *)p; nd_opt->nd_opt_type = ND_OPT_TARGET_LINKADDR; @@ -2602,7 +2601,7 @@ icmp6_redirect_output(struct mbuf *m0, s bcopy(&ln->ll_addr, lladdr, ifp->if_addrlen); p += len; } - IF_AFDATA_UNLOCK(ifp); + LLE_RUNLOCK(ln); } nolladdropt:; Modified: user/kmacy/head_arpv2/sys/netinet6/in6.c ============================================================================== --- user/kmacy/head_arpv2/sys/netinet6/in6.c Tue Dec 9 04:30:47 2008 (r185784) +++ user/kmacy/head_arpv2/sys/netinet6/in6.c Tue Dec 9 04:54:17 2008 (r185785) @@ -2215,10 +2215,23 @@ in6_lltable_lookup(struct lltable *llt, lle->lle_head = lleh; LIST_INSERT_HEAD(lleh, lle, lle_next); } else { - if (flags & LLE_DELETE) + if (flags & LLE_DELETE) { + LLE_WLOCK(lle); lle->la_flags = LLE_DELETED; + LLE_WUNLOCK(lle); +#ifdef INVARIANTS + log(LOG_INFO, "ifaddr cache = %p is deleted\n", lle); +#endif + lle = NULL; + } + } + if (lle) { + if (flags & LLE_EXCLUSIVE) + LLE_WLOCK(lle); + else + LLE_RLOCK(lle); } - return lle; + return (lle); } static int Modified: user/kmacy/head_arpv2/sys/netinet6/nd6.c ============================================================================== --- user/kmacy/head_arpv2/sys/netinet6/nd6.c Tue Dec 9 04:30:47 2008 (r185784) +++ user/kmacy/head_arpv2/sys/netinet6/nd6.c Tue Dec 9 04:54:17 2008 (r185785) @@ -840,8 +840,12 @@ nd6_purge(struct ifnet *ifp) nd6_setdefaultiface(0); if (!V_ip6_forwarding && V_ip6_accept_rtadv) { /* XXX: too restrictive? */ - /* refresh default router list */ + /* refresh default router list + * + * + */ defrouter_select(); + } /* XXXXX @@ -851,21 +855,11 @@ nd6_purge(struct ifnet *ifp) * from if_detach() where everything gets purged. So let * in6_domifdetach() do the actual L2 table purging work. */ -#if 0 - /* - * Nuke neighbor cache entries for the ifp. - * Note that rt->rt_ifp may not be the same as ifp, - * due to KAME goto ours hack. See RTM_RESOLVE case in - * nd6_rtrequest(), and ip6_input(). - */ - IF_AFDATA_LOCK(ifp); - lltable_free(LLTABLE6(ifp)); - IF_AFDATA_UNLOCK(ifp); -#endif } /* Qing * the caller acquires and releases the lock on the lltbls + * Returns the llentry locked */ struct llentry * nd6_lookup(struct in6_addr *addr6, int flags, struct ifnet *ifp) @@ -880,6 +874,8 @@ nd6_lookup(struct in6_addr *addr6, int f sin6.sin6_family = AF_INET6; sin6.sin6_addr = *addr6; + IF_AFDATA_LOCK_ASSERT(ifp); + if (flags & ND6_CREATE) llflags |= LLE_CREATE; if (flags & ND6_EXCLUSIVE) @@ -890,6 +886,7 @@ nd6_lookup(struct in6_addr *addr6, int f ln->ln_state = ND6_LLINFO_NOSTATE; callout_init(&ln->ln_timer_ch, 0); } + return (ln); } @@ -978,7 +975,8 @@ nd6_is_addr_neighbor(struct sockaddr_in6 { struct llentry *lle; int rc = 0; - + + IF_AFDATA_UNLOCK_ASSERT(ifp); if (nd6_is_new_addr_neighbor(addr, ifp)) return (1); @@ -1401,6 +1399,8 @@ nd6_cache_lladdr(struct ifnet *ifp, stru int flags = 0; int newstate = 0; + IF_AFDATA_LOCK_ASSERT(ifp); + if (ifp == NULL) panic("ifp == NULL in nd6_cache_lladdr"); if (from == NULL) @@ -1598,16 +1598,27 @@ nd6_cache_lladdr(struct ifnet *ifp, stru * for those are not autoconfigured hosts, we explicitly avoid such * cases for safety. */ - if (do_update && ln->ln_router && !V_ip6_forwarding && V_ip6_accept_rtadv) + if (do_update && ln->ln_router && !V_ip6_forwarding && V_ip6_accept_rtadv) { +#ifdef notyet + /* + * XXX implement the boiler plate + */ + taskqueue_enqueue(ipv6_taskq, defrouter_select_task); +#endif + /* + * guaranteed recursion + */ defrouter_select(); + } + done: if (ln) { - if (ln->la_flags & LLE_STATIC) - ln = NULL; if (lladdr) LLE_WUNLOCK(ln); else LLE_RUNLOCK(ln); + if (ln->la_flags & LLE_STATIC) + ln = NULL; } return (ln); } @@ -1680,7 +1691,9 @@ nd6_output(struct ifnet *ifp, struct ifn * or an anycast address(i.e. not a multicast). */ flags = m ? LLE_EXCLUSIVE : 0; + IF_AFDATA_LOCK(rt->rt_ifp); ln = lla_lookup(LLTABLE6(ifp), 0, (struct sockaddr *)dst); + IF_AFDATA_UNLOCK(rt->rt_ifp); if ((ln == NULL) && nd6_is_addr_neighbor(dst, ifp)) { /* * Since nd6_is_addr_neighbor() internally calls nd6_lookup(), @@ -1688,7 +1701,9 @@ nd6_output(struct ifnet *ifp, struct ifn * it is tolerable, because this should be a rare case. */ flags = ND6_CREATE | (m ? ND6_EXCLUSIVE : 0); + IF_AFDATA_LOCK(rt->rt_ifp); ln = nd6_lookup(&dst->sin6_addr, flags, ifp); + IF_AFDATA_UNLOCK(rt->rt_ifp); } if (ln == NULL) { if ((ifp->if_flags & IFF_POINTOPOINT) == 0 && @@ -1700,7 +1715,6 @@ nd6_output(struct ifnet *ifp, struct ifn ip6_sprintf(ip6buf, &dst->sin6_addr), ln, rt); senderr(EIO); /* XXX: good error? */ } - goto sendpkt; /* send anyway */ } @@ -1786,6 +1800,12 @@ nd6_output(struct ifnet *ifp, struct ifn error = ENETDOWN; /* better error? */ goto bad; } + if (ln) { + if (m0) + LLE_WUNLOCK(ln); + else + LLE_RUNLOCK(ln); + } #ifdef MAC mac_netinet6_nd6_send(ifp, m); Modified: user/kmacy/head_arpv2/sys/netinet6/nd6_nbr.c ============================================================================== --- user/kmacy/head_arpv2/sys/netinet6/nd6_nbr.c Tue Dec 9 04:30:47 2008 (r185784) +++ user/kmacy/head_arpv2/sys/netinet6/nd6_nbr.c Tue Dec 9 04:54:17 2008 (r185785) @@ -115,7 +115,7 @@ nd6_ns_input(struct mbuf *m, int off, in struct ifaddr *ifa = NULL; int lladdrlen = 0; int anycast = 0, proxy = 0, tentative = 0; - int tlladdr; + int tlladdr, error; union nd_opts ndopts; struct sockaddr_dl *proxydl = NULL; char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN]; @@ -169,7 +169,8 @@ nd6_ns_input(struct mbuf *m, int off, in src_sa6.sin6_family = AF_INET6; src_sa6.sin6_len = sizeof(src_sa6); src_sa6.sin6_addr = saddr6; - if (!nd6_is_addr_neighbor(&src_sa6, ifp)) { + error = nd6_is_addr_neighbor(&src_sa6, ifp); + if (error) { nd6log((LOG_INFO, "nd6_ns_input: " "NS packet from non-neighbor\n")); goto bad; @@ -701,8 +702,8 @@ nd6_na_input(struct mbuf *m, int off, in */ IF_AFDATA_LOCK(ifp); ln = nd6_lookup(&taddr6, 0, ifp); + IF_AFDATA_UNLOCK(ifp); if (ln == NULL) { - IF_AFDATA_UNLOCK(ifp); goto freeit; } @@ -712,7 +713,6 @@ nd6_na_input(struct mbuf *m, int off, in * discard the packet. */ if (ifp->if_addrlen && lladdr == NULL) { - IF_AFDATA_UNLOCK(ifp); goto freeit; } @@ -786,7 +786,6 @@ nd6_na_input(struct mbuf *m, int off, in ln->ln_state = ND6_LLINFO_STALE; nd6_llinfo_settimer(ln, (long)V_nd6_gctimer * hz); } - IF_AFDATA_UNLOCK(ifp); goto freeit; } else if (is_override /* (2a) */ || (!is_override && (lladdr != NULL && !llchange)) /* (2b) */ @@ -883,8 +882,6 @@ nd6_na_input(struct mbuf *m, int off, in nd6_output(ifp, ifp, m_hold, L3_ADDR_SIN6(ln), NULL); } } - IF_AFDATA_UNLOCK(ifp); - freeit: m_freem(m); return;