From 9479029b1f5d85d26096a78e97053df9da4e5925 Mon Sep 17 00:00:00 2001 From: "Alexander V. Chernikov" Date: Sun, 23 Nov 2014 12:15:28 +0000 Subject: [PATCH] * Add lltable llt_hash callback * Move lltable items insertions/deletions to generic llt code. --- sys/net/if_llatbl.c | 36 ++++++++++++++++++++++++++ sys/net/if_llatbl.h | 8 ++++-- sys/netinet/in.c | 61 +++++++++++++++++++-------------------------- sys/netinet6/in6.c | 60 ++++++++++++++++++-------------------------- 4 files changed, 92 insertions(+), 73 deletions(-) diff --git a/sys/net/if_llatbl.c b/sys/net/if_llatbl.c index 2788b50d71ee..84c250244add 100644 --- a/sys/net/if_llatbl.c +++ b/sys/net/if_llatbl.c @@ -92,6 +92,42 @@ lltable_sysctl_dumparp(int af, struct sysctl_req *wr) 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 diff --git a/sys/net/if_llatbl.h b/sys/net/if_llatbl.h index ce970809bbb2..9493a932d573 100644 --- a/sys/net/if_llatbl.h +++ b/sys/net/if_llatbl.h @@ -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 lltable *, u_int flags, 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 *); diff --git a/sys/netinet/in.c b/sys/netinet/in.c index 9e96a7298566..e71db5c2a521 100644 --- a/sys/netinet/in.c +++ b/sys/netinet/in.c @@ -78,9 +78,6 @@ static int in_difaddr_ioctl(caddr_t, struct ifnet *, struct thread *); 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 *llt, const struct sockaddr *prefix, 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 *llt, const struct sockaddr *prefix, 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_int flags, const struct sockaddr *l3addr 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_int flags, 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_int flags, const struct sockaddr *l3add 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; diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index 86acce9f6a6c..8678e0a02864 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -149,9 +149,6 @@ static int in6_update_ifa_internal(struct ifnet *, struct in6_aliasreq *, 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 *llt, const struct sockaddr *prefix, { 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 *llt, const struct sockaddr *prefix, * (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 *llt, const struct sockaddr *prefix, 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, const struct in6_addr *dst) 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, u_int flags, 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, u_int flags, 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);