svn commit: r274916 - in projects/routing/sys: net netinet netinet6

Alexander V. Chernikov melifaro at FreeBSD.org
Sun Nov 23 12:15:30 UTC 2014


Author: melifaro
Date: Sun Nov 23 12:15:28 2014
New Revision: 274916
URL: https://svnweb.freebsd.org/changeset/base/274916

Log:
  * Add lltable llt_hash callback
  * Move lltable items insertions/deletions to generic llt code.

Modified:
  projects/routing/sys/net/if_llatbl.c
  projects/routing/sys/net/if_llatbl.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	Sun Nov 23 12:05:49 2014	(r274915)
+++ projects/routing/sys/net/if_llatbl.c	Sun Nov 23 12:15:28 2014	(r274916)
@@ -92,6 +92,42 @@ done:
 	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

Modified: projects/routing/sys/net/if_llatbl.h
==============================================================================
--- projects/routing/sys/net/if_llatbl.h	Sun Nov 23 12:05:49 2014	(r274915)
+++ projects/routing/sys/net/if_llatbl.h	Sun Nov 23 12:15:28 2014	(r274916)
@@ -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 lltabl
 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 *);

Modified: projects/routing/sys/netinet/in.c
==============================================================================
--- projects/routing/sys/netinet/in.c	Sun Nov 23 12:05:49 2014	(r274915)
+++ projects/routing/sys/netinet/in.c	Sun Nov 23 12:15:28 2014	(r274916)
@@ -78,9 +78,6 @@ static int in_difaddr_ioctl(caddr_t, str
 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 *l
 	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 *l
 					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_
 	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
 		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
 		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;
 

Modified: projects/routing/sys/netinet6/in6.c
==============================================================================
--- projects/routing/sys/netinet6/in6.c	Sun Nov 23 12:05:49 2014	(r274915)
+++ projects/routing/sys/netinet6/in6.c	Sun Nov 23 12:15:28 2014	(r274916)
@@ -149,9 +149,6 @@ static int in6_update_ifa_internal(struc
 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 *
 {
 	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 *
 	 * (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 *
 					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
 	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, 
 	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, 
 		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);


More information about the svn-src-projects mailing list