summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHenning Brauer <henning@cvs.openbsd.org>2010-11-17 19:43:24 +0000
committerHenning Brauer <henning@cvs.openbsd.org>2010-11-17 19:43:24 +0000
commit0f9c9c60023aab3fd40e5b36c4be37c454ac35cb (patch)
treedaa8d82e95e67a8f9425d5671c6b03a11f3e751e
parentb2e9bf51edb3a10f468a8c0f0b5d2a46042292ca (diff)
make ifa_ifwithaddr use the RB tree for lookups instead of nested list
walking. make the function shorter, easier and faster with many addresses while still being at least as fast as the old one with a common "on real IP" setup. tested by many, ok claudio sthen dlg krw
-rw-r--r--sys/net/if.c34
1 files changed, 12 insertions, 22 deletions
diff --git a/sys/net/if.c b/sys/net/if.c
index a51a24dcae0..93322f6c7c4 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if.c,v 1.229 2010/11/17 19:40:55 henning Exp $ */
+/* $OpenBSD: if.c,v 1.230 2010/11/17 19:43:23 henning Exp $ */
/* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */
/*
@@ -879,32 +879,22 @@ if_congestion_clear(void *arg)
struct ifaddr *
ifa_ifwithaddr(struct sockaddr *addr, u_int rdomain)
{
- struct ifnet *ifp;
- struct ifaddr *ifa;
+ struct ifaddr_item *ifai, key;
+
+ bzero(&key, sizeof(key));
+ key.ifai_addr = addr;
+ key.ifai_rdomain = rtable_l2(rdomain);
+
+ ifai = RB_FIND(ifaddr_items, &ifaddr_items, &key);
+ if (ifai)
+ return (ifai->ifai_ifa);
+ return (NULL);
+}
#define equal(a1, a2) \
(bcmp((caddr_t)(a1), (caddr_t)(a2), \
((struct sockaddr *)(a1))->sa_len) == 0)
- rdomain = rtable_l2(rdomain);
- TAILQ_FOREACH(ifp, &ifnet, if_list) {
- if (ifp->if_rdomain != rdomain)
- continue;
- TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
- if (ifa->ifa_addr->sa_family != addr->sa_family)
- continue;
- if (equal(addr, ifa->ifa_addr))
- return (ifa);
- if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr &&
- /* IP6 doesn't have broadcast */
- ifa->ifa_broadaddr->sa_len != 0 &&
- equal(ifa->ifa_broadaddr, addr))
- return (ifa);
- }
- }
- return (NULL);
-}
-
/*
* Locate the point to point interface with a given destination address.
*/