Annotation of researchv8dc/sys/chncp/chsend.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:  * 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.