Annotation of researchv8dc/sys/chncp/chclock.c, revision 1.1

1.1     ! root        1: #include "../chunix/chsys.h"
        !             2: #include "../chunix/chconf.h"
        !             3: #include "../chaos/chaos.h"
        !             4: 
        !             5: /*
        !             6:  * Clock level processing.
        !             7:  *     ch_clock should be called each clock tick (HZ per second)
        !             8:  *     at a priority equal to or higher that LOCK.
        !             9:  *
        !            10:  * Terminology:
        !            11:  *    Packet aging:    Retransmitting packets that are not acked within
        !            12:  *                     AGERATE ticks
        !            13:  *
        !            14:  *    Probe:           The sending of a SNS packet if not all of the packets
        !            15:  *                     we have sent have been acknowledged
        !            16:  *
        !            17:  *    Responding:      Send a SNS every so often to see if the guy is still
        !            18:  *                     alive (after NRESPONDS we declare him dead)
        !            19:  *
        !            20:  *    RFC aging:       The retransmission of RFC packets
        !            21:  *
        !            22:  *    Route aging:     Increase the cost of transmitting over gateways so we
        !            23:  *                     will use another gateway if the current gateway goes
        !            24:  *                     down.
        !            25:  *    Route broadcast: If we are connected to more than one subnet, broad
        !            26:  *                     cast our bridge status every BRIDGERATE seconds.
        !            27:  *
        !            28:  *    Interface hung:  Checking periodically for dead interfaces (or dead
        !            29:  *                     "other end"'s of point-to-point links).
        !            30:  *
        !            31:  * These rates might want to vary with the cost of getting to the host.
        !            32:  * They also might want to reside in the chconf.h file if they are not a real
        !            33:  * network standard.
        !            34:  *
        !            35:  * Since these rates are dependent on a run-time variable
        !            36:  * (This is a good idea if you think about it long enough),
        !            37:  * We might want to initialize specific variables at run-time to
        !            38:  * avoid recalculation if the profile of chclock is disturbing.
        !            39:  */
        !            40: #define MINRATE                ORATE           /* Minimum of following rates */
        !            41: #define HANGRATE       (Chhz>>1)       /* How often to check for hung
        !            42:                                           interfaces */
        !            43: #define AGERATE                (Chhz)          /* Re-xmit pkt if not rcptd in time */
        !            44: #define PROBERATE      (Chhz<<3)       /* Send SNS to get STS for receipts or
        !            45:                                           to make sure the conn. is alive */
        !            46: #define ORATE          (Chhz>>1)       /* Xmit current (stream) output packet
        !            47:                                           if not touched in this time */
        !            48: #define TESTRATE       (Chhz*45)       /* Respond testing rate */
        !            49: #define ROUTERATE      (Chhz<<2)       /* Route aging rate */
        !            50: #define BRIDGERATE     (Chhz*15)       /* Routing broadcast rate */
        !            51: #define NRESPONDS      3               /* Test this many times before timing
        !            52:                                           out the connection */
        !            53: #define UPTIME         (NRESPONDS*TESTRATE)    /* Nothing in this time and
        !            54:                                           the connection is flushed */
        !            55: #define RFCRATE                (Chhz*5)                /* Retransmit RFC's this often */
        !            56: #define RFCTIME                (RFCRATE*CHRFCTRYS)     /* Try CHRFCTRYS times to RFC */
        !            57: 
        !            58: chtime Chclock;
        !            59: 
        !            60: ch_clock()
        !            61: {
        !            62:        register struct connection *conn;
        !            63:        register struct connection **connptr;
        !            64:        register struct packet *pkt;
        !            65:        chtime inactive;
        !            66:        int probing;                    /* are we probing this time ? */
        !            67:        static chtime nextclk = 1;      /* next time to do anything */
        !            68:        static chtime nextprobe = 1;    /* next time to probe */
        !            69:        static chtime nexthang = 1;     /* next time to chxtime() */
        !            70:        static chtime nextroute = 1;    /* next time to age routing */
        !            71:        static chtime nextbridge = 1;   /* next time to send routing */
        !            72: 
        !            73:        if (nextclk != ++Chclock)
        !            74:                return;
        !            75:        nextclk += MINRATE;
        !            76:        if (cmp_gt(Chclock, nextprobe)) {
        !            77:                probing = 1;
        !            78:                nextprobe += PROBERATE;
        !            79:        } else
        !            80:                probing = 0;
        !            81:        if (cmp_gt(Chclock, nexthang)) {
        !            82:                chxtime();
        !            83:                nexthang += HANGRATE;
        !            84:        }
        !            85:        if (cmp_gt(Chclock, nextroute)) {
        !            86:                chroutage();
        !            87:                nextroute += ROUTERATE;
        !            88:        }
        !            89:        if (cmp_gt(Chclock, nextbridge)) {
        !            90:                chbridge();
        !            91:                nextbridge += BRIDGERATE;
        !            92:        }
        !            93:        debug(DNOCLK,return);
        !            94:        for (connptr = &Chconntab[0]; connptr < &Chconntab[CHNCONNS]; connptr++)
        !            95:                if ((conn = *connptr) == NOCONN)
        !            96:                        continue;
        !            97:                else if (conn->cn_state == CSOPEN) {
        !            98: #ifdef CHSTRCODE
        !            99:                        /*
        !           100:                         * Timeout the current output stream packet.
        !           101:                         * The timeout value should vary per connection.
        !           102:                         * (shades of x.29!!)
        !           103:                         */
        !           104:                        if ((pkt = conn->cn_toutput) != NOPKT &&
        !           105:                            cmp_gt(Chclock, pkt->pk_time + ORATE) &&
        !           106:                            !chtfull(conn)) {
        !           107:                                conn->cn_toutput = NOPKT;
        !           108:                                /*
        !           109:                                 * We don't care if the packet will
        !           110:                                 * be lost since either the connection
        !           111:                                 * is no longer open anyway, or an
        !           112:                                 * ANSOP was sent in the wrong state.
        !           113:                                 */
        !           114:                                (void)ch_write(conn, pkt);
        !           115:                        }
        !           116: #endif
        !           117:                        if (conn->cn_thead != NOPKT)
        !           118:                                clkretran(conn);
        !           119:                        if (probing) {
        !           120:                                inactive = Chclock - conn->cn_active;
        !           121:                                if (inactive >= UPTIME)
        !           122:                                        chdead(conn);
        !           123:                                else if (conn->cn_tacked != conn->cn_tlast &&
        !           124:                                         inactive >= PROBERATE ||
        !           125:                                         inactive >= TESTRATE) {
        !           126:                                        debug(DCONN,
        !           127:                                                printf("Conn #%x: Probe: %D\n",
        !           128:                                                        conn->cn_lidx,
        !           129:                                                        inactive));
        !           130:                                        sendsns(conn);
        !           131:                                }
        !           132:                        }
        !           133:                } else if (conn->cn_state == CSRFCSENT) {
        !           134:                        /*
        !           135:                         * The RFC packet, if it has finished being sent out
        !           136:                         * will be at cn_thead.  If it is still in the process
        !           137:                         * of being sent it will not be there yet.
        !           138:                         */
        !           139:                        pkt = conn->cn_thead;
        !           140:                        inactive = Chclock - conn->cn_active;
        !           141:                        if (inactive >= RFCTIME) {
        !           142:                                debug(DCONN|DABNOR, printf("Conn #%x: RFC Timeout\n",conn->cn_lidx));
        !           143:                                clsconn(conn, CSCLOSED, NOPKT);
        !           144:                        } else if (pkt != NOPKT &&
        !           145:                                   cmp_gt(Chclock, pkt->pk_time + RFCRATE)) {
        !           146:                                debug(DCONN|DABNOR,printf("Conn #%x: RFC Retransmit\n",conn->cn_lidx));
        !           147:                                conn->cn_ttail = conn->cn_thead = NOPKT;
        !           148:                                senddata(pkt);
        !           149:                        }
        !           150:                }
        !           151: }
        !           152: 
        !           153: clkretran(conn)
        !           154: struct connection *conn;
        !           155: {
        !           156:        register struct packet *pkt, **opkt;
        !           157:        register struct packet *lastpkt;
        !           158:        struct packet *firstpkt = NOPKT;
        !           159: 
        !           160:        for (opkt = &conn->cn_thead; pkt = *opkt;)
        !           161:                if (cmp_gt(Chclock, pkt->pk_time + AGERATE)) {
        !           162:                        if (firstpkt == NOPKT) 
        !           163:                                firstpkt = pkt;
        !           164:                        else
        !           165:                                lastpkt->pk_next = pkt;
        !           166:                        lastpkt = pkt;
        !           167:                        *opkt = pkt->pk_next;
        !           168:                        pkt->pk_next = NOPKT;
        !           169:                } else
        !           170:                        opkt = &pkt->pk_next;
        !           171:        if (firstpkt != NOPKT) {
        !           172:                debug(DCONN|DABNOR,
        !           173:                        printf("Conn #%x: Rexmit (op:%d, pkn:%d)\n",
        !           174:                                conn->cn_lidx, firstpkt->pk_op,
        !           175:                                firstpkt->pk_pkn));
        !           176:                senddata(firstpkt);
        !           177:        }
        !           178: }
        !           179: /*
        !           180:  * The connection has been inactive too long, close it.
        !           181:  */
        !           182: chdead(conn)
        !           183: register struct connection *conn;
        !           184: {
        !           185:        static char tomsg[] = "Foreign host not responding";
        !           186:        register struct packet *pkt;
        !           187: 
        !           188:        debug(DCONN|DABNOR,printf("Conn #%x: Timeout\n", conn->cn_lidx));
        !           189:        if ((pkt = pkalloc(sizeof(tomsg), 1)) != NOPKT) {
        !           190:                pkt = pktstr(pkt, tomsg, sizeof(tomsg));
        !           191:                pkt->pk_op = LOSOP;
        !           192:        }
        !           193:        clsconn(conn, CSINCT, pkt);
        !           194: }
        !           195: /*
        !           196:  * Increase the cost of accessing a subnet via a gateway
        !           197:  */
        !           198: chroutage()
        !           199: {
        !           200:        register struct chroute *r;
        !           201: 
        !           202:        for (r = Chroutetab; r < &Chroutetab[CHNSUBNET]; r++)
        !           203:                if ((r->rt_type == CHBRIDGE || r->rt_type == CHDIRECT) &&
        !           204:                    r->rt_cost < CHHCOST)
        !           205:                        r->rt_cost++;
        !           206: }
        !           207: /*
        !           208:  * Send routing packets on all directly connected subnets, unless we are on
        !           209:  * only one.
        !           210:  */
        !           211: chbridge()
        !           212: {
        !           213:        register struct chroute *r;
        !           214:        register struct packet *pkt;
        !           215:        register struct rut_data *rd;
        !           216:        register int ndirect;
        !           217:        register int n;
        !           218: 
        !           219:        /*
        !           220:         * Count the number of subnets to which we are directly connected.
        !           221:         * If not more than one, then we are not a bridge and shouldn't
        !           222:         * send out routing packets at all.
        !           223:         * While we're at it, count the number of subnets we know we
        !           224:         * have any access to.  This number determines the size of the
        !           225:         * routine packet we need to send, if any.
        !           226:         */
        !           227:        n = ndirect = 0;
        !           228:        for (r = Chroutetab; r <= &Chroutetab[CHNSUBNET]; r++)
        !           229:                switch(r->rt_type) {
        !           230:                case CHDIRECT:
        !           231:                        ndirect++;
        !           232:                default:
        !           233:                        n++;
        !           234:                        break;
        !           235:                case CHNOPATH:
        !           236:                        ;       
        !           237:                }
        !           238:        if (ndirect <= 1 ||
        !           239:            (pkt = pkalloc(n * sizeof(struct rut_data), 1)) == NOPKT)
        !           240:                return;
        !           241:        /*
        !           242:         * Build the routing packet to send out on each directly connected
        !           243:         * subnet.  It is complete except for the cost of the directly
        !           244:         * connected subnet we are sending it out on.  This cost must be
        !           245:         * added to each entry in the packet each time it is sent.
        !           246:         */
        !           247:        pkt->pk_len = n * sizeof(struct rut_data);
        !           248:        pkt->pk_op = RUTOP;
        !           249:        pkt->pk_type = pkt->pk_daddr = pkt->pk_sidx = pkt->pk_didx = 0;
        !           250:        pkt->pk_next = NOPKT;
        !           251:        rd = pkt->pk_rutdata;
        !           252:        for (n = 0, r = Chroutetab; r < &Chroutetab[CHNSUBNET]; r++, n++)
        !           253:                if (r->rt_type != CHNOPATH) {
        !           254:                        rd->pk_subnet = n;
        !           255:                        rd->pk_cost = r->rt_cost;
        !           256:                        rd++;
        !           257:                }
        !           258:        /*
        !           259:         * Now send out this packet on each directly connected subnet.
        !           260:         * ndirect becomes zero on last such subnet.
        !           261:         */
        !           262:        for (r = Chroutetab; r < &Chroutetab[CHNSUBNET]; r++)
        !           263:                if (r->rt_type == CHDIRECT)
        !           264:                        sendrut(pkt, r->rt_xcvr, r->rt_cost, --ndirect);
        !           265: }

unix.superglobalmegacorp.com

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