diff options
author | Henning Brauer <henning@cvs.openbsd.org> | 2010-11-17 19:43:24 +0000 |
---|---|---|
committer | Henning Brauer <henning@cvs.openbsd.org> | 2010-11-17 19:43:24 +0000 |
commit | 0f9c9c60023aab3fd40e5b36c4be37c454ac35cb (patch) | |
tree | daa8d82e95e67a8f9425d5671c6b03a11f3e751e | |
parent | b2e9bf51edb3a10f468a8c0f0b5d2a46042292ca (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.c | 34 |
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. */ |