summaryrefslogtreecommitdiffstats
path: root/sys/netinet/if_ether.c
diff options
context:
space:
mode:
authorjlemon <jlemon@FreeBSD.org>2001-09-29 04:34:11 +0000
committerjlemon <jlemon@FreeBSD.org>2001-09-29 04:34:11 +0000
commit3164f24b5544749a98ad715c69b320a68f5e5316 (patch)
tree9043eb0a3862514449a171c6cb63e1c0ef78e293 /sys/netinet/if_ether.c
parent17d77e934622c40b38b3ea7e9d9486bf6c67f15f (diff)
downloadFreeBSD-src-3164f24b5544749a98ad715c69b320a68f5e5316.zip
FreeBSD-src-3164f24b5544749a98ad715c69b320a68f5e5316.tar.gz
Add a hash table that contains the list of internet addresses, and use
this in place of the in_ifaddr list when appropriate. This improves performance on hosts which have a large number of IP aliases.
Diffstat (limited to 'sys/netinet/if_ether.c')
-rw-r--r--sys/netinet/if_ether.c41
1 files changed, 24 insertions, 17 deletions
diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c
index cbd4e1f..ce1fb20 100644
--- a/sys/netinet/if_ether.c
+++ b/sys/netinet/if_ether.c
@@ -526,7 +526,8 @@ in_arpinput(m)
struct iso88025_header *th = (struct iso88025_header *)0;
register struct llinfo_arp *la = 0;
register struct rtentry *rt;
- struct in_ifaddr *ia, *maybe_ia = 0;
+ struct ifaddr *ifa;
+ struct in_ifaddr *ia;
struct sockaddr_dl *sdl;
struct sockaddr sa;
struct in_addr isaddr, itaddr, myaddr;
@@ -542,30 +543,36 @@ in_arpinput(m)
op = ntohs(ea->arp_op);
(void)memcpy(&isaddr, ea->arp_spa, sizeof (isaddr));
(void)memcpy(&itaddr, ea->arp_tpa, sizeof (itaddr));
- TAILQ_FOREACH(ia, &in_ifaddrhead, ia_link) {
- /*
- * For a bridge, we want to check the address irrespective
- * of the receive interface. (This will change slightly
- * when we have clusters of interfaces).
- */
#ifdef BRIDGE
#define BRIDGE_TEST (do_bridge)
#else
#define BRIDGE_TEST (0) /* cc will optimise the test away */
#endif
- if ((BRIDGE_TEST) || (ia->ia_ifp == &ac->ac_if)) {
- maybe_ia = ia;
- if ((itaddr.s_addr == ia->ia_addr.sin_addr.s_addr) ||
- (isaddr.s_addr == ia->ia_addr.sin_addr.s_addr)) {
- break;
- }
- }
- }
- if (maybe_ia == 0) {
+ /*
+ * For a bridge, we want to check the address irrespective
+ * of the receive interface. (This will change slightly
+ * when we have clusters of interfaces).
+ */
+ LIST_FOREACH(ia, INADDR_HASH(itaddr.s_addr), ia_hash)
+ if ((BRIDGE_TEST || (ia->ia_ifp == &ac->ac_if)) &&
+ itaddr.s_addr == ia->ia_addr.sin_addr.s_addr)
+ goto match;
+ LIST_FOREACH(ia, INADDR_HASH(isaddr.s_addr), ia_hash)
+ if ((BRIDGE_TEST || (ia->ia_ifp == &ac->ac_if)) &&
+ isaddr.s_addr == ia->ia_addr.sin_addr.s_addr)
+ goto match;
+ /*
+ * No match, use the first address on the receive interface
+ * as a dummy address for the rest of the function.
+ */
+ ifa = TAILQ_FIRST(&ac->ac_if.if_addrhead);
+ if (ifa == NULL) {
m_freem(m);
return;
}
- myaddr = ia ? ia->ia_addr.sin_addr : maybe_ia->ia_addr.sin_addr;
+ ia = ifatoia(ifa);
+match:
+ myaddr = ia->ia_addr.sin_addr;
if (!bcmp((caddr_t)ea->arp_sha, (caddr_t)ac->ac_enaddr,
sizeof (ea->arp_sha))) {
m_freem(m); /* it's from me, ignore it. */
OpenPOWER on IntegriCloud