Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 5 Jan 2015 17:23:03 +0000 (UTC)
From:      "Alexander V. Chernikov" <melifaro@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r276712 - in projects/routing/sys: net netinet netinet6
Message-ID:  <201501051723.t05HN3lw031769@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: melifaro
Date: Mon Jan  5 17:23:02 2015
New Revision: 276712
URL: https://svnweb.freebsd.org/changeset/base/276712

Log:
  * 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

Modified:
  projects/routing/sys/net/if_llatbl.c
  projects/routing/sys/net/if_llatbl_var.h
  projects/routing/sys/netinet/in.c
  projects/routing/sys/netinet6/in6.c

Modified: projects/routing/sys/net/if_llatbl.c
==============================================================================
--- projects/routing/sys/net/if_llatbl.c	Mon Jan  5 16:52:25 2015	(r276711)
+++ projects/routing/sys/net/if_llatbl.c	Mon Jan  5 17:23:02 2015	(r276712)
@@ -94,7 +94,7 @@ lltable_foreach_lle(struct lltable *llt,
 
 	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, str
 	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);

Modified: projects/routing/sys/net/if_llatbl_var.h
==============================================================================
--- projects/routing/sys/net/if_llatbl_var.h	Mon Jan  5 16:52:25 2015	(r276711)
+++ projects/routing/sys/net/if_llatbl_var.h	Mon Jan  5 17:23:02 2015	(r276712)
@@ -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
 
 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 *);

Modified: projects/routing/sys/netinet/in.c
==============================================================================
--- projects/routing/sys/netinet/in.c	Mon Jan  5 16:52:25 2015	(r276711)
+++ projects/routing/sys/netinet/in.c	Mon Jan  5 17:23:02 2015	(r276712)
@@ -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_
 }
 
 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 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 *ll
 	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;

Modified: projects/routing/sys/netinet6/in6.c
==============================================================================
--- projects/routing/sys/netinet6/in6.c	Mon Jan  5 16:52:25 2015	(r276711)
+++ projects/routing/sys/netinet6/in6.c	Mon Jan  5 17:23:02 2015	(r276712)
@@ -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
 {
 	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 *l
 	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;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201501051723.t05HN3lw031769>