[BACK]Return to cache.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / systat

Annotation of src/usr.bin/systat/cache.c, Revision 1.8

1.8     ! tedu        1: /* $OpenBSD: cache.c,v 1.7 2016/08/26 09:10:11 guenther Exp $ */
1.1       canacar     2: /*
                      3:  * Copyright (c) 2001, 2007 Can Erkin Acar <canacar@openbsd.org>
                      4:  *
                      5:  * Permission to use, copy, modify, and distribute this software for any
                      6:  * purpose with or without fee is hereby granted, provided that the above
                      7:  * copyright notice and this permission notice appear in all copies.
                      8:  *
                      9:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     10:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     11:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     12:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     13:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     14:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     15:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     16:  */
                     17:
                     18: #include <sys/types.h>
                     19: #include <sys/ioctl.h>
                     20: #include <sys/socket.h>
                     21:
                     22: #include <net/if.h>
                     23: #include <netinet/in.h>
                     24:
                     25: #include <netinet/tcp_fsm.h>
                     26: #ifdef TEST_COMPAT
                     27: #include "pfvarmux.h"
                     28: #else
                     29: #include <net/pfvar.h>
                     30: #endif
                     31: #include <arpa/inet.h>
                     32:
                     33: #include <stdio.h>
                     34: #include <stdlib.h>
1.7       guenther   35: #include <time.h>
1.1       canacar    36:
                     37: #include <assert.h>
                     38:
                     39: #include "cache.h"
                     40:
                     41: /* prototypes */
1.2       canacar    42: void update_state(struct sc_ent *, struct pfsync_state *, double);
                     43: struct sc_ent *cache_state(struct pfsync_state *);
1.1       canacar    44: static __inline int sc_cmp(struct sc_ent *s1, struct sc_ent *s2);
                     45:
                     46: /* initialize the tree and queue */
                     47: RB_HEAD(sc_tree, sc_ent) sctree;
                     48: TAILQ_HEAD(sc_queue, sc_ent) scq1, scq2, scq_free;
1.3       canacar    49: RB_GENERATE(sc_tree, sc_ent, tlink, sc_cmp)
1.1       canacar    50:
                     51: struct sc_queue *scq_act = NULL;
                     52: struct sc_queue *scq_exp = NULL;
                     53:
                     54: int cache_max = 0;
                     55: int cache_size = 0;
                     56:
                     57: struct sc_ent *sc_store = NULL;
                     58:
                     59: /* preallocate the cache and insert into the 'free' queue */
                     60: int
                     61: cache_init(int max)
                     62: {
                     63:        int n;
                     64:        static int initialized = 0;
                     65:
                     66:        if (max < 0 || initialized)
                     67:                return (1);
                     68:
                     69:        if (max == 0) {
                     70:                sc_store = NULL;
                     71:        } else {
1.5       doug       72:                sc_store = reallocarray(NULL, max, sizeof(struct sc_ent));
1.1       canacar    73:                if (sc_store == NULL)
                     74:                        return (1);
                     75:        }
                     76:
                     77:        RB_INIT(&sctree);
                     78:        TAILQ_INIT(&scq1);
                     79:        TAILQ_INIT(&scq2);
                     80:        TAILQ_INIT(&scq_free);
                     81:
                     82:        scq_act = &scq1;
                     83:        scq_exp = &scq2;
                     84:
                     85:        for (n = 0; n < max; n++)
                     86:                TAILQ_INSERT_HEAD(&scq_free, sc_store + n, qlink);
                     87:
                     88:        cache_size = cache_max = max;
                     89:        initialized++;
                     90:
                     91:        return (0);
                     92: }
                     93:
                     94: void
1.2       canacar    95: update_state(struct sc_ent *prev, struct pfsync_state *new, double rate)
1.1       canacar    96: {
                     97:        assert (prev != NULL && new != NULL);
                     98:        prev->t = time(NULL);
                     99:        prev->rate = rate;
                    100:        prev->bytes = COUNTER(new->bytes[0]) + COUNTER(new->bytes[1]);
                    101:        if (prev->peak < rate)
                    102:                prev->peak = rate;
                    103: }
                    104:
                    105: void
1.2       canacar   106: add_state(struct pfsync_state *st)
1.1       canacar   107: {
                    108:        struct sc_ent *ent;
                    109:        assert(st != NULL);
                    110:
                    111:        if (cache_max == 0)
                    112:                return;
                    113:
                    114:        if (TAILQ_EMPTY(&scq_free))
                    115:                return;
                    116:
                    117:        ent = TAILQ_FIRST(&scq_free);
                    118:        TAILQ_REMOVE(&scq_free, ent, qlink);
                    119:
                    120:        cache_size--;
                    121:
1.4       dlg       122:        ent->id = st->id;
                    123:        ent->creatorid = st->creatorid;
1.1       canacar   124:        ent->bytes = COUNTER(st->bytes[0]) + COUNTER(st->bytes[1]);
                    125:        ent->peak = 0;
                    126:        ent->rate = 0;
1.6       canacar   127:        ent->t = 0;
1.1       canacar   128:
                    129:        RB_INSERT(sc_tree, &sctree, ent);
                    130:        TAILQ_INSERT_HEAD(scq_act, ent, qlink);
                    131: }
                    132:
                    133: /* must be called only once for each state before cache_endupdate */
                    134: struct sc_ent *
1.2       canacar   135: cache_state(struct pfsync_state *st)
1.1       canacar   136: {
                    137:        struct sc_ent ent, *old;
                    138:        double sd, td, r;
                    139:
                    140:        if (cache_max == 0)
                    141:                return (NULL);
                    142:
1.4       dlg       143:        ent.id = st->id;
                    144:        ent.creatorid = st->creatorid;
1.1       canacar   145:        old = RB_FIND(sc_tree, &sctree, &ent);
                    146:
                    147:        if (old == NULL) {
                    148:                add_state(st);
                    149:                return (NULL);
                    150:        }
                    151:
                    152:        if (COUNTER(st->bytes[0]) + COUNTER(st->bytes[1]) < old->bytes)
                    153:                return (NULL);
                    154:
                    155:        sd = COUNTER(st->bytes[0]) + COUNTER(st->bytes[1]) - old->bytes;
                    156:        td = time(NULL) - old->t;
                    157:
                    158:        if (td > 0) {
                    159:                r = sd/td;
                    160:                update_state(old, st, r);
                    161:        }
                    162:
                    163:        /* move to active queue */
                    164:        TAILQ_REMOVE(scq_exp, old, qlink);
                    165:        TAILQ_INSERT_HEAD(scq_act, old, qlink);
                    166:
                    167:        return (old);
                    168: }
                    169:
                    170: /* remove the states that are not updated in this cycle */
                    171: void
                    172: cache_endupdate(void)
                    173: {
                    174:        struct sc_queue *tmp;
                    175:        struct sc_ent *ent;
                    176:
                    177:        while (! TAILQ_EMPTY(scq_exp)) {
                    178:                ent = TAILQ_FIRST(scq_exp);
                    179:                TAILQ_REMOVE(scq_exp, ent, qlink);
                    180:                RB_REMOVE(sc_tree, &sctree, ent);
                    181:                TAILQ_INSERT_HEAD(&scq_free, ent, qlink);
                    182:                cache_size++;
                    183:        }
                    184:
                    185:        tmp = scq_act;
                    186:        scq_act = scq_exp;
                    187:        scq_exp = tmp;
                    188: }
                    189:
                    190: static __inline int
                    191: sc_cmp(struct sc_ent *a, struct sc_ent *b)
                    192: {
1.4       dlg       193:        if (a->id > b->id)
1.1       canacar   194:                return (1);
1.4       dlg       195:        if (a->id < b->id)
1.1       canacar   196:                return (-1);
1.4       dlg       197:        if (a->creatorid > b->creatorid)
1.1       canacar   198:                return (1);
1.4       dlg       199:        if (a->creatorid < b->creatorid)
1.1       canacar   200:                return (-1);
                    201:        return (0);
                    202: }