svn commit: r275578 - in projects/routing/sys: net netinet netinet6
Alexander V. Chernikov
melifaro at FreeBSD.org
Sun Dec 7 17:32:09 UTC 2014
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);
More information about the svn-src-projects
mailing list