From f8983475c65dd9ce5cbc8faa2028058e1551a198 Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Mon, 9 Jun 2008 11:24:24 +0000 Subject: [PATCH] Parallelize in_ifaddrhashtbl --- sys/net/if_var.h | 3 +- sys/net/ipfw/ip_fw2.c | 6 +- sys/net/sppp/if_spppsubr.c | 9 +-- sys/net/stf/if_stf.c | 11 ++-- sys/netinet/if_ether.c | 11 +++- sys/netinet/in.c | 131 +++++++++++++++++++++++++++---------- sys/netinet/in_var.h | 34 +++++----- sys/netinet/ip_icmp.c | 11 +++- sys/netinet/ip_input.c | 18 +++-- sys/netinet/ip_output.c | 14 ++-- 10 files changed, 170 insertions(+), 78 deletions(-) diff --git a/sys/net/if_var.h b/sys/net/if_var.h index f9b82106f2..ac56c938b3 100644 --- a/sys/net/if_var.h +++ b/sys/net/if_var.h @@ -32,7 +32,7 @@ * * From: @(#)if.h 8.1 (Berkeley) 6/10/93 * $FreeBSD: src/sys/net/if_var.h,v 1.18.2.16 2003/04/15 18:11:19 fjoe Exp $ - * $DragonFly: src/sys/net/if_var.h,v 1.56 2008/06/08 08:38:05 sephe Exp $ + * $DragonFly: src/sys/net/if_var.h,v 1.57 2008/06/09 11:24:24 sephe Exp $ */ #ifndef _NET_IF_VAR_H_ @@ -393,6 +393,7 @@ struct ifaddr_container { #define IFA_LIST_IFADDRHEAD 0x1 /* on ifnet.if_addrheads[cpuid] */ #define IFA_LIST_IN_IFADDRHEAD 0x2 /* on in_ifaddrheads[cpuid] */ +#define IFA_LIST_IN_IFADDRHASH 0x4 /* on in_ifaddrhashtbls[cpuid] */ /* * The ifaddr structure contains information about one address diff --git a/sys/net/ipfw/ip_fw2.c b/sys/net/ipfw/ip_fw2.c index 7f5f83be3c..e6411268c2 100644 --- a/sys/net/ipfw/ip_fw2.c +++ b/sys/net/ipfw/ip_fw2.c @@ -23,7 +23,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/netinet/ip_fw2.c,v 1.6.2.12 2003/04/08 10:42:32 maxim Exp $ - * $DragonFly: src/sys/net/ipfw/ip_fw2.c,v 1.41 2008/03/07 11:34:20 sephe Exp $ + * $DragonFly: src/sys/net/ipfw/ip_fw2.c,v 1.42 2008/06/09 11:24:24 sephe Exp $ */ #define DEB(x) @@ -1645,7 +1645,7 @@ check_body: if (hlen > 0) { struct ifnet *tif; - INADDR_TO_IFP(src_ip, tif); + tif = INADDR_TO_IFP(&src_ip); match = (tif != NULL); } break; @@ -1685,7 +1685,7 @@ check_body: if (hlen > 0) { struct ifnet *tif; - INADDR_TO_IFP(dst_ip, tif); + tif = INADDR_TO_IFP(&dst_ip); match = (tif != NULL); } break; diff --git a/sys/net/sppp/if_spppsubr.c b/sys/net/sppp/if_spppsubr.c index 18f37f648a..46010a0f76 100644 --- a/sys/net/sppp/if_spppsubr.c +++ b/sys/net/sppp/if_spppsubr.c @@ -18,7 +18,7 @@ * From: Version 2.4, Thu Apr 30 17:17:21 MSD 1997 * * $FreeBSD: src/sys/net/if_spppsubr.c,v 1.59.2.13 2002/07/03 15:44:41 joerg Exp $ - * $DragonFly: src/sys/net/sppp/if_spppsubr.c,v 1.34 2008/05/14 11:59:24 sephe Exp $ + * $DragonFly: src/sys/net/sppp/if_spppsubr.c,v 1.35 2008/06/09 11:24:24 sephe Exp $ */ #include @@ -4955,11 +4955,12 @@ sppp_set_ip_addr(struct sppp *sp, u_long src) SPP_ARGS(ifp), error); } + ia = ifatoia(ifa); + in_iahash_remove(ia); + /* set new address */ si->sin_addr.s_addr = htonl(src); - ia = ifatoia(ifa); - LIST_REMOVE(ia, ia_hash); - LIST_INSERT_HEAD(INADDR_HASH(si->sin_addr.s_addr), ia, ia_hash); + in_iahash_insert(ia); /* add new route */ error = rtinit(ifa, (int)RTM_ADD, RTF_HOST); diff --git a/sys/net/stf/if_stf.c b/sys/net/stf/if_stf.c index 907aad933f..a6de013a7c 100644 --- a/sys/net/stf/if_stf.c +++ b/sys/net/stf/if_stf.c @@ -1,5 +1,5 @@ /* $FreeBSD: src/sys/net/if_stf.c,v 1.1.2.11 2003/01/23 21:06:44 sam Exp $ */ -/* $DragonFly: src/sys/net/stf/if_stf.c,v 1.23 2008/06/08 08:38:05 sephe Exp $ */ +/* $DragonFly: src/sys/net/stf/if_stf.c,v 1.24 2008/06/09 11:24:24 sephe Exp $ */ /* $KAME: if_stf.c,v 1.73 2001/12/03 11:08:30 keiichi Exp $ */ /* @@ -274,12 +274,12 @@ static struct in6_ifaddr * stf_getsrcifa6(struct ifnet *ifp) { struct ifaddr_container *ifac; - struct in_ifaddr *ia4; struct sockaddr_in6 *sin6; struct in_addr in; TAILQ_FOREACH(ifac, &ifp->if_addrheads[mycpuid], ifa_link) { struct ifaddr *ia = ifac->ifa; + struct in_ifaddr_container *iac; if (ia->ifa_addr == NULL) continue; @@ -290,10 +290,11 @@ stf_getsrcifa6(struct ifnet *ifp) continue; bcopy(GET_V4(&sin6->sin6_addr), &in, sizeof(in)); - LIST_FOREACH(ia4, INADDR_HASH(in.s_addr), ia_hash) - if (ia4->ia_addr.sin_addr.s_addr == in.s_addr) + LIST_FOREACH(iac, INADDR_HASH(in.s_addr), ia_hash) { + if (iac->ia->ia_addr.sin_addr.s_addr == in.s_addr) break; - if (ia4 == NULL) + } + if (iac == NULL) continue; return (struct in6_ifaddr *)ia; diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c index 725c137eb4..16e22e90f1 100644 --- a/sys/netinet/if_ether.c +++ b/sys/netinet/if_ether.c @@ -64,7 +64,7 @@ * * @(#)if_ether.c 8.1 (Berkeley) 6/10/93 * $FreeBSD: src/sys/netinet/if_ether.c,v 1.64.2.23 2003/04/11 07:23:15 fjoe Exp $ - * $DragonFly: src/sys/netinet/if_ether.c,v 1.48 2008/05/31 08:29:05 sephe Exp $ + * $DragonFly: src/sys/netinet/if_ether.c,v 1.49 2008/06/09 11:24:24 sephe Exp $ */ /* @@ -658,6 +658,7 @@ in_arpinput(struct mbuf *m) struct ether_header *eh; struct rtentry *rt; struct ifaddr_container *ifac; + struct in_ifaddr_container *iac; struct in_ifaddr *ia; struct sockaddr sa; struct in_addr isaddr, itaddr, myaddr; @@ -688,7 +689,9 @@ in_arpinput(struct mbuf *m) * the interface owning the address are on the same bridge. * (This will change slightly when we have clusters of interfaces). */ - LIST_FOREACH(ia, INADDR_HASH(itaddr.s_addr), ia_hash) { + LIST_FOREACH(iac, INADDR_HASH(itaddr.s_addr), ia_hash) { + ia = iac->ia; + /* Skip all ia's which don't match */ if (itaddr.s_addr != ia->ia_addr.sin_addr.s_addr) continue; @@ -713,7 +716,9 @@ in_arpinput(struct mbuf *m) goto match; #endif } - LIST_FOREACH(ia, INADDR_HASH(isaddr.s_addr), ia_hash) { + LIST_FOREACH(iac, INADDR_HASH(isaddr.s_addr), ia_hash) { + ia = iac->ia; + /* Skip all ia's which don't match */ if (isaddr.s_addr != ia->ia_addr.sin_addr.s_addr) continue; diff --git a/sys/netinet/in.c b/sys/netinet/in.c index 009244d7a0..a38df2d969 100644 --- a/sys/netinet/in.c +++ b/sys/netinet/in.c @@ -32,7 +32,7 @@ * * @(#)in.c 8.4 (Berkeley) 1/9/95 * $FreeBSD: src/sys/netinet/in.c,v 1.44.2.14 2002/11/08 00:45:50 suz Exp $ - * $DragonFly: src/sys/netinet/in.c,v 1.38 2008/06/09 04:59:22 sephe Exp $ + * $DragonFly: src/sys/netinet/in.c,v 1.39 2008/06/09 11:24:24 sephe Exp $ */ #include "opt_bootp.h" @@ -318,6 +318,57 @@ in_iaunlink_dispatch(struct netmsg *nmsg) ifa_forwardmsg(lmsg, cpu + 1); } +static void +in_iahashins_dispatch(struct netmsg *nmsg) +{ + struct lwkt_msg *lmsg = &nmsg->nm_lmsg; + struct in_ifaddr *ia = lmsg->u.ms_resultp; + struct ifaddr_container *ifac; + struct in_ifaddr_container *iac; + int cpu = mycpuid; + + crit_enter(); + + ifac = &ia->ia_ifa.ifa_containers[cpu]; + ASSERT_IFAC_VALID(ifac); + KASSERT((ifac->ifa_listmask & IFA_LIST_IN_IFADDRHASH) == 0, + ("ia is on in_ifaddrhashtbls\n")); + + ifac->ifa_listmask |= IFA_LIST_IN_IFADDRHASH; + iac = &ifac->ifa_proto_u.u_in_ifac; + LIST_INSERT_HEAD(INADDR_HASH(ia->ia_addr.sin_addr.s_addr), + iac, ia_hash); + + crit_exit(); + + ifa_forwardmsg(lmsg, cpu + 1); +} + +static void +in_iahashrem_dispatch(struct netmsg *nmsg) +{ + struct lwkt_msg *lmsg = &nmsg->nm_lmsg; + struct in_ifaddr *ia = lmsg->u.ms_resultp; + struct ifaddr_container *ifac; + struct in_ifaddr_container *iac; + int cpu = mycpuid; + + crit_enter(); + + ifac = &ia->ia_ifa.ifa_containers[cpu]; + ASSERT_IFAC_VALID(ifac); + KASSERT(ifac->ifa_listmask & IFA_LIST_IN_IFADDRHASH, + ("ia is not on in_ifaddrhashtbls\n")); + + iac = &ifac->ifa_proto_u.u_in_ifac; + LIST_REMOVE(iac, ia_hash); + ifac->ifa_listmask &= ~IFA_LIST_IN_IFADDRHASH; + + crit_exit(); + + ifa_forwardmsg(lmsg, cpu + 1); +} + static void in_ialink(struct in_ifaddr *ia) { @@ -344,6 +395,32 @@ in_iaunlink(struct in_ifaddr *ia) ifa_domsg(lmsg); } +void +in_iahash_insert(struct in_ifaddr *ia) +{ + struct netmsg nmsg; + struct lwkt_msg *lmsg; + + netmsg_init(&nmsg, &curthread->td_msgport, 0, in_iahashins_dispatch); + lmsg = &nmsg.nm_lmsg; + lmsg->u.ms_resultp = ia; + + ifa_domsg(lmsg); +} + +void +in_iahash_remove(struct in_ifaddr *ia) +{ + struct netmsg nmsg; + struct lwkt_msg *lmsg; + + netmsg_init(&nmsg, &curthread->td_msgport, 0, in_iahashrem_dispatch); + lmsg = &nmsg.nm_lmsg; + lmsg->u.ms_resultp = ia; + + ifa_domsg(lmsg); +} + static __inline struct in_ifaddr * in_ianext(struct in_ifaddr *oia) { @@ -372,6 +449,7 @@ in_control_internal(u_long cmd, caddr_t data, struct ifnet *ifp, struct in_addr dst; struct in_aliasreq *ifra = (struct in_aliasreq *)data; struct ifaddr_container *ifac; + struct in_ifaddr_container *iac; struct sockaddr_in oldaddr; int hostIsNew, iaIsNew, maskIsNew; int error = 0; @@ -388,12 +466,14 @@ in_control_internal(u_long cmd, caddr_t data, struct ifnet *ifp, struct in_ifaddr *iap; dst = ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr; - LIST_FOREACH(iap, INADDR_HASH(dst.s_addr), ia_hash) + LIST_FOREACH(iac, INADDR_HASH(dst.s_addr), ia_hash) { + iap = iac->ia; if (iap->ia_ifp == ifp && iap->ia_addr.sin_addr.s_addr == dst.s_addr) { ia = iap; break; } + } if (ia == NULL) { TAILQ_FOREACH(ifac, &ifp->if_addrheads[mycpuid], ifa_link) { @@ -452,8 +532,6 @@ in_control_internal(u_long cmd, caddr_t data, struct ifnet *ifp, * Setup per-CPU information */ for (i = 0; i < ncpus; ++i) { - struct in_ifaddr_container *iac; - ifac = &ifa->ifa_containers[i]; iac = &ifac->ifa_proto_u.u_in_ifac; iac->ia = ia; @@ -635,16 +713,9 @@ in_control_internal(u_long cmd, caddr_t data, struct ifnet *ifp, ifa_ifunlink(&ia->ia_ifa, ifp); in_iaunlink(ia); - /* - * Protect from NETISR_IP traversing address list while we're modifying - * it. - */ - crit_enter(); /* XXX MP */ - if (cmd == SIOCDIFADDR && ia->ia_addr.sin_family == AF_INET) { - /* XXX Assume that 'ia' is in hash table */ - LIST_REMOVE(ia, ia_hash); - } - crit_exit(); /* XXX MP */ + ifac = &ia->ia_ifa.ifa_containers[mycpuid]; + if (ifac->ifa_listmask & IFA_LIST_IN_IFADDRHASH) + in_iahash_remove(ia); ifa_destroy(&ia->ia_ifa); @@ -856,23 +927,21 @@ in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia, { u_long i = ntohl(sin->sin_addr.s_addr); struct sockaddr_in oldaddr; + struct ifaddr_container *ifac; int flags = RTF_UP, error = 0; - int old_hash = 0, new_hash = 0; + int was_hash = 0; - crit_enter(); + ifac = &ia->ia_ifa.ifa_containers[mycpuid]; oldaddr = ia->ia_addr; - if (oldaddr.sin_family == AF_INET) { - old_hash = 1; - LIST_REMOVE(ia, ia_hash); + + if (ifac->ifa_listmask & IFA_LIST_IN_IFADDRHASH) { + was_hash = 1; + in_iahash_remove(ia); } ia->ia_addr = *sin; - if (ia->ia_addr.sin_family == AF_INET) { - new_hash = 1; - LIST_INSERT_HEAD(INADDR_HASH(ia->ia_addr.sin_addr.s_addr), - ia, ia_hash); - } - crit_exit(); + if (ia->ia_addr.sin_family == AF_INET) + in_iahash_insert(ia); /* * Give the interface a chance to initialize @@ -967,16 +1036,12 @@ in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia, } return (0); fail: - crit_enter(); - if (new_hash) - LIST_REMOVE(ia, ia_hash); + if (ifac->ifa_listmask & IFA_LIST_IN_IFADDRHASH) + in_iahash_remove(ia); ia->ia_addr = oldaddr; - if (old_hash) { - LIST_INSERT_HEAD(INADDR_HASH(ia->ia_addr.sin_addr.s_addr), - ia, ia_hash); - } - crit_exit(); + if (was_hash) + in_iahash_insert(ia); return (error); } diff --git a/sys/netinet/in_var.h b/sys/netinet/in_var.h index 0b33312983..0be0c04845 100644 --- a/sys/netinet/in_var.h +++ b/sys/netinet/in_var.h @@ -32,7 +32,7 @@ * * @(#)in_var.h 8.2 (Berkeley) 1/9/95 * $FreeBSD: src/sys/netinet/in_var.h,v 1.33.2.3 2001/12/14 20:09:34 jlemon Exp $ - * $DragonFly: src/sys/netinet/in_var.h,v 1.12 2008/06/08 08:38:05 sephe Exp $ + * $DragonFly: src/sys/netinet/in_var.h,v 1.13 2008/06/09 11:24:24 sephe Exp $ */ #ifndef _NETINET_IN_VAR_H_ @@ -67,7 +67,7 @@ struct in_ifaddr { u_long ia_subnet; /* subnet number, including net */ u_long ia_subnetmask; /* mask of subnet part */ struct in_addr ia_netbroadcast; /* to recognize net broadcasts */ - LIST_ENTRY(in_ifaddr) ia_hash; /* entry in bucket of inet addresses */ + void *ia_pad1[2]; void *ia_pad2[2]; struct sockaddr_in ia_addr; /* reserve space for interface name */ struct sockaddr_in ia_dstaddr; /* reserve space for broadcast addr */ @@ -102,7 +102,7 @@ extern u_char inetctlerrmap[]; /* * Hash table for IP addresses. */ -extern LIST_HEAD(in_ifaddrhashhead, in_ifaddr) *in_ifaddrhashtbl; +extern LIST_HEAD(in_ifaddrhashhead, in_ifaddr_container) *in_ifaddrhashtbls[]; extern TAILQ_HEAD(in_ifaddrhead, in_ifaddr_container) in_ifaddrheads[]; extern u_long in_ifaddrhmask; /* mask for hash table */ @@ -110,27 +110,27 @@ extern u_long in_ifaddrhmask; /* mask for hash table */ #define INADDR_NHASH (1 << INADDR_NHASH_LOG2) #define INADDR_HASHVAL(x) fnv_32_buf((&(x)), sizeof(x), FNV1_32_INIT) #define INADDR_HASH(x) \ - (&in_ifaddrhashtbl[INADDR_HASHVAL(x) & in_ifaddrhmask]) + (&in_ifaddrhashtbls[mycpuid][INADDR_HASHVAL(x) & in_ifaddrhmask]) /* - * Macro for finding the interface (ifnet structure) corresponding to one + * Function for finding the interface (ifnet structure) corresponding to one * of our IP addresses. */ -#define INADDR_TO_IFP(addr, ifp) \ - /* struct in_addr addr; */ \ - /* struct ifnet *ifp; */ \ -{ \ - struct in_ifaddr *ia; \ -\ - LIST_FOREACH(ia, INADDR_HASH((addr).s_addr), ia_hash) \ - if (IA_SIN(ia)->sin_addr.s_addr == (addr).s_addr) \ - break; \ - (ifp) = (ia == NULL) ? NULL : ia->ia_ifp; \ +static __inline struct ifnet * +INADDR_TO_IFP(const struct in_addr *_addr) +{ + struct in_ifaddr_container *_iac; + + LIST_FOREACH(_iac, INADDR_HASH(_addr->s_addr), ia_hash) { + if (IA_SIN(_iac->ia)->sin_addr.s_addr == _addr->s_addr) + return _iac->ia->ia_ifp; + } + return NULL; } /* - * Macro for finding the internet address structure (in_ifaddr) corresponding + * Function for finding the internet address structure (in_ifaddr) corresponding * to a given interface (ifnet structure). */ static __inline struct in_ifaddr * @@ -250,6 +250,8 @@ void ip_input (struct mbuf *); int in_ifadown (struct ifaddr *ifa, int); void in_ifscrub (struct ifnet *, struct in_ifaddr *); void in_iaunlink (struct in_ifaddr *); +void in_iahash_insert (struct in_ifaddr *); +void in_iahash_remove (struct in_ifaddr *); int ipflow_fastforward (struct mbuf *, struct lwkt_serialize *); void ipflow_create (const struct route *, struct mbuf *); void ipflow_slowtimo (void); diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c index 080a81f9e8..9eae51cb1a 100644 --- a/sys/netinet/ip_icmp.c +++ b/sys/netinet/ip_icmp.c @@ -32,7 +32,7 @@ * * @(#)ip_icmp.c 8.2 (Berkeley) 1/4/94 * $FreeBSD: src/sys/netinet/ip_icmp.c,v 1.39.2.19 2003/01/24 05:11:34 sam Exp $ - * $DragonFly: src/sys/netinet/ip_icmp.c,v 1.29 2008/05/27 01:10:42 dillon Exp $ + * $DragonFly: src/sys/netinet/ip_icmp.c,v 1.30 2008/06/09 11:24:24 sephe Exp $ */ #include "opt_ipsec.h" @@ -612,6 +612,7 @@ icmp_reflect(struct mbuf *m) { struct ip *ip = mtod(m, struct ip *); struct in_ifaddr *ia; + struct in_ifaddr_container *iac; struct in_addr t; struct mbuf *opts = 0; int optlen = (IP_VHL_HL(ip->ip_vhl) << 2) - sizeof(struct ip); @@ -634,9 +635,13 @@ icmp_reflect(struct mbuf *m) * or anonymous), use the address which corresponds * to the incoming interface. */ - LIST_FOREACH(ia, INADDR_HASH(t.s_addr), ia_hash) - if (t.s_addr == IA_SIN(ia)->sin_addr.s_addr) + ia = NULL; + LIST_FOREACH(iac, INADDR_HASH(t.s_addr), ia_hash) { + if (t.s_addr == IA_SIN(iac->ia)->sin_addr.s_addr) { + ia = iac->ia; goto match; + } + } if (m->m_pkthdr.rcvif != NULL && m->m_pkthdr.rcvif->if_flags & IFF_BROADCAST) { struct ifaddr_container *ifac; diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index f247753b6a..beda59d387 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -65,7 +65,7 @@ * * @(#)ip_input.c 8.2 (Berkeley) 1/4/94 * $FreeBSD: src/sys/netinet/ip_input.c,v 1.130.2.52 2003/03/07 07:01:28 silby Exp $ - * $DragonFly: src/sys/netinet/ip_input.c,v 1.80 2008/06/08 08:38:05 sephe Exp $ + * $DragonFly: src/sys/netinet/ip_input.c,v 1.81 2008/06/09 11:24:24 sephe Exp $ */ #define _IP_VHL @@ -206,7 +206,8 @@ extern struct domain inetdomain; extern struct protosw inetsw[]; u_char ip_protox[IPPROTO_MAX]; struct in_ifaddrhead in_ifaddrheads[MAXCPU]; /* first inet address */ -struct in_ifaddrhashhead *in_ifaddrhashtbl; /* inet addr hash table */ +struct in_ifaddrhashhead *in_ifaddrhashtbls[MAXCPU]; + /* inet addr hash table */ u_long in_ifaddrhmask; /* mask for hash table */ struct ip_stats ipstats_percpu[MAXCPU]; @@ -318,9 +319,11 @@ ip_init(void) */ mpipe_init(&ipq_mpipe, M_IPQ, sizeof(struct ipq), IFQ_MAXLEN, 4000, 0, NULL); - for (i = 0; i < ncpus; ++i) + for (i = 0; i < ncpus; ++i) { TAILQ_INIT(&in_ifaddrheads[i]); - in_ifaddrhashtbl = hashinit(INADDR_NHASH, M_IFADDR, &in_ifaddrhmask); + in_ifaddrhashtbls[i] = + hashinit(INADDR_NHASH, M_IFADDR, &in_ifaddrhmask); + } pr = pffindproto(PF_INET, IPPROTO_RAW, SOCK_RAW); if (pr == NULL) panic("ip_init"); @@ -433,6 +436,7 @@ ip_input(struct mbuf *m) struct ip *ip; struct ipq *fp; struct in_ifaddr *ia = NULL; + struct in_ifaddr_container *iac; int i, hlen, checkif; u_short sum; struct in_addr pkt_dst; @@ -697,7 +701,9 @@ pass: /* * Check for exact addresses in the hash bucket. */ - LIST_FOREACH(ia, INADDR_HASH(pkt_dst.s_addr), ia_hash) { + LIST_FOREACH(iac, INADDR_HASH(pkt_dst.s_addr), ia_hash) { + ia = iac->ia; + /* * If the address matches, verify that the packet * arrived via the correct interface if checking is @@ -707,6 +713,8 @@ pass: (!checkif || ia->ia_ifp == m->m_pkthdr.rcvif)) goto ours; } + ia = NULL; + /* * Check for broadcast addresses. * diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index d97525b6b8..fd4762e0a0 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -28,7 +28,7 @@ * * @(#)ip_output.c 8.3 (Berkeley) 1/21/94 * $FreeBSD: src/sys/netinet/ip_output.c,v 1.99.2.37 2003/04/15 06:44:45 silby Exp $ - * $DragonFly: src/sys/netinet/ip_output.c,v 1.43 2008/06/08 08:38:05 sephe Exp $ + * $DragonFly: src/sys/netinet/ip_output.c,v 1.44 2008/06/09 11:24:24 sephe Exp $ */ #define _IP_VHL @@ -837,6 +837,7 @@ spd_done: goto done; #else struct in_ifaddr *ia; + struct in_ifaddr_container *iac; /* * XXX sro_fwd below is static, and a pointer @@ -867,16 +868,19 @@ spd_done: * as the packet runs through ip_input() as * it is done through a ISR. */ - LIST_FOREACH(ia, INADDR_HASH(dst->sin_addr.s_addr), + ia = NULL; + LIST_FOREACH(iac, INADDR_HASH(dst->sin_addr.s_addr), ia_hash) { /* * If the addr to forward to is one * of ours, we pretend to * be the destination for this packet. */ - if (IA_SIN(ia)->sin_addr.s_addr == - dst->sin_addr.s_addr) + if (IA_SIN(iac->ia)->sin_addr.s_addr == + dst->sin_addr.s_addr) { + ia = iac->ia; break; + } } if (ia != NULL) { /* tell ip_input "dont filter" */ struct m_hdr tag; @@ -1786,7 +1790,7 @@ ip_multicast_if(struct in_addr *a, int *ifindexp) if (ifindexp) *ifindexp = ifindex; } else { - INADDR_TO_IFP(*a, ifp); + ifp = INADDR_TO_IFP(a); } return ifp; } -- 2.41.0