Annotation of lucent/sys/src/9/port/f002543, revision 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.