From owner-svn-src-projects@FreeBSD.ORG Sun Nov 23 15:38:09 2014 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id E5779855; Sun, 23 Nov 2014 15:38:09 +0000 (UTC) Received: from svn.freebsd.org (svn.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 D10D320C; Sun, 23 Nov 2014 15:38:09 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id sANFc9sE026706; Sun, 23 Nov 2014 15:38:09 GMT (envelope-from melifaro@FreeBSD.org) Received: (from melifaro@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id sANFc7HN026690; Sun, 23 Nov 2014 15:38:07 GMT (envelope-from melifaro@FreeBSD.org) Message-Id: <201411231538.sANFc7HN026690@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: melifaro set sender to melifaro@FreeBSD.org using -f From: "Alexander V. Chernikov" Date: Sun, 23 Nov 2014 15:38:07 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r274917 - in projects/routing/sys: net netinet netinet6 X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 23 Nov 2014 15:38:10 -0000 Author: melifaro Date: Sun Nov 23 15:38:06 2014 New Revision: 274917 URL: https://svnweb.freebsd.org/changeset/base/274917 Log: Do more fine-grained lltable locking: use table runtime lock as rare as we can. Modified: projects/routing/sys/net/if.c projects/routing/sys/net/if_llatbl.c projects/routing/sys/net/if_var.h projects/routing/sys/net/rt_nhops.c projects/routing/sys/netinet/if_ether.c projects/routing/sys/netinet/in.c projects/routing/sys/netinet/toecore.c projects/routing/sys/netinet6/in6.c projects/routing/sys/netinet6/nd6.c projects/routing/sys/netinet6/scope6.c Modified: projects/routing/sys/net/if.c ============================================================================== --- projects/routing/sys/net/if.c Sun Nov 23 12:15:28 2014 (r274916) +++ projects/routing/sys/net/if.c Sun Nov 23 15:38:06 2014 (r274917) @@ -774,16 +774,16 @@ if_attachdomain1(struct ifnet *ifp) * Since dp->dom_ifattach calls malloc() with M_WAITOK, we * cannot lock ifp->if_afdata initialization, entirely. */ - if (IF_AFDATA_TRY_WLOCK(ifp) == 0) + if (IF_AFDATA_CFG_TRY_WLOCK(ifp) == 0) return; if (ifp->if_afdata_initialized >= domain_init_status) { - IF_AFDATA_UNLOCK(ifp); + IF_AFDATA_CFG_WUNLOCK(ifp); log(LOG_WARNING, "%s called more than once on %s\n", __func__, ifp->if_xname); return; } ifp->if_afdata_initialized = domain_init_status; - IF_AFDATA_UNLOCK(ifp); + IF_AFDATA_CFG_WUNLOCK(ifp); /* address family dependent data region */ bzero(ifp->if_afdata, sizeof(ifp->if_afdata)); @@ -961,10 +961,10 @@ if_detach_internal(struct ifnet *ifp, in * sleep, for example trying to drain a callout, thus open up the * theoretical race with re-attaching. */ - IF_AFDATA_LOCK(ifp); + IF_AFDATA_CFG_WLOCK(ifp); i = ifp->if_afdata_initialized; ifp->if_afdata_initialized = 0; - IF_AFDATA_UNLOCK(ifp); + IF_AFDATA_CFG_WUNLOCK(ifp); for (dp = domains; i > 0 && dp; dp = dp->dom_next) { if (dp->dom_ifdetach && ifp->if_afdata[dp->dom_family]) (*dp->dom_ifdetach)(ifp, @@ -3967,36 +3967,10 @@ if_afdata_cfg_wunlock(struct ifnet *ifp) rw_wunlock(&ifp->if_afdata_cfg_lock); } -void -if_afdata_cfg_lock_assert(struct ifnet *ifp, int what) -{ - - rw_assert(&ifp->if_afdata_cfg_lock, what); -} - -void -if_afdata_wlock(struct ifnet *ifp) -{ - - if_afdata_cfg_wlock(ifp); - IF_AFDATA_RUN_WLOCK(ifp); -} - -void -if_afdata_wunlock(struct ifnet *ifp) -{ - - if_afdata_cfg_wunlock(ifp); - IF_AFDATA_RUN_WUNLOCK(ifp); -} - int -if_afdata_try_wlock(struct ifnet *ifp) +if_afdata_cfg_try_wlock(struct ifnet *ifp) { - if (rw_try_wlock(&ifp->if_afdata_cfg_lock) == 0) - return (0); - IF_AFDATA_RUN_WLOCK(ifp); - return (1); + return (rw_try_wlock(&ifp->if_afdata_cfg_lock)); } Modified: projects/routing/sys/net/if_llatbl.c ============================================================================== --- projects/routing/sys/net/if_llatbl.c Sun Nov 23 12:15:28 2014 (r274916) +++ projects/routing/sys/net/if_llatbl.c Sun Nov 23 15:38:06 2014 (r274917) @@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #ifdef DDB #include @@ -99,6 +100,11 @@ llentry_link(struct lltable *llt, struct struct llentries *lleh; uint32_t hashkey; + if ((lle->la_flags & LLE_LINKED) != 0) + return; + + IF_AFDATA_RUN_WLOCK_ASSERT(llt->llt_ifp); + hashkey = llt->llt_hash(lle); lleh = &llt->lle_head[LLATBL_HASH(hashkey, LLTBL_HASHMASK)]; @@ -112,10 +118,13 @@ void llentry_unlink(struct llentry *lle) { - LIST_REMOVE(lle, lle_next); - lle->la_flags &= ~(LLE_VALID | LLE_LINKED); - lle->lle_tbl = NULL; - lle->lle_head = NULL; + if ((lle->la_flags & LLE_LINKED) != 0) { + IF_AFDATA_RUN_WLOCK_ASSERT(lle->lle_tbl->llt_ifp); + LIST_REMOVE(lle, lle_next); + lle->la_flags &= ~(LLE_VALID | LLE_LINKED); + lle->lle_tbl = NULL; + lle->lle_head = NULL; + } } void @@ -143,12 +152,7 @@ llentry_free(struct llentry *lle) struct mbuf *next; LLE_WLOCK_ASSERT(lle); - - if ((lle->la_flags & LLE_LINKED) != 0) { - IF_AFDATA_WLOCK_ASSERT(lle->lle_tbl->llt_ifp); - LIST_REMOVE(lle, lle_next); - lle->la_flags &= ~(LLE_VALID | LLE_LINKED); - } + KASSERT((lle->la_flags & LLE_LINKED) == 0, ("Freeing linked lle")); pkts_dropped = 0; while ((lle->la_numheld > 0) && (lle->la_hold != NULL)) { @@ -172,6 +176,8 @@ llentry_free(struct llentry *lle) * (al)locate an llentry for address dst (equivalent to rtalloc for new-arp). * * If found the llentry * is returned referenced and unlocked. + * + * XXX: Remove after converting flowtable */ struct llentry * llentry_alloc(struct ifnet *ifp, struct lltable *lt, @@ -184,9 +190,14 @@ llentry_alloc(struct ifnet *ifp, struct IF_AFDATA_RUNLOCK(ifp); if ((la == NULL) && (ifp->if_flags & (IFF_NOARP | IFF_STATICARP)) == 0) { - IF_AFDATA_WLOCK(ifp); + IF_AFDATA_CFG_WLOCK(ifp); la = lla_create(lt, 0, (struct sockaddr *)dst); - IF_AFDATA_WUNLOCK(ifp); + if (la != NULL) { + IF_AFDATA_RUN_WLOCK(ifp); + llentry_link(lt, la); + IF_AFDATA_RUN_WUNLOCK(ifp); + } + IF_AFDATA_CFG_WUNLOCK(ifp); } if (la != NULL) { @@ -204,6 +215,7 @@ void lltable_free(struct lltable *llt) { struct llentry *lle, *next; + struct llentries dchain; int i; KASSERT(llt != NULL, ("%s: llt is NULL", __func__)); @@ -212,7 +224,8 @@ lltable_free(struct lltable *llt) SLIST_REMOVE(&V_lltables, llt, lltable, llt_link); LLTABLE_WUNLOCK(); - IF_AFDATA_WLOCK(llt->llt_ifp); + LIST_INIT(&dchain); + IF_AFDATA_CFG_WLOCK(llt->llt_ifp); for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) { LIST_FOREACH_SAFE(lle, &llt->lle_head[i], lle_next, next) { LLE_WLOCK(lle); @@ -220,10 +233,15 @@ lltable_free(struct lltable *llt) LLE_REMREF(lle); lle->la_flags &= ~LLE_CALLOUTREF; } - llentry_free(lle); + LIST_INSERT_HEAD(&dchain, lle, lle_chain); } } - IF_AFDATA_WUNLOCK(llt->llt_ifp); + IF_AFDATA_RUN_WLOCK(llt->llt_ifp); + llentries_unlink(&dchain); + IF_AFDATA_RUN_WUNLOCK(llt->llt_ifp); + LIST_FOREACH_SAFE(lle, &dchain, lle_chain, next) + llentry_free(lle); + IF_AFDATA_CFG_WUNLOCK(llt->llt_ifp); free(llt, M_LLTABLE); } @@ -337,14 +355,15 @@ lla_rt_output(struct rt_msghdr *rtm, str switch (rtm->rtm_type) { case RTM_ADD: /* Add static LLE */ - IF_AFDATA_WLOCK(ifp); + IF_AFDATA_CFG_WLOCK(ifp); lle = lla_create(llt, 0, dst); if (lle == NULL) { - IF_AFDATA_WUNLOCK(ifp); + IF_AFDATA_CFG_WUNLOCK(ifp); return (ENOMEM); } + IF_AFDATA_RUN_WLOCK(ifp); bcopy(LLADDR(dl), &lle->ll_addr, ifp->if_addrlen); if ((rtm->rtm_flags & RTF_ANNOUNCE)) lle->la_flags |= LLE_PUB; @@ -366,9 +385,11 @@ lla_rt_output(struct rt_msghdr *rtm, str lle->la_expire = 0; } else lle->la_expire = rtm->rtm_rmx.rmx_expire; + llentry_link(llt, lle); + IF_AFDATA_RUN_WUNLOCK(ifp); laflags = lle->la_flags; LLE_WUNLOCK(lle); - IF_AFDATA_WUNLOCK(ifp); + IF_AFDATA_CFG_WUNLOCK(ifp); #ifdef INET /* gratuitous ARP */ if ((laflags & LLE_PUB) && dst->sa_family == AF_INET) @@ -381,9 +402,9 @@ lla_rt_output(struct rt_msghdr *rtm, str break; case RTM_DELETE: - IF_AFDATA_WLOCK(ifp); + IF_AFDATA_CFG_WLOCK(ifp); error = lla_delete(llt, 0, dst); - IF_AFDATA_WUNLOCK(ifp); + IF_AFDATA_CFG_WUNLOCK(ifp); return (error == 0 ? 0 : ENOENT); default: Modified: projects/routing/sys/net/if_var.h ============================================================================== --- projects/routing/sys/net/if_var.h Sun Nov 23 12:15:28 2014 (r274916) +++ projects/routing/sys/net/if_var.h Sun Nov 23 15:38:06 2014 (r274917) @@ -355,17 +355,26 @@ EVENTHANDLER_DECLARE(group_change_event, #define IF_AFDATA_CFG_RUNLOCK(ifp) if_afdata_cfg_runlock(ifp) #define IF_AFDATA_CFG_WLOCK(ifp) if_afdata_cfg_wlock(ifp) #define IF_AFDATA_CFG_WUNLOCK(ifp) if_afdata_cfg_wunlock(ifp) +#define IF_AFDATA_CFG_TRY_WLOCK(ifp) if_afdata_cfg_try_wlock(ifp) #define IF_AFDATA_CFG_LOCK_ASSERT(i) if_afdata_cfg_lock_assert(i, RA_LOCKED) #define IF_AFDATA_CFG_RLOCK_ASSERT(i) if_afdata_cfg_lock_assert(i, RA_RLOCKED) #define IF_AFDATA_CFG_WLOCK_ASSERT(i) if_afdata_cfg_lock_assert(i, RA_WLOCKED) #define IF_AFDATA_CFG_UNLOCK_ASSERT(i) if_afdata_cfg_lock_assert(i,RA_UNLOCKED) +#define if_afdata_cfg_lock_assert(ifp, what) \ + rw_assert(&(ifp)->if_afdata_cfg_lock, what) + void if_afdata_cfg_rlock(struct ifnet *ifp); void if_afdata_cfg_runlock(struct ifnet *ifp); void if_afdata_cfg_wlock(struct ifnet *ifp); void if_afdata_cfg_wunlock(struct ifnet *ifp); -void if_afdata_cfg_lock_assert(struct ifnet *ifp, int what); +int if_afdata_cfg_try_wlock(struct ifnet *ifp); + +/* Wrappers */ +#define IF_AFDATA_RLOCK IF_AFDATA_CFG_RLOCK +#define IF_AFDATA_RUNLOCK IF_AFDATA_CFG_RUNLOCK + /* if_afdata lock: fast path */ #define IF_AFDATA_RUN_WLOCK(ifp) rm_wlock(&(ifp)->if_afdata_run_lock) @@ -376,23 +385,8 @@ void if_afdata_cfg_lock_assert(struct if rm_runlock(&(ifp)->if_afdata_run_lock, &if_afdata_tracker) #define IF_AFDATA_RUN_TRACKER struct rm_priotracker if_afdata_tracker -/* Common wrappers */ -#define IF_AFDATA_RLOCK(ifp) IF_AFDATA_CFG_RLOCK(ifp) -#define IF_AFDATA_RUNLOCK(ifp) IF_AFDATA_CFG_RUNLOCK(ifp) -#define IF_AFDATA_WLOCK(ifp) if_afdata_wlock(ifp) -#define IF_AFDATA_WUNLOCK(ifp) if_afdata_wunlock(ifp) - -#define IF_AFDATA_TRY_WLOCK(ifp) if_afdata_try_wlock(ifp) -#define IF_AFDATA_LOCK(ifp) IF_AFDATA_WLOCK(ifp) -#define IF_AFDATA_UNLOCK(ifp) IF_AFDATA_WUNLOCK(ifp) -void if_afdata_wlock(struct ifnet *ifp); -void if_afdata_wunlock(struct ifnet *ifp); -int if_afdata_try_wlock(struct ifnet *ifp); - -#define IF_AFDATA_LOCK_ASSERT(ifp) IF_AFDATA_CFG_LOCK_ASSERT(ifp) -#define IF_AFDATA_RLOCK_ASSERT(ifp) IF_AFDATA_CFG_RLOCK_ASSERT(ifp) -#define IF_AFDATA_WLOCK_ASSERT(ifp) IF_AFDATA_CFG_WLOCK_ASSERT(ifp) -#define IF_AFDATA_UNLOCK_ASSERT(ifp) IF_AFDATA_CFG_UNLOCK_ASSERT(ifp) +#define IF_AFDATA_RUN_WLOCK_ASSERT(ifp) \ + rm_assert(&(ifp)->if_afdata_run_lock, RA_WLOCKED) /* * 72 was chosen below because it is the size of a TCP/IP Modified: projects/routing/sys/net/rt_nhops.c ============================================================================== --- projects/routing/sys/net/rt_nhops.c Sun Nov 23 12:15:28 2014 (r274916) +++ projects/routing/sys/net/rt_nhops.c Sun Nov 23 15:38:06 2014 (r274917) @@ -699,7 +699,7 @@ fib6_storelladdr(struct ifnet *ifp, stru * the entry should have been created in nd6_store_lladdr */ IF_AFDATA_RUN_RLOCK(ifp); - ln = lla_lookup(LLTABLE6(ifp), 0, (struct sockaddr *)&dst_sa); + ln = lla_lookup(LLTABLE6(ifp), LLE_UNLOCKED, (struct sockaddr *)&dst_sa); /* * Perform fast path for the following cases: Modified: projects/routing/sys/netinet/if_ether.c ============================================================================== --- projects/routing/sys/netinet/if_ether.c Sun Nov 23 12:15:28 2014 (r274916) +++ projects/routing/sys/netinet/if_ether.c Sun Nov 23 15:38:06 2014 (r274917) @@ -164,9 +164,9 @@ arp_ifscrub(struct ifnet *ifp, uint32_t addr4.sin_len = sizeof(addr4); addr4.sin_family = AF_INET; addr4.sin_addr.s_addr = addr; - IF_AFDATA_WLOCK(ifp); + IF_AFDATA_CFG_WLOCK(ifp); lla_delete(LLTABLE(ifp), LLE_IFADDR, (struct sockaddr *)&addr4); - IF_AFDATA_WUNLOCK(ifp); + IF_AFDATA_CFG_WUNLOCK(ifp); } #endif @@ -247,7 +247,7 @@ arptimer(void *arg) /* XXX: LOR avoidance. We still have ref on lle. */ LLE_WUNLOCK(lle); - IF_AFDATA_LOCK(ifp); + IF_AFDATA_CFG_WLOCK(ifp); LLE_WLOCK(lle); /* @@ -262,7 +262,7 @@ arptimer(void *arg) pkts_dropped = llentry_free(lle); ARPSTAT_ADD(dropped, pkts_dropped); - IF_AFDATA_UNLOCK(ifp); + IF_AFDATA_CFG_WUNLOCK(ifp); ARPSTAT_INC(timeouts); @@ -492,9 +492,14 @@ arpresolve_slow(struct ifnet *ifp, int i IF_AFDATA_RUNLOCK(ifp); if (la == NULL && (ifp->if_flags & (IFF_NOARP | IFF_STATICARP)) == 0) { create = 1; - IF_AFDATA_WLOCK(ifp); + IF_AFDATA_CFG_WLOCK(ifp); la = lla_create(LLTABLE(ifp), 0, dst); - IF_AFDATA_WUNLOCK(ifp); + if (la != NULL) { + IF_AFDATA_RUN_WLOCK(ifp); + llentry_link(LLTABLE(ifp), la); + IF_AFDATA_RUN_WUNLOCK(ifp); + } + IF_AFDATA_CFG_WUNLOCK(ifp); } if (la == NULL) { if (create != 0) @@ -508,6 +513,7 @@ arpresolve_slow(struct ifnet *ifp, int i 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 0 /* * If entry has an expiry time and it is approaching, * see if we need to send an ARP request within this @@ -518,7 +524,7 @@ arpresolve_slow(struct ifnet *ifp, int i arprequest(ifp, NULL, &SIN(dst)->sin_addr, NULL); la->la_preempt--; } - +#endif *lle = la; error = 0; goto done; @@ -851,15 +857,15 @@ match: sin.sin_addr = isaddr; create = (itaddr.s_addr == myaddr.s_addr) ? 1 : 0; flags = LLE_EXCLUSIVE; - IF_AFDATA_LOCK(ifp); - if (create != 0) + IF_AFDATA_CFG_WLOCK(ifp); + if (create != 0) { la = lla_create(LLTABLE(ifp), 0, (struct sockaddr *)&sin); - else + } else la = lla_lookup(LLTABLE(ifp), flags, (struct sockaddr *)&sin); - IF_AFDATA_UNLOCK(ifp); + IF_AFDATA_CFG_WUNLOCK(ifp); if (la != NULL) { /* the following is not an error when doing bridging */ - if (!bridged && la->lle_tbl->llt_ifp != ifp) { + if (!bridged && la->lle_tbl && la->lle_tbl->llt_ifp != ifp) { if (log_arp_wrong_iface) ARP_LOG(LOG_WARNING, "%s is on %s " "but got reply from %*D on %s\n", @@ -910,17 +916,20 @@ match: /* use afdata WLOCK to update fields */ LLE_ADDREF(la); LLE_WUNLOCK(la); - IF_AFDATA_WLOCK(ifp); + IF_AFDATA_CFG_WLOCK(ifp); LLE_WLOCK(la); /* Update data */ + IF_AFDATA_RUN_WLOCK(ifp); memcpy(&la->ll_addr, ar_sha(ah), ifp->if_addrlen); la->la_flags |= LLE_VALID; la->r_flags |= RLLE_VALID; if ((la->la_flags & LLE_STATIC) == 0) la->la_expire = time_uptime + V_arpt_keep; + llentry_link(LLTABLE(ifp), la); + IF_AFDATA_RUN_WUNLOCK(ifp); - IF_AFDATA_WUNLOCK(ifp); + IF_AFDATA_CFG_WUNLOCK(ifp); LLE_REMREF(la); } @@ -1084,12 +1093,18 @@ arp_ifinit(struct ifnet *ifp, struct ifa * because the output of the arp utility shows * that L2 entry as permanent */ - IF_AFDATA_LOCK(ifp); + IF_AFDATA_CFG_WLOCK(ifp); lle = lla_create(LLTABLE(ifp), LLE_IFADDR | LLE_STATIC, (struct sockaddr *)IA_SIN(ifa)); - if (lle != NULL) + if (lle != NULL) { + IF_AFDATA_RUN_WLOCK(ifp); + bcopy(IF_LLADDR(ifp), &lle->ll_addr, ifp->if_addrlen); + lle->la_flags |= (LLE_VALID | LLE_STATIC); lle->r_flags |= RLLE_VALID; - IF_AFDATA_UNLOCK(ifp); + llentry_link(LLTABLE(ifp), lle); + IF_AFDATA_RUN_WUNLOCK(ifp); + } + IF_AFDATA_CFG_WUNLOCK(ifp); if (lle == NULL) log(LOG_INFO, "arp_ifinit: cannot create arp " "entry for interface address\n"); Modified: projects/routing/sys/netinet/in.c ============================================================================== --- projects/routing/sys/netinet/in.c Sun Nov 23 12:15:28 2014 (r274916) +++ projects/routing/sys/netinet/in.c Sun Nov 23 15:38:06 2014 (r274917) @@ -1050,7 +1050,7 @@ in_lltable_prefix_free(struct lltable *l size_t pkts_dropped; LIST_INIT(&dchain); - IF_AFDATA_WLOCK(llt->llt_ifp); + IF_AFDATA_CFG_WLOCK(llt->llt_ifp); for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) { LIST_FOREACH_SAFE(lle, &llt->lle_head[i], lle_next, next) { /* @@ -1070,12 +1070,14 @@ in_lltable_prefix_free(struct lltable *l } } /* Unlink chain */ + IF_AFDATA_RUN_WLOCK(llt->llt_ifp); llentries_unlink(&dchain); + IF_AFDATA_RUN_WUNLOCK(llt->llt_ifp); LIST_FOREACH_SAFE(lle, &dchain, lle_chain, next) { pkts_dropped = llentry_free(lle); ARPSTAT_ADD(dropped, pkts_dropped); } - IF_AFDATA_WUNLOCK(llt->llt_ifp); + IF_AFDATA_CFG_WUNLOCK(llt->llt_ifp); } @@ -1159,7 +1161,7 @@ in_lltable_delete(struct lltable *llt, u struct ifnet *ifp = llt->llt_ifp; struct llentry *lle; - IF_AFDATA_WLOCK_ASSERT(ifp); + IF_AFDATA_CFG_WLOCK_ASSERT(ifp); KASSERT(l3addr->sa_family == AF_INET, ("sin_family %d", l3addr->sa_family)); @@ -1175,7 +1177,9 @@ in_lltable_delete(struct lltable *llt, u LLE_WLOCK(lle); lle->la_flags |= LLE_DELETED; EVENTHANDLER_INVOKE(lle_event, lle, LLENTRY_DELETED); + IF_AFDATA_RUN_WLOCK(ifp); llentry_unlink(lle); + IF_AFDATA_RUN_WUNLOCK(ifp); #ifdef DIAGNOSTIC log(LOG_INFO, "ifaddr cache = %p is deleted\n", lle); #endif @@ -1195,7 +1199,7 @@ in_lltable_create(struct lltable *llt, u struct ifnet *ifp = llt->llt_ifp; struct llentry *lle; - IF_AFDATA_WLOCK_ASSERT(ifp); + IF_AFDATA_CFG_WLOCK_ASSERT(ifp); KASSERT(l3addr->sa_family == AF_INET, ("sin_family %d", l3addr->sa_family)); @@ -1223,12 +1227,6 @@ in_lltable_create(struct lltable *llt, u return (NULL); } lle->la_flags = flags; - if ((flags & LLE_IFADDR) == LLE_IFADDR) { - bcopy(IF_LLADDR(ifp), &lle->ll_addr, ifp->if_addrlen); - lle->la_flags |= (LLE_VALID | LLE_STATIC); - } - - llentry_link(llt, lle); LLE_WLOCK(lle); return (lle); Modified: projects/routing/sys/netinet/toecore.c ============================================================================== --- projects/routing/sys/netinet/toecore.c Sun Nov 23 12:15:28 2014 (r274916) +++ projects/routing/sys/netinet/toecore.c Sun Nov 23 15:38:06 2014 (r274917) @@ -462,9 +462,9 @@ restart: lle = lla_lookup(LLTABLE6(ifp), flags, sa); IF_AFDATA_RUNLOCK(ifp); if (lle == NULL) { - IF_AFDATA_LOCK(ifp); + IF_AFDATA_CFG_WLOCK(ifp); lle = nd6_create(&sin6->sin6_addr, 0, ifp); - IF_AFDATA_UNLOCK(ifp); + IF_AFDATA_CFG_WUNLOCK(ifp); if (lle == NULL) return (ENOMEM); /* Couldn't create entry in cache. */ lle->ln_state = ND6_LLINFO_INCOMPLETE; Modified: projects/routing/sys/netinet6/in6.c ============================================================================== --- projects/routing/sys/netinet6/in6.c Sun Nov 23 12:15:28 2014 (r274916) +++ projects/routing/sys/netinet6/in6.c Sun Nov 23 15:38:06 2014 (r274917) @@ -72,6 +72,8 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include +#include #include #include #include @@ -2100,7 +2102,7 @@ in6_lltable_prefix_free(struct lltable * * including static ND6 entries. */ LIST_INIT(&dchain); - IF_AFDATA_WLOCK(llt->llt_ifp); + IF_AFDATA_CFG_WLOCK(llt->llt_ifp); for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) { LIST_FOREACH_SAFE(lle, &llt->lle_head[i], lle_next, next) { if (IN6_ARE_MASKED_ADDR_EQUAL( @@ -2117,10 +2119,12 @@ in6_lltable_prefix_free(struct lltable * } } } + IF_AFDATA_RUN_WLOCK(llt->llt_ifp); llentries_unlink(&dchain); + IF_AFDATA_RUN_WUNLOCK(llt->llt_ifp); LIST_FOREACH_SAFE(lle, &dchain, lle_chain, next) llentry_free(lle); - IF_AFDATA_WUNLOCK(llt->llt_ifp); + IF_AFDATA_CFG_WUNLOCK(llt->llt_ifp); } static int @@ -2198,7 +2202,7 @@ in6_lltable_delete(struct lltable *llt, const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)l3addr; struct llentry *lle; - IF_AFDATA_LOCK_ASSERT(llt->llt_ifp); + IF_AFDATA_CFG_WLOCK_ASSERT(llt->llt_ifp); KASSERT(l3addr->sa_family == AF_INET6, ("sin_family %d", l3addr->sa_family)); @@ -2210,7 +2214,9 @@ in6_lltable_delete(struct lltable *llt, if (!(lle->la_flags & LLE_IFADDR) || (flags & LLE_IFADDR)) { LLE_WLOCK(lle); lle->la_flags |= LLE_DELETED; + IF_AFDATA_RUN_WLOCK(llt->llt_ifp); llentry_unlink(lle); + IF_AFDATA_RUN_WUNLOCK(llt->llt_ifp); #ifdef DIAGNOSTIC log(LOG_INFO, "ifaddr cache = %p is deleted\n", lle); #endif @@ -2231,7 +2237,7 @@ in6_lltable_create(struct lltable *llt, struct ifnet *ifp = llt->llt_ifp; struct llentry *lle; - IF_AFDATA_WLOCK_ASSERT(ifp); + IF_AFDATA_CFG_WLOCK_ASSERT(ifp); KASSERT(l3addr->sa_family == AF_INET6, ("sin_family %d", l3addr->sa_family)); @@ -2257,12 +2263,6 @@ in6_lltable_create(struct lltable *llt, return NULL; } lle->la_flags = flags; - if ((flags & LLE_IFADDR) == LLE_IFADDR) { - bcopy(IF_LLADDR(ifp), &lle->ll_addr, ifp->if_addrlen); - lle->la_flags |= (LLE_VALID | LLE_STATIC); - } - - llentry_link(llt, lle); LLE_WLOCK(lle); return (lle); @@ -2290,7 +2290,7 @@ in6_lltable_lookup(struct lltable *llt, if (flags & LLE_EXCLUSIVE) LLE_WLOCK(lle); - else + else if ((flags & LLE_UNLOCKED) == 0) LLE_RLOCK(lle); return (lle); } Modified: projects/routing/sys/netinet6/nd6.c ============================================================================== --- projects/routing/sys/netinet6/nd6.c Sun Nov 23 12:15:28 2014 (r274916) +++ projects/routing/sys/netinet6/nd6.c Sun Nov 23 15:38:06 2014 (r274917) @@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -854,7 +855,9 @@ nd6_lookup(struct in6_addr *addr6, int f sin6.sin6_family = AF_INET6; sin6.sin6_addr = *addr6; - IF_AFDATA_LOCK_ASSERT(ifp); + /* + * IF_AFDATA_LOCK_ASSERT(ifp); + */ llflags = (flags & ND6_EXCLUSIVE) ? LLE_EXCLUSIVE : 0; ln = lla_lookup(LLTABLE6(ifp), llflags, (struct sockaddr *)&sin6); @@ -877,11 +880,15 @@ nd6_create(struct in6_addr *addr6, int f sin6.sin6_family = AF_INET6; sin6.sin6_addr = *addr6; - IF_AFDATA_WLOCK_ASSERT(ifp); + IF_AFDATA_CFG_WLOCK_ASSERT(ifp); ln = lla_create(LLTABLE6(ifp), 0, (struct sockaddr *)&sin6); - if (ln != NULL) + if (ln != NULL) { + IF_AFDATA_RUN_WLOCK(ifp); ln->ln_state = ND6_LLINFO_NOSTATE; + llentry_link(LLTABLE6(ifp), ln); + IF_AFDATA_RUN_WUNLOCK(ifp); + } return (ln); } @@ -998,7 +1005,7 @@ nd6_is_addr_neighbor(struct sockaddr_in6 struct llentry *lle; int rc = 0; - IF_AFDATA_UNLOCK_ASSERT(ifp); + IF_AFDATA_CFG_UNLOCK_ASSERT(ifp); if (nd6_is_new_addr_neighbor(addr, ifp)) return (1); @@ -1137,7 +1144,7 @@ nd6_free(struct llentry *ln, int gc) * free(9) in llentry_free() if someone else holds one as well. */ LLE_WUNLOCK(ln); - IF_AFDATA_LOCK(ifp); + IF_AFDATA_CFG_WLOCK(ifp); LLE_WLOCK(ln); /* @@ -1149,9 +1156,13 @@ nd6_free(struct llentry *ln, int gc) ln->la_flags &= ~LLE_CALLOUTREF; } + IF_AFDATA_RUN_WLOCK(ifp); + llentry_unlink(ln); + IF_AFDATA_RUN_WUNLOCK(ifp); + llentry_free(ln); - IF_AFDATA_UNLOCK(ifp); + IF_AFDATA_CFG_WUNLOCK(ifp); return (next); } @@ -1579,7 +1590,7 @@ nd6_cache_lladdr(struct ifnet *ifp, stru struct mbuf *chain = NULL; int static_route = 0; - IF_AFDATA_UNLOCK_ASSERT(ifp); + IF_AFDATA_CFG_UNLOCK_ASSERT(ifp); KASSERT(ifp != NULL, ("%s: ifp == NULL", __func__)); KASSERT(from != NULL, ("%s: from == NULL", __func__)); @@ -1598,14 +1609,14 @@ nd6_cache_lladdr(struct ifnet *ifp, stru * description on it in NS section (RFC 2461 7.2.3). */ flags = lladdr ? ND6_EXCLUSIVE : 0; - IF_AFDATA_RLOCK(ifp); + IF_AFDATA_CFG_RLOCK(ifp); ln = nd6_lookup(from, flags, ifp); - IF_AFDATA_RUNLOCK(ifp); + IF_AFDATA_CFG_RUNLOCK(ifp); if (ln == NULL) { flags |= ND6_EXCLUSIVE; - IF_AFDATA_LOCK(ifp); + IF_AFDATA_CFG_WLOCK(ifp); ln = nd6_create(from, 0, ifp); - IF_AFDATA_UNLOCK(ifp); + IF_AFDATA_CFG_WUNLOCK(ifp); is_newentry = 1; } else { /* do nothing if static ndp is set */ @@ -2004,9 +2015,9 @@ nd6_output_lle(struct ifnet *ifp, struct * the condition below is not very efficient. But we believe * it is tolerable, because this should be a rare case. */ - IF_AFDATA_LOCK(ifp); + IF_AFDATA_CFG_WLOCK(ifp); lle = nd6_create(&dst->sin6_addr, 0, ifp); - IF_AFDATA_UNLOCK(ifp); + IF_AFDATA_CFG_WUNLOCK(ifp); } } if (lle == NULL) { @@ -2257,14 +2268,23 @@ nd6_add_ifa_lle(struct in6_ifaddr *ia) struct llentry *ln; ifp = ia->ia_ifa.ifa_ifp; - IF_AFDATA_LOCK(ifp); - ia->ia_ifa.ifa_rtrequest = nd6_rtrequest; + IF_AFDATA_CFG_WLOCK(ifp); ln = lla_create(LLTABLE6(ifp), LLE_IFADDR, (struct sockaddr *)&ia->ia_addr); - IF_AFDATA_UNLOCK(ifp); if (ln != NULL) { + IF_AFDATA_RUN_WLOCK(ifp); + bcopy(IF_LLADDR(ifp), &ln->ll_addr, ifp->if_addrlen); + ln->la_flags |= (LLE_VALID | LLE_STATIC); + ln->r_flags |= RLLE_VALID; ln->la_expire = 0; /* for IPv6 this means permanent */ ln->ln_state = ND6_LLINFO_REACHABLE; + llentry_link(LLTABLE6(ifp), ln); + IF_AFDATA_RUN_WUNLOCK(ifp); + } + + ia->ia_ifa.ifa_rtrequest = nd6_rtrequest; + IF_AFDATA_CFG_WUNLOCK(ifp); + if (ln != NULL) { LLE_WUNLOCK(ln); in6_newaddrmsg(ia, RTM_ADD); return (0); @@ -2306,7 +2326,7 @@ nd6_storelladdr(struct ifnet *ifp, struc struct llentry *ln; *lle = NULL; - IF_AFDATA_UNLOCK_ASSERT(ifp); + IF_AFDATA_CFG_UNLOCK_ASSERT(ifp); if (m != NULL && m->m_flags & M_MCAST) { int i; Modified: projects/routing/sys/netinet6/scope6.c ============================================================================== --- projects/routing/sys/netinet6/scope6.c Sun Nov 23 12:15:28 2014 (r274916) +++ projects/routing/sys/netinet6/scope6.c Sun Nov 23 15:38:06 2014 (r274917) @@ -148,11 +148,11 @@ scope6_set(struct ifnet *ifp, struct sco int error = 0; struct scope6_id *sid = NULL; - IF_AFDATA_WLOCK(ifp); + IF_AFDATA_CFG_WLOCK(ifp); sid = SID(ifp); if (!sid) { /* paranoid? */ - IF_AFDATA_WUNLOCK(ifp); + IF_AFDATA_CFG_WUNLOCK(ifp); return (EINVAL); } @@ -175,7 +175,7 @@ scope6_set(struct ifnet *ifp, struct sco */ if (i == IPV6_ADDR_SCOPE_INTFACELOCAL && idlist->s6id_list[i] != ifp->if_index) { - IF_AFDATA_WUNLOCK(ifp); + IF_AFDATA_CFG_WUNLOCK(ifp); return (EINVAL); } @@ -187,7 +187,7 @@ scope6_set(struct ifnet *ifp, struct sco * IDs, but we check the consistency for * safety in later use. */ - IF_AFDATA_WUNLOCK(ifp); + IF_AFDATA_CFG_WUNLOCK(ifp); return (EINVAL); } @@ -196,10 +196,11 @@ scope6_set(struct ifnet *ifp, struct sco * but we simply set the new value in this initial * implementation. */ + /* XXX: Use runtime lock? */ sid->s6id_list[i] = idlist->s6id_list[i]; } } - IF_AFDATA_WUNLOCK(ifp); + IF_AFDATA_CFG_WUNLOCK(ifp); return (error); }