* Add lltable llt_hash callback
* Move lltable items insertions/deletions to generic llt code.
This commit is contained in:
parent
7c066c18db
commit
9479029b1f
@ -92,6 +92,42 @@ lltable_sysctl_dumparp(int af, struct sysctl_req *wr)
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
llentry_link(struct lltable *llt, struct llentry *lle)
|
||||
{
|
||||
struct llentries *lleh;
|
||||
uint32_t hashkey;
|
||||
|
||||
hashkey = llt->llt_hash(lle);
|
||||
lleh = &llt->lle_head[LLATBL_HASH(hashkey, LLTBL_HASHMASK)];
|
||||
|
||||
lle->lle_tbl = llt;
|
||||
lle->lle_head = lleh;
|
||||
lle->la_flags |= LLE_LINKED;
|
||||
LIST_INSERT_HEAD(lleh, lle, lle_next);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void
|
||||
llentries_unlink(struct llentries *head)
|
||||
{
|
||||
struct llentry *lle, *next;
|
||||
|
||||
LIST_FOREACH_SAFE(lle, head, lle_chain, next) {
|
||||
llentry_unlink(lle);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Deletes an address from the address table.
|
||||
* This function is called by the timer functions
|
||||
|
@ -80,6 +80,7 @@ struct llentry {
|
||||
uint16_t ln_router;
|
||||
time_t ln_ntick;
|
||||
int lle_refcnt;
|
||||
LIST_ENTRY(llentry) lle_chain; /* chain of deleted items */
|
||||
struct rwlock lle_lock;
|
||||
|
||||
/* XXX af-private? */
|
||||
@ -94,8 +95,6 @@ struct llentry {
|
||||
#define LLE_RLOCK(lle) rw_rlock(&(lle)->lle_lock)
|
||||
#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_LOCK_DESTROY(lle) rw_destroy(&(lle)->lle_lock)
|
||||
#define LLE_WLOCK_ASSERT(lle) rw_assert(&(lle)->lle_lock, RA_WLOCKED)
|
||||
@ -157,6 +156,7 @@ typedef int (llt_delete_t)(struct lltable *, u_int flags,
|
||||
typedef void (llt_prefix_free_t)(struct lltable *,
|
||||
const struct sockaddr *prefix, const struct sockaddr *mask, u_int flags);
|
||||
typedef int (llt_dump_t)(struct lltable *, struct sysctl_req *);
|
||||
typedef uint32_t (llt_hash_t)(const struct llentry *);
|
||||
|
||||
struct lltable {
|
||||
SLIST_ENTRY(lltable) llt_link;
|
||||
@ -169,6 +169,7 @@ struct lltable {
|
||||
llt_delete_t *llt_delete;
|
||||
llt_prefix_free_t *llt_prefix_free;
|
||||
llt_dump_t *llt_dump;
|
||||
llt_hash_t *llt_hash;
|
||||
};
|
||||
|
||||
MALLOC_DECLARE(M_LLTABLE);
|
||||
@ -204,6 +205,9 @@ void lltable_drain(int);
|
||||
#endif
|
||||
int lltable_sysctl_dumparp(int, struct sysctl_req *);
|
||||
|
||||
void llentry_link(struct lltable *, struct llentry *);
|
||||
void llentry_unlink(struct llentry *);
|
||||
void llentries_unlink(struct llentries *);
|
||||
size_t llentry_free(struct llentry *);
|
||||
struct llentry *llentry_alloc(struct ifnet *, struct lltable *,
|
||||
struct sockaddr_storage *);
|
||||
|
@ -78,9 +78,6 @@ static int in_difaddr_ioctl(caddr_t, struct ifnet *, struct thread *);
|
||||
static void in_socktrim(struct sockaddr_in *);
|
||||
static void in_purgemaddrs(struct ifnet *);
|
||||
|
||||
static void in_lltable_link(struct lltable *llt, struct llentry *lle);
|
||||
static void in_lltable_unlink(struct llentry *lle);
|
||||
|
||||
static VNET_DEFINE(int, nosameprefix);
|
||||
#define V_nosameprefix VNET(nosameprefix)
|
||||
SYSCTL_INT(_net_inet_ip, OID_AUTO, no_same_prefix, CTLFLAG_VNET | CTLFLAG_RW,
|
||||
@ -1048,9 +1045,11 @@ in_lltable_prefix_free(struct lltable *llt, const struct sockaddr *prefix,
|
||||
const struct sockaddr_in *pfx = (const struct sockaddr_in *)prefix;
|
||||
const struct sockaddr_in *msk = (const struct sockaddr_in *)mask;
|
||||
struct llentry *lle, *next;
|
||||
struct llentries dchain;
|
||||
int i;
|
||||
size_t pkts_dropped;
|
||||
|
||||
LIST_INIT(&dchain);
|
||||
IF_AFDATA_WLOCK(llt->llt_ifp);
|
||||
for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) {
|
||||
LIST_FOREACH_SAFE(lle, &llt->lle_head[i], lle_next, next) {
|
||||
@ -1066,11 +1065,16 @@ in_lltable_prefix_free(struct lltable *llt, const struct sockaddr *prefix,
|
||||
LLE_REMREF(lle);
|
||||
lle->la_flags &= ~LLE_CALLOUTREF;
|
||||
}
|
||||
pkts_dropped = llentry_free(lle);
|
||||
ARPSTAT_ADD(dropped, pkts_dropped);
|
||||
LIST_INSERT_HEAD(&dchain, lle, lle_chain);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Unlink chain */
|
||||
llentries_unlink(&dchain);
|
||||
LIST_FOREACH_SAFE(lle, &dchain, lle_chain, next) {
|
||||
pkts_dropped = llentry_free(lle);
|
||||
ARPSTAT_ADD(dropped, pkts_dropped);
|
||||
}
|
||||
IF_AFDATA_WUNLOCK(llt->llt_ifp);
|
||||
}
|
||||
|
||||
@ -1116,6 +1120,20 @@ in_lltable_rtcheck(struct ifnet *ifp, u_int flags, const struct sockaddr *l3addr
|
||||
return (0);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
in_lltable_hash_dst(const struct in_addr dst)
|
||||
{
|
||||
|
||||
return (dst.s_addr);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
in_lltable_hash(const struct llentry *lle)
|
||||
{
|
||||
|
||||
return (in_lltable_hash_dst(lle->r_l3addr.addr4));
|
||||
}
|
||||
|
||||
static inline struct llentry *
|
||||
in_lltable_find_dst(struct lltable *llt, struct in_addr dst)
|
||||
{
|
||||
@ -1157,7 +1175,7 @@ in_lltable_delete(struct lltable *llt, u_int flags,
|
||||
LLE_WLOCK(lle);
|
||||
lle->la_flags |= LLE_DELETED;
|
||||
EVENTHANDLER_INVOKE(lle_event, lle, LLENTRY_DELETED);
|
||||
in_lltable_unlink(lle);
|
||||
llentry_unlink(lle);
|
||||
#ifdef DIAGNOSTIC
|
||||
log(LOG_INFO, "ifaddr cache = %p is deleted\n", lle);
|
||||
#endif
|
||||
@ -1210,40 +1228,12 @@ in_lltable_create(struct lltable *llt, u_int flags, const struct sockaddr *l3add
|
||||
lle->la_flags |= (LLE_VALID | LLE_STATIC);
|
||||
}
|
||||
|
||||
in_lltable_link(llt, lle);
|
||||
llentry_link(llt, lle);
|
||||
LLE_WLOCK(lle);
|
||||
|
||||
return (lle);
|
||||
}
|
||||
|
||||
static void
|
||||
in_lltable_link(struct lltable *llt, struct llentry *lle)
|
||||
{
|
||||
struct in_addr dst;
|
||||
struct llentries *lleh;
|
||||
u_int hashkey;
|
||||
|
||||
dst = lle->r_l3addr.addr4;
|
||||
hashkey = dst.s_addr;
|
||||
lleh = &llt->lle_head[LLATBL_HASH(hashkey, LLTBL_HASHMASK)];
|
||||
|
||||
lle->lle_tbl = llt;
|
||||
lle->lle_head = lleh;
|
||||
lle->la_flags |= LLE_LINKED;
|
||||
LIST_INSERT_HEAD(lleh, lle, lle_next);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
in_lltable_unlink(struct llentry *lle)
|
||||
{
|
||||
|
||||
LIST_REMOVE(lle, lle_next);
|
||||
lle->la_flags &= ~(LLE_VALID | LLE_LINKED);
|
||||
lle->lle_tbl = NULL;
|
||||
lle->lle_head = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return NULL if not found or marked for deletion.
|
||||
* If found return lle read locked.
|
||||
@ -1363,6 +1353,7 @@ in_domifattach(struct ifnet *ifp)
|
||||
llt->llt_create = in_lltable_create;
|
||||
llt->llt_delete = in_lltable_delete;
|
||||
llt->llt_dump = in_lltable_dump;
|
||||
llt->llt_hash = in_lltable_hash;
|
||||
}
|
||||
ii->ii_llt = llt;
|
||||
|
||||
|
@ -149,9 +149,6 @@ static int in6_update_ifa_internal(struct ifnet *, struct in6_aliasreq *,
|
||||
static int in6_broadcast_ifa(struct ifnet *, struct in6_aliasreq *,
|
||||
struct in6_ifaddr *, int);
|
||||
|
||||
static void in6_lltable_link(struct lltable *llt, struct llentry *lle);
|
||||
static void in6_lltable_unlink(struct llentry *lle);
|
||||
|
||||
#define ifa2ia6(ifa) ((struct in6_ifaddr *)(ifa))
|
||||
#define ia62ifa(ia6) (&((ia6)->ia_ifa))
|
||||
|
||||
@ -2094,6 +2091,7 @@ in6_lltable_prefix_free(struct lltable *llt, const struct sockaddr *prefix,
|
||||
{
|
||||
const struct sockaddr_in6 *pfx = (const struct sockaddr_in6 *)prefix;
|
||||
const struct sockaddr_in6 *msk = (const struct sockaddr_in6 *)mask;
|
||||
struct llentries dchain;
|
||||
struct llentry *lle, *next;
|
||||
int i;
|
||||
|
||||
@ -2101,6 +2099,7 @@ in6_lltable_prefix_free(struct lltable *llt, const struct sockaddr *prefix,
|
||||
* (flags & LLE_STATIC) means deleting all entries
|
||||
* including static ND6 entries.
|
||||
*/
|
||||
LIST_INIT(&dchain);
|
||||
IF_AFDATA_WLOCK(llt->llt_ifp);
|
||||
for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) {
|
||||
LIST_FOREACH_SAFE(lle, &llt->lle_head[i], lle_next, next) {
|
||||
@ -2114,10 +2113,13 @@ in6_lltable_prefix_free(struct lltable *llt, const struct sockaddr *prefix,
|
||||
LLE_REMREF(lle);
|
||||
lle->la_flags &= ~LLE_CALLOUTREF;
|
||||
}
|
||||
llentry_free(lle);
|
||||
LIST_INSERT_HEAD(&dchain, lle, lle_chain);
|
||||
}
|
||||
}
|
||||
}
|
||||
llentries_unlink(&dchain);
|
||||
LIST_FOREACH_SAFE(lle, &dchain, lle_chain, next)
|
||||
llentry_free(lle);
|
||||
IF_AFDATA_WUNLOCK(llt->llt_ifp);
|
||||
}
|
||||
|
||||
@ -2158,6 +2160,20 @@ in6_lltable_rtcheck(struct ifnet *ifp,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
in6_lltable_hash_dst(const struct in6_addr *dst)
|
||||
{
|
||||
|
||||
return (dst->s6_addr32[3]);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
in6_lltable_hash(const struct llentry *lle)
|
||||
{
|
||||
|
||||
return (in6_lltable_hash_dst(&lle->r_l3addr.addr6));
|
||||
}
|
||||
|
||||
static inline struct llentry *
|
||||
in6_lltable_find_dst(struct lltable *llt, const struct in6_addr *dst)
|
||||
{
|
||||
@ -2165,7 +2181,7 @@ in6_lltable_find_dst(struct lltable *llt, const struct in6_addr *dst)
|
||||
struct llentries *lleh;
|
||||
u_int hashkey;
|
||||
|
||||
hashkey = dst->s6_addr32[3];
|
||||
hashkey = in6_lltable_hash_dst(dst);
|
||||
lleh = &llt->lle_head[LLATBL_HASH(hashkey, LLTBL_HASHMASK)];
|
||||
LIST_FOREACH(lle, lleh, lle_next) {
|
||||
if (IN6_ARE_ADDR_EQUAL(&lle->r_l3addr.addr6, dst) != 0)
|
||||
@ -2194,7 +2210,7 @@ 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;
|
||||
in6_lltable_unlink(lle);
|
||||
llentry_unlink(lle);
|
||||
#ifdef DIAGNOSTIC
|
||||
log(LOG_INFO, "ifaddr cache = %p is deleted\n", lle);
|
||||
#endif
|
||||
@ -2246,41 +2262,12 @@ in6_lltable_create(struct lltable *llt, u_int flags,
|
||||
lle->la_flags |= (LLE_VALID | LLE_STATIC);
|
||||
}
|
||||
|
||||
in6_lltable_link(llt, lle);
|
||||
llentry_link(llt, lle);
|
||||
LLE_WLOCK(lle);
|
||||
|
||||
return (lle);
|
||||
}
|
||||
|
||||
static void
|
||||
in6_lltable_link(struct lltable *llt, struct llentry *lle)
|
||||
{
|
||||
struct in6_addr dst;
|
||||
struct llentries *lleh;
|
||||
u_int hashkey;
|
||||
|
||||
dst = lle->r_l3addr.addr6;;
|
||||
hashkey = dst.s6_addr32[3];
|
||||
lleh = &llt->lle_head[LLATBL_HASH(hashkey, LLTBL_HASHMASK)];
|
||||
|
||||
lle->lle_tbl = llt;
|
||||
lle->lle_head = lleh;
|
||||
lle->la_flags |= LLE_LINKED;
|
||||
LIST_INSERT_HEAD(lleh, lle, lle_next);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
in6_lltable_unlink(struct llentry *lle)
|
||||
{
|
||||
|
||||
LIST_REMOVE(lle, lle_next);
|
||||
lle->la_flags &= ~(LLE_VALID | LLE_LINKED);
|
||||
lle->lle_tbl = NULL;
|
||||
lle->lle_head = NULL;
|
||||
}
|
||||
|
||||
|
||||
static struct llentry *
|
||||
in6_lltable_lookup(struct lltable *llt, u_int flags,
|
||||
const struct sockaddr *l3addr)
|
||||
@ -2421,6 +2408,7 @@ in6_domifattach(struct ifnet *ifp)
|
||||
ext->lltable->llt_create = in6_lltable_create;
|
||||
ext->lltable->llt_delete = in6_lltable_delete;
|
||||
ext->lltable->llt_dump = in6_lltable_dump;
|
||||
ext->lltable->llt_hash = in6_lltable_hash;
|
||||
}
|
||||
|
||||
ext->mld_ifinfo = mld_domifattach(ifp);
|
||||
|
Loading…
Reference in New Issue
Block a user