Annotation of XNU/bsd/net/hostcache.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.