From 1b562c2435536c235208ab6f2a6c42e4a4149952 Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Sun, 8 Jun 2008 08:38:06 +0000 Subject: [PATCH] Parallelize in_ifaddrhead operation --- sys/net/if_var.h | 21 +++- sys/net/stf/if_stf.c | 9 +- sys/netinet/igmp.c | 4 +- sys/netinet/in.c | 132 ++++++++++++++++++++++++-- sys/netinet/in_gif.c | 8 +- sys/netinet/in_pcb.c | 24 +++-- sys/netinet/in_var.h | 29 +++--- sys/netinet/ip_carp.c | 7 +- sys/netinet/ip_input.c | 10 +- sys/netinet/ip_output.c | 6 +- sys/netinet/raw_ip.c | 16 +++- sys/netproto/atm/atm_if.c | 8 +- sys/netproto/atm/ipatm/ipatm_load.c | 10 +- sys/netproto/atm/ipatm/ipatm_output.c | 8 +- sys/netproto/ipsec/key.c | 8 +- sys/netproto/ipx/ipx_ip.c | 16 ++-- sys/netproto/key/key.c | 8 +- sys/vfs/nfs/nfs_vnops.c | 6 +- 18 files changed, 251 insertions(+), 79 deletions(-) diff --git a/sys/net/if_var.h b/sys/net/if_var.h index 39840b2cb2..f9b82106f2 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.55 2008/06/07 07:22:22 sephe Exp $ + * $DragonFly: src/sys/net/if_var.h,v 1.56 2008/06/08 08:38:05 sephe Exp $ */ #ifndef _NET_IF_VAR_H_ @@ -363,6 +363,17 @@ if_handoff(struct ifqueue *_ifq, struct mbuf *_m, struct ifnet *_ifp, #endif /* _KERNEL */ +struct in_ifaddr; + +struct in_ifaddr_container { + struct in_ifaddr *ia; + LIST_ENTRY(in_ifaddr_container) ia_hash; + /* entry in bucket of inet addresses */ + TAILQ_ENTRY(in_ifaddr_container) ia_link; + /* list of internet addresses */ + struct ifaddr_container *ia_ifac; /* parent ifaddr_container */ +}; + struct ifaddr_container { #define IFA_CONTAINER_MAGIC 0x19810219 #define IFA_CONTAINER_DEAD 0xc0dedead @@ -371,9 +382,17 @@ struct ifaddr_container { TAILQ_ENTRY(ifaddr_container) ifa_link; /* queue macro glue */ u_int ifa_refcnt; /* references to this structure */ uint32_t ifa_listmask; /* IFA_LIST_ */ + + /* + * Protocol specific states + */ + union { + struct in_ifaddr_container u_in_ifac; + } ifa_proto_u; }; #define IFA_LIST_IFADDRHEAD 0x1 /* on ifnet.if_addrheads[cpuid] */ +#define IFA_LIST_IN_IFADDRHEAD 0x2 /* on in_ifaddrheads[cpuid] */ /* * The ifaddr structure contains information about one address diff --git a/sys/net/stf/if_stf.c b/sys/net/stf/if_stf.c index 1419b5797a..907aad933f 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.22 2008/05/14 11:59:24 sephe Exp $ */ +/* $DragonFly: src/sys/net/stf/if_stf.c,v 1.23 2008/06/08 08:38:05 sephe Exp $ */ /* $KAME: if_stf.c,v 1.73 2001/12/03 11:08:30 keiichi Exp $ */ /* @@ -424,7 +424,7 @@ stf_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, static int stf_checkaddr4(struct stf_softc *sc, struct in_addr *in, struct ifnet *inifp) { - struct in_ifaddr *ia4; + struct in_ifaddr_container *iac; /* * reject packets with the following address: @@ -440,8 +440,9 @@ stf_checkaddr4(struct stf_softc *sc, struct in_addr *in, struct ifnet *inifp) /* * reject packets with broadcast */ - TAILQ_FOREACH(ia4, &in_ifaddrhead, ia_link) - { + TAILQ_FOREACH(iac, &in_ifaddrheads[mycpuid], ia_link) { + struct in_ifaddr *ia4 = iac->ia; + if ((ia4->ia_ifa.ifa_ifp->if_flags & IFF_BROADCAST) == 0) continue; if (in->s_addr == ia4->ia_broadaddr.sin_addr.s_addr) diff --git a/sys/netinet/igmp.c b/sys/netinet/igmp.c index ac63be9ce6..7179b26447 100644 --- a/sys/netinet/igmp.c +++ b/sys/netinet/igmp.c @@ -36,7 +36,7 @@ * * @(#)igmp.c 8.1 (Berkeley) 7/19/93 * $FreeBSD: src/sys/netinet/igmp.c,v 1.29.2.2 2003/01/23 21:06:44 sam Exp $ - * $DragonFly: src/sys/netinet/igmp.c,v 1.13 2006/12/22 23:57:52 swildner Exp $ + * $DragonFly: src/sys/netinet/igmp.c,v 1.14 2008/06/08 08:38:05 sephe Exp $ */ /* @@ -299,7 +299,7 @@ igmp_input(struct mbuf *m, ...) * can potentially get looped back if we are a multicast * router, so discard reports sourced by me. */ - IFP_TO_IA(ifp, ia); + ia = IFP_TO_IA(ifp); if (ia && ip->ip_src.s_addr == IA_SIN(ia)->sin_addr.s_addr) break; diff --git a/sys/netinet/in.c b/sys/netinet/in.c index 9818151e8e..e0ac707cd7 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.36 2008/06/08 03:58:03 sephe Exp $ + * $DragonFly: src/sys/netinet/in.c,v 1.37 2008/06/08 08:38:05 sephe Exp $ */ #include "opt_bootp.h" @@ -94,16 +94,23 @@ int in_localaddr(struct in_addr in) { u_long i = ntohl(in.s_addr); + struct in_ifaddr_container *iac; struct in_ifaddr *ia; if (subnetsarelocal) { - TAILQ_FOREACH(ia, &in_ifaddrhead, ia_link) + TAILQ_FOREACH(iac, &in_ifaddrheads[mycpuid], ia_link) { + ia = iac->ia; + if ((i & ia->ia_netmask) == ia->ia_net) return (1); + } } else { - TAILQ_FOREACH(ia, &in_ifaddrhead, ia_link) + TAILQ_FOREACH(iac, &in_ifaddrheads[mycpuid], ia_link) { + ia = iac->ia; + if ((i & ia->ia_subnetmask) == ia->ia_subnet) return (1); + } } return (0); } @@ -261,6 +268,101 @@ in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp, } } +static void +in_ialink_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_IFADDRHEAD) == 0, + ("ia is on in_ifaddrheads\n")); + + ifac->ifa_listmask |= IFA_LIST_IN_IFADDRHEAD; + iac = &ifac->ifa_proto_u.u_in_ifac; + TAILQ_INSERT_TAIL(&in_ifaddrheads[cpu], iac, ia_link); + + crit_exit(); + + ifa_forwardmsg(lmsg, cpu + 1); +} + +static void +in_iaunlink_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_IFADDRHEAD, + ("ia is not on in_ifaddrheads\n")); + + iac = &ifac->ifa_proto_u.u_in_ifac; + TAILQ_REMOVE(&in_ifaddrheads[cpu], iac, ia_link); + ifac->ifa_listmask &= ~IFA_LIST_IN_IFADDRHEAD; + + crit_exit(); + + ifa_forwardmsg(lmsg, cpu + 1); +} + +static void +in_ialink(struct in_ifaddr *ia) +{ + struct netmsg nmsg; + struct lwkt_msg *lmsg; + + netmsg_init(&nmsg, &curthread->td_msgport, 0, in_ialink_dispatch); + lmsg = &nmsg.nm_lmsg; + lmsg->u.ms_resultp = ia; + + ifa_domsg(lmsg); +} + +void +in_iaunlink(struct in_ifaddr *ia) +{ + struct netmsg nmsg; + struct lwkt_msg *lmsg; + + netmsg_init(&nmsg, &curthread->td_msgport, 0, in_iaunlink_dispatch); + lmsg = &nmsg.nm_lmsg; + lmsg->u.ms_resultp = ia; + + ifa_domsg(lmsg); +} + +static __inline struct in_ifaddr * +in_ianext(struct in_ifaddr *oia) +{ + struct ifaddr_container *ifac; + struct in_ifaddr_container *iac; + + ifac = &oia->ia_ifa.ifa_containers[mycpuid]; + ASSERT_IFAC_VALID(ifac); + KASSERT(ifac->ifa_listmask & IFA_LIST_IN_IFADDRHEAD, + ("ia is not on in_ifaddrheads\n")); + + iac = &ifac->ifa_proto_u.u_in_ifac; + iac = TAILQ_NEXT(iac, ia_link); + if (iac != NULL) + return iac->ia; + else + return NULL; +} + static int in_control_internal(u_long cmd, caddr_t data, struct ifnet *ifp, struct thread *td) @@ -269,6 +371,7 @@ in_control_internal(u_long cmd, caddr_t data, struct ifnet *ifp, struct in_ifaddr *ia = 0, *iap; struct in_addr dst; struct in_aliasreq *ifra = (struct in_aliasreq *)data; + struct ifaddr_container *ifac; struct sockaddr_in oldaddr; int hostIsNew, iaIsNew, maskIsNew; int error = 0; @@ -290,8 +393,6 @@ in_control_internal(u_long cmd, caddr_t data, struct ifnet *ifp, break; } if (ia == NULL) { - struct ifaddr_container *ifac; - TAILQ_FOREACH(ifac, &ifp->if_addrheads[mycpuid], ifa_link) { iap = ifatoia(ifac->ifa); @@ -314,7 +415,7 @@ in_control_internal(u_long cmd, caddr_t data, struct ifnet *ifp, ia->ia_addr.sin_addr.s_addr == ifra->ifra_addr.sin_addr.s_addr) break; - ia = TAILQ_NEXT(ia, ia_link); + ia = in_ianext(ia); } if ((ifp->if_flags & IFF_POINTOPOINT) && cmd == SIOCAIFADDR && @@ -340,8 +441,22 @@ in_control_internal(u_long cmd, caddr_t data, struct ifnet *ifp, if (ia == NULL) { struct ifaddr *ifa; + int i; ia = ifa_create(sizeof(*ia), M_WAITOK); + ifa = &ia->ia_ifa; + + /* + * 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; + iac->ia_ifac = ifac; + } /* * Protect from NETISR_IP traversing address list @@ -349,8 +464,7 @@ in_control_internal(u_long cmd, caddr_t data, struct ifnet *ifp, */ crit_enter(); - TAILQ_INSERT_TAIL(&in_ifaddrhead, ia, ia_link); - ifa = &ia->ia_ifa; + in_ialink(ia); ifa_iflink(ifa, ifp, 1); ifa->ifa_addr = (struct sockaddr *)&ia->ia_addr; @@ -517,13 +631,13 @@ 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 */ - TAILQ_REMOVE(&in_ifaddrhead, ia, ia_link); if (cmd == SIOCDIFADDR && ia->ia_addr.sin_family == AF_INET) { /* XXX Assume that 'ia' is in hash table */ LIST_REMOVE(ia, ia_hash); diff --git a/sys/netinet/in_gif.c b/sys/netinet/in_gif.c index 74684ac0e2..0b7ce017fd 100644 --- a/sys/netinet/in_gif.c +++ b/sys/netinet/in_gif.c @@ -1,6 +1,6 @@ /* * $FreeBSD: src/sys/netinet/in_gif.c,v 1.5.2.11 2003/01/23 21:06:45 sam Exp $ - * $DragonFly: src/sys/netinet/in_gif.c,v 1.16 2006/12/22 23:57:52 swildner Exp $ + * $DragonFly: src/sys/netinet/in_gif.c,v 1.17 2008/06/08 08:38:05 sephe Exp $ * $KAME: in_gif.c,v 1.54 2001/05/14 14:02:16 itojun Exp $ */ /* @@ -296,7 +296,7 @@ static int gif_validate4(const struct ip *ip, struct gif_softc *sc, struct ifnet *ifp) { struct sockaddr_in *src, *dst; - struct in_ifaddr *ia4; + struct in_ifaddr_container *iac; src = (struct sockaddr_in *)sc->gif_psrc; dst = (struct sockaddr_in *)sc->gif_pdst; @@ -314,7 +314,9 @@ gif_validate4(const struct ip *ip, struct gif_softc *sc, struct ifnet *ifp) return 0; } /* reject packets with broadcast on source */ - TAILQ_FOREACH(ia4, &in_ifaddrhead, ia_link) { + TAILQ_FOREACH(iac, &in_ifaddrheads[mycpuid], ia_link) { + struct in_ifaddr *ia4 = iac->ia; + if (!(ia4->ia_ifa.ifa_ifp->if_flags & IFF_BROADCAST)) continue; if (ip->ip_src.s_addr == ia4->ia_broadaddr.sin_addr.s_addr) diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c index afaa40f5c4..a69b9c165e 100644 --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -65,7 +65,7 @@ * * @(#)in_pcb.c 8.4 (Berkeley) 5/24/95 * $FreeBSD: src/sys/netinet/in_pcb.c,v 1.59.2.27 2004/01/02 04:06:42 ambrisko Exp $ - * $DragonFly: src/sys/netinet/in_pcb.c,v 1.45 2008/03/26 14:44:59 sephe Exp $ + * $DragonFly: src/sys/netinet/in_pcb.c,v 1.46 2008/06/08 08:38:05 sephe Exp $ */ #include "opt_ipsec.h" @@ -246,7 +246,7 @@ in_pcbbind(struct inpcb *inp, struct sockaddr *nam, struct thread *td) KKASSERT(p); - if (TAILQ_EMPTY(&in_ifaddrhead)) /* XXX broken! */ + if (TAILQ_EMPTY(&in_ifaddrheads[mycpuid])) /* XXX broken! */ return (EADDRNOTAVAIL); if (inp->inp_lport != 0 || inp->inp_laddr.s_addr != INADDR_ANY) return (EINVAL); /* already bound */ @@ -453,8 +453,8 @@ in_pcbladdr(struct inpcb *inp, struct sockaddr *nam, cred = td->td_proc->p_ucred; if (cred && cred->cr_prison) jailed = 1; - if (!TAILQ_EMPTY(&in_ifaddrhead)) { - ia = TAILQ_FIRST(&in_ifaddrhead); + if (!TAILQ_EMPTY(&in_ifaddrheads[mycpuid])) { + ia = TAILQ_FIRST(&in_ifaddrheads[mycpuid])->ia; /* * If the destination address is INADDR_ANY, * use the primary local address. @@ -530,8 +530,9 @@ in_pcbladdr(struct inpcb *inp, struct sockaddr *nam, sintosa(&ia->ia_addr))) ia = NULL; sin->sin_port = fport; - if (ia == NULL) - ia = TAILQ_FIRST(&in_ifaddrhead); + if (ia == NULL && + !TAILQ_EMPTY(&in_ifaddrheads[mycpuid])) + ia = TAILQ_FIRST(&in_ifaddrheads[mycpuid])->ia; if (ia && jailed && !jailed_ip(cred->cr_prison, sintosa(&ia->ia_addr))) ia = NULL; @@ -551,10 +552,17 @@ in_pcbladdr(struct inpcb *inp, struct sockaddr *nam, imo = inp->inp_moptions; if (imo->imo_multicast_ifp != NULL) { + struct in_ifaddr_container *iac; + ifp = imo->imo_multicast_ifp; - TAILQ_FOREACH(ia, &in_ifaddrhead, ia_link) - if (ia->ia_ifp == ifp) + ia = NULL; + TAILQ_FOREACH(iac, + &in_ifaddrheads[mycpuid], ia_link) { + if (iac->ia->ia_ifp == ifp) { + ia = iac->ia; break; + } + } if (ia == NULL) goto fail; } diff --git a/sys/netinet/in_var.h b/sys/netinet/in_var.h index a9d665f05a..0b33312983 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.11 2006/05/20 02:42:12 dillon Exp $ + * $DragonFly: src/sys/netinet/in_var.h,v 1.12 2008/06/08 08:38:05 sephe Exp $ */ #ifndef _NETINET_IN_VAR_H_ @@ -68,7 +68,7 @@ struct in_ifaddr { 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 */ - TAILQ_ENTRY(in_ifaddr) ia_link; /* list of internet addresses */ + void *ia_pad2[2]; struct sockaddr_in ia_addr; /* reserve space for interface name */ struct sockaddr_in ia_dstaddr; /* reserve space for broadcast addr */ #define ia_broadaddr ia_dstaddr @@ -94,6 +94,8 @@ struct in_aliasreq { #ifdef _KERNEL +struct in_ifaddr_container; + extern struct in_addr zeroin_addr; extern u_char inetctlerrmap[]; @@ -101,7 +103,7 @@ extern u_char inetctlerrmap[]; * Hash table for IP addresses. */ extern LIST_HEAD(in_ifaddrhashhead, in_ifaddr) *in_ifaddrhashtbl; -extern TAILQ_HEAD(in_ifaddrhead, in_ifaddr) in_ifaddrhead; +extern TAILQ_HEAD(in_ifaddrhead, in_ifaddr_container) in_ifaddrheads[]; extern u_long in_ifaddrhmask; /* mask for hash table */ #define INADDR_NHASH_LOG2 9 @@ -131,16 +133,18 @@ extern u_long in_ifaddrhmask; /* mask for hash table */ * Macro for finding the internet address structure (in_ifaddr) corresponding * to a given interface (ifnet structure). */ -#define IFP_TO_IA(ifp, ia) \ - /* struct ifnet *ifp; */ \ - /* struct in_ifaddr *ia; */ \ -{ \ - for ((ia) = TAILQ_FIRST(&in_ifaddrhead); \ - (ia) != NULL && (ia)->ia_ifp != (ifp); \ - (ia) = TAILQ_NEXT((ia), ia_link)) \ - continue; \ +static __inline struct in_ifaddr * +IFP_TO_IA(const struct ifnet *_ifp) +{ + struct in_ifaddr_container *_iac; + + TAILQ_FOREACH(_iac, &in_ifaddrheads[mycpuid], ia_link) + if (_iac->ia->ia_ifp == _ifp) + return _iac->ia; + return NULL; } -#endif + +#endif /* _KERNEL */ /* * This information should be part of the ifnet structure but we don't wish @@ -245,6 +249,7 @@ void in_rtqdrain (void); 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 *); 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_carp.c b/sys/netinet/ip_carp.c index f775f29c4d..7ab954684d 100644 --- a/sys/netinet/ip_carp.c +++ b/sys/netinet/ip_carp.c @@ -25,7 +25,7 @@ */ /* * $FreeBSD: src/sys/netinet/ip_carp.c,v 1.48 2007/02/02 09:39:09 glebius Exp $ - * $DragonFly: src/sys/netinet/ip_carp.c,v 1.8 2008/05/28 12:11:13 sephe Exp $ + * $DragonFly: src/sys/netinet/ip_carp.c,v 1.9 2008/06/08 08:38:05 sephe Exp $ */ #include "opt_carp.h" @@ -1431,6 +1431,7 @@ carp_set_addr(struct carp_softc *sc, struct sockaddr_in *sin) struct ifnet *ifp; struct carp_if *cif; struct in_ifaddr *ia, *ia_if; + struct in_ifaddr_container *iac; struct ip_moptions *imo = &sc->sc_imo; struct in_addr addr; u_long iaddr = htonl(sin->sin_addr.s_addr); @@ -1451,7 +1452,9 @@ carp_set_addr(struct carp_softc *sc, struct sockaddr_in *sin) } /* we have to do it by hands to check we won't match on us */ ia_if = NULL; own = 0; - TAILQ_FOREACH(ia, &in_ifaddrhead, ia_link) { + TAILQ_FOREACH(iac, &in_ifaddrheads[mycpuid], ia_link) { + ia = iac->ia; + /* and, yeah, we need a multicast-capable iface too */ if (ia->ia_ifp != SC2IFP(sc) && (ia->ia_ifp->if_flags & IFF_MULTICAST) && diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index ba9a853f3e..f247753b6a 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.79 2008/04/20 13:44:25 swildner Exp $ + * $DragonFly: src/sys/netinet/ip_input.c,v 1.80 2008/06/08 08:38:05 sephe Exp $ */ #define _IP_VHL @@ -205,7 +205,7 @@ static int ipprintfs = 0; extern struct domain inetdomain; extern struct protosw inetsw[]; u_char ip_protox[IPPROTO_MAX]; -struct in_ifaddrhead in_ifaddrhead; /* first inet address */ +struct in_ifaddrhead in_ifaddrheads[MAXCPU]; /* first inet address */ struct in_ifaddrhashhead *in_ifaddrhashtbl; /* inet addr hash table */ u_long in_ifaddrhmask; /* mask for hash table */ @@ -318,7 +318,8 @@ ip_init(void) */ mpipe_init(&ipq_mpipe, M_IPQ, sizeof(struct ipq), IFQ_MAXLEN, 4000, 0, NULL); - TAILQ_INIT(&in_ifaddrhead); + for (i = 0; i < ncpus; ++i) + TAILQ_INIT(&in_ifaddrheads[i]); in_ifaddrhashtbl = hashinit(INADDR_NHASH, M_IFADDR, &in_ifaddrhmask); pr = pffindproto(PF_INET, IPPROTO_RAW, SOCK_RAW); if (pr == NULL) @@ -663,7 +664,8 @@ pass: * we receive might be for us (and let the upper layers deal * with it). */ - if (TAILQ_EMPTY(&in_ifaddrhead) && !(m->m_flags & (M_MCAST | M_BCAST))) + if (TAILQ_EMPTY(&in_ifaddrheads[mycpuid]) && + !(m->m_flags & (M_MCAST | M_BCAST))) goto ours; /* diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index 34e754e29e..d97525b6b8 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.42 2008/05/14 11:59:24 sephe Exp $ + * $DragonFly: src/sys/netinet/ip_output.c,v 1.43 2008/06/08 08:38:05 sephe Exp $ */ #define _IP_VHL @@ -272,7 +272,7 @@ ip_output(struct mbuf *m0, struct mbuf *opt, struct route *ro, * packets if the interface is specified. */ ifp = imo->imo_multicast_ifp; - IFP_TO_IA(ifp, ia); + ia = IFP_TO_IA(ifp); isbroadcast = 0; /* fool gcc */ } else { /* @@ -2111,7 +2111,7 @@ ip_getmoptions(struct sockopt *sopt, struct ip_moptions *imo) /* return the value user has set */ addr = imo->imo_multicast_addr; } else { - IFP_TO_IA(imo->imo_multicast_ifp, ia); + ia = IFP_TO_IA(imo->imo_multicast_ifp); addr.s_addr = (ia == NULL) ? INADDR_ANY : IA_SIN(ia)->sin_addr.s_addr; } diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c index 9363832344..b6c05edd37 100644 --- a/sys/netinet/raw_ip.c +++ b/sys/netinet/raw_ip.c @@ -32,7 +32,7 @@ * * @(#)raw_ip.c 8.7 (Berkeley) 5/15/95 * $FreeBSD: src/sys/netinet/raw_ip.c,v 1.64.2.16 2003/08/24 08:24:38 hsu Exp $ - * $DragonFly: src/sys/netinet/raw_ip.c,v 1.29 2008/05/17 20:33:35 dillon Exp $ + * $DragonFly: src/sys/netinet/raw_ip.c,v 1.30 2008/06/08 08:38:05 sephe Exp $ */ #include "opt_inet6.h" @@ -448,13 +448,16 @@ void rip_ctlinput(int cmd, struct sockaddr *sa, void *vip) { struct in_ifaddr *ia; + struct in_ifaddr_container *iac; struct ifnet *ifp; int err; int flags; switch (cmd) { case PRC_IFDOWN: - TAILQ_FOREACH(ia, &in_ifaddrhead, ia_link) { + TAILQ_FOREACH(iac, &in_ifaddrheads[mycpuid], ia_link) { + ia = iac->ia; + if (ia->ia_ifa.ifa_addr == sa && (ia->ia_flags & IFA_ROUTE)) { /* @@ -474,11 +477,14 @@ rip_ctlinput(int cmd, struct sockaddr *sa, void *vip) break; case PRC_IFUP: - TAILQ_FOREACH(ia, &in_ifaddrhead, ia_link) { - if (ia->ia_ifa.ifa_addr == sa) + ia = NULL; + TAILQ_FOREACH(iac, &in_ifaddrheads[mycpuid], ia_link) { + if (iac->ia->ia_ifa.ifa_addr == sa) { + ia = iac->ia; break; + } } - if (ia == 0 || (ia->ia_flags & IFA_ROUTE)) + if (ia == NULL || (ia->ia_flags & IFA_ROUTE)) return; flags = RTF_UP; ifp = ia->ia_ifa.ifa_ifp; diff --git a/sys/netproto/atm/atm_if.c b/sys/netproto/atm/atm_if.c index bedb637603..5c59bba309 100644 --- a/sys/netproto/atm/atm_if.c +++ b/sys/netproto/atm/atm_if.c @@ -24,7 +24,7 @@ * notice must be reproduced on all copies. * * @(#) $FreeBSD: src/sys/netatm/atm_if.c,v 1.5 1999/08/28 00:48:35 peter Exp $ - * @(#) $DragonFly: src/sys/netproto/atm/atm_if.c,v 1.17 2008/05/14 11:59:24 sephe Exp $ + * @(#) $DragonFly: src/sys/netproto/atm/atm_if.c,v 1.18 2008/06/08 08:38:05 sephe Exp $ */ /* @@ -360,7 +360,7 @@ atm_physif_ioctl(int code, caddr_t data, caddr_t arg) KM_ZERO((caddr_t)&anr, sizeof(anr)); ksnprintf(anr.anp_intf, sizeof(anr.anp_intf), "%s", ifp->if_xname); - IFP_TO_IA(ifp, ia); + ia = IFP_TO_IA(ifp); if (ia) { anr.anp_proto_addr = *ia->ia_ifa.ifa_addr; } @@ -799,7 +799,7 @@ atm_nif_detach(struct atm_nif *nip) * Free all interface routes and addresses */ while (1) { - IFP_TO_IA(ifp, ia); + ia = IFP_TO_IA(ifp); if (ia == NULL) break; @@ -809,7 +809,7 @@ atm_nif_detach(struct atm_nif *nip) /* Remove interface address from queues */ ifa = &ia->ia_ifa; ifa_ifunlink(ifa, ifp); - TAILQ_REMOVE(&in_ifaddrhead, ia, ia_link); + in_iaunlink(ia); /* Free interface address */ ifa_destroy(ifa); diff --git a/sys/netproto/atm/ipatm/ipatm_load.c b/sys/netproto/atm/ipatm/ipatm_load.c index dd1013c9b4..844b75bd68 100644 --- a/sys/netproto/atm/ipatm/ipatm_load.c +++ b/sys/netproto/atm/ipatm/ipatm_load.c @@ -24,7 +24,7 @@ * notice must be reproduced on all copies. * * @(#) $FreeBSD: src/sys/netatm/ipatm/ipatm_load.c,v 1.6 2000/01/17 20:49:43 mks Exp $ - * @(#) $DragonFly: src/sys/netproto/atm/ipatm/ipatm_load.c,v 1.9 2006/01/14 13:36:39 swildner Exp $ + * @(#) $DragonFly: src/sys/netproto/atm/ipatm/ipatm_load.c,v 1.10 2008/06/08 08:38:05 sephe Exp $ */ /* @@ -414,6 +414,7 @@ ipatm_start(void) for (nip = pip->pif_nif; nip; nip = nip->nif_pnext) { struct ifnet *ifp = (struct ifnet *)nip; struct in_ifaddr *ia; + struct in_ifaddr_container *iac; /* * Attach interface @@ -427,11 +428,12 @@ ipatm_start(void) /* * If IP address has been set, register it */ - TAILQ_FOREACH(ia, &in_ifaddrhead, ia_link) { - if (ia->ia_ifp == ifp) + TAILQ_FOREACH(iac, &in_ifaddrheads[mycpuid], ia_link) { + if (iac->ia->ia_ifp == ifp) break; } - if (ia) { + if (iac) { + ia = iac->ia; err = ipatm_nifstat(NCM_SETADDR, nip, (int)ia); if (err) { crit_exit(); diff --git a/sys/netproto/atm/ipatm/ipatm_output.c b/sys/netproto/atm/ipatm/ipatm_output.c index c1ae39280d..64c444ea35 100644 --- a/sys/netproto/atm/ipatm/ipatm_output.c +++ b/sys/netproto/atm/ipatm/ipatm_output.c @@ -24,7 +24,7 @@ * notice must be reproduced on all copies. * * @(#) $FreeBSD: src/sys/netatm/ipatm/ipatm_output.c,v 1.4.2.1 2000/06/02 22:39:08 archie Exp $ - * @(#) $DragonFly: src/sys/netproto/atm/ipatm/ipatm_output.c,v 1.7 2006/01/14 13:36:39 swildner Exp $ + * @(#) $DragonFly: src/sys/netproto/atm/ipatm/ipatm_output.c,v 1.8 2008/06/08 08:38:05 sephe Exp $ */ /* @@ -110,7 +110,7 @@ ipatm_ifoutput(struct ifnet *ifp, KBuffer *m, struct sockaddr *dst) ivp->iv_queue = m; } } else { - struct in_ifaddr *ia; + struct in_ifaddr_container *iac; /* * No VCC to destination @@ -119,7 +119,9 @@ ipatm_ifoutput(struct ifnet *ifp, KBuffer *m, struct sockaddr *dst) /* * Is packet for our interface address? */ - TAILQ_FOREACH(ia, &in_ifaddrhead, ia_link) { + TAILQ_FOREACH(iac, &in_ifaddrheads[mycpuid], ia_link) { + struct in_ifaddr *ia = iac->ia; + if (ia->ia_ifp != ifp) continue; if (((struct sockaddr_in *)dst)->sin_addr.s_addr == diff --git a/sys/netproto/ipsec/key.c b/sys/netproto/ipsec/key.c index a6fc2cf6f0..edf2a0c67c 100644 --- a/sys/netproto/ipsec/key.c +++ b/sys/netproto/ipsec/key.c @@ -1,5 +1,5 @@ /* $FreeBSD: src/sys/netipsec/key.c,v 1.3.2.1 2003/01/24 05:11:35 sam Exp $ */ -/* $DragonFly: src/sys/netproto/ipsec/key.c,v 1.25 2007/05/13 18:33:58 swildner Exp $ */ +/* $DragonFly: src/sys/netproto/ipsec/key.c,v 1.26 2008/06/08 08:38:05 sephe Exp $ */ /* $KAME: key.c,v 1.191 2001/06/27 10:46:49 sakane Exp $ */ /* @@ -3506,7 +3506,7 @@ key_ismyaddr(struct sockaddr *sa) { #ifdef INET struct sockaddr_in *sin; - struct in_ifaddr *ia; + struct in_ifaddr_container *iac; #endif /* sanity check */ @@ -3517,7 +3517,9 @@ key_ismyaddr(struct sockaddr *sa) #ifdef INET case AF_INET: sin = (struct sockaddr_in *)sa; - TAILQ_FOREACH(ia, &in_ifaddrhead, ia_link) { + TAILQ_FOREACH(iac, &in_ifaddrheads[mycpuid], ia_link) { + struct in_ifaddr *ia = iac->ia; + if (sin->sin_family == ia->ia_addr.sin_family && sin->sin_len == ia->ia_addr.sin_len && sin->sin_addr.s_addr == ia->ia_addr.sin_addr.s_addr) diff --git a/sys/netproto/ipx/ipx_ip.c b/sys/netproto/ipx/ipx_ip.c index 83be382148..4f4cab588a 100644 --- a/sys/netproto/ipx/ipx_ip.c +++ b/sys/netproto/ipx/ipx_ip.c @@ -34,7 +34,7 @@ * @(#)ipx_ip.c * * $FreeBSD: src/sys/netipx/ipx_ip.c,v 1.24.2.2 2003/01/23 21:06:48 sam Exp $ - * $DragonFly: src/sys/netproto/ipx/ipx_ip.c,v 1.17 2008/05/14 11:59:24 sephe Exp $ + * $DragonFly: src/sys/netproto/ipx/ipx_ip.c,v 1.18 2008/06/08 08:38:05 sephe Exp $ */ /* @@ -344,14 +344,18 @@ ipxip_route(struct socket *so, struct sockopt *sopt) */ { struct in_ifaddr *ia; + struct in_ifaddr_container *iac; struct ifnet *ifp = ro.ro_rt->rt_ifp; - for (ia = TAILQ_FIRST(&in_ifaddrhead); ia != NULL; - ia = TAILQ_NEXT(ia, ia_link)) - if (ia->ia_ifp == ifp) + ia = NULL; + TAILQ_FOREACH(iac, &in_ifaddrheads[mycpuid], ia_link) { + if (iac->ia->ia_ifp == ifp) { + ia = iac->ia; break; - if (ia == NULL) - ia = TAILQ_FIRST(&in_ifaddrhead); + } + } + if (ia == NULL && !TAILQ_EMPTY(&in_ifaddrheads[mycpuid])) + ia = TAILQ_FIRST(&in_ifaddrheads[mycpuid])->ia; if (ia == NULL) { RTFREE(ro.ro_rt); return (EADDRNOTAVAIL); diff --git a/sys/netproto/key/key.c b/sys/netproto/key/key.c index 2e39146660..c2a0fd5b75 100644 --- a/sys/netproto/key/key.c +++ b/sys/netproto/key/key.c @@ -1,5 +1,5 @@ /* $FreeBSD: src/sys/netkey/key.c,v 1.16.2.13 2002/07/24 18:17:40 ume Exp $ */ -/* $DragonFly: src/sys/netproto/key/key.c,v 1.20 2007/05/13 18:33:58 swildner Exp $ */ +/* $DragonFly: src/sys/netproto/key/key.c,v 1.21 2008/06/08 08:38:05 sephe Exp $ */ /* $KAME: key.c,v 1.191 2001/06/27 10:46:49 sakane Exp $ */ /* @@ -3714,7 +3714,7 @@ key_ismyaddr(struct sockaddr *sa) { #ifdef INET struct sockaddr_in *sin; - struct in_ifaddr *ia; + struct in_ifaddr_container *iac; #endif /* sanity check */ @@ -3725,7 +3725,9 @@ key_ismyaddr(struct sockaddr *sa) #ifdef INET case AF_INET: sin = (struct sockaddr_in *)sa; - TAILQ_FOREACH(ia, &in_ifaddrhead, ia_link) { + TAILQ_FOREACH(iac, &in_ifaddrheads[mycpuid], ia_link) { + struct in_ifaddr *ia = iac->ia; + if (sin->sin_family == ia->ia_addr.sin_family && sin->sin_len == ia->ia_addr.sin_len && sin->sin_addr.s_addr == ia->ia_addr.sin_addr.s_addr) diff --git a/sys/vfs/nfs/nfs_vnops.c b/sys/vfs/nfs/nfs_vnops.c index 99ef9552f3..2b5658ed4f 100644 --- a/sys/vfs/nfs/nfs_vnops.c +++ b/sys/vfs/nfs/nfs_vnops.c @@ -35,7 +35,7 @@ * * @(#)nfs_vnops.c 8.16 (Berkeley) 5/27/95 * $FreeBSD: src/sys/nfs/nfs_vnops.c,v 1.150.2.5 2001/12/20 19:56:28 dillon Exp $ - * $DragonFly: src/sys/vfs/nfs/nfs_vnops.c,v 1.76 2007/11/02 19:52:28 dillon Exp $ + * $DragonFly: src/sys/vfs/nfs/nfs_vnops.c,v 1.77 2008/06/08 08:38:06 sephe Exp $ */ @@ -1498,8 +1498,8 @@ again: *tl = txdr_unsigned(NFSV3CREATE_EXCLUSIVE); nfsm_build(tl, u_int32_t *, NFSX_V3CREATEVERF); #ifdef INET - if (!TAILQ_EMPTY(&in_ifaddrhead)) - *tl++ = IA_SIN(TAILQ_FIRST(&in_ifaddrhead))->sin_addr.s_addr; + if (!TAILQ_EMPTY(&in_ifaddrheads[mycpuid])) + *tl++ = IA_SIN(TAILQ_FIRST(&in_ifaddrheads[mycpuid])->ia)->sin_addr.s_addr; else #endif *tl++ = create_verf; -- 2.41.0