|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 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. ! 11: * ! 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 ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * Copyright 1997 Massachusetts Institute of Technology ! 24: * ! 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 ! 35: * warranty. ! 36: * ! 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 ! 48: * SUCH DAMAGE. ! 49: * ! 50: */ ! 51: ! 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> ! 57: ! 58: #include <net/hostcache.h> ! 59: #include <net/route.h> ! 60: ! 61: MALLOC_DEFINE(M_HOSTCACHE, "hostcache", "per-host cache structure"); ! 62: ! 63: static struct hctable hctable[AF_MAX]; ! 64: static int hc_timeout_interval = 120; ! 65: static int hc_maxidle = 1800; ! 66: ! 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); ! 70: ! 71: int ! 72: hc_init(int af, struct hccallback *hccb, int init_nelem, int primes) ! 73: { ! 74: struct hctable *hct; ! 75: struct hchead *heads; ! 76: u_long nelem; ! 77: ! 78: hct = &hctable[af]; ! 79: nelem = init_nelem; ! 80: if (hct->hct_nentries) ! 81: return 0; ! 82: ! 83: if (primes) { ! 84: heads = phashinit(init_nelem, M_HOSTCACHE, &nelem); ! 85: } else { ! 86: int i; ! 87: MALLOC(heads, struct hchead *, nelem * sizeof *heads, ! 88: M_HOSTCACHE, M_WAITOK); ! 89: for (i = 0; i < nelem; i++) { ! 90: LIST_INIT(&heads[i]); ! 91: } ! 92: } ! 93: ! 94: hct->hct_heads = heads; ! 95: hct->hct_nentries = nelem; ! 96: hct->hct_primes = primes; ! 97: timeout(hc_timeout, hct, hc_timeout_interval * hz); ! 98: return 0; ! 99: } ! 100: ! 101: struct hcentry * ! 102: hc_get(struct sockaddr *sa) ! 103: { ! 104: u_long hash; ! 105: struct hcentry *hc; ! 106: struct hctable *hct; ! 107: int s; ! 108: ! 109: hct = &hctable[sa->sa_family]; ! 110: if (hct->hct_nentries == 0) ! 111: return 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) ! 116: break; ! 117: } ! 118: if (hc == 0) ! 119: return 0; ! 120: s = splnet(); ! 121: if (hc->hc_rt && (hc->hc_rt->rt_flags & RTF_UP) == 0) { ! 122: RTFREE(hc->hc_rt); ! 123: hc->hc_rt = 0; ! 124: } ! 125: if (hc->hc_rt == 0) { ! 126: hc->hc_rt = rtalloc1(hc->hc_host, 1, 0); ! 127: } ! 128: hc_ref(hc); ! 129: splx(s); ! 130: /* XXX move to front of list? */ ! 131: return hc; ! 132: } ! 133: ! 134: void ! 135: hc_ref(struct hcentry *hc) ! 136: { ! 137: int s = splnet(); ! 138: if (hc->hc_refcnt++ == 0) { ! 139: hc->hc_hct->hct_idle--; ! 140: hc->hc_hct->hct_active++; ! 141: } ! 142: splx(s); ! 143: } ! 144: ! 145: void ! 146: hc_rele(struct hcentry *hc) ! 147: { ! 148: int s = splnet(); ! 149: #ifdef DIAGNOSTIC ! 150: printf("hc_rele: %p: negative refcnt!\n", (void *)hc); ! 151: #endif ! 152: hc->hc_refcnt--; ! 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? */ ! 157: } ! 158: splx(s); ! 159: } ! 160: ! 161: /* ! 162: * The user is expected to initialize hc_host with the address and everything ! 163: * else to the appropriate form of `0'. ! 164: */ ! 165: int ! 166: hc_insert(struct hcentry *hc) ! 167: { ! 168: struct hcentry *hc2; ! 169: struct hctable *hct; ! 170: u_long hash; ! 171: int s; ! 172: ! 173: hct = &hctable[hc->hc_host->sa_family]; ! 174: hash = hct->hct_cb->hccb_hash(hc->hc_host, hct->hct_nentries); ! 175: ! 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) ! 179: break; ! 180: } ! 181: if (hc2 != 0) ! 182: return EEXIST; ! 183: hc->hc_hct = hct; ! 184: s = splnet(); ! 185: LIST_INSERT_HEAD(&hct->hct_heads[hash], hc, hc_link); ! 186: hct->hct_idle++; ! 187: /* ! 188: * If the table is now more than 75% full, consider bumping it. ! 189: */ ! 190: if (100 * (hct->hct_idle + hct->hct_active) > 75 * hct->hct_nentries) ! 191: maybe_bump_hash(hct); ! 192: splx(s); ! 193: return 0; ! 194: } ! 195: ! 196: /* ! 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 ! 199: * the cache timeout. ! 200: */ ! 201: int ! 202: hc_delete(struct hcentry *hc) ! 203: { ! 204: struct hctable *hct; ! 205: int error, s; ! 206: ! 207: if (hc->hc_refcnt > 0) ! 208: return 0; ! 209: ! 210: hct = hc->hc_hct; ! 211: error = hct->hct_cb->hccb_delete(hc); ! 212: if (error) ! 213: return 0; ! 214: ! 215: s = splnet(); ! 216: LIST_REMOVE(hc, hc_link); ! 217: hc->hc_hct->hct_idle--; ! 218: splx(s); ! 219: FREE(hc, M_HOSTCACHE); ! 220: return 0; ! 221: } ! 222: ! 223: static void ! 224: hc_timeout(void *xhct) ! 225: { ! 226: struct hcentry *hc; ! 227: struct hctable *hct; ! 228: int j, s; ! 229: time_t start; ! 230: ! 231: hct = xhct; ! 232: start = mono_time.tv_sec; /* for simplicity */ ! 233: ! 234: if (hct->hct_idle == 0) ! 235: return; ! 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) ! 240: continue; ! 241: if (hc->hc_idlesince.tv_sec + hc_maxidle <= start) { ! 242: if (hct->hct_cb->hccb_delete(hc)) ! 243: continue; ! 244: s = splnet(); ! 245: LIST_REMOVE(hc, hc_link); ! 246: hct->hct_idle--; ! 247: splx(s); ! 248: } ! 249: } ! 250: } ! 251: /* ! 252: * Fiddle something here based on tot_idle... ! 253: */ ! 254: timeout(hc_timeout, xhct, hc_timeout_interval * hz); ! 255: } ! 256: ! 257: static int ! 258: cmpsa(const struct sockaddr *sa1, const struct sockaddr *sa2) ! 259: { ! 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); ! 263: } ! 264: ! 265: static void ! 266: maybe_bump_hash(struct hctable *hct) ! 267: { ! 268: ; /* XXX fill me in */ ! 269: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.