Date: Mon, 24 Nov 2008 03:02:00 GMT From: Qing Li <qingli@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 153420 for review Message-ID: <200811240302.mAO320N8080767@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=153420 Change 153420 by qingli@FreeBSD-newarp on 2008/11/24 03:01:52 1. removed the unnecessary lle_mtx as noted by Sam 2. removed the if_lltbls_mtx from the ifnet{} 3. incorporate previous review comments from Gleb Smirnoff 4. the L2 tables (for AF_INET and AF_INET6) now live under the per ifnet{} if_afdata[] member field 5. access to the L2 tables is synchronized through the IF_AFDATA_LOCK 6. changed the if_afdata_mtx to a MTX_RECURSE lock due to the recursive locking challenges in IPv6 Unit Testing: 1. ping (x.x.x.255) 2. ping6 3. arp (various combo of -an, -s, -d, -ad) 4. ndp (various combo of -s, -d) 5. netperf (TCP_STREAM) test Immediate issue to be resolved: Now a global "lltables" is used to track all of L2 tables (both AF_INET and AF_INET6) for dumping these tables (e.g. for "arp" and "ndp" output). Not sure how to synchronize this list. Affected files ... .. //depot/projects/arp-v2/src/sys/net/if.c#7 edit .. //depot/projects/arp-v2/src/sys/net/if_llatbl.c#5 edit .. //depot/projects/arp-v2/src/sys/net/if_llatbl.h#4 edit .. //depot/projects/arp-v2/src/sys/net/if_var.h#8 edit .. //depot/projects/arp-v2/src/sys/netinet/if_ether.c#15 edit .. //depot/projects/arp-v2/src/sys/netinet/in.c#6 edit .. //depot/projects/arp-v2/src/sys/netinet/in_proto.c#3 edit .. //depot/projects/arp-v2/src/sys/netinet/in_var.h#4 edit .. //depot/projects/arp-v2/src/sys/netinet6/icmp6.c#7 edit .. //depot/projects/arp-v2/src/sys/netinet6/in6.c#8 edit .. //depot/projects/arp-v2/src/sys/netinet6/in6_var.h#2 edit .. //depot/projects/arp-v2/src/sys/netinet6/ip6_forward.c#5 edit .. //depot/projects/arp-v2/src/sys/netinet6/ip6_input.c#6 edit .. //depot/projects/arp-v2/src/sys/netinet6/ip6_mroute.c#5 edit .. //depot/projects/arp-v2/src/sys/netinet6/ip6_output.c#7 edit .. //depot/projects/arp-v2/src/sys/netinet6/nd6.c#8 edit .. //depot/projects/arp-v2/src/sys/netinet6/nd6_nbr.c#7 edit .. //depot/projects/arp-v2/src/sys/netinet6/nd6_rtr.c#6 edit Differences ... ==== //depot/projects/arp-v2/src/sys/net/if.c#7 (text+ko) ==== @@ -137,7 +137,7 @@ #endif extern uma_zone_t llezone; -extern uma_zone_t lltzone; +extern struct mtx lltables_mtx; int if_index = 0; int ifqmaxlen = IFQ_MAXLEN; @@ -375,8 +375,6 @@ */ llezone = uma_zcreate("llentry", sizeof(struct llentry), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); - lltzone = uma_zcreate("lltable", sizeof(struct lltable), NULL, NULL, - NULL, NULL, UMA_ALIGN_PTR, 0); } static void @@ -518,13 +516,11 @@ TASK_INIT(&ifp->if_starttask, 0, if_start_deferred, ifp); TASK_INIT(&ifp->if_linktask, 0, do_link_state_change, ifp); IF_AFDATA_LOCK_INIT(ifp); - IF_LLTBLS_LOCK_INIT(ifp); ifp->if_afdata_initialized = 0; TAILQ_INIT(&ifp->if_addrhead); TAILQ_INIT(&ifp->if_prefixhead); TAILQ_INIT(&ifp->if_multiaddrs); - TAILQ_INIT(&ifp->if_lltables); TAILQ_INIT(&ifp->if_groups); if_addgroup(ifp, IFG_ALL); ==== //depot/projects/arp-v2/src/sys/net/if_llatbl.c#5 (text+ko) ==== @@ -22,6 +22,9 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + #include "opt_inet.h" #include "opt_inet6.h" @@ -48,23 +51,27 @@ #include <netinet6/in6_var.h> #include <netinet6/nd6.h> +MALLOC_DEFINE(M_LLTABLE, "lltable", "link level address tables"); uma_zone_t llezone; -uma_zone_t lltzone; + +SLIST_HEAD(, lltable) lltables = SLIST_HEAD_INITIALIZER(lltables); -static struct lltable *lltable_new(struct ifnet *ifp, int af); int sysctl_dumparp(int af, struct sysctl_req *wr); extern void arprequest(struct ifnet *, struct in_addr *, struct in_addr *, u_char *); + static int -dump_llcache(struct ifnet *ifp, int af, struct llentries *head, - struct sysctl_req *wr) +dump_llcache(struct lltable *llt, int af, struct sysctl_req *wr) { + struct ifnet *ifp = llt->llt_ifp; struct llentry *lle; - struct rt_msghdr *rtm; - struct sockaddr_dl *sdl; - uint8_t *msg; - int msgsize, error; + struct rt_msghdr *rtm = NULL; + struct sockaddr_dl *sdl = NULL; + uint8_t *msg = NULL; + int msgsize = 0; + int error = 0; + int i; #ifdef INET struct { struct rt_msghdr rtm; @@ -102,63 +109,71 @@ return EINVAL; } - IF_LLTBLS_LOCK_ASSERT(ifp); + /* XXXXX + * current IFNET_RLOCK() is mapped to IFNET_WLOCK() + * so it is okay to use this ASSERT, change it when + * IFNET lock is finalized + */ + IFNET_WLOCK_ASSERT(); + + for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) { + LIST_FOREACH(lle, &llt->lle_head[i], lle_next) { + if (lle->la_flags & LLE_DELETED) /* skip deleted entries */ + continue; + /* + * produce a msg made of: + * struct rt_msghdr; + * struct sockaddr_inarp; (IPv4) struct sockaddr_in6 (IPv6) + * struct sockaddr_dl; + */ + bzero(msg, msgsize); + rtm->rtm_msglen = msgsize; - error = 0; - LIST_FOREACH(lle, head, lle_next) { - if (lle->la_flags & LLE_DELETED) /* skip deleted entries */ - continue; - /* - * produce a msg made of: - * struct rt_msghdr; - * struct sockaddr_inarp; (IPv4) struct sockaddr_in6 (IPv6) - * struct sockaddr_dl; - */ - bzero(msg, msgsize); - rtm->rtm_msglen = msgsize; - switch (af) { + switch (af) { #ifdef INET - case AF_INET: - arpc.sin.sin_family = AF_INET; - arpc.sin.sin_len = sizeof(arpc.sin); - arpc.sin.sin_addr.s_addr = lle->l3_addr4.sin_addr.s_addr; - break; + case AF_INET: + arpc.sin.sin_family = AF_INET; + arpc.sin.sin_len = sizeof(arpc.sin); + arpc.sin.sin_addr.s_addr = lle->l3_addr4.sin_addr.s_addr; + break; #endif #ifdef INET6 - case AF_INET6: - ndpc.sin6.sin6_family = AF_INET6; - ndpc.sin6.sin6_len = sizeof(ndpc.sin6); - bcopy(&lle->l3_addr6, &ndpc.sin6, lle->l3_addr6.sin6_len); - break; + case AF_INET6: + ndpc.sin6.sin6_family = AF_INET6; + ndpc.sin6.sin6_len = sizeof(ndpc.sin6); + bcopy(&lle->l3_addr6, &ndpc.sin6, lle->l3_addr6.sin6_len); + break; #endif - } - /* publish */ - if (lle->la_flags & LLE_PUB) { - rtm->rtm_flags |= RTF_ANNOUNCE; - /* proxy only */ - if ((af == AF_INET) && (lle->la_flags & LLE_PROXY)) - arpc.sin.sin_other = SIN_PROXY; - } + } + /* publish */ + if (lle->la_flags & LLE_PUB) { + rtm->rtm_flags |= RTF_ANNOUNCE; + /* proxy only */ + if ((af == AF_INET) && (lle->la_flags & LLE_PROXY)) + arpc.sin.sin_other = SIN_PROXY; + } - if (lle->la_flags & LLE_VALID) { /* valid MAC */ - sdl->sdl_family = AF_LINK; - sdl->sdl_len = sizeof(*sdl); - sdl->sdl_alen = ifp->if_addrlen; - sdl->sdl_index = ifp->if_index; - sdl->sdl_type = ifp->if_type; - bcopy(&lle->ll_addr, LLADDR(sdl), ifp->if_addrlen); + if (lle->la_flags & LLE_VALID) { /* valid MAC */ + sdl->sdl_family = AF_LINK; + sdl->sdl_len = sizeof(*sdl); + sdl->sdl_alen = ifp->if_addrlen; + sdl->sdl_index = ifp->if_index; + sdl->sdl_type = ifp->if_type; + bcopy(&lle->ll_addr, LLADDR(sdl), ifp->if_addrlen); + } + rtm->rtm_rmx.rmx_expire = + lle->la_flags & LLE_STATIC ? 0 : lle->la_expire; + rtm->rtm_flags |= (RTF_LLINFO | RTF_HOST); + if (lle->la_flags & LLE_STATIC) + rtm->rtm_flags |= RTF_STATIC; + rtm->rtm_index = ifp->if_index; + error = SYSCTL_OUT(wr, msg, msgsize); + if (error) + break; } - rtm->rtm_rmx.rmx_expire = - lle->la_flags & LLE_STATIC ? 0 : lle->la_expire; - rtm->rtm_flags |= (RTF_LLINFO | RTF_HOST); - if (lle->la_flags & LLE_STATIC) - rtm->rtm_flags |= RTF_STATIC; - rtm->rtm_index = ifp->if_index; - error = SYSCTL_OUT(wr, msg, msgsize); - if (error) - break; } - return error; + + return (error); } /* @@ -168,43 +183,34 @@ sysctl_dumparp(int af, struct sysctl_req *wr) { struct lltable *llt; - struct ifnet *ifp; - int i, error = 0; + int error = 0; IFNET_RLOCK(); - TAILQ_FOREACH(ifp, &V_ifnet, if_link) { - IF_LLTBLS_LOCK(ifp); - TAILQ_FOREACH(llt, &ifp->if_lltables, llt_link) { - if (llt->llt_af != af) - continue; - for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) { - error = dump_llcache(ifp, af, - &llt->lle_head[i], wr); - if (error) { - IF_LLTBLS_UNLOCK(ifp); - goto done; - } - } + SLIST_FOREACH(llt, &lltables, llt_link) { + if (llt->llt_af == af) { + error = dump_llcache(llt, af, wr); + if (error != 0) + goto done; } - IF_LLTBLS_UNLOCK(ifp); } done: IFNET_RUNLOCK(); - return error; + return (error); } /* - * delete an address from the address table + * Deletes an address from the address table. + * This function is called by the timer functions + * such as arptimer() and nd6_llinfo_timer(), and + * the caller does the locking. */ int llentry_free(struct llentry *lle) { + KASSERT(lle != NULL, ("%s: lle is NULL", __func__)); - KASSERT(lle != NULL, ("null lle")); - IF_LLTBLS_LOCK_ASSERT(lle->lle_tbl->llt_ifp); + LIST_REMOVE(lle, lle_next); - LIST_REMOVE(lle, lle_next); - IF_LLE_LOCK_DESTROY(lle); if (lle->la_hold != NULL) m_freem(lle->la_hold); uma_zfree(llezone, lle); @@ -212,130 +218,111 @@ } /* - * delete an address table from the interface ifp + * Free all entries from given table and free itself. + * Since lltables collects from all of the intefaces, + * the caller of this function must acquire IFNET_WLOCK(). */ -int -lltable_free(struct ifnet *ifp, int af) +void lltable_free(struct lltable *llt) { - struct lltable *llt; struct llentry *lle; int i; - KASSERT(ifp != NULL, ("null ifp")); + KASSERT(llt != NULL, ("%s: llt is NULL", __func__)); - IF_LLTBLS_LOCK_ASSERT(ifp); + IFNET_WLOCK(); + SLIST_REMOVE(&lltables, llt, lltable, llt_link); + IFNET_WUNLOCK(); - TAILQ_FOREACH(llt, &ifp->if_lltables, llt_link) { - if (llt->llt_af != af) - continue; - for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) { - LIST_FOREACH(lle, &llt->lle_head[i], lle_next) - llentry_free(lle); + for (i=0; i < LLTBL_HASHTBL_SIZE; i++) { + LIST_FOREACH(lle, &llt->lle_head[i], lle_next) { + callout_drain(&lle->la_timer); + llentry_free(lle); } - TAILQ_REMOVE(&ifp->if_lltables, llt, llt_link); - uma_zfree(lltzone, llt); - break; } - return 0; + + free(llt, M_LLTABLE); } void lltable_drain(int af) { - struct ifnet *ifp; - struct lltable *llt = NULL; - struct llentry *lle; - int i; + struct lltable *llt; + struct llentry *lle; + register int i; + + IFNET_RLOCK(); + SLIST_FOREACH(llt, &lltables, llt_link) { + if (llt->llt_af != af) + continue; - TAILQ_FOREACH(ifp, &ifnet, if_link) { - IF_LLTBLS_LOCK(ifp); - TAILQ_FOREACH(llt, &ifp->if_lltables, llt_link) { - if (llt->llt_af != af) - continue; - for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) { - LIST_FOREACH(lle, &llt->lle_head[i], - lle_next) { - if (lle->la_hold != NULL) { - m_freem(lle->la_hold); - lle->la_hold = NULL; - } + for (i=0; i < LLTBL_HASHTBL_SIZE; i++) { + LIST_FOREACH(lle, &llt->lle_head[i], lle_next) { + if (lle->la_hold) { + m_freem(lle->la_hold); + lle->la_hold = NULL; } } - break; } - IF_LLTBLS_LOCK(ifp); } + IFNET_RUNLOCK(); } + /* - * Add a new table at the head of the list for interface ifp + * Create a new lltable. */ -static struct lltable * -lltable_new(struct ifnet *ifp, int af) +struct lltable * +lltable_init(struct ifnet *ifp, int af) { struct lltable *llt; - int i; + register int i; + + llt = malloc(sizeof(struct lltable), M_LLTABLE, M_WAITOK); + if (llt == NULL) + return (NULL); - /* XXX can this happen? */ - if (ifp == NULL) - return NULL; - llt = uma_zalloc(lltzone, M_DONTWAIT | M_ZERO); - if (llt == NULL) { - log(LOG_INFO, "lltable_new: malloc failed for new lla-table\n"); - return NULL; - } - llt->llt_af = af; + llt->llt_af = af; llt->llt_ifp = ifp; for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) LIST_INIT(&llt->lle_head[i]); - IF_LLTBLS_LOCK_ASSERT(ifp); - TAILQ_INSERT_HEAD(&ifp->if_lltables, llt, llt_link); + IFNET_WLOCK(); + SLIST_INSERT_HEAD(&lltables, llt, llt_link); + IFNET_WUNLOCK(); - return llt; + return (llt); } + /* * Generic link layer address lookup function, replacement * of the old "arplookup" */ struct llentry * -lla_lookup(struct ifnet *ifp, u_int flags, struct sockaddr *l3addr) +lla_lookup(struct lltable *llt, u_int flags, struct sockaddr *l3addr) { - struct llentry *lle; + struct ifnet *ifp; + struct llentry *lle; struct llentries *lleh; - struct lltable *llt; - struct rtentry *rt; + struct rtentry *rt; u_int hashkey; #ifdef INET6 char ip6buf[INET6_ADDRSTRLEN]; #endif - KASSERT(ifp != NULL, ("null ifp")); - KASSERT(l3addr != NULL, ("null L3 address")); + KASSERT(llt != NULL, ("%s: llt is NULL", __func__)); + KASSERT(l3addr != NULL, ("%s: L3 address is NULL", __func__)); - IF_LLTBLS_LOCK_ASSERT(ifp); - - TAILQ_FOREACH(llt, &ifp->if_lltables, llt_link) - if (llt->llt_af == l3addr->sa_family) - break; - if ((flags & LLE_CREATE) && llt == NULL) { - llt = lltable_new(ifp, l3addr->sa_family); - if (llt == NULL) - return NULL; - } - + ifp = llt->llt_ifp; switch (l3addr->sa_family) { -#ifdef INET case AF_INET: hashkey = ((struct sockaddr_in *)l3addr)->sin_addr.s_addr; break; -#endif -#ifdef INET6 + case AF_INET6: hashkey = ((struct sockaddr_in6 *)l3addr)->sin6_addr.s6_addr32[3]; break; -#endif + default: return NULL; } @@ -346,43 +333,40 @@ continue; if (bcmp((void *)&lle->l3_addr, l3addr, l3addr->sa_len) == 0) break; - } + } if (lle == NULL) { if (!(flags & LLE_CREATE)) - return NULL; + return (NULL); /* - * A route that covers the given address must have been - * installed 1st because we are doing a resolution. + * a route that covers the given address must have been + * installed 1st because we are doing a resolution */ if (!(flags & LLE_IFADDR)) { rt = rtalloc1(l3addr, 0, 0); - if (rt == NULL || (rt->rt_flags & RTF_GATEWAY) || - rt->rt_ifp != ifp) { + if ((rt == NULL) || (rt->rt_flags & RTF_GATEWAY) || (rt->rt_ifp != ifp)) { if (l3addr->sa_family == AF_INET6) { /* - * Creating an ND6 cache for an IPv6 - * neighbor that is not covered by our - * own prefix. + * Creating a ND6 cache for an IPv6 neighbor + * that is not covered by our own prefix. */ - struct ifaddr *ifa = ifaof_ifpforaddr( - (struct sockaddr *)l3addr, ifp); - if (ifa != NULL) + struct ifaddr *ifa = + ifaof_ifpforaddr((struct sockaddr *)l3addr, ifp); + if (ifa != NULL) { + if (rt) + rtfree(rt); goto lla_lookup_1; + } } switch (l3addr->sa_family) { -#ifdef INET case AF_INET: - log(LOG_INFO, "IPv4 address: \"%s\" is " - "not on the network\n", + log(LOG_INFO, "IPv4 address: \"%s\" is not on the network\n", \ inet_ntoa(((struct sockaddr_in *)l3addr)->sin_addr)); break; -#endif #ifdef INET6 case AF_INET6: - log(LOG_INFO, "IPv6 address: \"%s\" is " - "not on the network\n", + log(LOG_INFO, "IPv6 address: \"%s\" is not on the network\n", \ ip6_sprintf(ip6buf, &((struct sockaddr_in6 *)l3addr)->sin6_addr)); break; #endif @@ -397,14 +381,13 @@ lla_lookup_1: lle = uma_zalloc(llezone, M_DONTWAIT | M_ZERO); if (lle == NULL) { - log(LOG_INFO, "%s: malloc failed\n", __func__); + log(LOG_INFO, "lla_lookup: new lle malloc failed\n"); return (NULL); } - IF_LLE_LOCK_INIT(lle); - callout_init_mtx(&lle->la_timer, &ifp->if_lltbls_mtx, 0); + callout_init(&lle->la_timer, CALLOUT_MPSAFE); - /* + /* qing * For IPv4 this will trigger "arpresolve" to generate * an ARP request */ @@ -415,9 +398,9 @@ if ((flags & (LLE_CREATE | LLE_IFADDR)) == (LLE_CREATE | LLE_IFADDR)) { bcopy(IF_LLADDR(ifp), &lle->ll_addr, ifp->if_addrlen); - lle->la_flags |= LLE_VALID | LLE_STATIC; + lle->la_flags |= (LLE_VALID | LLE_STATIC); } - + lle->lle_tbl = llt; lle->lle_head = lleh; LIST_INSERT_HEAD(lleh, lle, lle_next); @@ -425,9 +408,11 @@ if (flags & LLE_DELETE) lle->la_flags = LLE_DELETED; } + return (lle); } + /* * Called in route_output when adding/deleting a route to an interface. */ @@ -437,6 +422,7 @@ struct sockaddr_dl *dl = (struct sockaddr_dl *)info->rti_info[RTAX_GATEWAY]; struct sockaddr *dst = (struct sockaddr *)info->rti_info[RTAX_DST]; struct ifnet *ifp; + struct lltable *llt; struct llentry *lle; u_int flags = 0; @@ -486,8 +472,22 @@ return EINVAL; /* XXX not implemented yet */ } - IF_LLTBLS_LOCK(ifp); - lle = lla_lookup(ifp, flags, dst); + /* + * XXXXXXXX: A big and ugly hack! + * I must redesign this before even committing to perforce. This is + * just a hack to make new design working. + */ + IFNET_WLOCK(); + SLIST_FOREACH(llt, &lltables, llt_link) { + if (llt->llt_af == dst->sa_family && + llt->llt_ifp == ifp) + break; + } + IFNET_WUNLOCK(); + KASSERT(llt != NULL, ("Yep, ugly hacks are bad\n")); + + IF_AFDATA_LOCK(ifp); + lle = lla_lookup(llt, flags, dst); if (lle != NULL) { if (flags & LLE_CREATE) { /* qing: if we delay the delete, then if a subsequent @@ -527,10 +527,11 @@ } } else { if (flags & LLE_DELETE) { - IF_LLTBLS_UNLOCK(ifp); + IF_AFDATA_UNLOCK(ifp); return EINVAL; } } - IF_LLTBLS_UNLOCK(ifp); + + IF_AFDATA_UNLOCK(ifp); return 0; } ==== //depot/projects/arp-v2/src/sys/net/if_llatbl.h#4 (text+ko) ==== @@ -22,6 +22,8 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); #ifndef _NET_IF_LLATBL_H_ #define _NET_IF_LLATBL_H_ @@ -37,9 +39,9 @@ struct llentry { LIST_ENTRY(llentry) lle_next; - struct lltable *lle_tbl; - struct llentries *lle_head; - struct mbuf *la_hold; + struct lltable *lle_tbl; + struct llentries *lle_head; + struct mbuf *la_hold; time_t la_expire; uint16_t la_flags; uint16_t la_asked; @@ -60,7 +62,6 @@ struct callout ln_timer_ch; struct callout la_timer; } lle_timer; - struct mtx lle_mtx; /* mutex for lle entry */ }; #define ln_timer_ch lle_timer.ln_timer_ch @@ -78,12 +79,13 @@ #endif struct lltable { - TAILQ_ENTRY(lltable) llt_link; + SLIST_ENTRY(lltable) llt_link; struct llentries lle_head[LLTBL_HASHTBL_SIZE]; int llt_af; - struct ifnet *llt_ifp; + struct ifnet *llt_ifp; }; + /* * flags to be passed to arplookup. */ @@ -99,16 +101,14 @@ #define LLATBL_HASH(key, mask) \ (((((((key >> 8) ^ key) >> 8) ^ key) >> 8) ^ key) & mask) -#define IF_LLE_LOCK_INIT(lle) \ - mtx_init(&(lle)->lle_mtx, "if_llentry_mtx", NULL, MTX_DEF | MTX_RECURSE) -#define IF_LLE_LOCK_DESTROY(lle) mtx_destroy(&(lle)->lle_mtx) -#define IF_LLE_LOCK(lle) mtx_lock(&(lle)->lle_mtx) -#define IF_LLE_UNLOCK(lle) mtx_unlock(&(lle)->lle_mtx) +struct llentry *lla_lookup(struct lltable *, u_int, struct sockaddr *); +int lla_rt_output(struct rt_msghdr *, struct rt_addrinfo *); +int llentry_free(struct llentry *); + +struct lltable *lltable_init(struct ifnet *, int); +void lltable_free(struct lltable *); +void lltable_drain(int); + +#endif /* _NET_IF_LLATBL_H_ */ + -struct llentry *lla_lookup(struct ifnet *, u_int flags, - struct sockaddr *l3addr); -int lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info); -int llentry_free(struct llentry *lle); -int lltable_free(struct ifnet *ifp, int af); -void lltable_drain(int af); -#endif /* _NET_IF_LLATBL_H_ */ ==== //depot/projects/arp-v2/src/sys/net/if_var.h#8 (text+ko) ==== @@ -93,7 +93,6 @@ TAILQ_HEAD(ifprefixhead, ifprefix); TAILQ_HEAD(ifmultihead, ifmultiaddr); TAILQ_HEAD(ifgrouphead, ifg_group); -TAILQ_HEAD(lltables, lltable); /* L2/L3 address resolution table */ /* * Structure defining a queue for a network interface. @@ -171,8 +170,6 @@ void *if_bridge; /* bridge glue */ - struct lltables if_lltables; /* list of L3-L2 resolution tables */ - struct label *if_label; /* interface MAC label */ /* these are only used by IPv6 */ @@ -183,8 +180,7 @@ struct task if_starttask; /* task for IFF_NEEDSGIANT */ struct task if_linktask; /* task for link change events */ struct mtx if_addr_mtx; /* mutex to protect address lists */ - struct mtx if_lltbls_mtx; /* mutex to protect link-layer - address tables */ + LIST_ENTRY(ifnet) if_clones; /* interfaces of a cloner */ TAILQ_HEAD(, ifg_list) if_groups; /* linked list of groups per if */ /* protected by if_addr_mtx */ @@ -239,17 +235,6 @@ #define IF_ADDR_LOCK_ASSERT(if) mtx_assert(&(if)->if_addr_mtx, MA_OWNED) /* - * Locks for link-layer address tables on the network interface. - */ -#define IF_LLTBLS_LOCK_INIT(if) mtx_init(&(if)->if_lltbls_mtx, \ - "if_lltbls_mtx", NULL, MTX_DEF | MTX_RECURSE) -#define IF_LLTBLS_LOCK_DESTROY(if) mtx_destroy(&(if)->if_lltbls_mtx) -#define IF_LLTBLS_LOCK(if) mtx_lock(&(if)->if_lltbls_mtx) -#define IF_LLTBLS_UNLOCK(if) mtx_unlock(&(if)->if_lltbls_mtx) -#define IF_LLTBLS_LOCK_ASSERT(if) mtx_assert(&(if)->if_lltbls_mtx, MA_OWNED) - - -/* * Output queues (ifp->if_snd) and slow device input queues (*ifp->if_slowq) * are queues of messages stored on ifqueue structures * (defined above). Entries are added to and deleted from these structures @@ -370,7 +355,8 @@ EVENTHANDLER_DECLARE(group_change_event, group_change_event_handler_t); #define IF_AFDATA_LOCK_INIT(ifp) \ - mtx_init(&(ifp)->if_afdata_mtx, "if_afdata", NULL, MTX_DEF) + mtx_init(&(ifp)->if_afdata_mtx, "if_afdata", NULL, \ + (MTX_DEF | MTX_RECURSE)) #define IF_AFDATA_LOCK(ifp) mtx_lock(&(ifp)->if_afdata_mtx) #define IF_AFDATA_TRYLOCK(ifp) mtx_trylock(&(ifp)->if_afdata_mtx) #define IF_AFDATA_UNLOCK(ifp) mtx_unlock(&(ifp)->if_afdata_mtx) ==== //depot/projects/arp-v2/src/sys/netinet/if_ether.c#15 (text+ko) ==== @@ -78,6 +78,7 @@ #define SIN(s) ((struct sockaddr_in *)s) #define SDL(s) ((struct sockaddr_dl *)s) +#define LLTABLE(ifp) ((struct lltable *)(ifp)->if_afdata[AF_INET]) SYSCTL_DECL(_net_link_ether); SYSCTL_NODE(_net_link_ether, PF_INET, inet, CTLFLAG_RW, 0, ""); @@ -130,9 +131,10 @@ addr4.sin_len = sizeof(addr4); addr4.sin_family = AF_INET; addr4.sin_addr.s_addr = addr; - IF_LLTBLS_LOCK(ifp); - lle = lla_lookup(ifp, (LLE_DELETE | LLE_IFADDR), (struct sockaddr *)&addr4); - IF_LLTBLS_UNLOCK(ifp); + IF_AFDATA_LOCK(ifp); + lle = lla_lookup(LLTABLE(ifp), (LLE_DELETE | LLE_IFADDR), + (struct sockaddr *)&addr4); + IF_AFDATA_UNLOCK(ifp); #if 0 if (lle == NULL) log(LOG_INFO, "arp_ifscrub: interface address is missing from cache\n"); @@ -150,19 +152,19 @@ struct llentry *lle = (struct llentry *)arg; if (lle == NULL) { - panic("arptimer: NULL entry!\n"); + panic("%s: NULL entry!\n", __func__); return; } ifp = lle->lle_tbl->llt_ifp; - IF_LLTBLS_LOCK(ifp); - if ((lle->la_flags & LLE_DELETED) && - !(lle->la_flags & LLE_STATIC)) { + IF_AFDATA_LOCK(ifp); + if ((lle->la_flags & LLE_DELETED) || + (time_second >= lle->la_expire)) { if (!callout_pending(&lle->la_timer) && (callout_active(&lle->la_timer))) { (void)llentry_free(lle); } } - IF_LLTBLS_UNLOCK(ifp); + IF_AFDATA_UNLOCK(ifp); } @@ -271,11 +273,11 @@ flags = (ifp->if_flags & (IFF_NOARP | IFF_STATICARP)) ? 0 : LLE_CREATE; - /* Qing - * because this function returns an llentry, - * the IF LLTBLS lock is held by the caller + /* XXXXX + * Since this function returns an llentry, the + * lock is held by the caller. */ - la = lla_lookup(ifp, flags, dst); + la = lla_lookup(LLTABLE(ifp), flags, dst); if (la == NULL) { if (flags & LLE_CREATE) log(LOG_DEBUG, @@ -559,8 +561,8 @@ sin.sin_family = AF_INET; sin.sin_addr = isaddr; flag = (itaddr.s_addr == myaddr.s_addr) ? LLE_CREATE : 0; -/* IF_LLTBLS_LOCK(ifp); */ - la = lla_lookup(ifp, flag, (struct sockaddr *)&sin); +/* Qing IF_AFDATA_LOCK(ifp); */ + la = lla_lookup(LLTABLE(ifp), flag, (struct sockaddr *)&sin); if (la != NULL) { /* the following is not an error when doing bridging */ if (!bridged && la->lle_tbl->llt_ifp != ifp @@ -693,7 +695,7 @@ } (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln); (void)memcpy(ar_sha(ah), &la->ll_addr, ah->ar_hln); -/* IF_LLTBLS_UNLOCK(ifp);*/ +/* QING IF_AFDATA_UNLOCK(ifp); */ } } @@ -722,10 +724,8 @@ return; drop: -/* - if (la != NULL) - IF_LLTBLS_UNLOCK(ifp); -*/ +/* if (la != NULL) + IF_AFDATA_UNLOCK(ifp); */ m_freem(m); } #endif @@ -738,13 +738,15 @@ if (ntohl(IA_SIN(ifa)->sin_addr.s_addr) != INADDR_ANY) arprequest(ifp, &IA_SIN(ifa)->sin_addr, &IA_SIN(ifa)->sin_addr, IF_LLADDR(ifp)); - /* Qing - * interface address is considered static entry (true ??) + /* + * interface address is considered static entry + * because the output of the arp utility shows + * that L2 entry as permanent */ - IF_LLTBLS_LOCK(ifp); - lle = lla_lookup(ifp, (LLE_CREATE | LLE_IFADDR | LLE_STATIC), + IF_AFDATA_LOCK(ifp); + lle = lla_lookup(LLTABLE(ifp), (LLE_CREATE | LLE_IFADDR | LLE_STATIC), (struct sockaddr *)IA_SIN(ifa)); - IF_LLTBLS_UNLOCK(ifp); + IF_AFDATA_UNLOCK(ifp); if (lle == NULL) log(LOG_INFO, "arp_ifinit: cannot create arp " "entry for interface address\n"); ==== //depot/projects/arp-v2/src/sys/netinet/in.c#6 (text+ko) ==== @@ -46,6 +46,7 @@ #include <sys/vimage.h> #include <net/if.h> +#include <net/if_llatbl.h> #include <net/if_types.h> #include <net/route.h> @@ -1017,3 +1018,19 @@ in_pcbpurgeif0(&V_udbinfo, ifp); in_purgemaddrs(ifp); } + +void * +in_domifattach(struct ifnet *ifp) +{ + struct lltable *llt = lltable_init(ifp, AF_INET); + + return (llt); +} + +void +in_domifdetach(struct ifnet *ifp __unused, void *aux) +{ + struct lltable *llt = (struct lltable *)aux; + + lltable_free(llt); +} ==== //depot/projects/arp-v2/src/sys/netinet/in_proto.c#3 (text+ko) ==== @@ -362,7 +362,9 @@ .dom_rtattach = in_inithead, #endif .dom_rtoffset = 32, - .dom_maxrtkey = sizeof(struct sockaddr_in) + .dom_maxrtkey = sizeof(struct sockaddr_in), + .dom_ifattach = in_domifattach, + .dom_ifdetach = in_domifdetach }; DOMAIN_SET(inet); ==== //depot/projects/arp-v2/src/sys/netinet/in_var.h#4 (text+ko) ==== @@ -305,6 +305,9 @@ int in_ifadown(struct ifaddr *ifa, int); void in_ifscrub(struct ifnet *, struct in_ifaddr *); struct mbuf *ip_fastforward(struct mbuf *); +void *in_domifattach(struct ifnet *); +void in_domifdetach(struct ifnet *, void *); + /* XXX */ void in_rtalloc_ign(struct route *ro, u_long ignflags, u_int fibnum); ==== //depot/projects/arp-v2/src/sys/netinet6/icmp6.c#7 (text+ko) ==== @@ -2389,10 +2389,10 @@ } /* RFC 2461 8.3 */ - IF_LLTBLS_LOCK(ifp); + IF_AFDATA_LOCK(ifp); nd6_cache_lladdr(ifp, &redtgt6, lladdr, lladdrlen, ND_REDIRECT, is_onlink ? ND_REDIRECT_ONLINK : ND_REDIRECT_ROUTER); - IF_LLTBLS_UNLOCK(ifp); + IF_AFDATA_UNLOCK(ifp); if (!is_onlink) { /* better router case. perform rtredirect. */ /* perform rtredirect */ @@ -2573,17 +2573,17 @@ struct nd_opt_hdr *nd_opt; char *lladdr; - IF_LLTBLS_LOCK(ifp); + IF_AFDATA_LOCK(ifp); ln = nd6_lookup(router_ll6, 0, ifp); if (!ln) { - IF_LLTBLS_UNLOCK(ifp); + IF_AFDATA_UNLOCK(ifp); goto nolladdropt; } len = sizeof(*nd_opt) + ifp->if_addrlen; len = (len + 7) & ~7; /* round by 8 */ /* safety check */ if (len + (p - (u_char *)ip6) > maxlen) { - IF_LLTBLS_UNLOCK(ifp); + IF_AFDATA_UNLOCK(ifp); goto nolladdropt; } if (ln->la_flags & LLE_VALID) { @@ -2594,7 +2594,7 @@ bcopy(&ln->ll_addr, lladdr, ifp->if_addrlen); p += len; } - IF_LLTBLS_UNLOCK(ifp); + IF_AFDATA_UNLOCK(ifp); } nolladdropt:; >>> TRUNCATED FOR MAIL (1000 lines) <<<
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200811240302.mAO320N8080767>