Parallelize in_ifaddrhashtbl
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Mon, 9 Jun 2008 11:24:24 +0000 (11:24 +0000)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Mon, 9 Jun 2008 11:24:24 +0000 (11:24 +0000)
sys/net/if_var.h
sys/net/ipfw/ip_fw2.c
sys/net/sppp/if_spppsubr.c
sys/net/stf/if_stf.c
sys/netinet/if_ether.c
sys/netinet/in.c
sys/netinet/in_var.h
sys/netinet/ip_icmp.c
sys/netinet/ip_input.c
sys/netinet/ip_output.c

index f9b8210..ac56c93 100644 (file)
@@ -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
index 7f5f83b..e641126 100644 (file)
@@ -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;
index 18f37f6..46010a0 100644 (file)
@@ -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 <sys/param.h>
@@ -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);
index 907aad9..a6de013 100644 (file)
@@ -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;
index 725c137..16e22e9 100644 (file)
@@ -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;
index 009244d..a38df2d 100644 (file)
@@ -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);
 }
 
index 0b33312..0be0c04 100644 (file)
@@ -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);
index 080a81f..9eae51c 100644 (file)
@@ -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;
index f247753..beda59d 100644 (file)
@@ -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.
         *
index d97525b..fd4762e 100644 (file)
@@ -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;
 }