Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 7 Dec 2014 17:32:07 +0000 (UTC)
From:      "Alexander V. Chernikov" <melifaro@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r275578 - in projects/routing/sys: net netinet netinet6
Message-ID:  <201412071732.sB7HW7jk018130@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: melifaro
Date: Sun Dec  7 17:32:06 2014
New Revision: 275578
URL: https://svnweb.freebsd.org/changeset/base/275578

Log:
  Do not enforce particular lle storage scheme:
  * move lltable allocation to per-domain callbacks.
  * make llentry_link/unlink functions overridable llt methods.
  * make hash table traversal another overridable llt method.

Modified:
  projects/routing/sys/net/if_llatbl.c
  projects/routing/sys/net/if_llatbl.h
  projects/routing/sys/netinet/if_ether.c
  projects/routing/sys/netinet/in.c
  projects/routing/sys/netinet/toecore.c
  projects/routing/sys/netinet6/in6.c
  projects/routing/sys/netinet6/nd6.c

Modified: projects/routing/sys/net/if_llatbl.c
==============================================================================
--- projects/routing/sys/net/if_llatbl.c	Sun Dec  7 15:42:46 2014	(r275577)
+++ projects/routing/sys/net/if_llatbl.c	Sun Dec  7 17:32:06 2014	(r275578)
@@ -71,14 +71,46 @@ 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);
+/* Default lltable methods */
+static void llentry_link(struct lltable *llt, struct llentry *lle);
+static void llentry_unlink(struct llentry *lle);
+static int lltable_foreach_lle(struct lltable *llt, llt_foreach_cb_t *f,
+    void *farg);
+static void lltable_free_tbl(struct lltable *llt);
+
+/*
+ * Runs specified callback for each entry in @llt.
+ * Called does the locking.
+ *
+ */
+static int
+lltable_foreach_lle(struct lltable *llt, llt_foreach_cb_t *f, void *farg)
+{
+	struct llentry *lle, *next;
+	int i, error;
+
+	error = 0;
+
+	for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) {
+		LIST_FOREACH_SAFE(lle, &llt->lle_head[i], lle_next, next) {
+			error = f(llt, lle, farg);
+			if (error != 0)
+				break;
+		}
+	}
+
+	return (error);
+}
+
 /*
  * Dump lle state for a specific address family.
  */
 static int
 lltable_dump_af(struct lltable *llt, struct sysctl_req *wr)
 {
-	struct llentry *lle;
-	int i, error;
+	int error;
 
 	LLTABLE_LOCK_ASSERT();
 
@@ -87,13 +119,8 @@ lltable_dump_af(struct lltable *llt, str
 	error = 0;
 
 	IF_AFDATA_CFG_RLOCK(llt->llt_ifp);
-	for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) {
-		LIST_FOREACH(lle, &llt->lle_head[i], lle_next) {
-			error = llt->llt_dump_entry(llt, lle, wr);
-			if (error != 0)
-				break;
-		}
-	}
+	error = lltable_foreach_lle(llt,
+	    (llt_foreach_cb_t *)llt->llt_dump_entry, wr);
 	IF_AFDATA_CFG_RUNLOCK(llt->llt_ifp);
 
 	return (error);
@@ -119,7 +146,7 @@ done:
 }
 
 
-void
+static void
 llentry_link(struct lltable *llt, struct llentry *lle)
 {
 	struct llentries *lleh;
@@ -139,7 +166,7 @@ llentry_link(struct lltable *llt, struct
 	LIST_INSERT_HEAD(lleh, lle, lle_next);
 }
 
-void
+static void
 llentry_unlink(struct llentry *lle)
 {
 
@@ -152,14 +179,13 @@ llentry_unlink(struct llentry *lle)
 	}
 }
 
-void
-llentries_unlink(struct llentries *head)
+static void
+llentries_unlink(struct lltable *llt, struct llentries *head)
 {
 	struct llentry *lle, *next;
 
-	LIST_FOREACH_SAFE(lle, head, lle_chain, next) {
-		llentry_unlink(lle);
-	}
+	LIST_FOREACH_SAFE(lle, head, lle_chain, next)
+		llt->llt_unlink_entry(lle);
 }
 
 /*
@@ -236,36 +262,73 @@ llentry_alloc(struct ifnet *ifp, struct 
 /*
  * Free all entries from given table and free itself.
  */
+
+static int
+lltable_free_cb(struct lltable *llt, struct llentry *lle, void *farg)
+{
+	struct llentries *dchain;
+
+	dchain = (struct llentries *)farg;
+
+	LLE_WLOCK(lle);
+	LIST_INSERT_HEAD(dchain, lle, lle_chain);
+
+	return (0);
+}
+
+static void
+lltable_free_tbl(struct lltable *llt)
+{
+
+	free(llt, M_LLTABLE);
+}
+
 void
 lltable_free(struct lltable *llt)
 {
 	struct llentry *lle, *next;
 	struct llentries dchain;
-	int i;
 
 	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_CFG_WLOCK(llt->llt_ifp);
-	for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) {
-		LIST_FOREACH_SAFE(lle, &llt->lle_head[i], lle_next, next) {
-			LLE_WLOCK(lle);
-			LIST_INSERT_HEAD(&dchain, lle, lle_chain);
-		}
-	}
+	/* Push all lles to @dchain */
+	lltable_foreach_lle(llt, lltable_free_cb, &dchain);
+
 	IF_AFDATA_RUN_WLOCK(llt->llt_ifp);
-	llentries_unlink(&dchain);
+	llentries_unlink(llt, &dchain);
 	IF_AFDATA_RUN_WUNLOCK(llt->llt_ifp);
 	IF_AFDATA_CFG_WUNLOCK(llt->llt_ifp);
 
 	LIST_FOREACH_SAFE(lle, &dchain, lle_chain, next)
 		llt->llt_clear_entry(llt, lle);
 
-	free(llt, M_LLTABLE);
+	llt->llt_free_tbl(llt);
+}
+
+struct prefix_match_data {
+	const struct sockaddr *prefix;
+	const struct sockaddr *mask;
+	struct llentries *dchain;
+	u_int flags;
+};
+
+static int
+lltable_prefix_free_cb(struct lltable *llt, struct llentry *lle, void *farg)
+{
+	struct prefix_match_data *pmd;
+
+	pmd = (struct prefix_match_data *)farg;
+
+	if (llt->llt_match_prefix(pmd->prefix, pmd->mask, pmd->flags, lle)) {
+		LLE_WLOCK(lle);
+		LIST_INSERT_HEAD(pmd->dchain, lle, lle_chain);
+	}
+
+	return (0);
 }
 
 static void
@@ -274,20 +337,21 @@ lltable_prefix_free_af(struct lltable *l
 {
 	struct llentries dchain;
 	struct llentry *lle, *next;
-	int i;
+	struct prefix_match_data pmd;
 
 	LIST_INIT(&dchain);
+	memset(&pmd, 0, sizeof(pmd));
+	pmd.prefix = prefix;
+	pmd.mask = mask;
+	pmd.flags = flags;
+	pmd.dchain = &dchain;
+
 	IF_AFDATA_CFG_WLOCK(llt->llt_ifp);
-	for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) {
-		LIST_FOREACH_SAFE(lle, &llt->lle_head[i], lle_next, next) {
-			if (llt->llt_match_prefix(prefix, mask, flags, lle)) {
-				LLE_WLOCK(lle);
-				LIST_INSERT_HEAD(&dchain, lle, lle_chain);
-			}
-		}
-	}
+	/* Push matching lles to chain */
+	lltable_foreach_lle(llt, lltable_prefix_free_cb, &pmd);
+
 	IF_AFDATA_RUN_WLOCK(llt->llt_ifp);
-	llentries_unlink(&dchain);
+	llentries_unlink(llt, &dchain);
 	IF_AFDATA_RUN_WUNLOCK(llt->llt_ifp);
 	IF_AFDATA_CFG_WUNLOCK(llt->llt_ifp);
 
@@ -339,29 +403,36 @@ lltable_prefix_free(int af, struct socka
 	LLTABLE_RUNLOCK();
 }
 
-
-
 /*
- * Create a new lltable.
+ * Links lltable to global llt list.
  */
-struct lltable *
-lltable_init(struct ifnet *ifp, int af)
+void
+lltable_link(struct lltable *llt)
 {
-	struct lltable *llt;
-	register int i;
-
-	llt = malloc(sizeof(struct lltable), M_LLTABLE, M_WAITOK);
 
-	llt->llt_af = af;
-	llt->llt_ifp = ifp;
-	for (i = 0; i < LLTBL_HASHTBL_SIZE; i++)
-		LIST_INIT(&llt->lle_head[i]);
+	/* Provide default verions of hash table methods */
+	if (llt->llt_link_entry == NULL)
+		llt->llt_link_entry = llentry_link;
+	if (llt->llt_unlink_entry == NULL)
+		llt->llt_unlink_entry = llentry_unlink;
+	if (llt->llt_foreach_entry == NULL)
+		llt->llt_foreach_entry = lltable_foreach_lle;
+	if (llt->llt_free_tbl == NULL)
+		llt->llt_free_tbl = lltable_free_tbl;
 
 	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);
 }
 
 /*

Modified: projects/routing/sys/net/if_llatbl.h
==============================================================================
--- projects/routing/sys/net/if_llatbl.h	Sun Dec  7 15:42:46 2014	(r275577)
+++ projects/routing/sys/net/if_llatbl.h	Sun Dec  7 17:32:06 2014	(r275578)
@@ -159,6 +159,13 @@ typedef uint32_t (llt_hash_t)(const stru
 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 *);
+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 *);
+
+typedef int (llt_foreach_cb_t)(struct lltable *, struct llentry *, void *);
+typedef int (llt_foreach_entry_t)(struct lltable *, llt_foreach_cb_t *, void *);
+
 
 struct lltable {
 	SLIST_ENTRY(lltable)	llt_link;
@@ -173,6 +180,10 @@ struct lltable {
 	llt_hash_t		*llt_hash;
 	llt_match_prefix_t	*llt_match_prefix;
 	llt_clear_entry_t	*llt_clear_entry;
+	llt_foreach_entry_t	*llt_foreach_entry;
+	llt_link_entry_t	*llt_link_entry;
+	llt_unlink_entry_t	*llt_unlink_entry;
+	llt_free_tbl_t		*llt_free_tbl;
 };
 
 MALLOC_DECLARE(M_LLTABLE);
@@ -199,7 +210,7 @@ MALLOC_DECLARE(M_LLTABLE);
 #define LLATBL_HASH(key, mask) \
 	(((((((key >> 8) ^ key) >> 8) ^ key) >> 8) ^ key) & mask)
 
-struct lltable *lltable_init(struct ifnet *, int);
+void		lltable_link(struct lltable *);
 void		lltable_free(struct lltable *);
 void		lltable_prefix_free(int, struct sockaddr *,
 		    struct sockaddr *, u_int);
@@ -208,9 +219,6 @@ 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 *);
@@ -242,6 +250,19 @@ lltable_delete_lle(struct lltable *llt, 
 	return llt->llt_delete(llt, flags, l3addr);
 }
 
+static __inline void
+lltable_link_entry(struct lltable *llt, struct llentry *lle)
+{
+
+	llt->llt_link_entry(llt, lle);
+}
+
+static __inline void
+lltable_unlink_entry(struct lltable *llt, struct llentry *lle)
+{
+
+	llt->llt_unlink_entry(lle);
+}
 
 int		lla_rt_output(struct rt_msghdr *, struct rt_addrinfo *);
 

Modified: projects/routing/sys/netinet/if_ether.c
==============================================================================
--- projects/routing/sys/netinet/if_ether.c	Sun Dec  7 15:42:46 2014	(r275577)
+++ projects/routing/sys/netinet/if_ether.c	Sun Dec  7 17:32:06 2014	(r275578)
@@ -291,7 +291,7 @@ arp_lltable_clear_entry(struct lltable *
 		LLE_REMREF(lle);
 
 		IF_AFDATA_RUN_WLOCK(ifp);
-		llentry_unlink(lle);
+		lltable_unlink_entry(llt, lle);
 		IF_AFDATA_RUN_WUNLOCK(ifp);
 		
 		IF_AFDATA_CFG_WUNLOCK(ifp);
@@ -544,7 +544,7 @@ arpresolve_slow(struct ifnet *ifp, int i
 				 * No entry has been found. Link new one.
 				 */
 				IF_AFDATA_RUN_WLOCK(ifp);
-				llentry_link(LLTABLE(ifp), la);
+				lltable_link_entry(LLTABLE(ifp), la);
 				IF_AFDATA_RUN_WUNLOCK(ifp);
 			}
 			IF_AFDATA_CFG_WUNLOCK(ifp);
@@ -1076,7 +1076,7 @@ arp_update_lle_addr(struct arphdr *ah, s
 	la->r_flags |= RLLE_VALID;
 	if ((la->la_flags & LLE_STATIC) == 0)
 		la->la_expire = time_uptime + V_arpt_keep;
-	llentry_link(LLTABLE(ifp), la);
+	lltable_link_entry(LLTABLE(ifp), la);
 	IF_AFDATA_RUN_WUNLOCK(ifp);
 }
 
@@ -1254,7 +1254,7 @@ arp_ifinit(struct ifnet *ifp, struct ifa
 	bcopy(IF_LLADDR(ifp), &lle->ll_addr, ifp->if_addrlen);
 	lle->la_flags |= (LLE_VALID | LLE_STATIC);
 	lle->r_flags |= RLLE_VALID;
-	llentry_link(LLTABLE(ifp), lle);
+	lltable_link_entry(LLTABLE(ifp), lle);
 	IF_AFDATA_RUN_WUNLOCK(ifp);
 
 	IF_AFDATA_CFG_WUNLOCK(ifp);

Modified: projects/routing/sys/netinet/in.c
==============================================================================
--- projects/routing/sys/netinet/in.c	Sun Dec  7 15:42:46 2014	(r275577)
+++ projects/routing/sys/netinet/in.c	Sun Dec  7 17:32:06 2014	(r275578)
@@ -1154,7 +1154,7 @@ in_lltable_delete(struct lltable *llt, u
 		lle->la_flags |= LLE_DELETED;
 		EVENTHANDLER_INVOKE(lle_event, lle, LLENTRY_DELETED);
 		IF_AFDATA_RUN_WLOCK(ifp);
-		llentry_unlink(lle);
+		lltable_unlink_entry(llt, lle);
 		IF_AFDATA_RUN_WUNLOCK(ifp);
 #ifdef DIAGNOSTIC
 		log(LOG_INFO, "ifaddr cache = %p is deleted\n", lle);
@@ -1294,21 +1294,25 @@ in_domifattach(struct ifnet *ifp)
 {
 	struct in_ifinfo *ii;
 	struct lltable *llt;
+	int i;
 
-	ii = malloc(sizeof(struct in_ifinfo), M_IFADDR, M_WAITOK|M_ZERO);
+	llt = malloc(sizeof(struct lltable), M_LLTABLE, M_WAITOK | M_ZERO);
+	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;
+	llt->llt_delete = in_lltable_delete;
+	llt->llt_dump_entry = in_lltable_dump_entry;
+	llt->llt_hash = in_lltable_hash;
+	llt->llt_clear_entry = arp_lltable_clear_entry;
+	llt->llt_match_prefix = in_lltable_match_prefix;
+	lltable_link(llt);
 
-	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_clear_entry = arp_lltable_clear_entry;
-		llt->llt_match_prefix = in_lltable_match_prefix;
-	}
+	ii = malloc(sizeof(struct in_ifinfo), M_IFADDR, M_WAITOK|M_ZERO);
 	ii->ii_llt = llt;
-
 	ii->ii_igmp = igmp_domifattach(ifp);
 
 	return ii;

Modified: projects/routing/sys/netinet/toecore.c
==============================================================================
--- projects/routing/sys/netinet/toecore.c	Sun Dec  7 15:42:46 2014	(r275577)
+++ projects/routing/sys/netinet/toecore.c	Sun Dec  7 17:32:06 2014	(r275578)
@@ -477,7 +477,7 @@ restart:
 			 * No entry has been found. Link new one.
 			 */
 			IF_AFDATA_RUN_WLOCK(ifp);
-			llentry_link(LLTABLE6(ifp), lle);
+			lltable_link_entry(LLTABLE6(ifp), lle);
 			IF_AFDATA_RUN_WUNLOCK(ifp);
 		}
 		IF_AFDATA_CFG_WUNLOCK(ifp);

Modified: projects/routing/sys/netinet6/in6.c
==============================================================================
--- projects/routing/sys/netinet6/in6.c	Sun Dec  7 15:42:46 2014	(r275577)
+++ projects/routing/sys/netinet6/in6.c	Sun Dec  7 17:32:06 2014	(r275578)
@@ -2188,7 +2188,7 @@ in6_lltable_delete(struct lltable *llt, 
 		LLE_WLOCK(lle);
 		lle->la_flags |= LLE_DELETED;
 		IF_AFDATA_RUN_WLOCK(llt->llt_ifp);
-		llentry_unlink(lle);
+		lltable_unlink_entry(llt, lle);
 		IF_AFDATA_RUN_WUNLOCK(llt->llt_ifp);
 #ifdef DIAGNOSTIC
 		log(LOG_INFO, "ifaddr cache = %p is deleted\n", lle);
@@ -2330,6 +2330,8 @@ 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) {
@@ -2354,16 +2356,22 @@ 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_clear_entry = nd6_lltable_clear_entry;
-		ext->lltable->llt_match_prefix = in6_lltable_match_prefix;
-	}
+
+	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_delete = in6_lltable_delete;
+	llt->llt_dump_entry = in6_lltable_dump_entry;
+	llt->llt_hash = in6_lltable_hash;
+	llt->llt_clear_entry = nd6_lltable_clear_entry;
+	llt->llt_match_prefix = in6_lltable_match_prefix;
+	lltable_link(llt);
+	ext->lltable = llt;
 
 	ext->mld_ifinfo = mld_domifattach(ifp);
 

Modified: projects/routing/sys/netinet6/nd6.c
==============================================================================
--- projects/routing/sys/netinet6/nd6.c	Sun Dec  7 15:42:46 2014	(r275577)
+++ projects/routing/sys/netinet6/nd6.c	Sun Dec  7 17:32:06 2014	(r275578)
@@ -1120,7 +1120,7 @@ nd6_lltable_clear_entry(struct lltable *
 		LLE_REMREF(ln);
 
 		IF_AFDATA_RUN_WLOCK(ifp);
-		llentry_unlink(ln);
+		lltable_unlink_entry(llt, ln);
 		IF_AFDATA_RUN_WUNLOCK(ifp);
 		
 		IF_AFDATA_CFG_WUNLOCK(ifp);
@@ -1892,7 +1892,7 @@ nd6_cache_lladdr(struct ifnet *ifp, stru
 		if (r_update != 0) {
 			IF_AFDATA_RUN_WLOCK(ifp);
 			if (is_newentry != 0)
-				llentry_link(LLTABLE6(ifp), ln);
+				lltable_link_entry(LLTABLE6(ifp), ln);
 			if (lladdr != NULL) {
 				bcopy(lladdr, &ln->ll_addr, ifp->if_addrlen);
 				ln->la_flags |= LLE_VALID;
@@ -2197,7 +2197,7 @@ nd6_output_lle(struct ifnet *ifp, struct
 					 * Link new one.
 					 */
 					IF_AFDATA_RUN_WLOCK(ifp);
-					llentry_link(LLTABLE6(ifp), lle);
+					lltable_link_entry(LLTABLE6(ifp), lle);
 					IF_AFDATA_RUN_WUNLOCK(ifp);
 				}
 				IF_AFDATA_CFG_WUNLOCK(ifp);
@@ -2485,7 +2485,7 @@ nd6_add_ifa_lle(struct in6_ifaddr *ia)
 	bcopy(IF_LLADDR(ifp), &ln->ll_addr, ifp->if_addrlen);
 	/* Finally, link our lle to the list */
 	IF_AFDATA_RUN_WLOCK(ifp);
-	llentry_link(LLTABLE6(ifp), ln);
+	lltable_link_entry(LLTABLE6(ifp), ln);
 	IF_AFDATA_RUN_WUNLOCK(ifp);
 	IF_AFDATA_CFG_WUNLOCK(ifp);
 



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