diff --git a/sys/net/if_llatbl.c b/sys/net/if_llatbl.c index 18276f00cd75..b68c19c6f238 100644 --- a/sys/net/if_llatbl.c +++ b/sys/net/if_llatbl.c @@ -70,6 +70,7 @@ static void vnet_lltable_init(void); struct rwlock lltable_rwlock; RW_SYSINIT(lltable_rwlock, &lltable_rwlock, "lltable_rwlock"); +static void lltable_unlink(struct lltable *llt); static void llentries_unlink(struct lltable *llt, struct llentries *head); static void htable_unlink_entry(struct llentry *lle); @@ -138,7 +139,7 @@ htable_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) @@ -160,7 +161,7 @@ htable_link_entry(struct lltable *llt, struct llentry *lle) IF_AFDATA_WLOCK_ASSERT(llt->llt_ifp); - hashidx = llt->llt_hash(lle, LLTBL_HASHTBL_SIZE); + hashidx = llt->llt_hash(lle, llt->llt_hsize); lleh = &llt->lle_head[hashidx]; lle->lle_tbl = llt; @@ -230,6 +231,14 @@ htable_prefix_free(struct lltable *llt, const struct sockaddr *prefix, llt->llt_free_entry(llt, lle); } +static void +htable_free_tbl(struct lltable *llt) +{ + + free(llt->lle_head, M_LLTABLE); + free(llt, M_LLTABLE); +} + static void llentries_unlink(struct lltable *llt, struct llentries *head) { @@ -355,9 +364,7 @@ lltable_free(struct lltable *llt) KASSERT(llt != NULL, ("%s: llt is NULL", __func__)); - LLTABLE_WLOCK(); - SLIST_REMOVE(&V_lltables, llt, lltable, llt_link); - LLTABLE_WUNLOCK(); + lltable_unlink(llt); LIST_INIT(&dchain); IF_AFDATA_WLOCK(llt->llt_ifp); @@ -372,7 +379,7 @@ lltable_free(struct lltable *llt) llentry_free(lle); } - free(llt, M_LLTABLE); + llt->llt_free_tbl(llt); } #if 0 @@ -388,7 +395,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) { @@ -419,20 +426,18 @@ lltable_prefix_free(int af, struct sockaddr *prefix, struct sockaddr *mask, LLTABLE_RUNLOCK(); } -/* - * Create a new lltable. - */ struct lltable * -lltable_init(struct ifnet *ifp, int af) +lltable_allocate_htbl(uint32_t hsize) { struct lltable *llt; - register int i; + int i; - llt = malloc(sizeof(struct lltable), M_LLTABLE, M_WAITOK); + 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); - llt->llt_af = af; - llt->llt_ifp = ifp; - for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) + for (i = 0; i < llt->llt_hsize; i++) LIST_INIT(&llt->lle_head[i]); /* Set some default callbacks */ @@ -440,12 +445,31 @@ lltable_init(struct ifnet *ifp, int af) llt->llt_unlink_entry = htable_unlink_entry; llt->llt_prefix_free = htable_prefix_free; llt->llt_foreach_entry = htable_foreach_lle; + llt->llt_free_tbl = htable_free_tbl; + + return (llt); +} + +/* + * Links lltable to global llt list. + */ +void +lltable_link(struct lltable *llt) +{ LLTABLE_WLOCK(); SLIST_INSERT_HEAD(&V_lltables, llt, llt_link); LLTABLE_WUNLOCK(); +} + +static void +lltable_unlink(struct lltable *llt) +{ + + LLTABLE_WLOCK(); + SLIST_REMOVE(&V_lltables, llt, lltable, llt_link); + LLTABLE_WUNLOCK(); - return (llt); } /* @@ -685,7 +709,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); diff --git a/sys/net/if_llatbl.h b/sys/net/if_llatbl.h index 8ea711c28175..084f61c17e35 100644 --- a/sys/net/if_llatbl.h +++ b/sys/net/if_llatbl.h @@ -138,14 +138,6 @@ struct llentry { #define L3_ADDR(lle) ((struct sockaddr *)(&lle[1])) #define L3_ADDR_LEN(lle) (((struct sockaddr *)(&lle[1]))->sa_len) -#ifndef LLTBL_HASHTBL_SIZE -#define LLTBL_HASHTBL_SIZE 32 /* default 32 ? */ -#endif - -#ifndef LLTBL_HASHMASK -#define LLTBL_HASHMASK (LLTBL_HASHTBL_SIZE - 1) -#endif - typedef struct llentry *(llt_lookup_t)(struct lltable *, u_int flags, const struct sockaddr *l3addr); typedef struct llentry *(llt_create_t)(struct lltable *, u_int flags, @@ -161,6 +153,7 @@ typedef int (llt_match_prefix_t)(const struct sockaddr *, const struct sockaddr *, u_int, struct llentry *); typedef void (llt_free_entry_t)(struct lltable *, struct llentry *); typedef void (llt_fill_sa_entry_t)(const struct llentry *, struct sockaddr *); +typedef void (llt_free_tbl_t)(struct lltable *); typedef void (llt_link_entry_t)(struct lltable *, struct llentry *); typedef void (llt_unlink_entry_t)(struct llentry *); @@ -169,8 +162,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; @@ -185,6 +179,7 @@ struct lltable { llt_link_entry_t *llt_link_entry; llt_unlink_entry_t *llt_unlink_entry; llt_fill_sa_entry_t *llt_fill_sa_entry; + llt_free_tbl_t *llt_free_tbl; }; MALLOC_DECLARE(M_LLTABLE); @@ -204,8 +199,9 @@ MALLOC_DECLARE(M_LLTABLE); #define LLATBL_HASH(key, mask) \ (((((((key >> 8) ^ key) >> 8) ^ key) >> 8) ^ key) & mask) -struct lltable *lltable_init(struct ifnet *, int); +struct lltable *lltable_allocate_htbl(uint32_t hsize); void lltable_free(struct lltable *); +void lltable_link(struct lltable *llt); void lltable_prefix_free(int, struct sockaddr *, struct sockaddr *, u_int); #if 0 diff --git a/sys/netinet/in.c b/sys/netinet/in.c index 5f3620a1f958..746fe691c232 100644 --- a/sys/netinet/in.c +++ b/sys/netinet/in.c @@ -1159,7 +1159,7 @@ in_lltable_find_dst(struct lltable *llt, struct in_addr dst) struct sockaddr_in *sin; u_int hashidx; - hashidx = in_lltable_hash_dst(dst, LLTBL_HASHTBL_SIZE); + hashidx = in_lltable_hash_dst(dst, llt->llt_hsize); lleh = &llt->lle_head[hashidx]; LIST_FOREACH(lle, lleh, lle_next) { sin = satosin(L3_ADDR(lle)); @@ -1342,30 +1342,39 @@ in_lltable_dump_entry(struct lltable *llt, struct llentry *lle, return (error); } +static struct lltable * +in_lltattach(struct ifnet *ifp) +{ + struct lltable *llt; + + llt = lltable_allocate_htbl(IN_LLTBL_DEFAULT_HSIZE); + llt->llt_af = AF_INET; + llt->llt_ifp = ifp; + + llt->llt_lookup = in_lltable_lookup; + llt->llt_create = in_lltable_create; + llt->llt_delete = in_lltable_delete; + llt->llt_dump_entry = in_lltable_dump_entry; + llt->llt_hash = in_lltable_hash; + llt->llt_fill_sa_entry = in_lltable_fill_sa_entry; + llt->llt_free_entry = in_lltable_free_entry; + llt->llt_match_prefix = in_lltable_match_prefix; + lltable_link(llt); + + return (llt); +} + void * in_domifattach(struct ifnet *ifp) { struct in_ifinfo *ii; - struct lltable *llt; ii = malloc(sizeof(struct in_ifinfo), M_IFADDR, M_WAITOK|M_ZERO); - llt = lltable_init(ifp, AF_INET); - if (llt != NULL) { - llt->llt_lookup = in_lltable_lookup; - llt->llt_create = in_lltable_create; - llt->llt_delete = in_lltable_delete; - llt->llt_dump_entry = in_lltable_dump_entry; - llt->llt_hash = in_lltable_hash; - llt->llt_fill_sa_entry = in_lltable_fill_sa_entry; - llt->llt_free_entry = in_lltable_free_entry; - llt->llt_match_prefix = in_lltable_match_prefix; - } - ii->ii_llt = llt; - + ii->ii_llt = in_lltattach(ifp); ii->ii_igmp = igmp_domifattach(ifp); - return ii; + return (ii); } void diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index a53ca2b9097e..db83137a2751 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -2199,7 +2199,7 @@ in6_lltable_find_dst(struct lltable *llt, const struct in6_addr *dst) const struct sockaddr_in6 *sin6; u_int hashidx; - hashidx = in6_lltable_hash_dst(dst, LLTBL_HASHTBL_SIZE); + hashidx = in6_lltable_hash_dst(dst, llt->llt_hsize); lleh = &llt->lle_head[hashidx]; LIST_FOREACH(lle, lleh, lle_next) { sin6 = (const struct sockaddr_in6 *)L3_CADDR(lle); @@ -2378,6 +2378,28 @@ 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_delete = in6_lltable_delete; + llt->llt_dump_entry = in6_lltable_dump_entry; + llt->llt_hash = in6_lltable_hash; + llt->llt_fill_sa_entry = in6_lltable_fill_sa_entry; + llt->llt_free_entry = in6_lltable_free_entry; + llt->llt_match_prefix = in6_lltable_match_prefix; + lltable_link(llt); + + return (llt); +} + void * in6_domifattach(struct ifnet *ifp) { @@ -2406,17 +2428,7 @@ in6_domifattach(struct ifnet *ifp) ext->nd_ifinfo = nd6_ifattach(ifp); ext->scope6_id = scope6_ifattach(ifp); - ext->lltable = lltable_init(ifp, AF_INET6); - if (ext->lltable != NULL) { - ext->lltable->llt_lookup = in6_lltable_lookup; - ext->lltable->llt_create = in6_lltable_create; - ext->lltable->llt_delete = in6_lltable_delete; - ext->lltable->llt_dump_entry = in6_lltable_dump_entry; - ext->lltable->llt_hash = in6_lltable_hash; - ext->lltable->llt_fill_sa_entry = in6_lltable_fill_sa_entry; - ext->lltable->llt_free_entry = in6_lltable_free_entry; - ext->lltable->llt_match_prefix = in6_lltable_match_prefix; - } + ext->lltable = in6_lltattach(ifp); ext->mld_ifinfo = mld_domifattach(ifp);