Annotation of researchv8dc/sys/chncp/chsend.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:  * Send a STS packet on this connection
                      7:  *     if allocation fails it is not sent
                      8:  */
                      9: sendsts(conn)
                     10: register struct connection *conn;
                     11: {
                     12:        register struct packet *pkt;
                     13: 
                     14:        if ((pkt = pkalloc(sizeof(struct sts_data), 1)) != NOPKT) {
                     15:                setpkt(conn, pkt);
                     16:                makests(conn, pkt);
                     17:                sendctl(pkt);
                     18:        }
                     19: }
                     20: 
                     21: /*
                     22:  * Send a SNS packet on this connection
                     23:  *     if allocation failed nothing is sent
                     24:  */
                     25: sendsns(conn)
                     26: register struct connection *conn;
                     27: {
                     28:        register struct packet *pkt;
                     29: 
                     30:        if ((pkt = pkalloc(0, 1)) != NOPKT) {
                     31:                setpkt(conn, pkt);
                     32:                pkt->pk_op = SNSOP;
                     33:                pkt->pk_lenword = 0;
                     34:                pkt->pk_ackn = conn->cn_racked = conn->cn_rread;
                     35:                sendctl(pkt);
                     36:        }
                     37: }
                     38: 
                     39: /*
                     40:  * Send an open in response to a RFC
                     41:  *     return NOPKT is allocation fails else, open packet
                     42:  */
                     43: sendopn(conn)
                     44: register struct connection *conn;
                     45: {
                     46:        register struct packet *pkt;
                     47: 
                     48:        if ((pkt = pkalloc(sizeof(struct sts_data), 1)) != NOPKT) {
                     49:                conn->cn_rsts = conn->cn_rwsize >> 1;
                     50:                conn->cn_tlast = 0;
                     51:                pkt->pk_op = OPNOP;
                     52:                pkt->pk_len = sizeof(struct sts_data);
                     53:                pkt->pk_receipt = conn->cn_rlast;
                     54:                pkt->pk_rwsize = conn->cn_rwsize;
                     55:                debug(DCONN,printf("Conn #%x: open sent\n",conn->cn_lidx));
                     56:                (void)ch_write(conn, pkt);
                     57:        }
                     58: }
                     59: 
                     60: 
                     61: /*
                     62:  * Following are functions and macros that deal with tranmitters directly
                     63:  *
                     64:  * Macro XMITHEAD (pkt, xcvr) queues pkt on xcvr for transmission, putting
                     65:  * it at the head of the queue for "quick" action.  The transmitter is
                     66:  * started if no packet is currently being transmitted.
                     67:  * It is assumed that the pkt is a single one and not a list.
                     68:  * Macro XMITTAIL is similar except that is queues the packet at the tail
                     69:  * of the transmit list, treats the pkt argument as a list, and puts a time
                     70:  * stamp in each packet in the list.
                     71:  * Note that XMITTAIL modifies the variable pkt.
                     72:  */
                     73: #define XMITHEAD(pkt, axcvr) \
                     74:                {       register struct chxcvr *xcvr = axcvr; \
                     75:                        pkt->pk_next = xcvr->xc_list; \
                     76:                        xcvr->xc_list = pkt; \
                     77:                        if (xcvr->xc_tail == NOPKT) { \
                     78:                                xcvr->xc_tail = pkt; \
                     79:                                if (xcvr->xc_tpkt == NOPKT) \
                     80:                                        (*xcvr->xc_start)(xcvr); \
                     81:                        } \
                     82:                }
                     83: /*
                     84:  * Sendctl - send a control packet that will not be acknowledged and
                     85:  *     will not be retransmitted (this actual packet).  Put the
                     86:  *     given packet at the head of the transmit queue so it is transmitted
                     87:  *     "quickly", i.e. before data packets queued at the tail of the queue.
                     88:  *     If anything is wrong (no path, bad subnet) we just throw it
                     89:  *     away. Remember, pk_next is assumed to be == NOPKT.
                     90:  */
                     91: sendctl(pkt)
                     92: register struct packet *pkt;
                     93: {
                     94:        register struct chroute *r;
                     95: 
                     96:        debug(DSEND, (printf("Sending: %d ", pkt->pk_op), prpkt(pkt, "ctl"), printf("\n")));
                     97:        if (pkt->pk_dsubnet >= CHNSUBNET ||
                     98:            (r = &Chroutetab[pkt->pk_dsubnet])->rt_type == CHNOPATH)
                     99:                ch_free((char *)pkt);
                    100:        else if (pkt->pk_daddr == Chmyaddr)
                    101:                sendtome(pkt);
                    102:        else {
                    103:                if (r->rt_type == CHFIXED || r->rt_type == CHBRIDGE) {
                    104:                        pkt->pk_xdest = r->rt_addr;
                    105:                        r = &Chroutetab[r->rt_subnet];
                    106:                } else
                    107:                        pkt->pk_xdest = pkt->pk_daddr;
                    108:                XMITHEAD(pkt, r->rt_xcvr);
                    109:        }
                    110: }
                    111: /*
                    112:  * Senddata - send a list of controlled packets, all assumed to be to the
                    113:  *     same destination.  Queue them on the end of the appropriate transmit
                    114:  *     queue.
                    115:  *     Similar to sendctl, but stuffs time, handles a list, and puts pkts
                    116:  *     at the end of the queue instead of at the beginning, and fakes
                    117:  *     transmission if it can't really send the packets (as opposed to
                    118:  *     throwing the packets away)
                    119:  */
                    120: senddata(pkt)
                    121: register struct packet *pkt;
                    122: {
                    123:        register struct chroute *r;
                    124: 
                    125:        debug(DSEND, (printf("Sending: %d ", pkt->pk_op), prpkt(pkt, "data"), printf("\n")));
                    126:        if (pkt->pk_dsubnet >= CHNSUBNET ||
                    127:            (r = &Chroutetab[pkt->pk_dsubnet])->rt_type == CHNOPATH) {
                    128:                struct packet *npkt;
                    129: 
                    130:                do {
                    131:                        npkt = pkt->pk_next;
                    132:                        pkt->pk_next = NOPKT;
                    133:                        xmitdone(pkt);
                    134:                } while ((pkt = npkt) != NOPKT);
                    135:        } else if (pkt->pk_daddr == Chmyaddr)
                    136:                sendtome(pkt);
                    137:        else {
                    138:                register struct chxcvr *xcvr;
                    139:                register unsigned short dest;
                    140: 
                    141:                if (r->rt_type == CHFIXED || r->rt_type == CHBRIDGE) {
                    142:                        dest = r->rt_addr;
                    143:                        r = &Chroutetab[r->rt_subnet];
                    144:                } else
                    145:                        dest = pkt->pk_daddr;
                    146:                xcvr = r->rt_xcvr;
                    147:                if (xcvr->xc_list == NOPKT)
                    148:                        xcvr->xc_list = pkt;
                    149:                else
                    150:                        xcvr->xc_tail->pk_next = pkt;
                    151:                for (;;) {
                    152:                        pkt->pk_time = Chclock;
                    153:                        pkt->pk_xdest = dest;
                    154:                        if (pkt->pk_next == NOPKT)
                    155:                                break;
                    156:                        pkt = pkt->pk_next;
                    157:                }
                    158:                xcvr->xc_tail = pkt; 
                    159:                if (xcvr->xc_tpkt == NOPKT)
                    160:                        (*xcvr->xc_start)(xcvr);
                    161:        }
                    162: }
                    163: /*
                    164:  * Send the given RUT packet out on the given tranceiver, which has the given
                    165:  * cost.  If the "copy" flag is true, make a copy of the packet.
                    166:  * Note that if copy is not set, the packet data gets modified.
                    167:  */
                    168: sendrut(pkt, axcvr, cost, copy)
                    169: register struct packet *pkt;
                    170: register struct chxcvr *axcvr;
                    171: unsigned short cost;
                    172: int copy;
                    173: {
                    174:        register struct rut_data *rd;
                    175:        struct rut_data *rdend;
                    176: 
                    177:        if (copy) {
                    178:                struct packet *npkt;
                    179: 
                    180:                if ((npkt = pkalloc((int)pkt->pk_len, 1)) == NOPKT)
                    181:                        return;
                    182:                movepkt(pkt, npkt);
                    183:                pkt = npkt;
                    184:        }
                    185:        rdend = (struct rut_data *)(pkt->pk_cdata + pkt->pk_len);
                    186:        for (rd = pkt->pk_rutdata; rd < rdend; rd++)
                    187:                rd->pk_cost += cost;
                    188:        pkt->pk_saddr = axcvr->xc_addr;
                    189:        pkt->pk_xdest = 0;
                    190:        XMITHEAD(pkt, axcvr);
                    191: }
                    192: /*
                    193:  * Send the (list of) packet(s) to myself - NOTE THIS CAN BE RECURSIVE!
                    194:  */
                    195: sendtome(pkt)
                    196: register struct packet *pkt;
                    197: {
                    198:        register struct packet *rpkt, *npkt;
                    199:        static struct chxcvr fakexcvr;
                    200: 
                    201:        /*
                    202:         * Static structure is used to economize on stack space.
                    203:         * We are careful to use it very locally so that recursion still
                    204:         * works. Cleaner solutions don't recurse very well.
                    205:         * Basically for each packet in the list, prepare it for
                    206:         * transmission by executing xmitnext,
                    207:         * complete the transmission by calling xmitdone,
                    208:         * then receive the packet on the other side, possibly
                    209:         * causing this routine to recurse (after we're done with the
                    210:         * static structure until next time around the loop)
                    211:         * When this routine is called with a list of data packets, things
                    212:         * can get pretty weird.
                    213:         */
                    214:        while (pkt != NOPKT) {
                    215:                /*
                    216:                 * Make the transmit list consist of one packet to send.
                    217:                 * Save the rest of the list in npkt.
                    218:                 */
                    219:                npkt = pkt->pk_next;
                    220:                pkt->pk_next = NOPKT;
                    221:                fakexcvr.xc_tpkt = NOPKT;
                    222:                fakexcvr.xc_list = fakexcvr.xc_tail = pkt;
                    223:                /*
                    224:                 * The xmitnext just dequeues pkt and sets ackn.
                    225:                 * It will free the packet if its not worth sending.
                    226:                 */
                    227:                (void)xmitnext(&fakexcvr);
                    228:                if (fakexcvr.xc_tpkt) {
                    229:                        /*
                    230:                         * So it really should be sent.
                    231:                         * First make a copy for the receiving side in rpkt.
                    232:                         */
                    233:                        if ((rpkt = pkalloc((int)pkt->pk_len, 1)) != NOPKT)
                    234:                                movepkt(pkt, rpkt);
                    235:                        /*
                    236:                         * This xmitdone just completes transmission.
                    237:                         * Now pkt is out of our hands.
                    238:                         */
                    239:                        xmitdone(pkt);
                    240:                        /*
                    241:                         * So transmission is complete. Now receive it.
                    242:                         */
                    243:                        if (rpkt != NOPKT)
                    244:                                rcvpkt(rpkt);
                    245:                }
                    246:                pkt = npkt;
                    247:        }
                    248: }
                    249: /*
                    250:  * Indicate that actual transmission of the current packet has been completed.
                    251:  * Called by the device dependent interrupt routine when transmission
                    252:  *  of a packet has finished.
                    253:  */
                    254: xmitdone(pkt)
                    255: register struct packet *pkt;
                    256: {
                    257:        register struct connection *conn;
                    258:        register struct packet *npkt;
                    259: 
                    260:        if (pkt->pk_saddr == Chmyaddr && CONTPKT(pkt) &&
                    261:            pkt->pk_stindex < CHNCONNS &&
                    262:            (conn = Chconntab[pkt->pk_stindex]) != NOCONN &&
                    263:            pkt->pk_sidx == conn->cn_lidx &&
                    264:            (conn->cn_state == CSOPEN || conn->cn_state == CSRFCSENT) &&
                    265:            cmp_gt(pkt->pk_pkn, conn->cn_trecvd)) {
                    266:                pkt->pk_time = Chclock;
                    267:                if ((npkt = conn->cn_thead) == NOPKT || 
                    268:                    cmp_lt(pkt->pk_pkn, npkt->pk_pkn)) {
                    269:                        pkt->pk_next = npkt;
                    270:                        conn->cn_thead = pkt;
                    271:                } else {
                    272:                        for( ; npkt->pk_next != NOPKT; npkt = npkt->pk_next)
                    273:                                if(cmp_lt(pkt->pk_pkn, npkt->pk_next->pk_pkn))
                    274:                                        break;
                    275:                        pkt->pk_next = npkt->pk_next;
                    276:                        npkt->pk_next = pkt;
                    277:                }
                    278:                if(pkt->pk_next == NOPKT)
                    279:                        conn->cn_ttail = pkt;
                    280:        } else
                    281:                ch_free((char *)pkt);
                    282: }
                    283: /*
                    284:  * Return the next packet on which to begin transmission (if none,  NOPKT).
                    285:  */
                    286: struct packet *
                    287: xmitnext(xcvr)
                    288: register struct chxcvr *xcvr;
                    289: {
                    290:        register struct packet *pkt;
                    291:        register struct connection *conn;
                    292: 
                    293:        while ((pkt = xcvr->xc_tpkt = xcvr->xc_list) != NOPKT) {
                    294:                if ((xcvr->xc_list = pkt->pk_next) == NOPKT)
                    295:                        xcvr->xc_tail = NOPKT;
                    296:                if (pkt->pk_saddr == Chmyaddr && CONTPKT(pkt))
                    297:                        if (pkt->pk_stindex < CHNCONNS &&
                    298:                            (conn = Chconntab[pkt->pk_stindex]) != NOCONN &&
                    299:                            pkt->pk_sidx == conn->cn_lidx &&
                    300:                            (conn->cn_state == CSOPEN || conn->cn_state == CSRFCSENT) &&
                    301:                            cmp_gt(pkt->pk_pkn, conn->cn_trecvd))
                    302:                                pkt->pk_ackn = conn->cn_racked = conn->cn_rread;
                    303:                        else {
                    304:                                debug(DPKT,
                    305:                                        printf("invalid pkt to send: #%x\n",
                    306:                                                conn->cn_lidx));
                    307:                                ch_free((char *)pkt);
                    308:                                continue;
                    309:                        }
                    310:                xcvr->xc_ttime = Chclock;
                    311:                break;
                    312:        }
                    313:        return (pkt);
                    314: }

unix.superglobalmegacorp.com

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