]>
git.saurik.com Git - apple/xnu.git/blob - bsd/net/hostcache.c
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright 1997 Massachusetts Institute of Technology
25 * Permission to use, copy, modify, and distribute this software and
26 * its documentation for any purpose and without fee is hereby
27 * granted, provided that both the above copyright notice and this
28 * permission notice appear in all copies, that both the above
29 * copyright notice and this permission notice appear in all
30 * supporting documentation, and that the name of M.I.T. not be used
31 * in advertising or publicity pertaining to distribution of the
32 * software without specific, written prior permission. M.I.T. makes
33 * no representations about the suitability of this software for any
34 * purpose. It is provided "as is" without express or implied
37 * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
38 * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
39 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
40 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
41 * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52 #include <sys/param.h>
53 #include <sys/systm.h>
54 #include <sys/kernel.h>
55 #include <sys/malloc.h>
56 #include <sys/socket.h>
58 #include <net/hostcache.h>
59 #include <net/route.h>
61 MALLOC_DEFINE(M_HOSTCACHE
, "hostcache", "per-host cache structure");
63 static struct hctable hctable
[AF_MAX
];
64 static int hc_timeout_interval
= 120;
65 static int hc_maxidle
= 1800;
67 static int cmpsa(const struct sockaddr
*sa1
, const struct sockaddr
*sa2
);
68 static void hc_timeout(void *xhct
);
69 static void maybe_bump_hash(struct hctable
*hct
);
72 hc_init(int af
, struct hccallback
*hccb
, int init_nelem
, int primes
)
80 if (hct
->hct_nentries
)
84 heads
= phashinit(init_nelem
, M_HOSTCACHE
, &nelem
);
87 MALLOC(heads
, struct hchead
*, nelem
* sizeof *heads
,
88 M_HOSTCACHE
, M_WAITOK
);
89 for (i
= 0; i
< nelem
; i
++) {
94 hct
->hct_heads
= heads
;
95 hct
->hct_nentries
= nelem
;
96 hct
->hct_primes
= primes
;
97 timeout(hc_timeout
, hct
, hc_timeout_interval
* hz
);
102 hc_get(struct sockaddr
*sa
)
109 hct
= &hctable
[sa
->sa_family
];
110 if (hct
->hct_nentries
== 0)
112 hash
= hct
->hct_cb
->hccb_hash(sa
, hct
->hct_nentries
);
113 hc
= hct
->hct_heads
[hash
].lh_first
;
114 for (; hc
; hc
= hc
->hc_link
.le_next
) {
115 if (cmpsa(hc
->hc_host
, sa
) == 0)
121 if (hc
->hc_rt
&& (hc
->hc_rt
->rt_flags
& RTF_UP
) == 0) {
125 if (hc
->hc_rt
== 0) {
126 hc
->hc_rt
= rtalloc1(hc
->hc_host
, 1, 0);
130 /* XXX move to front of list? */
135 hc_ref(struct hcentry
*hc
)
138 if (hc
->hc_refcnt
++ == 0) {
139 hc
->hc_hct
->hct_idle
--;
140 hc
->hc_hct
->hct_active
++;
146 hc_rele(struct hcentry
*hc
)
150 printf("hc_rele: %p: negative refcnt!\n", (void *)hc
);
153 if (hc
->hc_refcnt
== 0) {
154 hc
->hc_hct
->hct_idle
++;
155 hc
->hc_hct
->hct_active
--;
156 hc
->hc_idlesince
= mono_time
; /* XXX right one? */
162 * The user is expected to initialize hc_host with the address and everything
163 * else to the appropriate form of `0'.
166 hc_insert(struct hcentry
*hc
)
173 hct
= &hctable
[hc
->hc_host
->sa_family
];
174 hash
= hct
->hct_cb
->hccb_hash(hc
->hc_host
, hct
->hct_nentries
);
176 hc2
= hct
->hct_heads
[hash
].lh_first
;
177 for (; hc2
; hc2
= hc2
->hc_link
.le_next
) {
178 if (cmpsa(hc2
->hc_host
, hc
->hc_host
) == 0)
185 LIST_INSERT_HEAD(&hct
->hct_heads
[hash
], hc
, hc_link
);
188 * If the table is now more than 75% full, consider bumping it.
190 if (100 * (hct
->hct_idle
+ hct
->hct_active
) > 75 * hct
->hct_nentries
)
191 maybe_bump_hash(hct
);
197 * It's not clear to me how much sense this makes as an external interface,
198 * since it is expected that the deletion will normally be handled by
202 hc_delete(struct hcentry
*hc
)
207 if (hc
->hc_refcnt
> 0)
211 error
= hct
->hct_cb
->hccb_delete(hc
);
216 LIST_REMOVE(hc
, hc_link
);
217 hc
->hc_hct
->hct_idle
--;
219 FREE(hc
, M_HOSTCACHE
);
224 hc_timeout(void *xhct
)
232 start
= mono_time
.tv_sec
; /* for simplicity */
234 if (hct
->hct_idle
== 0)
236 for (j
= 0; j
< hct
->hct_nentries
; j
++) {
237 for (hc
= hct
->hct_heads
[j
].lh_first
; hc
;
238 hc
= hc
->hc_link
.le_next
) {
239 if (hc
->hc_refcnt
> 0)
241 if (hc
->hc_idlesince
.tv_sec
+ hc_maxidle
<= start
) {
242 if (hct
->hct_cb
->hccb_delete(hc
))
245 LIST_REMOVE(hc
, hc_link
);
252 * Fiddle something here based on tot_idle...
254 timeout(hc_timeout
, xhct
, hc_timeout_interval
* hz
);
258 cmpsa(const struct sockaddr
*sa1
, const struct sockaddr
*sa2
)
260 if (sa1
->sa_len
!= sa2
->sa_len
)
261 return ((int)sa1
->sa_len
- sa2
->sa_len
);
262 return bcmp(sa1
, sa2
, sa1
->sa_len
);
266 maybe_bump_hash(struct hctable
*hct
)
268 ; /* XXX fill me in */