Annotation of XNU/bsd/net/hostcache.c, revision 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.