Annotation of lucent/sys/src/9/port/f002543, revision 1.1.1.1

1.1       root        1: #include       "u.h"
                      2: #include       "../port/lib.h"
                      3: #include       "mem.h"
                      4: #include       "dat.h"
                      5: #include       "fns.h"
                      6: #include       "../port/error.h"
                      7: #include       "arp.h"
                      8: #include       "../port/ipdat.h"
                      9: 
                     10: #define DPRINT if(tcpdbg) print
                     11: 
                     12: extern int tcpdbg;
                     13: extern ushort tcp_mss;
                     14:        int tcptimertype;
                     15: 
                     16: void
                     17: tcpoutput(Ipconv *s)
                     18: {
                     19:        Tcp seg;
                     20:        int qlen;
                     21:        Tcphdr ph;
                     22:        Tcpctl *tcb;
                     23:        Block *hbp,*dbp, *sndq;
                     24:        ushort ssize, dsize, usable, sent;
                     25: 
                     26:        tcb = &s->tcpctl;
                     27: 
                     28:        switch(tcb->state) {
                     29:        case Listen:
                     30:        case Closed:
                     31:                return;
                     32:        }
                     33: 
                     34:        for(;;) {
                     35:                qlen = tcb->sndcnt;
                     36:                sent = tcb->snd.ptr - tcb->snd.una;
                     37:                sndq = tcb->sndq;
                     38: 
                     39:                /* Don't send anything else until our SYN has been acked */
                     40:                if(sent != 0)
                     41:                if((tcb->flags & SYNACK) == 0)
                     42:                        break;
                     43: 
                     44:                /* Compute usable segment based on offered window and limit
                     45:                 * window probes to one
                     46:                 */
                     47:                if(tcb->snd.wnd == 0){
                     48:                        if(sent != 0) {
                     49:                                if ((tcb->flags&FORCE) == 0)
                     50:                                        break;
                     51:                                tcb->snd.ptr = tcb->snd.una;
                     52:                        }
                     53:                        usable = 1;
                     54:                }
                     55:                else {
                     56:                        usable = MIN(tcb->snd.wnd,tcb->cwind) - sent;
                     57:                        if(sent != 0)
                     58:                        if(qlen - sent < tcb->mss) 
                     59:                                usable = 0;
                     60:                }
                     61: 
                     62:                ssize = MIN(qlen - sent, usable);
                     63:                ssize = MIN(ssize, tcb->mss);
                     64:                dsize = ssize;
                     65:                seg.up = 0;
                     66: 
                     67:                if(ssize == 0)
                     68:                if((tcb->flags&FORCE) == 0)
                     69:                        break;
                     70: 
                     71:                tcphalt(&tcb->acktimer);
                     72: 
                     73:                tcb->flags &= ~FORCE;
                     74:                tcprcvwin(s);
                     75: 
                     76:                /* By default we will generate an ack */
                     77:                seg.source = s->psrc;
                     78:                seg.dest = s->pdst;
                     79:                seg.flags = ACK;        
                     80:                seg.mss = 0;
                     81: 
                     82:                switch(tcb->state){
                     83:                case Syn_sent:
                     84:                        seg.flags = 0;
                     85:                        /* No break */
                     86:                case Syn_received:
                     87:                        if(tcb->snd.ptr == tcb->iss){
                     88:                                seg.flags |= SYN;
                     89:                                dsize--;
                     90:                                seg.mss = tcp_mss;
                     91:                        }
                     92:                        break;
                     93:                }
                     94:                tcb->last_ack = tcb->rcv.nxt;
                     95:                seg.seq = tcb->snd.ptr;
                     96:                seg.ack = tcb->rcv.nxt;
                     97:                seg.wnd = tcb->rcv.wnd;
                     98: 
                     99:                /* Pull out data to send */
                    100:                dbp = 0;
                    101:                if(dsize != 0){
                    102:                        if(dupb(&dbp, sndq, sent, dsize) != dsize) {
                    103:                                seg.flags |= FIN;
                    104:                                dsize--;
                    105:                        }
                    106:                        DPRINT("dupb: %d\n", dbp->rptr[0]);
                    107:                }
                    108: 
                    109:                if(sent+dsize == qlen)
                    110:                        seg.flags |= PSH;
                    111: 
                    112:                /*
                    113:                 * keep track of balance of resent data */
                    114:                if(tcb->snd.ptr < tcb->snd.nxt)
                    115:                        tcb->resent += MIN(tcb->snd.nxt - tcb->snd.ptr,(int)ssize);
                    116: 
                    117:                tcb->snd.ptr += ssize;
                    118: 
                    119:                /* Pull up the send pointer so we can accept acks for this window */
                    120:                if(seq_gt(tcb->snd.ptr,tcb->snd.nxt))
                    121:                        tcb->snd.nxt = tcb->snd.ptr;
                    122: 
                    123:                /* Fill in fields of pseudo IP header */
                    124:                hnputl(ph.tcpdst, s->dst);
                    125:                if(s->src == 0)
                    126:                        s->src = ipgetsrc(ph.tcpdst);
                    127:                hnputl(ph.tcpsrc, s->src);
                    128:                hnputs(ph.tcpsport, s->psrc);
                    129:                hnputs(ph.tcpdport, s->pdst);
                    130: 
                    131:                /* Build header, link data and compute cksum */
                    132:                if((hbp = htontcp(&seg, dbp, &ph)) == 0) {
                    133:                        freeb(dbp);
                    134:                        return;
                    135:                }
                    136: 
                    137:                /* Start the transmission timers if there is new data and we
                    138:                 * expect acknowledges
                    139:                 */
                    140:                if(ssize != 0){
                    141:                        tcb->timer.start = backoff(tcb->backoff) *
                    142:                         (2 * tcb->mdev + tcb->srtt + MSPTICK) / MSPTICK;
                    143:                        if(!run_timer(&tcb->timer))
                    144:                                tcpgo(&tcb->timer);
                    145: 
                    146:                        /* If round trip timer isn't running, start it */
                    147:                        if(!run_timer(&tcb->rtt_timer)){
                    148:                                tcpgo(&tcb->rtt_timer);
                    149:                                tcb->rttseq = tcb->snd.ptr;
                    150:                        }
                    151:                }
                    152:                ipmuxoput(0, hbp);
                    153:        }
                    154: }
                    155: 
                    156: /*
                    157:  *  the BSD convention (hack?) for keep alives.  resend last byte acked.
                    158:  */
                    159: void
                    160: tcpkeepalive(Ipconv *s)
                    161: {
                    162:        Tcp seg;
                    163:        Tcphdr ph;
                    164:        Tcpctl *tcb;
                    165:        Block *hbp,*dbp;
                    166: 
                    167:        tcb = &s->tcpctl;
                    168: 
                    169:        dbp = 0;
                    170:        seg.up = 0;
                    171:        seg.source = s->psrc;
                    172:        seg.dest = s->pdst;
                    173:        seg.flags = ACK|PSH;    
                    174:        seg.mss = 0;
                    175:        seg.seq = tcb->snd.una-1;
                    176:        seg.ack = tcb->rcv.nxt;
                    177:        seg.wnd = tcb->rcv.wnd;
                    178:        tcb->last_ack = tcb->rcv.nxt;
                    179:        if(tcb->state == Finwait2){
                    180:                seg.flags |= FIN;
                    181:        } else {
                    182:                dbp = allocb(1);
                    183:                dbp->wptr++;
                    184:        }
                    185: 
                    186:        /* Fill in fields of pseudo IP header */
                    187:        hnputl(ph.tcpdst, s->dst);
                    188:        if(s->src == 0)
                    189:                s->src = ipgetsrc(ph.tcpdst);
                    190:        hnputl(ph.tcpsrc, s->src);
                    191:        hnputs(ph.tcpsport, s->psrc);
                    192:        hnputs(ph.tcpdport, s->pdst);
                    193: 
                    194:        /* Build header, link data and compute cksum */
                    195:        if((hbp = htontcp(&seg, dbp, &ph)) == 0) {
                    196:                freeb(dbp);
                    197:                return;
                    198:        }
                    199: 
                    200:        ipmuxoput(0, hbp);
                    201: }
                    202: 
                    203: void
                    204: tcprxmit(Ipconv *s)
                    205: {
                    206:        Tcpctl *tcb;
                    207: 
                    208:        tcb = &s->tcpctl;
                    209:        qlock(tcb);
                    210:        tcb->flags |= RETRAN|FORCE;
                    211:        tcb->snd.ptr = tcb->snd.una;
                    212: 
                    213:        /* Pull window down to a single packet and halve the slow
                    214:         * start threshold
                    215:         */
                    216:        tcb->ssthresh = tcb->cwind / 2;
                    217:        tcb->ssthresh = MAX(tcb->ssthresh, tcb->mss);
                    218: 
                    219:        tcb->cwind = tcb->mss;
                    220:        tcpoutput(s);
                    221:        qunlock(tcb);
                    222: }
                    223: 
                    224: void
                    225: tcptimeout(void *arg)
                    226: {
                    227:        Tcpctl *tcb;
                    228:        Ipconv *s;
                    229: 
                    230:        s = (Ipconv *)arg;
                    231:        tcb = &s->tcpctl;
                    232:        switch(tcb->state){
                    233:        default:
                    234:                tcb->backoff++;
                    235:                if (tcb->backoff >= MAXBACKOFF && tcb->snd.wnd > 0) {
                    236:                        qlock(tcb);
                    237:                        localclose(s, Etimedout);
                    238:                        qunlock(tcb);
                    239:                        break;
                    240:                }
                    241:                tcprxmit(s);
                    242:                break;
                    243: 
                    244:        case Finwait2:
                    245:                if(--(tcb->kacounter) == 0){
                    246:                        qlock(tcb);
                    247:                        localclose(s, Etimedout);
                    248:                        qunlock(tcb);
                    249:                } else {
                    250:                        qlock(tcb);
                    251:                        tcpkeepalive(s);
                    252:                        qunlock(tcb);
                    253:                        tcpgo(&tcb->timer);
                    254:                }
                    255:                break;
                    256: 
                    257:        case Time_wait:
                    258:                qlock(tcb);
                    259:                localclose(s, 0);
                    260:                qunlock(tcb);
                    261:                break;
                    262:        }
                    263: }
                    264: 
                    265: int
                    266: backoff(int n)
                    267: {
                    268:        if(tcptimertype == 1) 
                    269:                return n+1;
                    270: 
                    271:        if(n <= 6)
                    272:                return 1 << n;
                    273: 
                    274:        return 64;
                    275: }
                    276: 
                    277: void
                    278: tcpacktimer(Ipconv *s)
                    279: {
                    280:        Tcpctl *tcb = &s->tcpctl;
                    281: 
                    282:        qlock(tcb);
                    283:        tcb->flags |= FORCE;
                    284:        tcprcvwin(s);
                    285:        tcpoutput(s);
                    286:        qunlock(tcb);
                    287: }
                    288: 
                    289: void
                    290: tcprcvwin(Ipconv *s)                           /* Call with tcb locked */
                    291: {
                    292:        int w;
                    293:        Tcpctl *tcb;
                    294: 
                    295:        tcb = &s->tcpctl;
                    296:        qlock(s);
                    297:        if(s->readq) {
                    298:                w = Streamhi - s->readq->next->len;
                    299:                if(w < 0)
                    300:                        tcb->rcv.wnd = 0;
                    301:                else
                    302:                        tcb->rcv.wnd = w;
                    303:        }
                    304:        else
                    305:                tcb->rcv.wnd = Streamhi;
                    306:        qunlock(s);
                    307: }
                    308: 
                    309: /*
                    310:  * Network byte order functions
                    311:  */
                    312: 
                    313: void
                    314: hnputs(uchar *ptr, ushort val)
                    315: {
                    316:        ptr[0] = val>>8;
                    317:        ptr[1] = val;
                    318: }
                    319: 
                    320: void
                    321: hnputl(uchar *ptr, ulong val)
                    322: {
                    323:        ptr[0] = val>>24;
                    324:        ptr[1] = val>>16;
                    325:        ptr[2] = val>>8;
                    326:        ptr[3] = val;
                    327: }
                    328: 
                    329: ulong
                    330: nhgetl(uchar *ptr)
                    331: {
                    332:        return ((ptr[0]<<24) | (ptr[1]<<16) | (ptr[2]<<8) | ptr[3]);
                    333: }
                    334: 
                    335: ushort
                    336: nhgets(uchar *ptr)
                    337: {
                    338:        return ((ptr[0]<<8) | ptr[1]);
                    339: }

unix.superglobalmegacorp.com

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