diff options
| author | tls <tls@NetBSD.org> | 1998-02-13 18:21:38 +0000 |
|---|---|---|
| committer | tls <tls@NetBSD.org> | 1998-02-13 18:21:38 +0000 |
| commit | c9934a9084072c26dce46dec672ca96af20b1b4e (patch) | |
| tree | a8301bd074fd52744bde22806c5b526d3aac893c /sys | |
| parent | 561bc2f4adcfc785278fc189f1a5ef95ff941871 (diff) | |
Change list of interface IP addresses to a hash. Improves performance on hosts with a large number of IP addresses significantly.
Diffstat (limited to 'sys')
| -rw-r--r-- | sys/netinet/if_arp.c | 33 | ||||
| -rw-r--r-- | sys/netinet/igmp.c | 8 | ||||
| -rw-r--r-- | sys/netinet/in.c | 23 | ||||
| -rw-r--r-- | sys/netinet/in_pcb.c | 52 | ||||
| -rw-r--r-- | sys/netinet/in_var.h | 53 | ||||
| -rw-r--r-- | sys/netinet/ip_icmp.c | 31 | ||||
| -rw-r--r-- | sys/netinet/ip_input.c | 32 | ||||
| -rw-r--r-- | sys/netinet/ip_output.c | 11 |
8 files changed, 152 insertions, 91 deletions
diff --git a/sys/netinet/if_arp.c b/sys/netinet/if_arp.c index be09d1a24cf..ed8cbd91ed1 100644 --- a/sys/netinet/if_arp.c +++ b/sys/netinet/if_arp.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_arp.c,v 1.43 1998/01/05 10:31:44 thorpej Exp $ */ +/* $NetBSD: if_arp.c,v 1.44 1998/02/13 18:21:38 tls Exp $ */ /* * Copyright (c) 1982, 1986, 1988, 1993 @@ -467,7 +467,7 @@ in_arpinput(m) register struct ifnet *ifp = m->m_pkthdr.rcvif; register struct llinfo_arp *la = 0; register struct rtentry *rt; - struct in_ifaddr *ia, *maybe_ia = 0; + struct in_ifaddr *ia; struct sockaddr_dl *sdl; struct sockaddr sa; struct in_addr isaddr, itaddr, myaddr; @@ -488,24 +488,27 @@ in_arpinput(m) /* * If the source IP address is zero, this is most likely a - * confused host trying to use IP address zero. (Windoze?) - * XXX: Should we bother trying to reply to these? + * confused host trying to use IP address zero. (Windoze?) + * XXX: Should we bother trying to reply to these? */ if (in_nullhost(isaddr)) goto out; - /* Search for a matching interface address. */ - for (ia = in_ifaddr.tqh_first; ia != 0; ia = ia->ia_list.tqe_next) - if (ia->ia_ifp == ifp) { - maybe_ia = ia; - if (in_hosteq(itaddr, ia->ia_addr.sin_addr) || - in_hosteq(isaddr, ia->ia_addr.sin_addr)) - break; - } - if (maybe_ia == 0) - goto out; + /* + * Search for a matching interface address + * or any address on the interface to use + * as a dummy address in the rest of this function + */ + INADDR_TO_IA(itaddr, ia); + if (ia == NULL) { + INADDR_TO_IA(isaddr, ia); + if (ia == NULL) { + IFP_TO_IA(ifp, ia); + if (ia == NULL) goto out; + } + } + myaddr = ia->ia_addr.sin_addr; - myaddr = ia ? ia->ia_addr.sin_addr : maybe_ia->ia_addr.sin_addr; if (!bcmp((caddr_t)ar_sha(ah), LLADDR(ifp->if_sadl), ifp->if_data.ifi_addrlen)) goto out; /* it's from me, ignore it. */ diff --git a/sys/netinet/igmp.c b/sys/netinet/igmp.c index 73a5fa049ae..b0528a6bdf0 100644 --- a/sys/netinet/igmp.c +++ b/sys/netinet/igmp.c @@ -1,4 +1,4 @@ -/* $NetBSD: igmp.c,v 1.17 1998/01/12 03:02:48 scottr Exp $ */ +/* $NetBSD: igmp.c,v 1.18 1998/02/13 18:21:40 tls Exp $ */ /* * Internet Group Management Protocol (IGMP) routines. @@ -266,7 +266,7 @@ igmp_input(m, va_alist) * determine the arrival interface of an incoming packet. */ if ((ip->ip_src.s_addr & IN_CLASSA_NET) == 0) { - IFP_TO_IA(ifp, ia); + IFP_TO_IA(ifp, ia); /* XXX */ if (ia) ip->ip_src.s_addr = ia->ia_subnet; } @@ -305,7 +305,7 @@ igmp_input(m, va_alist) * leave requires knowing that we are the only member of a * group. */ - IFP_TO_IA(ifp, ia); + IFP_TO_IA(ifp, ia); /* XXX */ if (ia && in_hosteq(ip->ip_src, ia->ia_addr.sin_addr)) break; #endif @@ -333,7 +333,7 @@ igmp_input(m, va_alist) */ if ((ip->ip_src.s_addr & IN_CLASSA_NET) == 0) { #ifndef MROUTING - IFP_TO_IA(ifp, ia); + IFP_TO_IA(ifp, ia); /* XXX */ #endif if (ia) ip->ip_src.s_addr = ia->ia_subnet; diff --git a/sys/netinet/in.c b/sys/netinet/in.c index d926425fa38..99dc7f3bfb9 100644 --- a/sys/netinet/in.c +++ b/sys/netinet/in.c @@ -1,4 +1,4 @@ -/* $NetBSD: in.c,v 1.37 1998/01/12 03:02:49 scottr Exp $ */ +/* $NetBSD: in.c,v 1.38 1998/02/13 18:21:40 tls Exp $ */ /* * Copyright (c) 1982, 1986, 1991, 1993 @@ -150,7 +150,7 @@ in_setmaxmtu() if ((ifp->if_flags & (IFF_UP|IFF_LOOPBACK)) != IFF_UP) continue; if (ifp->if_mtu > maxmtu) - maxmtu = ifp->if_mtu; + maxmtu = ifp->if_mtu; } if (maxmtu) in_maxmtu = maxmtu; @@ -181,18 +181,18 @@ in_control(so, cmd, data, ifp, p) * Find address for this interface, if it exists. */ if (ifp) - for (ia = in_ifaddr.tqh_first; ia != 0; ia = ia->ia_list.tqe_next) - if (ia->ia_ifp == ifp) - break; + IFP_TO_IA(ifp, ia); switch (cmd) { case SIOCAIFADDR: case SIOCDIFADDR: if (ifra->ifra_addr.sin_family == AF_INET) - for (; ia != 0; ia = ia->ia_list.tqe_next) { + for (ia = IN_IFADDR_HASH(ifra->ifra_addr.sin_addr.s_addr).lh_first; + ia != 0; ia = ia->ia_hash.le_next) { if (ia->ia_ifp == ifp && - in_hosteq(ia->ia_addr.sin_addr, ifra->ifra_addr.sin_addr)) + in_hosteq(ia->ia_addr.sin_addr, + ifra->ifra_addr.sin_addr)) break; } if (cmd == SIOCDIFADDR && ia == 0) @@ -330,6 +330,7 @@ in_control(so, cmd, data, ifp, p) case SIOCDIFADDR: in_ifscrub(ifp, ia); + LIST_REMOVE(ia, ia_hash); TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list); TAILQ_REMOVE(&in_ifaddr, ia, ia_list); IFAFREE((&ia->ia_ifa)); @@ -389,7 +390,11 @@ in_ifinit(ifp, ia, sin, scrub) * Set up new addresses. */ oldaddr = ia->ia_addr; + if (ia->ia_addr.sin_family == AF_INET) + LIST_REMOVE(ia, ia_hash); ia->ia_addr = *sin; + LIST_INSERT_HEAD(&IN_IFADDR_HASH(ia->ia_addr.sin_addr.s_addr), ia, ia_hash); + /* * Give the interface a chance to initialize * if this is its first address, @@ -460,7 +465,11 @@ in_ifinit(ifp, ia, sin, scrub) return (error); bad: splx(s); + LIST_REMOVE(ia, ia_hash); ia->ia_addr = oldaddr; + if (ia->ia_addr.sin_family == AF_INET) + LIST_INSERT_HEAD(&IN_IFADDR_HASH(ia->ia_addr.sin_addr.s_addr), + ia, ia_hash); return (error); } diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c index eb239d682d6..28439876133 100644 --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -1,4 +1,4 @@ -/* $NetBSD: in_pcb.c,v 1.48 1998/02/07 02:44:55 chs Exp $ */ +/* $NetBSD: in_pcb.c,v 1.49 1998/02/13 18:21:41 tls Exp $ */ /* * Copyright (c) 1982, 1986, 1991, 1993, 1995 @@ -254,16 +254,21 @@ in_pcbconnect(v, nam) if (in_ifaddr.tqh_first != 0) { /* * If the destination address is INADDR_ANY, - * use the primary local address. + * use any local address (likely loopback). * If the supplied address is INADDR_BROADCAST, - * and the primary interface supports broadcast, - * choose the broadcast address for that interface. + * use the broadcast address of an interface + * which supports broadcast. (loopback does not) */ + if (in_nullhost(sin->sin_addr)) - sin->sin_addr = in_ifaddr.tqh_first->ia_addr.sin_addr; - else if (sin->sin_addr.s_addr == INADDR_BROADCAST && - (in_ifaddr.tqh_first->ia_ifp->if_flags & IFF_BROADCAST)) - sin->sin_addr = in_ifaddr.tqh_first->ia_broadaddr.sin_addr; + sin->sin_addr = in_ifaddr.tqh_first->ia_broadaddr.sin_addr; + else if (sin->sin_addr.s_addr == INADDR_BROADCAST) + for (ia = in_ifaddr.tqh_first; ia != NULL; + ia = ia->ia_list.tqe_next) + if (ia->ia_ifp->if_flags & IFF_BROADCAST) { + sin->sin_addr = ia->ia_broadaddr.sin_addr; + break; + } } /* * If we haven't bound which network number to use as ours, @@ -307,19 +312,25 @@ in_pcbconnect(v, nam) * corresponding to the outgoing interface * unless it is the loopback (in case a route * to our address on another net goes to loopback). + * + * XXX Is this still true? Do we care? */ if (ro->ro_rt && !(ro->ro_rt->rt_ifp->if_flags & IFF_LOOPBACK)) ia = ifatoia(ro->ro_rt->rt_ifa); if (ia == 0) { - u_int16_t fport = sin->sin_port; - - sin->sin_port = 0; - ia = ifatoia(ifa_ifwithladdr(sintosa(sin))); - sin->sin_port = fport; - if (ia == 0) - ia = in_ifaddr.tqh_first; - if (ia == 0) - return (EADDRNOTAVAIL); + u_int16_t fport = sin->sin_port; + + sin->sin_port = 0; + ia = ifatoia(ifa_ifwithladdr(sintosa(sin))); + sin->sin_port = fport; + if (ia == 0) + /* Find 1st non-loopback AF_INET address */ + for (ia = in_ifaddr.tqh_first ; ia != NULL ; + ia = ia->ia_list.tqe_next) + if (!(ia->ia_ifp->if_flags & IFF_LOOPBACK)) + break; + if (ia == 0) + return (EADDRNOTAVAIL); } /* * If the destination address is multicast and an outgoing @@ -334,10 +345,7 @@ in_pcbconnect(v, nam) imo = inp->inp_moptions; if (imo->imo_multicast_ifp != NULL) { ifp = imo->imo_multicast_ifp; - for (ia = in_ifaddr.tqh_first; ia != 0; - ia = ia->ia_list.tqe_next) - if (ia->ia_ifp == ifp) - break; + IFP_TO_IA(ifp, ia); /* XXX */ if (ia == 0) return (EADDRNOTAVAIL); } @@ -550,7 +558,7 @@ in_rtchange(inp, errno) * output is attempted. */ } - /* SHOULD NOTIFY HIGHER-LEVEL PROTOCOLS */ + /* XXX SHOULD NOTIFY HIGHER-LEVEL PROTOCOLS */ } struct inpcb * diff --git a/sys/netinet/in_var.h b/sys/netinet/in_var.h index 4f954f699bd..3552dffa6ff 100644 --- a/sys/netinet/in_var.h +++ b/sys/netinet/in_var.h @@ -1,4 +1,4 @@ -/* $NetBSD: in_var.h,v 1.20 1998/02/10 01:26:42 perry Exp $ */ +/* $NetBSD: in_var.h,v 1.21 1998/02/13 18:21:42 tls Exp $ */ /* * Copyright (c) 1985, 1986, 1993 @@ -56,6 +56,7 @@ struct in_ifaddr { u_int32_t ia_subnet; /* subnet number, including net */ u_int32_t 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_list; /* list of internet addresses */ struct sockaddr_in ia_addr; /* reserve space for interface name */ struct sockaddr_in ia_dstaddr; /* reserve space for broadcast addr */ @@ -79,13 +80,39 @@ struct in_aliasreq { #ifdef _KERNEL -TAILQ_HEAD(in_ifaddrhead, in_ifaddr); -extern struct in_ifaddrhead in_ifaddr; +#ifndef IN_IFADDR_HASH_SIZE +#define IN_IFADDR_HASH_SIZE 293 +#endif + +#define IN_IFADDR_HASH(x) in_ifaddrhashtbl[(u_long)(x) % IN_IFADDR_HASH_SIZE] + +u_long in_ifaddrhash; /* size of hash table - 1 */ +int in_ifaddrentries; /* total number of addrs */ +LIST_HEAD(in_ifaddrhashhead, in_ifaddr); /* Type of the hash head */ +TAILQ_HEAD(in_ifaddrhead, in_ifaddr); /* Type of the list head */ + +extern struct in_ifaddrhashhead *in_ifaddrhashtbl; /* Hash table head */ +extern struct in_ifaddrhead in_ifaddr; /* List head (in ip_input) */ + extern struct ifqueue ipintrq; /* ip packet input queue */ void in_socktrim __P((struct sockaddr_in *)); /* + * Macro for finding whether an internet address (in_addr) belongs to one + * of our interfaces (in_ifaddr). NULL if the address isn't ours. + */ +#define INADDR_TO_IA(addr, ia) \ + /* struct in_addr addr; */ \ + /* struct in_ifaddr *ia; */ \ +{ \ + for (ia = IN_IFADDR_HASH((addr).s_addr).lh_first; \ + ia != NULL && !in_hosteq(ia->ia_addr.sin_addr, (addr)); \ + ia = ia->ia_hash.le_next) \ + continue; \ +} + +/* * Macro for finding the interface (ifnet structure) corresponding to one * of our IP addresses. */ @@ -95,25 +122,25 @@ void in_socktrim __P((struct sockaddr_in *)); { \ register struct in_ifaddr *ia; \ \ - for (ia = in_ifaddr.tqh_first; \ - ia != NULL && ia->ia_addr.sin_addr.s_addr != (addr).s_addr; \ - ia = ia->ia_list.tqe_next) \ - continue; \ + INADDR_TO_IA(addr, ia); \ (ifp) = (ia == NULL) ? NULL : ia->ia_ifp; \ } /* - * Macro for finding the internet address structure (in_ifaddr) corresponding + * Macro for finding an 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) = in_ifaddr.tqh_first; \ - (ia) != NULL && (ia)->ia_ifp != (ifp); \ - (ia) = (ia)->ia_list.tqe_next) \ + register struct ifaddr *ifa; \ +\ + for (ifa = (ifp)->if_addrlist.tqh_first; \ + ifa != NULL && ifa->ifa_addr->sa_family != AF_INET; \ + ifa = ifa->ifa_list.tqe_next) \ continue; \ + (ia) = ifatoia(ifa); \ } #endif @@ -165,12 +192,12 @@ struct in_multistep { { \ register struct in_ifaddr *ia; \ \ - IFP_TO_IA((ifp), ia); \ + IFP_TO_IA((ifp), ia); /* multicast */ \ if (ia == NULL) \ (inm) = NULL; \ else \ for ((inm) = ia->ia_multiaddrs.lh_first; \ - (inm) != NULL && (inm)->inm_addr.s_addr != (addr).s_addr; \ + (inm) != NULL && !in_hosteq((inm)->inm_addr, (addr)); \ (inm) = inm->inm_list.le_next) \ continue; \ } diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c index 926795a391a..63ab5ec20db 100644 --- a/sys/netinet/ip_icmp.c +++ b/sys/netinet/ip_icmp.c @@ -1,4 +1,4 @@ -/* $NetBSD: ip_icmp.c,v 1.26 1997/10/29 05:28:44 kml Exp $ */ +/* $NetBSD: ip_icmp.c,v 1.27 1998/02/13 18:21:43 tls Exp $ */ /* * Copyright (c) 1982, 1986, 1988, 1993 @@ -435,6 +435,7 @@ icmp_reflect(m) { register struct ip *ip = mtod(m, struct ip *); register struct in_ifaddr *ia; + register struct ifaddr *ifa; struct in_addr t; struct mbuf *opts = 0; int optlen = (ip->ip_hl << 2) - sizeof(struct ip); @@ -453,23 +454,35 @@ icmp_reflect(m) * or anonymous), use the address which corresponds * to the incoming interface. */ - for (ia = in_ifaddr.tqh_first; ia; ia = ia->ia_list.tqe_next) { - if (in_hosteq(t, ia->ia_addr.sin_addr)) - break; - if ((ia->ia_ifp->if_flags & IFF_BROADCAST) && - in_hosteq(t, ia->ia_broadaddr.sin_addr)) - break; + INADDR_TO_IA(t, ia); + if (ia == NULL && (m->m_pkthdr.rcvif->if_flags & IFF_BROADCAST)) { + for (ifa = m->m_pkthdr.rcvif->if_addrlist.tqh_first; + ifa != NULL; ifa = ifa->ifa_list.tqe_next) { + if (ifa->ifa_addr->sa_family != AF_INET) + continue; + ia = ifatoia(ifa); + if (in_hosteq(t, ia->ia_broadaddr.sin_addr)) + break; + } } + icmpdst.sin_addr = t; if (ia == (struct in_ifaddr *)0) ia = ifatoia(ifaof_ifpforaddr(sintosa(&icmpdst), m->m_pkthdr.rcvif)); /* * The following happens if the packet was not addressed to us, - * and was received on an interface with no IP address. + * and was received on an interface with no IP address: + * We find the first AF_INET address on the first non-loopback + * interface. */ if (ia == (struct in_ifaddr *)0) - ia = in_ifaddr.tqh_first; + for (ia = in_ifaddr.tqh_first; ia != NULL; + ia = ia->ia_list.tqe_next) { + if (ia->ia_ifp->if_flags & IFF_LOOPBACK) + continue; + break; + } t = ia->ia_addr.sin_addr; ip->ip_src = t; ip->ip_ttl = MAXTTL; diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index 5e55aa6aa08..d009b4aace9 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -1,4 +1,4 @@ -/* $NetBSD: ip_input.c,v 1.56 1998/01/28 02:36:10 thorpej Exp $ */ +/* $NetBSD: ip_input.c,v 1.57 1998/02/13 18:21:44 tls Exp $ */ /* * Copyright (c) 1982, 1986, 1988, 1993 @@ -113,6 +113,7 @@ extern struct protosw inetsw[]; u_char ip_protox[IPPROTO_MAX]; int ipqmaxlen = IFQ_MAXLEN; struct in_ifaddrhead in_ifaddr; +struct in_ifaddrhashhead *in_ifaddrhashtbl; struct ifqueue ipintrq; /* @@ -156,6 +157,8 @@ ip_init() ip_id = time.tv_sec & 0xffff; ipintrq.ifq_maxlen = ipqmaxlen; TAILQ_INIT(&in_ifaddr); + in_ifaddrhashtbl = + hashinit(IN_IFADDR_HASH_SIZE, M_IFADDR, M_WAITOK, &in_ifaddrhash); } struct sockaddr_in ipaddr = { sizeof(ipaddr), AF_INET }; @@ -172,6 +175,7 @@ ipintr() register struct mbuf *m; register struct ipq *fp; register struct in_ifaddr *ia; + register struct ifaddr *ifa; struct ipqent *ipqe; int hlen = 0, mff, len, s; #ifdef PFIL_HOOKS @@ -281,12 +285,13 @@ next: /* * Check our list of addresses, to see if the packet is for us. */ - for (ia = in_ifaddr.tqh_first; ia; ia = ia->ia_list.tqe_next) { - if (in_hosteq(ip->ip_dst, ia->ia_addr.sin_addr)) - goto ours; - if (((ip_directedbcast == 0) || (ip_directedbcast && - ia->ia_ifp == m->m_pkthdr.rcvif)) && - (ia->ia_ifp->if_flags & IFF_BROADCAST)) { + INADDR_TO_IA(ip->ip_dst, ia); + if (ia != NULL) goto ours; + if (m->m_pkthdr.rcvif->if_flags & IFF_BROADCAST) { + for (ifa = m->m_pkthdr.rcvif->if_addrlist.tqh_first; + ifa != NULL; ifa = ifa->ifa_list.tqe_next) { + if (ifa->ifa_addr->sa_family != AF_INET) continue; + ia = ifatoia(ifa); if (in_hosteq(ip->ip_dst, ia->ia_broadaddr.sin_addr) || in_hosteq(ip->ip_dst, ia->ia_netbroadcast) || /* @@ -296,14 +301,13 @@ next: ip->ip_dst.s_addr == ia->ia_subnet || ip->ip_dst.s_addr == ia->ia_net) goto ours; + /* + * An interface with IP address zero accepts + * all packets that arrive on that interface. + */ + if (in_nullhost(ia->ia_addr.sin_addr)) + goto ours; } - /* - * An interface with IP address zero accepts - * all packets that arrive on that interface. - */ - if ((ia->ia_ifp == m->m_pkthdr.rcvif) && - in_nullhost(ia->ia_addr.sin_addr)) - goto ours; } if (IN_MULTICAST(ip->ip_dst.s_addr)) { struct in_multi *inm; diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index 0618d41770c..ca63a5fae4f 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -1,4 +1,4 @@ -/* $NetBSD: ip_output.c,v 1.43 1998/02/13 10:23:49 kleink Exp $ */ +/* $NetBSD: ip_output.c,v 1.44 1998/02/13 18:21:45 tls Exp $ */ /* * Copyright (c) 1982, 1986, 1988, 1990, 1993 @@ -211,17 +211,14 @@ ip_output(m0, va_alist) goto bad; } /* - * If source address not specified yet, use address + * If source address not specified yet, use an address * of outgoing interface. */ if (in_nullhost(ip->ip_src)) { register struct in_ifaddr *ia; - for (ia = in_ifaddr.tqh_first; ia; ia = ia->ia_list.tqe_next) - if (ia->ia_ifp == ifp) { - ip->ip_src = ia->ia_addr.sin_addr; - break; - } + IFP_TO_IA(ifp, ia); + ip->ip_src = ia->ia_addr.sin_addr; } IN_LOOKUP_MULTI(ip->ip_dst, ifp, inm); |
