* Add lltable llt_hash callback

* Move lltable items insertions/deletions to generic llt code.
This commit is contained in:
Alexander V. Chernikov 2014-11-23 12:15:28 +00:00
parent 7c066c18db
commit 9479029b1f
4 changed files with 92 additions and 73 deletions

View File

@ -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

View File

@ -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 *);

View File

@ -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;

View File

@ -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);