Skip to content

Commit b986aa0

Browse files
committed
lltable: use own lock
Add struct mtx to struct lltable and stop using IF_AFDATA_LOCK, that was created for a completely different purpose. No functional change intended. Reviewed by: zlei, melifaro Differential Revision: https://reviews.freebsd.org/D54086
1 parent 607f110 commit b986aa0

File tree

8 files changed

+65
-64
lines changed

8 files changed

+65
-64
lines changed

sys/net/if_llatbl.c

Lines changed: 24 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ htable_link_entry(struct lltable *llt, struct llentry *lle)
206206
if ((lle->la_flags & LLE_LINKED) != 0)
207207
return (0);
208208

209-
IF_AFDATA_WLOCK_ASSERT(llt->llt_ifp);
209+
LLTABLE_LOCK_ASSERT(llt);
210210

211211
if (llt->llt_maxentries > 0 &&
212212
llt->llt_entries >= llt->llt_maxentries)
@@ -233,7 +233,7 @@ htable_unlink_entry(struct llentry *lle)
233233
return (0);
234234

235235
llt = lle->lle_tbl;
236-
IF_AFDATA_WLOCK_ASSERT(llt->llt_ifp);
236+
LLTABLE_LOCK_ASSERT(llt);
237237
KASSERT(llt->llt_entries > 0, ("%s: lltable %p (%s) entries %d <= 0",
238238
__func__, llt, if_name(llt->llt_ifp), llt->llt_entries));
239239

@@ -283,12 +283,12 @@ htable_prefix_free(struct lltable *llt, const struct sockaddr *addr,
283283
pmd.flags = flags;
284284
CK_LIST_INIT(&pmd.dchain);
285285

286-
IF_AFDATA_WLOCK(llt->llt_ifp);
286+
LLTABLE_LOCK(llt);
287287
/* Push matching lles to chain */
288288
lltable_foreach_lle(llt, htable_prefix_free_cb, &pmd);
289289

290290
llentries_unlink(llt, &pmd.dchain);
291-
IF_AFDATA_WUNLOCK(llt->llt_ifp);
291+
LLTABLE_UNLOCK(llt);
292292

293293
CK_LIST_FOREACH_SAFE(lle, &pmd.dchain, lle_chain, next)
294294
lltable_free_entry(llt, lle);
@@ -298,6 +298,7 @@ static void
298298
htable_free_tbl(struct lltable *llt)
299299
{
300300

301+
mtx_destroy(&llt->llt_lock);
301302
free(llt->lle_head, M_LLTABLE);
302303
free(llt, M_LLTABLE);
303304
}
@@ -357,22 +358,20 @@ lltable_set_entry_addr(struct ifnet *ifp, struct llentry *lle,
357358
* On failure, false is returned and lle wlock is still held.
358359
*/
359360
bool
360-
lltable_acquire_wlock(struct ifnet *ifp, struct llentry *lle)
361+
lltable_trylock(struct llentry *lle)
361362
{
362363
NET_EPOCH_ASSERT();
363364

364-
/* Perform real LLE update */
365-
/* use afdata WLOCK to update fields */
366365
LLE_WUNLOCK(lle);
367-
IF_AFDATA_WLOCK(ifp);
366+
LLTABLE_LOCK(lle->lle_tbl);
368367
LLE_WLOCK(lle);
369368

370369
/*
371370
* Since we droppped LLE lock, other thread might have deleted
372371
* this lle. Check and return
373372
*/
374373
if ((lle->la_flags & LLE_DELETED) != 0) {
375-
IF_AFDATA_WUNLOCK(ifp);
374+
LLTABLE_UNLOCK(lle->lle_tbl);
376375
return (false);
377376
}
378377

@@ -392,13 +391,13 @@ lltable_try_set_entry_addr(struct ifnet *ifp, struct llentry *lle,
392391
const char *linkhdr, size_t linkhdrsize, int lladdr_off)
393392
{
394393

395-
if (!lltable_acquire_wlock(ifp, lle))
394+
if (!lltable_trylock(lle))
396395
return (0);
397396

398397
/* Update data */
399398
lltable_set_entry_addr(ifp, lle, linkhdr, linkhdrsize, lladdr_off);
400399

401-
IF_AFDATA_WUNLOCK(ifp);
400+
LLTABLE_UNLOCK(lle->lle_tbl);
402401

403402
return (1);
404403
}
@@ -630,9 +629,9 @@ lltable_update_ifaddr(struct lltable *llt)
630629
if (llt->llt_ifp->if_flags & IFF_LOOPBACK)
631630
return;
632631

633-
IF_AFDATA_WLOCK(llt->llt_ifp);
632+
LLTABLE_LOCK(llt);
634633
lltable_foreach_lle(llt, llentry_update_ifaddr, llt->llt_ifp);
635-
IF_AFDATA_WUNLOCK(llt->llt_ifp);
634+
LLTABLE_UNLOCK(llt);
636635
}
637636

638637
/*
@@ -696,11 +695,11 @@ lltable_free(struct lltable *llt)
696695
lltable_unlink(llt);
697696

698697
CK_LIST_INIT(&dchain);
699-
IF_AFDATA_WLOCK(llt->llt_ifp);
698+
LLTABLE_LOCK(llt);
700699
/* Push all lles to @dchain */
701700
lltable_foreach_lle(llt, lltable_free_cb, &dchain);
702701
llentries_unlink(llt, &dchain);
703-
IF_AFDATA_WUNLOCK(llt->llt_ifp);
702+
LLTABLE_UNLOCK(llt);
704703

705704
CK_LIST_FOREACH_SAFE(lle, &dchain, lle_chain, next) {
706705
llentry_free(lle);
@@ -722,24 +721,22 @@ lltable_delete_addr(struct lltable *llt, u_int flags,
722721
const struct sockaddr *l3addr)
723722
{
724723
struct llentry *lle;
725-
struct ifnet *ifp;
726724

727-
ifp = llt->llt_ifp;
728-
IF_AFDATA_WLOCK(ifp);
725+
LLTABLE_LOCK(llt);
729726
lle = lla_lookup(llt, LLE_SF(l3addr->sa_family, LLE_EXCLUSIVE), l3addr);
730727

731728
if (lle == NULL) {
732-
IF_AFDATA_WUNLOCK(ifp);
729+
LLTABLE_UNLOCK(llt);
733730
return (ENOENT);
734731
}
735732
if ((lle->la_flags & LLE_IFADDR) != 0 && (flags & LLE_IFADDR) == 0) {
736-
IF_AFDATA_WUNLOCK(ifp);
733+
LLTABLE_UNLOCK(llt);
737734
LLE_WUNLOCK(lle);
738735
return (EPERM);
739736
}
740737

741738
lltable_unlink_entry(llt, lle);
742-
IF_AFDATA_WUNLOCK(ifp);
739+
LLTABLE_UNLOCK(llt);
743740

744741
llt->llt_delete_entry(llt, lle);
745742

@@ -798,10 +795,10 @@ lltable_delete_conditional(struct lltable *llt, llt_match_cb_t *func,
798795
lmd.func = func;
799796
lmd.farg = farg;
800797

801-
IF_AFDATA_WLOCK(llt->llt_ifp);
798+
LLTABLE_LOCK(llt);
802799
lltable_foreach_lle(llt, lltable_delete_conditional_cb, &lmd);
803800
llentries_unlink(llt, &lmd.dchain);
804-
IF_AFDATA_WUNLOCK(llt->llt_ifp);
801+
LLTABLE_UNLOCK(llt);
805802

806803
CK_LIST_FOREACH_SAFE(lle, &lmd.dchain, lle_chain, next)
807804
llt->llt_delete_entry(llt, lle);
@@ -817,6 +814,7 @@ lltable_allocate_htbl(uint32_t hsize)
817814
llt->llt_hsize = hsize;
818815
llt->lle_head = malloc(sizeof(struct llentries) * hsize,
819816
M_LLTABLE, M_WAITOK | M_ZERO);
817+
mtx_init(&llt->llt_lock, "lltable", NULL, MTX_DEF);
820818

821819
for (i = 0; i < llt->llt_hsize; i++)
822820
CK_LIST_INIT(&llt->lle_head[i]);
@@ -1021,13 +1019,13 @@ lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info)
10211019

10221020
/* Try to link new entry */
10231021
lle_tmp = NULL;
1024-
IF_AFDATA_WLOCK(ifp);
1022+
LLTABLE_LOCK(llt);
10251023
LLE_WLOCK(lle);
10261024
lle_tmp = lla_lookup(llt, LLE_EXCLUSIVE, dst);
10271025
if (lle_tmp != NULL) {
10281026
/* Check if we are trying to replace immutable entry */
10291027
if ((lle_tmp->la_flags & LLE_IFADDR) != 0) {
1030-
IF_AFDATA_WUNLOCK(ifp);
1028+
LLTABLE_UNLOCK(llt);
10311029
LLE_WUNLOCK(lle_tmp);
10321030
lltable_free_entry(llt, lle);
10331031
return (EPERM);
@@ -1036,7 +1034,7 @@ lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info)
10361034
lltable_unlink_entry(llt, lle_tmp);
10371035
}
10381036
lltable_link_entry(llt, lle);
1039-
IF_AFDATA_WUNLOCK(ifp);
1037+
LLTABLE_UNLOCK(llt);
10401038

10411039
if (lle_tmp != NULL) {
10421040
EVENTHANDLER_INVOKE(lle_event, lle_tmp,LLENTRY_EXPIRED);

sys/net/if_llatbl.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ struct lltable {
174174
int llt_maxentries;
175175
struct llentries *lle_head;
176176
struct ifnet *llt_ifp;
177+
struct mtx llt_lock;
177178

178179
llt_lookup_t *llt_lookup;
179180
llt_alloc_t *llt_alloc_entry;
@@ -192,6 +193,12 @@ struct lltable {
192193
llt_post_resolved_t *llt_post_resolved;
193194
};
194195

196+
#define LLTABLE_LOCK(llt) mtx_lock(&(llt)->llt_lock)
197+
#define LLTABLE_UNLOCK(llt) mtx_unlock(&(llt)->llt_lock)
198+
#define LLTABLE_LOCK_ASSERT(llt) mtx_assert(&(llt)->llt_lock, MA_OWNED)
199+
#define LLTABLE_RLOCK_ASSERT(llt) MPASS(in_epoch(net_epoch_preempt) || \
200+
mtx_owned(&(llt)->llt_lock))
201+
195202
MALLOC_DECLARE(M_LLTABLE);
196203

197204
/*
@@ -261,7 +268,7 @@ void lltable_fill_sa_entry(const struct llentry *lle, struct sockaddr *sa);
261268
struct ifnet *lltable_get_ifp(const struct lltable *llt);
262269
int lltable_get_af(const struct lltable *llt);
263270

264-
bool lltable_acquire_wlock(struct ifnet *ifp, struct llentry *lle);
271+
bool lltable_trylock(struct llentry *lle);
265272

266273
int lltable_foreach_lle(struct lltable *llt, llt_foreach_cb_t *f,
267274
void *farg);

sys/netinet/if_ether.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -288,15 +288,15 @@ arptimer(void *arg)
288288

289289
/* XXX: LOR avoidance. We still have ref on lle. */
290290
LLE_WUNLOCK(lle);
291-
IF_AFDATA_LOCK(ifp);
291+
LLTABLE_LOCK(LLTABLE(ifp));
292292
LLE_WLOCK(lle);
293293

294294
/* Guard against race with other llentry_free(). */
295295
if (lle->la_flags & LLE_LINKED) {
296296
LLE_REMREF(lle);
297297
lltable_unlink_entry(lle->lle_tbl, lle);
298298
}
299-
IF_AFDATA_UNLOCK(ifp);
299+
LLTABLE_UNLOCK(LLTABLE(ifp));
300300

301301
size_t pkts_dropped = llentry_free(lle);
302302

@@ -488,13 +488,13 @@ arpresolve_full(struct ifnet *ifp, int is_gw, int flags, struct mbuf *m,
488488
return (EINVAL);
489489
}
490490

491-
IF_AFDATA_WLOCK(ifp);
491+
LLTABLE_LOCK(LLTABLE(ifp));
492492
LLE_WLOCK(la);
493493
la_tmp = lla_lookup(LLTABLE(ifp), LLE_EXCLUSIVE, dst);
494494
/* Prefer ANY existing lle over newly-created one */
495495
if (la_tmp == NULL)
496496
lltable_link_entry(LLTABLE(ifp), la);
497-
IF_AFDATA_WUNLOCK(ifp);
497+
LLTABLE_UNLOCK(LLTABLE(ifp));
498498
if (la_tmp != NULL) {
499499
lltable_free_entry(LLTABLE(ifp), la);
500500
la = la_tmp;
@@ -961,7 +961,7 @@ in_arpinput(struct mbuf *m)
961961
lltable_set_entry_addr(ifp, la, linkhdr, linkhdrsize,
962962
lladdr_off);
963963

964-
IF_AFDATA_WLOCK(ifp);
964+
LLTABLE_LOCK(LLTABLE(ifp));
965965
LLE_WLOCK(la);
966966
la_tmp = lla_lookup(LLTABLE(ifp), LLE_EXCLUSIVE, dst);
967967

@@ -983,7 +983,7 @@ in_arpinput(struct mbuf *m)
983983
*/
984984
if (la_tmp == NULL)
985985
lltable_link_entry(LLTABLE(ifp), la);
986-
IF_AFDATA_WUNLOCK(ifp);
986+
LLTABLE_UNLOCK(LLTABLE(ifp));
987987

988988
if (la_tmp == NULL) {
989989
arp_mark_lle_reachable(la, ifp);
@@ -1301,15 +1301,15 @@ arp_add_ifa_lle(struct ifnet *ifp, const struct sockaddr *dst)
13011301
return;
13021302
}
13031303

1304-
IF_AFDATA_WLOCK(ifp);
1304+
LLTABLE_LOCK(LLTABLE(ifp));
13051305
LLE_WLOCK(lle);
13061306
/* Unlink any entry if exists */
13071307
lle_tmp = lla_lookup(LLTABLE(ifp), LLE_EXCLUSIVE, dst);
13081308
if (lle_tmp != NULL)
13091309
lltable_unlink_entry(LLTABLE(ifp), lle_tmp);
13101310

13111311
lltable_link_entry(LLTABLE(ifp), lle);
1312-
IF_AFDATA_WUNLOCK(ifp);
1312+
LLTABLE_UNLOCK(LLTABLE(ifp));
13131313

13141314
if (lle_tmp != NULL)
13151315
EVENTHANDLER_INVOKE(lle_event, lle_tmp, LLENTRY_EXPIRED);

sys/netinet/in.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1546,7 +1546,7 @@ in_lltable_free_entry(struct lltable *llt, struct llentry *lle)
15461546

15471547
/* Unlink entry from table if not already */
15481548
if ((lle->la_flags & LLE_LINKED) != 0) {
1549-
IF_AFDATA_WLOCK_ASSERT(llt->llt_ifp);
1549+
LLTABLE_LOCK_ASSERT(llt);
15501550
lltable_unlink_entry(llt, lle);
15511551
}
15521552

@@ -1728,7 +1728,7 @@ in_lltable_lookup(struct lltable *llt, u_int flags, const struct sockaddr *l3add
17281728
const struct sockaddr_in *sin = (const struct sockaddr_in *)l3addr;
17291729
struct llentry *lle;
17301730

1731-
IF_AFDATA_LOCK_ASSERT(llt->llt_ifp);
1731+
LLTABLE_RLOCK_ASSERT(llt);
17321732
KASSERT(l3addr->sa_family == AF_INET,
17331733
("sin_family %d", l3addr->sa_family));
17341734
KASSERT((flags & (LLE_UNLOCKED | LLE_EXCLUSIVE)) !=

sys/netinet6/in6.c

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2253,15 +2253,13 @@ in6_lltable_match_prefix(const struct sockaddr *saddr,
22532253
static void
22542254
in6_lltable_free_entry(struct lltable *llt, struct llentry *lle)
22552255
{
2256-
struct ifnet *ifp __diagused;
22572256

22582257
LLE_WLOCK_ASSERT(lle);
22592258
KASSERT(llt != NULL, ("lltable is NULL"));
22602259

22612260
/* Unlink entry from table */
22622261
if ((lle->la_flags & LLE_LINKED) != 0) {
2263-
ifp = llt->llt_ifp;
2264-
IF_AFDATA_WLOCK_ASSERT(ifp);
2262+
LLTABLE_LOCK_ASSERT(llt);
22652263
lltable_unlink_entry(llt, lle);
22662264
}
22672265

@@ -2421,7 +2419,7 @@ in6_lltable_lookup(struct lltable *llt, u_int flags,
24212419
int family = flags >> 16;
24222420
struct llentry *lle;
24232421

2424-
IF_AFDATA_LOCK_ASSERT(llt->llt_ifp);
2422+
LLTABLE_RLOCK_ASSERT(llt);
24252423
KASSERT(l3addr->sa_family == AF_INET6,
24262424
("sin_family %d", l3addr->sa_family));
24272425
KASSERT((flags & (LLE_UNLOCKED | LLE_EXCLUSIVE)) !=
@@ -2445,7 +2443,7 @@ in6_lltable_lookup(struct lltable *llt, u_int flags,
24452443
LLE_RLOCK(lle);
24462444

24472445
/*
2448-
* If the afdata lock is not held, the LLE may have been unlinked while
2446+
* If the lltable lock is not held, the LLE may have been unlinked while
24492447
* we were blocked on the LLE lock. Check for this case.
24502448
*/
24512449
if (__predict_false((lle->la_flags & LLE_LINKED) == 0)) {
@@ -2743,9 +2741,9 @@ in6_purge_proxy_ndp(struct ifnet *ifp)
27432741
return;
27442742

27452743
llt = LLTABLE6(ifp);
2746-
IF_AFDATA_WLOCK(ifp);
2744+
LLTABLE_LOCK(llt);
27472745
need_purge = ((llt->llt_flags & LLT_ADDEDPROXY) != 0);
2748-
IF_AFDATA_WUNLOCK(ifp);
2746+
LLTABLE_UNLOCK(llt);
27492747

27502748
/*
27512749
* Ever added proxy ndp entries, leave solicited node multicast

sys/netinet6/mld6.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -165,8 +165,8 @@ static int sysctl_mld_ifinfo(SYSCTL_HANDLER_ARGS);
165165
* scope ID is only used by MLD to select the outgoing interface.
166166
*
167167
* During interface attach and detach, MLD will take MLD_LOCK *after*
168-
* the IF_AFDATA_LOCK.
169-
* As in6_setscope() takes IF_AFDATA_LOCK then SCOPE_LOCK, we can't call
168+
* the LLTABLE_LOCK.
169+
* As in6_setscope() takes LLTABLE_LOCK then SCOPE_LOCK, we can't call
170170
* it with MLD_LOCK held without triggering an LOR. A netisr with indirect
171171
* dispatch could work around this, but we'd rather not do that, as it
172172
* can introduce other races.
@@ -182,7 +182,7 @@ static int sysctl_mld_ifinfo(SYSCTL_HANDLER_ARGS);
182182
* calls in6_setscope() internally whilst MLD_LOCK is held. This will
183183
* trigger a LOR warning in WITNESS when the ifnet is detached.
184184
*
185-
* The right answer is probably to make IF_AFDATA_LOCK an rwlock, given
185+
* The right answer is probably to make LLTABLE_LOCK an rwlock, given
186186
* how it's used across the network stack. Here we're simply exploiting
187187
* the fact that MLD runs at a similar layer in the stack to scope6.c.
188188
*
@@ -553,7 +553,7 @@ mld_ifdetach(struct ifnet *ifp, struct in6_multi_head *inmh)
553553
* Hook for domifdetach.
554554
* Runs after link-layer cleanup; free MLD state.
555555
*
556-
* SMPng: Normally called with IF_AFDATA_LOCK held.
556+
* SMPng: Normally called with LLTABLE_LOCK held.
557557
*/
558558
void
559559
mld_domifdetach(struct ifnet *ifp)

0 commit comments

Comments
 (0)