* Allocate hash tables separately
* Make llt_hash() callback more flexible * Default hash size and hashing method is now per-af * Move lltable allocation to separate function
This commit is contained in:
parent
df485dbe3e
commit
3a7498636a
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/projects/routing/; revision=276712
@ -94,7 +94,7 @@ lltable_foreach_lle(struct lltable *llt, llt_foreach_cb_t *f, void *farg)
|
||||
|
||||
error = 0;
|
||||
|
||||
for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) {
|
||||
for (i = 0; i < llt->llt_hsize; i++) {
|
||||
LIST_FOREACH_SAFE(lle, &llt->lle_head[i], lle_next, next) {
|
||||
error = f(llt, lle, farg);
|
||||
if (error != 0)
|
||||
@ -151,15 +151,15 @@ static void
|
||||
llentry_link(struct lltable *llt, struct llentry *lle)
|
||||
{
|
||||
struct llentries *lleh;
|
||||
uint32_t hashkey;
|
||||
uint32_t hashidx;
|
||||
|
||||
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)];
|
||||
hashidx = llt->llt_hash(lle, llt->llt_hsize);
|
||||
lleh = &llt->lle_head[hashidx];
|
||||
|
||||
lle->lle_tbl = llt;
|
||||
lle->lle_head = lleh;
|
||||
@ -274,10 +274,28 @@ lltable_free_cb(struct lltable *llt, struct llentry *lle, void *farg)
|
||||
return (0);
|
||||
}
|
||||
|
||||
struct lltable *
|
||||
lltable_allocate_htbl(uint32_t hsize)
|
||||
{
|
||||
struct lltable *llt;
|
||||
int i;
|
||||
|
||||
llt = malloc(sizeof(struct lltable), M_LLTABLE, M_WAITOK | M_ZERO);
|
||||
llt->llt_hsize = hsize;
|
||||
llt->lle_head = malloc(sizeof(struct llentries) * hsize,
|
||||
M_LLTABLE, M_WAITOK | M_ZERO);
|
||||
|
||||
for (i = 0; i < llt->llt_hsize; i++)
|
||||
LIST_INIT(&llt->lle_head[i]);
|
||||
|
||||
return (llt);
|
||||
}
|
||||
|
||||
static void
|
||||
lltable_free_tbl(struct lltable *llt)
|
||||
{
|
||||
|
||||
free(llt->lle_head, M_LLTABLE);
|
||||
free(llt, M_LLTABLE);
|
||||
}
|
||||
|
||||
@ -370,7 +388,7 @@ lltable_drain(int af)
|
||||
if (llt->llt_af != af)
|
||||
continue;
|
||||
|
||||
for (i=0; i < LLTBL_HASHTBL_SIZE; i++) {
|
||||
for (i=0; i < llt->llt_hsize; i++) {
|
||||
LIST_FOREACH(lle, &llt->lle_head[i], lle_next) {
|
||||
LLE_WLOCK(lle);
|
||||
if (lle->la_hold) {
|
||||
@ -703,7 +721,7 @@ llatbl_llt_show(struct lltable *llt)
|
||||
db_printf("llt=%p llt_af=%d llt_ifp=%p\n",
|
||||
llt, llt->llt_af, llt->llt_ifp);
|
||||
|
||||
for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) {
|
||||
for (i = 0; i < llt->llt_hsize; i++) {
|
||||
LIST_FOREACH(lle, &llt->lle_head[i], lle_next) {
|
||||
|
||||
llatbl_lle_show((struct llentry_sa *)lle);
|
||||
|
@ -35,24 +35,13 @@ extern struct rwlock lltable_rwlock;
|
||||
#define LLTABLE_WUNLOCK() rw_wunlock(&lltable_rwlock)
|
||||
#define LLTABLE_LOCK_ASSERT() rw_assert(&lltable_rwlock, RA_LOCKED)
|
||||
|
||||
#ifndef LLTBL_HASHTBL_SIZE
|
||||
#define LLTBL_HASHTBL_SIZE 32 /* default 32 ? */
|
||||
#endif
|
||||
|
||||
#ifndef LLTBL_HASHMASK
|
||||
#define LLTBL_HASHMASK (LLTBL_HASHTBL_SIZE - 1)
|
||||
#endif
|
||||
|
||||
#define LLATBL_HASH(key, mask) \
|
||||
(((((((key >> 8) ^ key) >> 8) ^ key) >> 8) ^ key) & mask)
|
||||
|
||||
typedef struct llentry *(llt_lookup_t)(struct lltable *, u_int flags,
|
||||
const void *paddr);
|
||||
typedef struct llentry *(llt_create_t)(struct lltable *, u_int flags,
|
||||
const void *paddr);
|
||||
typedef int (llt_dump_entry_t)(struct lltable *, struct llentry *,
|
||||
struct sysctl_req *);
|
||||
typedef uint32_t (llt_hash_t)(const struct llentry *);
|
||||
typedef uint32_t (llt_hash_t)(const struct llentry *, uint32_t);
|
||||
typedef int (llt_match_prefix_t)(const struct sockaddr *,
|
||||
const struct sockaddr *, u_int, struct llentry *);
|
||||
typedef void (llt_clear_entry_t)(struct lltable *, struct llentry *);
|
||||
@ -70,8 +59,9 @@ typedef int (llt_foreach_entry_t)(struct lltable *, llt_foreach_cb_t *, void *);
|
||||
|
||||
struct lltable {
|
||||
SLIST_ENTRY(lltable) llt_link;
|
||||
struct llentries lle_head[LLTBL_HASHTBL_SIZE];
|
||||
int llt_af;
|
||||
int llt_hsize;
|
||||
struct llentries *lle_head;
|
||||
struct ifnet *llt_ifp;
|
||||
|
||||
llt_lookup_t *llt_lookup;
|
||||
@ -93,6 +83,7 @@ MALLOC_DECLARE(M_LLTABLE);
|
||||
|
||||
void lltable_link(struct lltable *llt);
|
||||
void lltable_free(struct lltable *llt);
|
||||
struct lltable *lltable_allocate_htbl(uint32_t hsize);
|
||||
|
||||
/* helper functions */
|
||||
size_t lltable_drop_entry_queue(struct llentry *);
|
||||
|
@ -989,6 +989,11 @@ in_purgemaddrs(struct ifnet *ifp)
|
||||
IN_MULTI_UNLOCK();
|
||||
}
|
||||
|
||||
|
||||
#define IN_LLTBL_DEFAULT_HSIZE 32
|
||||
#define IN_LLTBL_HASH(k, h) \
|
||||
(((((((k >> 8) ^ k) >> 8) ^ k) >> 8) ^ k) & ((h) - 1))
|
||||
|
||||
/*
|
||||
* Frees unlinked record.
|
||||
* This function is called by the timer functions
|
||||
@ -1086,17 +1091,17 @@ in_lltable_rtcheck(struct ifnet *ifp, u_int flags, struct in_addr dst)
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
in_lltable_hash_dst(const struct in_addr dst)
|
||||
in_lltable_hash_dst(const struct in_addr dst, uint32_t hsize)
|
||||
{
|
||||
|
||||
return (dst.s_addr);
|
||||
return (IN_LLTBL_HASH(dst.s_addr, hsize));
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
in_lltable_hash(const struct llentry *lle)
|
||||
in_lltable_hash(const struct llentry *lle, uint32_t hsize)
|
||||
{
|
||||
|
||||
return (in_lltable_hash_dst(lle->r_l3addr.addr4));
|
||||
return (in_lltable_hash_dst(lle->r_l3addr.addr4, hsize));
|
||||
}
|
||||
|
||||
static const void *
|
||||
@ -1126,10 +1131,10 @@ in_lltable_find_dst(struct lltable *llt, struct in_addr dst)
|
||||
{
|
||||
struct llentry *lle;
|
||||
struct llentries *lleh;
|
||||
u_int hashkey;
|
||||
u_int hashidx;
|
||||
|
||||
hashkey = dst.s_addr;
|
||||
lleh = &llt->lle_head[LLATBL_HASH(hashkey, LLTBL_HASHMASK)];
|
||||
hashidx = in_lltable_hash_dst(dst, llt->llt_hsize);
|
||||
lleh = &llt->lle_head[hashidx];
|
||||
LIST_FOREACH(lle, lleh, lle_next) {
|
||||
if (lle->r_l3addr.addr4.s_addr == dst.s_addr)
|
||||
break;
|
||||
@ -1256,18 +1261,14 @@ in_lltable_dump_entry(struct lltable *llt, struct llentry *lle,
|
||||
return (error);
|
||||
}
|
||||
|
||||
void *
|
||||
in_domifattach(struct ifnet *ifp)
|
||||
static struct lltable *
|
||||
in_lltattach(struct ifnet *ifp)
|
||||
{
|
||||
struct in_ifinfo *ii;
|
||||
struct lltable *llt;
|
||||
int i;
|
||||
|
||||
llt = malloc(sizeof(struct lltable), M_LLTABLE, M_WAITOK | M_ZERO);
|
||||
llt = lltable_allocate_htbl(IN_LLTBL_DEFAULT_HSIZE);
|
||||
llt->llt_af = AF_INET;
|
||||
llt->llt_ifp = ifp;
|
||||
for (i = 0; i < LLTBL_HASHTBL_SIZE; i++)
|
||||
LIST_INIT(&llt->lle_head[i]);
|
||||
|
||||
llt->llt_lookup = in_lltable_lookup;
|
||||
llt->llt_create = in_lltable_create;
|
||||
@ -1280,8 +1281,16 @@ in_domifattach(struct ifnet *ifp)
|
||||
llt->llt_prepare_static_entry = arp_lltable_prepare_static_entry;
|
||||
lltable_link(llt);
|
||||
|
||||
return (llt);
|
||||
}
|
||||
|
||||
void *
|
||||
in_domifattach(struct ifnet *ifp)
|
||||
{
|
||||
struct in_ifinfo *ii;
|
||||
|
||||
ii = malloc(sizeof(struct in_ifinfo), M_IFADDR, M_WAITOK|M_ZERO);
|
||||
ii->ii_llt = llt;
|
||||
ii->ii_llt = in_lltattach(ifp);
|
||||
ii->ii_igmp = igmp_domifattach(ifp);
|
||||
|
||||
return ii;
|
||||
|
@ -2047,6 +2047,10 @@ in6_if2idlen(struct ifnet *ifp)
|
||||
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#define IN6_LLTBL_DEFAULT_HSIZE 32
|
||||
#define IN6_LLTBL_HASH(k, h) \
|
||||
(((((((k >> 8) ^ k) >> 8) ^ k) >> 8) ^ k) & ((h) - 1))
|
||||
|
||||
/*
|
||||
* Frees already unlinked @lle.
|
||||
*/
|
||||
@ -2133,17 +2137,17 @@ in6_lltable_rtcheck(struct ifnet *ifp,
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
in6_lltable_hash_dst(const struct in6_addr *dst)
|
||||
in6_lltable_hash_dst(const struct in6_addr *dst, uint32_t hsize)
|
||||
{
|
||||
|
||||
return (dst->s6_addr32[3]);
|
||||
return (IN6_LLTBL_HASH(dst->s6_addr32[3], hsize));
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
in6_lltable_hash(const struct llentry *lle)
|
||||
in6_lltable_hash(const struct llentry *lle, uint32_t hsize)
|
||||
{
|
||||
|
||||
return (in6_lltable_hash_dst(&lle->r_l3addr.addr6));
|
||||
return (in6_lltable_hash_dst(&lle->r_l3addr.addr6, hsize));
|
||||
}
|
||||
|
||||
static const void *
|
||||
@ -2173,10 +2177,10 @@ in6_lltable_find_dst(struct lltable *llt, const struct in6_addr *dst)
|
||||
{
|
||||
struct llentry *lle;
|
||||
struct llentries *lleh;
|
||||
u_int hashkey;
|
||||
u_int hashidx;
|
||||
|
||||
hashkey = in6_lltable_hash_dst(dst);
|
||||
lleh = &llt->lle_head[LLATBL_HASH(hashkey, LLTBL_HASHMASK)];
|
||||
hashidx = in6_lltable_hash_dst(dst, llt->llt_hsize);
|
||||
lleh = &llt->lle_head[hashidx];
|
||||
LIST_FOREACH(lle, lleh, lle_next) {
|
||||
if (IN6_ARE_ADDR_EQUAL(&lle->r_l3addr.addr6, dst) != 0)
|
||||
break;
|
||||
@ -2307,12 +2311,33 @@ in6_lltable_dump_entry(struct lltable *llt, struct llentry *lle,
|
||||
return (error);
|
||||
}
|
||||
|
||||
static struct lltable *
|
||||
in6_lltattach(struct ifnet *ifp)
|
||||
{
|
||||
struct lltable *llt;
|
||||
|
||||
llt = lltable_allocate_htbl(IN6_LLTBL_DEFAULT_HSIZE);
|
||||
llt->llt_af = AF_INET6;
|
||||
llt->llt_ifp = ifp;
|
||||
|
||||
llt->llt_lookup = in6_lltable_lookup;
|
||||
llt->llt_create = in6_lltable_create;
|
||||
llt->llt_dump_entry = in6_lltable_dump_entry;
|
||||
llt->llt_hash = in6_lltable_hash;
|
||||
llt->llt_get_sa_addr = in6_lltable_get_sa_addr;
|
||||
llt->llt_fill_sa_entry = in6_lltable_fill_sa_entry;
|
||||
llt->llt_clear_entry = nd6_lltable_clear_entry;
|
||||
llt->llt_match_prefix = in6_lltable_match_prefix;
|
||||
llt->llt_prepare_static_entry = nd6_lltable_prepare_static_entry;
|
||||
lltable_link(llt);
|
||||
|
||||
return (llt);
|
||||
}
|
||||
|
||||
void *
|
||||
in6_domifattach(struct ifnet *ifp)
|
||||
{
|
||||
struct in6_ifextra *ext;
|
||||
struct lltable *llt;
|
||||
int i;
|
||||
|
||||
/* There are not IPv6-capable interfaces. */
|
||||
switch (ifp->if_type) {
|
||||
@ -2338,24 +2363,7 @@ in6_domifattach(struct ifnet *ifp)
|
||||
ext->nd_ifinfo = nd6_ifattach(ifp);
|
||||
ext->scope6_id = scope6_ifattach(ifp);
|
||||
|
||||
llt = malloc(sizeof(struct lltable), M_LLTABLE, M_WAITOK | M_ZERO);
|
||||
llt->llt_af = AF_INET6;
|
||||
llt->llt_ifp = ifp;
|
||||
for (i = 0; i < LLTBL_HASHTBL_SIZE; i++)
|
||||
LIST_INIT(&llt->lle_head[i]);
|
||||
|
||||
llt->llt_lookup = in6_lltable_lookup;
|
||||
llt->llt_create = in6_lltable_create;
|
||||
llt->llt_dump_entry = in6_lltable_dump_entry;
|
||||
llt->llt_hash = in6_lltable_hash;
|
||||
llt->llt_get_sa_addr = in6_lltable_get_sa_addr;
|
||||
llt->llt_fill_sa_entry = in6_lltable_fill_sa_entry;
|
||||
llt->llt_clear_entry = nd6_lltable_clear_entry;
|
||||
llt->llt_match_prefix = in6_lltable_match_prefix;
|
||||
llt->llt_prepare_static_entry = nd6_lltable_prepare_static_entry;
|
||||
lltable_link(llt);
|
||||
ext->lltable = llt;
|
||||
|
||||
ext->lltable = in6_lltattach(ifp);
|
||||
ext->mld_ifinfo = mld_domifattach(ifp);
|
||||
|
||||
return ext;
|
||||
|
Loading…
Reference in New Issue
Block a user