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>