Date: Wed, 10 Dec 2008 02:04:46 +0000 (UTC) From: Kip Macy <kmacy@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r185819 - in projects/arpv2_merge_1: lib/libstand sys/conf sys/contrib/rdma sys/dev/cxgb/ulp/tom sys/net sys/netinet sys/netinet6 usr.sbin/arp usr.sbin/ndp Message-ID: <200812100204.mBA24k3E008839@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kmacy Date: Wed Dec 10 02:04:46 2008 New Revision: 185819 URL: http://svn.freebsd.org/changeset/base/185819 Log: merge qingli's latest arpv2 patch Modified: projects/arpv2_merge_1/lib/libstand/if_ether.h projects/arpv2_merge_1/sys/conf/files projects/arpv2_merge_1/sys/contrib/rdma/rdma_addr.c projects/arpv2_merge_1/sys/dev/cxgb/ulp/tom/cxgb_l2t.c projects/arpv2_merge_1/sys/net/if.c projects/arpv2_merge_1/sys/net/if_arcsubr.c projects/arpv2_merge_1/sys/net/if_ethersubr.c projects/arpv2_merge_1/sys/net/if_fddisubr.c projects/arpv2_merge_1/sys/net/if_fwsubr.c projects/arpv2_merge_1/sys/net/if_iso88025subr.c projects/arpv2_merge_1/sys/net/if_var.h projects/arpv2_merge_1/sys/net/route.c projects/arpv2_merge_1/sys/net/rtsock.c projects/arpv2_merge_1/sys/netinet/if_ether.c projects/arpv2_merge_1/sys/netinet/if_ether.h projects/arpv2_merge_1/sys/netinet/in.c projects/arpv2_merge_1/sys/netinet/in_proto.c projects/arpv2_merge_1/sys/netinet/in_var.h projects/arpv2_merge_1/sys/netinet/ip_output.c projects/arpv2_merge_1/sys/netinet6/icmp6.c projects/arpv2_merge_1/sys/netinet6/in6.c projects/arpv2_merge_1/sys/netinet6/in6_var.h projects/arpv2_merge_1/sys/netinet6/ip6_forward.c projects/arpv2_merge_1/sys/netinet6/ip6_input.c projects/arpv2_merge_1/sys/netinet6/ip6_mroute.c projects/arpv2_merge_1/sys/netinet6/ip6_output.c projects/arpv2_merge_1/sys/netinet6/nd6.c projects/arpv2_merge_1/sys/netinet6/nd6.h projects/arpv2_merge_1/sys/netinet6/nd6_nbr.c projects/arpv2_merge_1/sys/netinet6/nd6_rtr.c projects/arpv2_merge_1/sys/netinet6/vinet6.h projects/arpv2_merge_1/usr.sbin/arp/arp.c projects/arpv2_merge_1/usr.sbin/ndp/ndp.c Modified: projects/arpv2_merge_1/lib/libstand/if_ether.h ============================================================================== --- projects/arpv2_merge_1/lib/libstand/if_ether.h Wed Dec 10 02:04:45 2008 (r185818) +++ projects/arpv2_merge_1/lib/libstand/if_ether.h Wed Dec 10 02:04:46 2008 (r185819) @@ -156,7 +156,7 @@ struct ifqueue arpintrq; void arpwhohas(struct arpcom *, struct in_addr *); void arpintr(void); int arpresolve(struct arpcom *, - struct rtentry *, struct mbuf *, struct sockaddr *, u_char *); + struct rtentry *, struct mbuf *, struct sockaddr *, u_char *, struct llentry **); void arp_ifinit(struct arpcom *, struct ifaddr *); void arp_rtrequest(int, struct rtentry *, struct sockaddr *); @@ -233,7 +233,7 @@ struct ether_multistep { #ifdef _KERNEL void arp_rtrequest(int, struct rtentry *, struct sockaddr *); int arpresolve(struct arpcom *, struct rtentry *, struct mbuf *, - struct sockaddr *, u_char *); + struct sockaddr *, u_char *, struct llentry **); void arpintr(void); int arpioctl(u_long, caddr_t); void arp_ifinit(struct arpcom *, struct ifaddr *); Modified: projects/arpv2_merge_1/sys/conf/files ============================================================================== --- projects/arpv2_merge_1/sys/conf/files Wed Dec 10 02:04:45 2008 (r185818) +++ projects/arpv2_merge_1/sys/conf/files Wed Dec 10 02:04:46 2008 (r185819) @@ -2171,6 +2171,7 @@ net/if_gre.c optional gre net/if_iso88025subr.c optional token net/if_lagg.c optional lagg net/if_loop.c optional loop +net/if_llatbl.c standard net/if_media.c standard net/if_mib.c standard net/if_ppp.c optional ppp Modified: projects/arpv2_merge_1/sys/contrib/rdma/rdma_addr.c ============================================================================== --- projects/arpv2_merge_1/sys/contrib/rdma/rdma_addr.c Wed Dec 10 02:04:45 2008 (r185818) +++ projects/arpv2_merge_1/sys/contrib/rdma/rdma_addr.c Wed Dec 10 02:04:46 2008 (r185819) @@ -163,6 +163,7 @@ static void addr_send_arp(struct sockadd struct route iproute; struct sockaddr_in *dst = (struct sockaddr_in *)&iproute.ro_dst; char dmac[ETHER_ADDR_LEN]; + struct llentry *lle; bzero(&iproute, sizeof iproute); *dst = *dst_in; @@ -172,7 +173,7 @@ static void addr_send_arp(struct sockadd return; arpresolve(iproute.ro_rt->rt_ifp, iproute.ro_rt, NULL, - rt_key(iproute.ro_rt), dmac); + rt_key(iproute.ro_rt), dmac, &lle); RTFREE(iproute.ro_rt); } @@ -186,6 +187,7 @@ static int addr_resolve_remote(struct so struct route iproute; struct sockaddr_in *dst = (struct sockaddr_in *)&iproute.ro_dst; char dmac[ETHER_ADDR_LEN]; + struct llentry *lle; bzero(&iproute, sizeof iproute); *dst = *dst_in; @@ -202,7 +204,7 @@ static int addr_resolve_remote(struct so goto put; } ret = arpresolve(iproute.ro_rt->rt_ifp, iproute.ro_rt, NULL, - rt_key(iproute.ro_rt), dmac); + rt_key(iproute.ro_rt), dmac, &lle); if (ret) { goto put; } Modified: projects/arpv2_merge_1/sys/dev/cxgb/ulp/tom/cxgb_l2t.c ============================================================================== --- projects/arpv2_merge_1/sys/dev/cxgb/ulp/tom/cxgb_l2t.c Wed Dec 10 02:04:45 2008 (r185818) +++ projects/arpv2_merge_1/sys/dev/cxgb/ulp/tom/cxgb_l2t.c Wed Dec 10 02:04:46 2008 (r185819) @@ -166,6 +166,7 @@ t3_l2t_send_slow(struct t3cdev *dev, str { struct rtentry *rt = e->neigh; struct sockaddr_in sin; + struct llentry *lle; bzero(&sin, sizeof(struct sockaddr_in)); sin.sin_family = AF_INET; @@ -177,7 +178,7 @@ again: switch (e->state) { case L2T_STATE_STALE: /* entry is stale, kick off revalidation */ arpresolve(rt->rt_ifp, rt, NULL, - (struct sockaddr *)&sin, e->dmac); + (struct sockaddr *)&sin, e->dmac, &lle); mtx_lock(&e->lock); if (e->state == L2T_STATE_STALE) e->state = L2T_STATE_VALID; @@ -201,7 +202,7 @@ again: * entries when there's no memory. */ if (arpresolve(rt->rt_ifp, rt, NULL, - (struct sockaddr *)&sin, e->dmac) == 0) { + (struct sockaddr *)&sin, e->dmac, &lle) == 0) { CTR6(KTR_CXGB, "mac=%x:%x:%x:%x:%x:%x\n", e->dmac[0], e->dmac[1], e->dmac[2], e->dmac[3], e->dmac[4], e->dmac[5]); @@ -228,6 +229,7 @@ t3_l2t_send_event(struct t3cdev *dev, st sin.sin_family = AF_INET; sin.sin_len = sizeof(struct sockaddr_in); sin.sin_addr.s_addr = e->addr; + struct llentry *lle; if ((m0 = m_gethdr(M_NOWAIT, MT_DATA)) == NULL) return; @@ -237,7 +239,7 @@ again: switch (e->state) { case L2T_STATE_STALE: /* entry is stale, kick off revalidation */ arpresolve(rt->rt_ifp, rt, NULL, - (struct sockaddr *)&sin, e->dmac); + (struct sockaddr *)&sin, e->dmac, &lle); mtx_lock(&e->lock); if (e->state == L2T_STATE_STALE) { e->state = L2T_STATE_VALID; @@ -263,7 +265,7 @@ again: * entries when there's no memory. */ arpresolve(rt->rt_ifp, rt, NULL, - (struct sockaddr *)&sin, e->dmac); + (struct sockaddr *)&sin, e->dmac, &lle); } return; Modified: projects/arpv2_merge_1/sys/net/if.c ============================================================================== --- projects/arpv2_merge_1/sys/net/if.c Wed Dec 10 02:04:45 2008 (r185818) +++ projects/arpv2_merge_1/sys/net/if.c Wed Dec 10 02:04:46 2008 (r185819) @@ -60,6 +60,7 @@ #include <sys/jail.h> #include <sys/vimage.h> #include <machine/stdarg.h> +#include <vm/uma.h> #include <net/if.h> #include <net/if_arp.h> @@ -70,6 +71,7 @@ #include <net/radix.h> #include <net/route.h> #include <net/vnet.h> +#include <net/if_llatbl.h> #if defined(INET) || defined(INET6) /*XXX*/ Modified: projects/arpv2_merge_1/sys/net/if_arcsubr.c ============================================================================== --- projects/arpv2_merge_1/sys/net/if_arcsubr.c Wed Dec 10 02:04:45 2008 (r185818) +++ projects/arpv2_merge_1/sys/net/if_arcsubr.c Wed Dec 10 02:04:46 2008 (r185819) @@ -64,6 +64,7 @@ #include <net/if_arc.h> #include <net/if_arp.h> #include <net/bpf.h> +#include <net/if_llatbl.h> #if defined(INET) || defined(INET6) #include <netinet/in.h> @@ -108,6 +109,7 @@ arc_output(struct ifnet *ifp, struct mbu u_int8_t atype, adst; int loop_copy = 0; int isphds; + struct llentry *lle; if (!((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))) @@ -127,7 +129,7 @@ arc_output(struct ifnet *ifp, struct mbu else if (ifp->if_flags & IFF_NOARP) adst = ntohl(SIN(dst)->sin_addr.s_addr) & 0xFF; else { - error = arpresolve(ifp, rt0, m, dst, &adst); + error = arpresolve(ifp, rt0, m, dst, &adst, &lle); if (error) return (error == EWOULDBLOCK ? 0 : error); } @@ -165,7 +167,7 @@ arc_output(struct ifnet *ifp, struct mbu #endif #ifdef INET6 case AF_INET6: - error = nd6_storelladdr(ifp, rt0, m, dst, (u_char *)&adst); + error = nd6_storelladdr(ifp, rt0, m, dst, (u_char *)&adst, &lle); if (error) return (error); atype = ARCTYPE_INET6; Modified: projects/arpv2_merge_1/sys/net/if_ethersubr.c ============================================================================== --- projects/arpv2_merge_1/sys/net/if_ethersubr.c Wed Dec 10 02:04:45 2008 (r185818) +++ projects/arpv2_merge_1/sys/net/if_ethersubr.c Wed Dec 10 02:04:46 2008 (r185819) @@ -62,6 +62,7 @@ #include <net/ethernet.h> #include <net/if_bridgevar.h> #include <net/if_vlan_var.h> +#include <net/if_llatbl.h> #include <net/pf_mtag.h> #include <net/vnet.h> @@ -148,6 +149,8 @@ static int ether_ipfw; #endif #endif +extern int useloopback; + /* * Ethernet output routine. * Encapsulate a packet of type family for the local net. @@ -161,6 +164,7 @@ ether_output(struct ifnet *ifp, struct m short type; int error, hdrcmplt = 0; u_char esrc[ETHER_ADDR_LEN], edst[ETHER_ADDR_LEN]; + struct llentry *lle = NULL; struct ether_header *eh; struct pf_mtag *t; int loop_copy = 1; @@ -183,7 +187,7 @@ ether_output(struct ifnet *ifp, struct m switch (dst->sa_family) { #ifdef INET case AF_INET: - error = arpresolve(ifp, rt0, m, dst, edst); + error = arpresolve(ifp, rt0, m, dst, edst, &lle); if (error) return (error == EWOULDBLOCK ? 0 : error); type = htons(ETHERTYPE_IP); @@ -218,7 +222,7 @@ ether_output(struct ifnet *ifp, struct m #endif #ifdef INET6 case AF_INET6: - error = nd6_storelladdr(ifp, rt0, m, dst, (u_char *)edst); + error = nd6_storelladdr(ifp, rt0, m, dst, (u_char *)edst, &lle); if (error) return error; type = htons(ETHERTYPE_IPV6); @@ -286,6 +290,17 @@ ether_output(struct ifnet *ifp, struct m senderr(EAFNOSUPPORT); } + if (lle && (lle->la_flags & LLE_IFADDR) && useloopback) { + int csum_flags = 0; + if (m->m_pkthdr.csum_flags & CSUM_IP) + csum_flags |= (CSUM_IP_CHECKED|CSUM_IP_VALID); + if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) + csum_flags |= (CSUM_DATA_VALID|CSUM_PSEUDO_HDR); + m->m_pkthdr.csum_flags |= csum_flags; + m->m_pkthdr.csum_data = 0xffff; + return (if_simloop(ifp, m, dst->sa_family, 0)); + } + /* * Add local net header. If no space in first mbuf, * allocate another. Modified: projects/arpv2_merge_1/sys/net/if_fddisubr.c ============================================================================== --- projects/arpv2_merge_1/sys/net/if_fddisubr.c Wed Dec 10 02:04:45 2008 (r185818) +++ projects/arpv2_merge_1/sys/net/if_fddisubr.c Wed Dec 10 02:04:46 2008 (r185819) @@ -55,6 +55,7 @@ #include <net/if_dl.h> #include <net/if_llc.h> #include <net/if_types.h> +#include <net/if_llatbl.h> #include <net/ethernet.h> #include <net/netisr.h> @@ -120,6 +121,7 @@ fddi_output(ifp, m, dst, rt0) int loop_copy = 0, error = 0, hdrcmplt = 0; u_char esrc[FDDI_ADDR_LEN], edst[FDDI_ADDR_LEN]; struct fddi_header *fh; + struct llentry *lle; #ifdef MAC error = mac_ifnet_check_transmit(ifp, m); @@ -137,7 +139,7 @@ fddi_output(ifp, m, dst, rt0) switch (dst->sa_family) { #ifdef INET case AF_INET: { - error = arpresolve(ifp, rt0, m, dst, edst); + error = arpresolve(ifp, rt0, m, dst, edst, &lle); if (error) return (error == EWOULDBLOCK ? 0 : error); type = htons(ETHERTYPE_IP); @@ -173,7 +175,7 @@ fddi_output(ifp, m, dst, rt0) #endif /* INET */ #ifdef INET6 case AF_INET6: - error = nd6_storelladdr(ifp, rt0, m, dst, (u_char *)edst); + error = nd6_storelladdr(ifp, rt0, m, dst, (u_char *)edst, &lle); if (error) return (error); /* Something bad happened */ type = htons(ETHERTYPE_IPV6); Modified: projects/arpv2_merge_1/sys/net/if_fwsubr.c ============================================================================== --- projects/arpv2_merge_1/sys/net/if_fwsubr.c Wed Dec 10 02:04:45 2008 (r185818) +++ projects/arpv2_merge_1/sys/net/if_fwsubr.c Wed Dec 10 02:04:46 2008 (r185819) @@ -51,6 +51,7 @@ #include <net/if_types.h> #include <net/bpf.h> #include <net/firewire.h> +#include <net/if_llatbl.h> #if defined(INET) || defined(INET6) #include <netinet/in.h> @@ -89,6 +90,7 @@ firewire_output(struct ifnet *ifp, struc struct mbuf *mtail; int unicast, dgl, foff; static int next_dgl; + struct llentry *lle; #ifdef MAC error = mac_ifnet_check_transmit(ifp, m); @@ -144,7 +146,7 @@ firewire_output(struct ifnet *ifp, struc * doesn't fit into the arp model. */ if (unicast) { - error = arpresolve(ifp, rt, m, dst, (u_char *) destfw); + error = arpresolve(ifp, rt, m, dst, (u_char *) destfw, &lle); if (error) return (error == EWOULDBLOCK ? 0 : error); } @@ -174,7 +176,7 @@ firewire_output(struct ifnet *ifp, struc case AF_INET6: if (unicast) { error = nd6_storelladdr(fc->fc_ifp, rt, m, dst, - (u_char *) destfw); + (u_char *) destfw, &lle); if (error) return (error); } Modified: projects/arpv2_merge_1/sys/net/if_iso88025subr.c ============================================================================== --- projects/arpv2_merge_1/sys/net/if_iso88025subr.c Wed Dec 10 02:04:45 2008 (r185818) +++ projects/arpv2_merge_1/sys/net/if_iso88025subr.c Wed Dec 10 02:04:46 2008 (r185819) @@ -59,6 +59,7 @@ #include <net/if_dl.h> #include <net/if_llc.h> #include <net/if_types.h> +#include <net/if_llatbl.h> #include <net/ethernet.h> #include <net/netisr.h> @@ -244,6 +245,7 @@ iso88025_output(ifp, m, dst, rt0) struct iso88025_header gen_th; struct sockaddr_dl *sdl = NULL; struct rtentry *rt = NULL; + struct llentry *lle; #ifdef MAC error = mac_ifnet_check_transmit(ifp, m); @@ -289,7 +291,7 @@ iso88025_output(ifp, m, dst, rt0) switch (dst->sa_family) { #ifdef INET case AF_INET: - error = arpresolve(ifp, rt0, m, dst, edst); + error = arpresolve(ifp, rt0, m, dst, edst, &lle); if (error) return (error == EWOULDBLOCK ? 0 : error); snap_type = ETHERTYPE_IP; @@ -324,7 +326,7 @@ iso88025_output(ifp, m, dst, rt0) #endif /* INET */ #ifdef INET6 case AF_INET6: - error = nd6_storelladdr(ifp, rt0, m, dst, (u_char *)edst); + error = nd6_storelladdr(ifp, rt0, m, dst, (u_char *)edst, &lle); if (error) return (error); snap_type = ETHERTYPE_IPV6; Modified: projects/arpv2_merge_1/sys/net/if_var.h ============================================================================== --- projects/arpv2_merge_1/sys/net/if_var.h Wed Dec 10 02:04:45 2008 (r185818) +++ projects/arpv2_merge_1/sys/net/if_var.h Wed Dec 10 02:04:46 2008 (r185819) @@ -68,6 +68,7 @@ struct rtentry; struct rt_addrinfo; struct socket; struct ether_header; +struct lltable; struct carp_if; struct ifvlantrunk; #endif @@ -169,8 +170,6 @@ struct ifnet { void *if_bridge; /* bridge glue */ - struct lltable *lltables; /* list of L3-L2 resolution tables */ - struct label *if_label; /* interface MAC label */ /* these are only used by IPv6 */ @@ -181,6 +180,7 @@ struct ifnet { 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 */ + 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 */ @@ -359,7 +359,8 @@ typedef void (*group_change_event_handle 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) Modified: projects/arpv2_merge_1/sys/net/route.c ============================================================================== --- projects/arpv2_merge_1/sys/net/route.c Wed Dec 10 02:04:45 2008 (r185818) +++ projects/arpv2_merge_1/sys/net/route.c Wed Dec 10 02:04:46 2008 (r185819) @@ -41,6 +41,7 @@ #include <sys/param.h> #include <sys/systm.h> +#include <sys/syslog.h> #include <sys/malloc.h> #include <sys/mbuf.h> #include <sys/socket.h> @@ -53,6 +54,7 @@ #include <sys/vimage.h> #include <net/if.h> +#include <net/if_dl.h> #include <net/route.h> #ifdef RADIX_MPATH @@ -420,7 +422,7 @@ rtfree(struct rtentry *rt) */ RT_REMREF(rt); if (rt->rt_refcnt > 0) { - printf("%s: %p has %lu refs\n", __func__, rt, rt->rt_refcnt); + log(LOG_DEBUG, "%s: %p has %lu refs\t", __func__, rt, rt->rt_refcnt); goto done; } @@ -1500,6 +1502,7 @@ rtinit1(struct ifaddr *ifa, int cmd, int char tempbuf[_SOCKADDR_TMPSIZE]; int didwork = 0; int a_failure = 0; + static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK}; if (flags & RTF_HOST) { dst = ifa->ifa_dstaddr; @@ -1604,7 +1607,14 @@ rtinit1(struct ifaddr *ifa, int cmd, int info.rti_ifa = ifa; info.rti_flags = flags | ifa->ifa_flags; info.rti_info[RTAX_DST] = dst; - info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr; + /* + * doing this for compatibility reasons + */ + if (cmd == RTM_ADD) + info.rti_info[RTAX_GATEWAY] = + (struct sockaddr *)&null_sdl; + else + info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr; info.rti_info[RTAX_NETMASK] = netmask; error = rtrequest1_fib(cmd, &info, &rt, fibnum); if (error == 0 && rt != NULL) { @@ -1628,6 +1638,15 @@ rtinit1(struct ifaddr *ifa, int cmd, int rt->rt_ifa = ifa; } #endif + /* + * doing this for compatibility reasons + */ + if (cmd == RTM_ADD) { + ((struct sockaddr_dl *)rt->rt_gateway)->sdl_type = + rt->rt_ifp->if_type; + ((struct sockaddr_dl *)rt->rt_gateway)->sdl_index = + rt->rt_ifp->if_index; + } rt_newaddrmsg(cmd, ifa, error, rt); if (cmd == RTM_DELETE) { /* Modified: projects/arpv2_merge_1/sys/net/rtsock.c ============================================================================== --- projects/arpv2_merge_1/sys/net/rtsock.c Wed Dec 10 02:04:45 2008 (r185818) +++ projects/arpv2_merge_1/sys/net/rtsock.c Wed Dec 10 02:04:46 2008 (r185819) @@ -53,6 +53,7 @@ #include <sys/vimage.h> #include <net/if.h> +#include <net/if_llatbl.h> #include <net/netisr.h> #include <net/raw_cb.h> #include <net/route.h> @@ -526,6 +527,11 @@ route_output(struct mbuf *m, struct sock if (info.rti_info[RTAX_GATEWAY] == NULL) senderr(EINVAL); saved_nrt = NULL; + /* support for new ARP code */ + if (info.rti_info[RTAX_GATEWAY]->sa_family == AF_LINK) { + error = lla_rt_output(rtm, &info); + break; + } error = rtrequest1_fib(RTM_ADD, &info, &saved_nrt, so->so_fibnum); if (error == 0 && saved_nrt) { @@ -541,6 +547,12 @@ route_output(struct mbuf *m, struct sock case RTM_DELETE: saved_nrt = NULL; + /* support for new ARP code */ + if (info.rti_info[RTAX_GATEWAY] && + (info.rti_info[RTAX_GATEWAY]->sa_family == AF_LINK)) { + error = lla_rt_output(rtm, &info); + break; + } error = rtrequest1_fib(RTM_DELETE, &info, &saved_nrt, so->so_fibnum); if (error == 0) { @@ -1432,6 +1444,11 @@ sysctl_rtsock(SYSCTL_HANDLER_ARGS) RADIX_NODE_HEAD_UNLOCK(rnh); } else if (af != 0) error = EAFNOSUPPORT; + /* + * take care of llinfo entries + */ + if (w.w_op == NET_RT_FLAGS && (RTF_LLINFO & w.w_arg)) + error = lltable_sysctl_dumparp(af, w.w_req); break; case NET_RT_IFLIST: Modified: projects/arpv2_merge_1/sys/netinet/if_ether.c ============================================================================== --- projects/arpv2_merge_1/sys/netinet/if_ether.c Wed Dec 10 02:04:45 2008 (r185818) +++ projects/arpv2_merge_1/sys/netinet/if_ether.c Wed Dec 10 02:04:46 2008 (r185819) @@ -65,6 +65,7 @@ __FBSDID("$FreeBSD$"); #include <netinet/in.h> #include <netinet/in_var.h> +#include <net/if_llatbl.h> #include <netinet/if_ether.h> #include <netinet/vinet.h> @@ -79,6 +80,7 @@ __FBSDID("$FreeBSD$"); #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, ""); @@ -87,23 +89,13 @@ SYSCTL_NODE(_net_link_ether, PF_INET, in #ifdef VIMAGE_GLOBALS static int arpt_keep; /* once resolved, good for 20 more minutes */ static int arp_maxtries; -static int useloopback; /* use loopback interface for local traffic */ +int useloopback; /* use loopback interface for local traffic */ static int arp_proxyall; #endif SYSCTL_V_INT(V_NET, vnet_inet, _net_link_ether_inet, OID_AUTO, max_age, CTLFLAG_RW, arpt_keep, 0, "ARP entry lifetime in seconds"); -#define rt_expire rt_rmx.rmx_expire - -struct llinfo_arp { - struct callout la_timer; - struct rtentry *la_rt; - struct mbuf *la_hold; /* last packet until resolved/timeout */ - u_short la_preempt; /* countdown for pre-expiry arps */ - u_short la_asked; /* # requests sent */ -}; - static struct ifqueue arpintrq; SYSCTL_V_INT(V_NET, vnet_inet, _net_link_ether_inet, OID_AUTO, maxtries, @@ -117,212 +109,104 @@ SYSCTL_V_INT(V_NET, vnet_inet, _net_link "Enable proxy ARP for all suitable requests"); static void arp_init(void); -static void arp_rtrequest(int, struct rtentry *, struct rt_addrinfo *); -static void arprequest(struct ifnet *, +void arprequest(struct ifnet *, struct in_addr *, struct in_addr *, u_char *); static void arpintr(struct mbuf *); static void arptimer(void *); -static struct rtentry - *arplookup(u_long, int, int, int); #ifdef INET static void in_arpinput(struct mbuf *); #endif +#ifdef AF_INET +void arp_ifscrub(struct ifnet *ifp, uint32_t addr); + /* - * Timeout routine. + * called by in_ifscrub to remove entry from the table when + * the interface goes away */ -static void -arptimer(void *arg) +void +arp_ifscrub(struct ifnet *ifp, uint32_t addr) { - struct rtentry *rt = (struct rtentry *)arg; - - RT_LOCK_ASSERT(rt); - /* - * The lock is needed to close a theoretical race - * between spontaneous expiry and intentional removal. - * We still got an extra reference on rtentry, so can - * safely pass pointers to its contents. - */ - RT_UNLOCK(rt); + struct sockaddr_in addr4; + struct llentry *lle; - in_rtrequest(RTM_DELETE, rt_key(rt), NULL, rt_mask(rt), 0, NULL, - rt->rt_fibnum); + bzero((void *)&addr4, sizeof(addr4)); + addr4.sin_len = sizeof(addr4); + addr4.sin_family = AF_INET; + addr4.sin_addr.s_addr = addr; + 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"); +#endif } +#endif /* - * Parallel to llc_rtrequest. + * Timeout routine. Age arp_tab entries periodically. */ static void -arp_rtrequest(int req, struct rtentry *rt, struct rt_addrinfo *info) +arptimer(void *arg) { - INIT_VNET_NET(curvnet); - INIT_VNET_INET(curvnet); - struct sockaddr *gate; - struct llinfo_arp *la; - static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK}; - struct in_ifaddr *ia; - struct ifaddr *ifa; + struct ifnet *ifp; + struct llentry *lle = (struct llentry *)arg; - RT_LOCK_ASSERT(rt); - - if (rt->rt_flags & RTF_GATEWAY) + if (lle == NULL) { + panic("%s: NULL entry!\n", __func__); return; - gate = rt->rt_gateway; - la = (struct llinfo_arp *)rt->rt_llinfo; - switch (req) { - - case RTM_ADD: - /* - * XXX: If this is a manually added route to interface - * such as older version of routed or gated might provide, - * restore cloning bit. - */ - if ((rt->rt_flags & RTF_HOST) == 0 && - rt_mask(rt) != NULL && - SIN(rt_mask(rt))->sin_addr.s_addr != 0xffffffff) - rt->rt_flags |= RTF_CLONING; - if (rt->rt_flags & RTF_CLONING) { - /* - * Case 1: This route should come from a route to iface. - */ - rt_setgate(rt, rt_key(rt), - (struct sockaddr *)&null_sdl); - gate = rt->rt_gateway; - SDL(gate)->sdl_type = rt->rt_ifp->if_type; - SDL(gate)->sdl_index = rt->rt_ifp->if_index; - rt->rt_expire = time_uptime; - break; - } - /* Announce a new entry if requested. */ - if (rt->rt_flags & RTF_ANNOUNCE) - arprequest(rt->rt_ifp, - &SIN(rt_key(rt))->sin_addr, - &SIN(rt_key(rt))->sin_addr, - (u_char *)LLADDR(SDL(gate))); - /*FALLTHROUGH*/ - case RTM_RESOLVE: - if (gate->sa_family != AF_LINK || - gate->sa_len < sizeof(null_sdl)) { - log(LOG_DEBUG, "%s: bad gateway %s%s\n", __func__, - inet_ntoa(SIN(rt_key(rt))->sin_addr), - (gate->sa_family != AF_LINK) ? - " (!AF_LINK)": ""); - break; - } - SDL(gate)->sdl_type = rt->rt_ifp->if_type; - SDL(gate)->sdl_index = rt->rt_ifp->if_index; - if (la != 0) - break; /* This happens on a route change */ - /* - * Case 2: This route may come from cloning, or a manual route - * add with a LL address. - */ - R_Zalloc(la, struct llinfo_arp *, sizeof(*la)); - rt->rt_llinfo = (caddr_t)la; - if (la == 0) { - log(LOG_DEBUG, "%s: malloc failed\n", __func__); - break; - } - /* - * We are storing a route entry outside of radix tree. So, - * it can be found and accessed by other means than radix - * lookup. The routing code assumes that any rtentry detached - * from radix can be destroyed safely. To prevent this, we - * add an additional reference. - */ - RT_ADDREF(rt); - la->la_rt = rt; - rt->rt_flags |= RTF_LLINFO; - callout_init_mtx(&la->la_timer, &rt->rt_mtx, - CALLOUT_RETURNUNLOCKED); - -#ifdef INET - /* - * This keeps the multicast addresses from showing up - * in `arp -a' listings as unresolved. It's not actually - * functional. Then the same for broadcast. - */ - if (IN_MULTICAST(ntohl(SIN(rt_key(rt))->sin_addr.s_addr)) && - rt->rt_ifp->if_type != IFT_ARCNET) { - ETHER_MAP_IP_MULTICAST(&SIN(rt_key(rt))->sin_addr, - LLADDR(SDL(gate))); - SDL(gate)->sdl_alen = 6; - rt->rt_expire = 0; - } - if (in_broadcast(SIN(rt_key(rt))->sin_addr, rt->rt_ifp)) { - memcpy(LLADDR(SDL(gate)), rt->rt_ifp->if_broadcastaddr, - rt->rt_ifp->if_addrlen); - SDL(gate)->sdl_alen = rt->rt_ifp->if_addrlen; - rt->rt_expire = 0; - } -#endif - - TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) { - if (ia->ia_ifp == rt->rt_ifp && - SIN(rt_key(rt))->sin_addr.s_addr == - (IA_SIN(ia))->sin_addr.s_addr) - break; - } - if (ia) { - /* - * This test used to be - * if (loif.if_flags & IFF_UP) - * It allowed local traffic to be forced - * through the hardware by configuring the loopback down. - * However, it causes problems during network configuration - * for boards that can't receive packets they send. - * It is now necessary to clear "useloopback" and remove - * the route to force traffic out to the hardware. - */ - rt->rt_expire = 0; - bcopy(IF_LLADDR(rt->rt_ifp), LLADDR(SDL(gate)), - SDL(gate)->sdl_alen = rt->rt_ifp->if_addrlen); - if (V_useloopback) { - rt->rt_ifp = V_loif; - rt->rt_rmx.rmx_mtu = V_loif->if_mtu; - } - - /* - * make sure to set rt->rt_ifa to the interface - * address we are using, otherwise we will have trouble - * with source address selection. - */ - ifa = &ia->ia_ifa; - if (ifa != rt->rt_ifa) { - IFAFREE(rt->rt_ifa); - IFAREF(ifa); - rt->rt_ifa = ifa; - } + } + ifp = lle->lle_tbl->llt_ifp; + 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); } - break; - - case RTM_DELETE: - if (la == NULL) /* XXX: at least CARP does this. */ - break; - callout_stop(&la->la_timer); - rt->rt_llinfo = NULL; - rt->rt_flags &= ~RTF_LLINFO; - RT_REMREF(rt); - if (la->la_hold) - m_freem(la->la_hold); - Free((caddr_t)la); } + IF_AFDATA_UNLOCK(ifp); } + /* * Broadcast an ARP request. Caller specifies: * - arp header source ip address * - arp header target ip address * - arp header source ethernet address */ -static void -arprequest(struct ifnet *ifp, struct in_addr *sip, struct in_addr *tip, +void +arprequest(struct ifnet *ifp, struct in_addr *sip, struct in_addr *tip, u_char *enaddr) { struct mbuf *m; struct arphdr *ah; struct sockaddr sa; + if (sip == NULL) { + /* + * The caller did not supply a source address, try to find + * a compatible one among those assigned to this interface. + */ + struct ifaddr *ifa; + + TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { + if (!ifa->ifa_addr || + ifa->ifa_addr->sa_family != AF_INET) + continue; + sip = &SIN(ifa->ifa_addr)->sin_addr; + if (0 == ((sip->s_addr ^ tip->s_addr) & + SIN(ifa->ifa_netmask)->sin_addr.s_addr) ) + break; /* found it. */ + } + if (sip == NULL) { + printf("%s: cannot find matching address\n", __func__); + return; + } + } + if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL) return; m->m_len = sizeof(*ah) + 2*sizeof(struct in_addr) + @@ -345,8 +229,6 @@ arprequest(struct ifnet *ifp, struct in_ sa.sa_len = 2; m->m_flags |= M_BCAST; (*ifp->if_output)(ifp, m, &sa, (struct rtentry *)0); - - return; } /* @@ -365,16 +247,16 @@ arprequest(struct ifnet *ifp, struct in_ */ int arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m, - struct sockaddr *dst, u_char *desten) + struct sockaddr *dst, u_char *desten, struct llentry **lle) { INIT_VNET_INET(ifp->if_vnet); - struct llinfo_arp *la = NULL; - struct rtentry *rt = NULL; - struct sockaddr_dl *sdl; + struct llentry *la = 0; + u_int flags; int error; - int fibnum = -1; - if (m) { + *lle = NULL; + + if (m != NULL) { if (m->m_flags & M_BCAST) { /* broadcast */ (void)memcpy(desten, @@ -386,95 +268,46 @@ arpresolve(struct ifnet *ifp, struct rte ETHER_MAP_IP_MULTICAST(&SIN(dst)->sin_addr, desten); return (0); } - fibnum = M_GETFIB(m); } - if (rt0 != NULL) { - /* Look for a cached arp (ll) entry. */ - if (m == NULL) - fibnum = rt0->rt_fibnum; - error = rt_check(&rt, &rt0, dst); - if (error) { - m_freem(m); - return error; - } - la = (struct llinfo_arp *)rt->rt_llinfo; - if (la == NULL) - RT_UNLOCK(rt); - } + flags = (ifp->if_flags & (IFF_NOARP | IFF_STATICARP)) ? 0 : LLE_CREATE; - /* - * If we had no mbuf and no route, then hope the caller - * has a fib in mind because we are running out of ideas. - * I think this should not happen in current code. - * (kmacy would know). + /* XXXXX + * Since this function returns an llentry, the + * lock is held by the caller. */ - if (fibnum == -1) - fibnum = curthread->td_proc->p_fibnum; /* last gasp */ - + la = lla_lookup(LLTABLE(ifp), flags, dst); if (la == NULL) { - /* - * We enter this block if rt0 was NULL, - * or if rt found by rt_check() didn't have llinfo. - * we should get a cloned route, which since it should - * come from the local interface should have a ll entry. - * It may be incomplete but that's ok. - */ - rt = arplookup(SIN(dst)->sin_addr.s_addr, 1, 0, fibnum); - if (rt == NULL) { - log(LOG_DEBUG, - "arpresolve: can't allocate route for %s\n", - inet_ntoa(SIN(dst)->sin_addr)); - m_freem(m); - return (EINVAL); /* XXX */ - } - la = (struct llinfo_arp *)rt->rt_llinfo; - if (la == NULL) { - RT_UNLOCK(rt); + if (flags & LLE_CREATE) log(LOG_DEBUG, "arpresolve: can't allocate llinfo for %s\n", inet_ntoa(SIN(dst)->sin_addr)); - m_freem(m); - return (EINVAL); /* XXX */ - } - } - sdl = SDL(rt->rt_gateway); - /* - * Check the address family and length is valid, the address - * is resolved; otherwise, try to resolve. - */ - if ((rt->rt_expire == 0 || rt->rt_expire > time_uptime) && - sdl->sdl_family == AF_LINK && sdl->sdl_alen != 0) { - - bcopy(LLADDR(sdl), desten, sdl->sdl_alen); + m_freem(m); + return (EINVAL); + } + if (la->la_flags & LLE_VALID && + (la->la_flags & LLE_STATIC || la->la_expire > time_uptime)) { + bcopy(&la->ll_addr, desten, ifp->if_addrlen); /* * If entry has an expiry time and it is approaching, - * send an ARP request. + * see if we need to send an ARP request within this + * arpt_down interval. */ - if ((rt->rt_expire != 0) && - (time_uptime + la->la_preempt > rt->rt_expire)) { - struct in_addr sin = - SIN(rt->rt_ifa->ifa_addr)->sin_addr; + if (!(la->la_flags & LLE_STATIC) && + time_uptime + la->la_preempt > la->la_expire) { + arprequest(ifp, NULL, + &SIN(dst)->sin_addr, IF_LLADDR(ifp)); la->la_preempt--; - RT_UNLOCK(rt); - arprequest(ifp, &sin, &SIN(dst)->sin_addr, - IF_LLADDR(ifp)); - return (0); } - - RT_UNLOCK(rt); + *lle = la; return (0); } - /* - * If ARP is disabled or static on this interface, stop. - * XXX - * Probably should not allocate empty llinfo struct if we are - * not going to be sending out an arp request. - */ - if (ifp->if_flags & (IFF_NOARP | IFF_STATICARP)) { - RT_UNLOCK(rt); + + if (la->la_flags & LLE_STATIC) { /* should not happen! */ + log(LOG_DEBUG, "arpresolve: ouch, empty static llinfo for %s\n", + inet_ntoa(SIN(dst)->sin_addr)); m_freem(m); return (EINVAL); } @@ -488,8 +321,6 @@ arpresolve(struct ifnet *ifp, struct rte m_freem(la->la_hold); la->la_hold = m; } - KASSERT(rt->rt_expire > 0, ("sending ARP request for static entry")); - /* * Return EWOULDBLOCK if we have tried less than arp_maxtries. It * will be masked by ether_output(). Return EHOSTDOWN/EHOSTUNREACH @@ -499,23 +330,19 @@ arpresolve(struct ifnet *ifp, struct rte if (la->la_asked < V_arp_maxtries) error = EWOULDBLOCK; /* First request. */ else - error = (rt == rt0) ? EHOSTDOWN : EHOSTUNREACH; + error = + (rt0->rt_flags & RTF_GATEWAY) ? EHOSTDOWN : EHOSTUNREACH; - if (la->la_asked == 0 || rt->rt_expire != time_uptime) { - struct in_addr sin = - SIN(rt->rt_ifa->ifa_addr)->sin_addr; - - rt->rt_expire = time_uptime; - callout_reset(&la->la_timer, hz, arptimer, rt); + if (la->la_asked == 0 || la->la_expire != time_uptime) { + la->la_expire = time_uptime; + callout_reset(&la->la_timer, hz, arptimer, la); la->la_asked++; - RT_UNLOCK(rt); - arprequest(ifp, &sin, &SIN(dst)->sin_addr, + arprequest(ifp, NULL, &SIN(dst)->sin_addr, IF_LLADDR(ifp)); - } else - RT_UNLOCK(rt); *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200812100204.mBA24k3E008839>