Annotation of researchv8dc/sys/chncp/chclock.c, revision 1.1.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.