Do more fine-grained lltable locking: use table runtime lock as rare
as we can.
This commit is contained in:
parent
9479029b1f
commit
73d770287d
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/projects/routing/; revision=274917
40
sys/net/if.c
40
sys/net/if.c
@ -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, int vmove)
|
||||
* 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));
|
||||
}
|
||||
|
||||
|
@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/rwlock.h>
|
||||
#include <sys/rmlock.h>
|
||||
|
||||
#ifdef DDB
|
||||
#include <ddb/ddb.h>
|
||||
@ -99,6 +100,11 @@ llentry_link(struct lltable *llt, struct llentry *lle)
|
||||
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,11 +118,14 @@ void
|
||||
llentry_unlink(struct llentry *lle)
|
||||
{
|
||||
|
||||
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
|
||||
llentries_unlink(struct llentries *head)
|
||||
@ -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 lltable *lt,
|
||||
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;
|
||||
}
|
||||
LIST_INSERT_HEAD(&dchain, lle, lle_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)
|
||||
llentry_free(lle);
|
||||
}
|
||||
}
|
||||
IF_AFDATA_WUNLOCK(llt->llt_ifp);
|
||||
IF_AFDATA_CFG_WUNLOCK(llt->llt_ifp);
|
||||
|
||||
free(llt, M_LLTABLE);
|
||||
}
|
||||
@ -337,14 +355,15 @@ lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info)
|
||||
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, struct rt_addrinfo *info)
|
||||
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, struct rt_addrinfo *info)
|
||||
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:
|
||||
|
@ -355,17 +355,26 @@ EVENTHANDLER_DECLARE(group_change_event, group_change_event_handler_t);
|
||||
#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 ifnet *ifp, int what);
|
||||
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
|
||||
|
@ -699,7 +699,7 @@ fib6_storelladdr(struct ifnet *ifp, struct in6_addr *dst, int mm_flags,
|
||||
* 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:
|
||||
|
@ -164,9 +164,9 @@ arp_ifscrub(struct ifnet *ifp, uint32_t addr)
|
||||
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 is_gw, struct mbuf *m,
|
||||
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 is_gw, struct mbuf *m,
|
||||
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 is_gw, struct mbuf *m,
|
||||
arprequest(ifp, NULL, &SIN(dst)->sin_addr, NULL);
|
||||
la->la_preempt--;
|
||||
}
|
||||
|
||||
#endif
|
||||
*lle = la;
|
||||
error = 0;
|
||||
goto done;
|
||||
@ -851,15 +857,15 @@ in_arpinput(struct mbuf *m)
|
||||
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 @@ in_arpinput(struct mbuf *m)
|
||||
/* 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 ifaddr *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");
|
||||
|
@ -1050,7 +1050,7 @@ in_lltable_prefix_free(struct lltable *llt, const struct sockaddr *prefix,
|
||||
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 *llt, const struct sockaddr *prefix,
|
||||
}
|
||||
}
|
||||
/* 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_int flags,
|
||||
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_int flags,
|
||||
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_int flags, const struct sockaddr *l3add
|
||||
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_int flags, const struct sockaddr *l3add
|
||||
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);
|
||||
|
@ -462,9 +462,9 @@ toe_nd6_resolve(struct ifnet *ifp, struct sockaddr *sa, uint8_t *lladdr)
|
||||
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;
|
||||
|
@ -72,6 +72,8 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/errno.h>
|
||||
#include <sys/jail.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/rmlock.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/socketvar.h>
|
||||
#include <sys/sockio.h>
|
||||
@ -2100,7 +2102,7 @@ in6_lltable_prefix_free(struct lltable *llt, const struct sockaddr *prefix,
|
||||
* 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 *llt, const struct sockaddr *prefix,
|
||||
}
|
||||
}
|
||||
}
|
||||
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, u_int flags,
|
||||
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, u_int flags,
|
||||
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, u_int flags,
|
||||
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, u_int flags,
|
||||
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, u_int flags,
|
||||
|
||||
if (flags & LLE_EXCLUSIVE)
|
||||
LLE_WLOCK(lle);
|
||||
else
|
||||
else if ((flags & LLE_UNLOCKED) == 0)
|
||||
LLE_RLOCK(lle);
|
||||
return (lle);
|
||||
}
|
||||
|
@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/syslog.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/rwlock.h>
|
||||
#include <sys/rmlock.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/sdt.h>
|
||||
#include <sys/sysctl.h>
|
||||
@ -854,7 +855,9 @@ nd6_lookup(struct in6_addr *addr6, int flags, struct ifnet *ifp)
|
||||
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 flags, struct ifnet *ifp)
|
||||
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 *addr, struct ifnet *ifp)
|
||||
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, struct in6_addr *from, char *lladdr,
|
||||
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, struct in6_addr *from, char *lladdr,
|
||||
* 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 ifnet *origifp, struct mbuf *m,
|
||||
* 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, struct mbuf *m,
|
||||
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;
|
||||
|
||||
|
@ -148,11 +148,11 @@ scope6_set(struct ifnet *ifp, struct scope6_id *idlist)
|
||||
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 scope6_id *idlist)
|
||||
*/
|
||||
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 scope6_id *idlist)
|
||||
* 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 scope6_id *idlist)
|
||||
* 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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user