| plan 9 kernel history: overview | file list | diff list |
2001/0505/ip/tcp.c (diff list | history)
| 1997/0327/sys/src/9/ip/tcp.c:239,251 – 1997/0403/sys/src/9/ip/tcp.c:239,252 (short | long) | ||
| 1997/0327 | static char* tcpconnect(Conv *c, char **argv, int argc) { | |
| 1997/0403 | char *e; | |
| 1997/0327 |
| |
| 1997/0403 | e = Fsstdconnect(c, argv, argc); if(e != nil) return e; | |
| 1997/0327 | tcpstart(c, TCP_CONNECT, QMAX); | |
| 1997/0403 | return nil; | |
| 1997/0327 | } int | |
| 1997/0327/sys/src/9/ip/tcp.c:273,283 – 1997/0403/sys/src/9/ip/tcp.c:274,291 | ||
| 1997/0327 | return isclose; } | |
| 1997/0403 | static char* tcpannounce(Conv *c, char **argv, int argc) | |
| 1997/0327 | { | |
| 1997/0403 | char *e; e = Fsstdannounce(c, argv, argc); if(e != nil) return e; | |
| 1997/0327 | tcpstart(c, TCP_LISTEN, QMAX); Fsconnected(&fs, c, nil); | |
| 1997/0403 | return nil; | |
| 1997/0327 | } static void | |
| 1997/0403/sys/src/9/ip/tcp.c:190,196 – 1997/0423/sys/src/9/ip/tcp.c:190,196 (short | long) | ||
| 1997/0327 | void getreseq(Tcpctl*, Tcp*, Block**, ushort*); void localclose(Conv*, char*); void procsyn(Conv*, Tcp*); | |
| 1997/0423 | void tcpiput(Media*, Block*); | |
| 1997/0327 | void tcpoutput(Conv*); int tcptrim(Tcpctl*, Tcp*, Block**, ushort*); void tcpstart(Conv*, int, ushort); | |
| 1997/0403/sys/src/9/ip/tcp.c:1052,1058 – 1997/0423/sys/src/9/ip/tcp.c:1052,1058 | ||
| 1997/0327 | } void | |
| 1997/0423 | tcpiput(Media *m, Block *bp) | |
| 1997/0327 | { Tcp seg; Tcphdr *h; | |
| 1997/0403/sys/src/9/ip/tcp.c:1062,1067 – 1997/0423/sys/src/9/ip/tcp.c:1062,1068 | ||
| 1997/0327 | Ipaddr source, dest; Conv *spec, *gen, *s, **p; | |
| 1997/0423 | USED(m); | |
| 1997/0327 | h = (Tcphdr*)(bp->rp); dest = nhgetl(h->tcpdst); | |
| 1997/0423/sys/src/9/ip/tcp.c:232,238 – 1997/0515/sys/src/9/ip/tcp.c:232,238 (short | long) | ||
| 1997/0327 | break; } | |
| 1997/0515 | if(oldstate == Syn_sent && newstate != Closed) | |
| 1997/0327 | Fsconnected(&fs, s, nil); } | |
| 1997/0515/sys/src/9/ip/tcp.c:900,906 – 1997/0802/sys/src/9/ip/tcp.c:900,906 (short | long) | ||
| 1997/0327 | return 1; } else { | |
| 1997/0802 | if(x >= low || x <= high) | |
| 1997/0327 | return 1; } return 0; | |
| 1997/0802/sys/src/9/ip/tcp.c:1469,1474 – 1997/0806/sys/src/9/ip/tcp.c:1469,1475 (short | long) | ||
| 1997/0327 | * window probes to one */ if(tcb->snd.wnd == 0){ | |
| 1997/0806 | tcp.wclosed++; | |
| 1997/0327 | if(sent != 0) { if ((tcb->flags&FORCE) == 0) break; | |
| 1997/0806/sys/src/9/ip/tcp.c:186,191 – 1997/0916/sys/src/9/ip/tcp.c:186,197 (short | long) | ||
| 1997/0327 | Timer *timers; /* List of active timers */ QLock tl; /* Protect timer list */ | |
| 1997/0916 | static struct Tcpstats { ulong dup; /* (partially) duplicated packets */ ulong dupb; /* duplicated bytes */ } tstats; | |
| 1997/0327 | void addreseq(Tcpctl*, Tcp*, Block*, ushort); void getreseq(Tcpctl*, Tcp*, Block**, ushort*); void localclose(Conv*, char*); | |
| 1997/0806/sys/src/9/ip/tcp.c:1250,1255 – 1997/0916/sys/src/9/ip/tcp.c:1256,1262 | ||
| 1997/0327 | if(seg.seq != tcb->rcv.nxt) if(length != 0 || (seg.flags & (SYN|FIN))) { update(s, &seg); | |
| 1997/0916 | tcp.order++; | |
| 1997/0327 | addreseq(tcb, &seg, bp, length); tcb->flags |= FORCE; goto output; | |
| 1997/0806/sys/src/9/ip/tcp.c:1469,1475 – 1997/0916/sys/src/9/ip/tcp.c:1476,1481 | ||
| 1997/0327 | * window probes to one */ if(tcb->snd.wnd == 0){ | |
| 1997/0806 |
| |
| 1997/0327 | if(sent != 0) { if ((tcb->flags&FORCE) == 0) break; | |
| 1997/0806/sys/src/9/ip/tcp.c:1846,1851 – 1997/0916/sys/src/9/ip/tcp.c:1852,1859 | ||
| 1997/0327 | dupcnt = tcb->rcv.nxt - seg->seq; if(dupcnt > 0){ tcb->rerecv += dupcnt; | |
| 1997/0916 | tstats.dup++; tstats.dupb += dupcnt; | |
| 1997/0327 | if(seg->flags & SYN){ seg->flags &= ~SYN; seg->seq++; | |
| 1997/0806/sys/src/9/ip/tcp.c:1924,1929 – 1997/0916/sys/src/9/ip/tcp.c:1932,1943 | ||
| 1997/0327 | return "unknown control request"; } | |
| 1997/0916 | int tcpstats(char *buf, int len) { return snprint(buf, len, "\tdupp %d dupb %d\n", tstats.dup, tstats.dupb); } | |
| 1997/0327 | void tcpinit(Fs *fs) { | |
| 1997/0806/sys/src/9/ip/tcp.c:1937,1942 – 1997/0916/sys/src/9/ip/tcp.c:1951,1957 | ||
| 1997/0327 | tcp.close = tcpclose; tcp.rcv = tcpiput; tcp.advise = tcpadvise; | |
| 1997/0916 | tcp.stats = tcpstats; | |
| 1997/0327 | tcp.ipproto = IP_TCPPROTO; tcp.nc = Nchans; tcp.ptclsize = sizeof(Tcpctl); | |
| 1997/0916/sys/src/9/ip/tcp.c:805,838 – 1997/1104/sys/src/9/ip/tcp.c:805,810 (short | long) | ||
| 1997/0327 | } /* | |
| 1997/1104/sys/src/9/ip/tcp.c:14,19 – 1998/0306/sys/src/9/ip/tcp.c:14,20 (short | long) | ||
| 1997/0327 | TCP_IPLEN = 8, TCP_PHDRSIZE = 12, TCP_HDRSIZE = 20, | |
| 1998/0306 | TCP_TCBPHDRSZ = 40, | |
| 1997/0327 | TCP_PKT = TCP_IPLEN+TCP_PHDRSIZE, TimerOFF = 0, TimerON = 1, | |
| 1997/1104/sys/src/9/ip/tcp.c:85,111 – 1998/0306/sys/src/9/ip/tcp.c:86,112 | ||
| 1997/0327 | typedef struct Tcphdr Tcphdr; struct Tcphdr { | |
| 1998/0306 | uchar vihl; /* Version and header length */ uchar tos; /* Type of service */ uchar length[2]; /* packet length */ uchar id[2]; /* Identification */ uchar frag[2]; /* Fragment information */ uchar Unused; uchar proto; uchar tcplen[2]; uchar tcpsrc[4]; uchar tcpdst[4]; uchar tcpsport[2]; uchar tcpdport[2]; uchar tcpseq[4]; uchar tcpack[4]; uchar tcpflag[2]; uchar tcpwin[2]; uchar tcpcksum[2]; uchar tcpurg[2]; | |
| 1997/0327 | /* Options segment */ | |
| 1998/0306 | uchar tcpopt[2]; uchar tcpmss[2]; | |
| 1997/0327 | }; typedef struct Tcp Tcp; | |
| 1997/1104/sys/src/9/ip/tcp.c:115,121 – 1998/0306/sys/src/9/ip/tcp.c:116,122 | ||
| 1997/0327 | ushort dest; ulong seq; ulong ack; | |
| 1998/0306 | uchar flags; | |
| 1997/0327 | ushort wnd; ushort urg; ushort mss; | |
| 1997/1104/sys/src/9/ip/tcp.c:134,142 – 1998/0306/sys/src/9/ip/tcp.c:135,143 | ||
| 1997/0327 | struct Tcpctl { QLock; | |
| 1998/0306 | uchar state; /* Connection state */ uchar type; /* Listening or active connection */ uchar code; /* Icmp code */ | |
| 1997/0327 | struct { ulong una; /* Unacked data pointer */ ulong nxt; /* Next sequence expected */ | |
| 1997/1104/sys/src/9/ip/tcp.c:147,153 – 1998/0306/sys/src/9/ip/tcp.c:148,154 | ||
| 1997/0327 | ulong wl2; } snd; struct { | |
| 1998/0306 | ulong nxt; /* Receive pointer to next uchar slot */ | |
| 1997/0327 | ushort wnd; /* Receive window incoming */ ulong urg; /* Urgent pointer */ int blocked; | |
| 1997/1104/sys/src/9/ip/tcp.c:162,169 – 1998/0306/sys/src/9/ip/tcp.c:163,170 | ||
| 1997/0327 | ushort window; /* Recevive window */ int max_snd; /* Max send */ ulong last_ack; /* Last acknowledege received */ | |
| 1998/0306 | uchar backoff; /* Exponential backoff counter */ uchar flags; /* State flags */ | |
| 1997/0327 | ulong sndcnt; /* Amount of data in send queue */ Reseq *reseq; /* Resequencing queue */ Timer timer; /* Activity timer */ | |
| 1997/1104/sys/src/9/ip/tcp.c:175,184 – 1998/0306/sys/src/9/ip/tcp.c:176,186 | ||
| 1997/0327 | int kacounter; /* count down for keep alive */ int f2counter; /* count down for finwait2 state */ uint sndsyntime; /* time syn sent */ | |
| 1998/0306 | Tcphdr protohdr; /* prototype header */ | |
| 1997/0327 | }; | |
| 1998/0306 | #define DBG(x) if((logmask & Logtcpmsg) && (iponlyset == 0 || memcmp(x, iponly+12, 4) == 0))netlog | |
| 1997/0327 | Proto tcp; int tcp_irtt = DEF_RTT; /* Initial guess at round trip time */ | |
| 1997/1104/sys/src/9/ip/tcp.c:189,195 – 1998/0306/sys/src/9/ip/tcp.c:191,197 | ||
| 1997/0916 | static struct Tcpstats { ulong dup; /* (partially) duplicated packets */ | |
| 1998/0306 | ulong dupb; /* duplicated uchars */ | |
| 1997/0916 | } tstats; | |
| 1997/0327 | void addreseq(Tcpctl*, Tcp*, Block*, ushort); | |
| 1997/1104/sys/src/9/ip/tcp.c:196,202 – 1998/0306/sys/src/9/ip/tcp.c:198,204 | ||
| 1997/0327 | void getreseq(Tcpctl*, Tcp*, Block**, ushort*); void localclose(Conv*, char*); void procsyn(Conv*, Tcp*); | |
| 1997/0423 |
| |
| 1998/0306 | void tcpiput(uchar*, Block*); | |
| 1997/0327 | void tcpoutput(Conv*); int tcptrim(Tcpctl*, Tcp*, Block**, ushort*); void tcpstart(Conv*, int, ushort); | |
| 1997/1104/sys/src/9/ip/tcp.c:206,215 – 1998/0306/sys/src/9/ip/tcp.c:208,217 | ||
| 1997/0327 | void tcpacktimer(Conv*); void | |
| 1998/0306 | tcpsetstate(Conv *s, uchar newstate) | |
| 1997/0327 | { Tcpctl *tcb; | |
| 1998/0306 | uchar oldstate; | |
| 1997/0327 | tcb = (Tcpctl*)s->ptcl; | |
| 1997/1104/sys/src/9/ip/tcp.c:231,237 – 1998/0306/sys/src/9/ip/tcp.c:233,239 | ||
| 1997/0327 | qclose(s->eq); s->lport = 0; /* This connection is toast */ s->rport = 0; | |
| 1998/0306 | ipmove(s->raddr, IPnoaddr); | |
| 1997/0327 | case Close_wait: /* Remote closes */ qhangup(s->rq, nil); | |
| 1997/1104/sys/src/9/ip/tcp.c:255,283 – 1998/0306/sys/src/9/ip/tcp.c:257,282 | ||
| 1997/0403 | return nil; | |
| 1997/0327 | } | |
| 1998/0306 | static int tcpstate(Conv *c, char *state, int n) | |
| 1997/0327 | { Tcpctl *s; | |
| 1998/0306 | return snprint(state, n, | |
| 1997/0327 | "%s srtt %d mdev %d timer.start %d timer.count %d\n", tcpstates[s->state], s->srtt, s->mdev, s->timer.start, s->timer.count); | |
| 1998/0306 | } | |
| 1997/0327 |
| |
| 1998/0306 | static int tcpinuse(Conv *c) { Tcpctl *s; s = (Tcpctl*)(c->ptcl); return s->state != Closed; | |
| 1997/0327 | } | |
| 1997/0403 | static char* | |
| 1997/1104/sys/src/9/ip/tcp.c:533,538 – 1998/0306/sys/src/9/ip/tcp.c:532,538 | ||
| 1997/0327 | inittcpctl(Conv *s) { Tcpctl *tcb; | |
| 1998/0306 | Tcphdr *h; | |
| 1997/0327 | tcb = (Tcpctl*)s->ptcl; | |
| 1997/1104/sys/src/9/ip/tcp.c:550,555 – 1998/0306/sys/src/9/ip/tcp.c:550,566 | ||
| 1997/0327 | tcb->acktimer.start = TCP_ACK / MSPTICK; tcb->acktimer.func = tcpacktimer; tcb->acktimer.arg = s; | |
| 1998/0306 | /* create a prototype(pseudo) header */ if(ipcmp(s->laddr, IPnoaddr) == 0) findlocalip(s->laddr, s->raddr); h = &tcb->protohdr; memset(h, 0, sizeof(*h)); h->proto = IP_TCPPROTO; hnputs(h->tcpsport, s->lport); hnputs(h->tcpdport, s->rport); v6tov4(h->tcpsrc, s->laddr); v6tov4(h->tcpdst, s->raddr); | |
| 1997/0327 | } /* mtu (- TCP + IP hdr len) of 1st hop */ | |
| 1997/1104/sys/src/9/ip/tcp.c:556,570 – 1998/0306/sys/src/9/ip/tcp.c:567,579 | ||
| 1997/0327 | int tcpmtu(Conv *s) { | |
| 1998/0306 | Ipifc *ifc; | |
| 1997/0327 | int mtu; mtu = 0; | |
| 1998/0306 | ifc = findipifc(s->raddr, 0); if(ifc != nil) mtu = ifc->maxmtu - ifc->m->hsize - (TCP_PKT + TCP_HDRSIZE); | |
| 1997/0327 | if(mtu < 4) mtu = DEF_MSS; return mtu; | |
| 1997/1104/sys/src/9/ip/tcp.c:647,669 – 1998/0306/sys/src/9/ip/tcp.c:656,671 | ||
| 1997/0327 | data->wp += hdrlen + TCP_PKT; } | |
| 1998/0306 | /* copy in pseudo ip header plus port numbers */ | |
| 1997/0327 | h = (Tcphdr *)(data->rp); | |
| 1998/0306 | memmove(h, ph, TCP_TCBPHDRSZ); /* copy in variable bits */ | |
| 1997/0327 | hnputs(h->tcplen, hdrlen + dlen); | |
| 1997/1104/sys/src/9/ip/tcp.c:674,680 – 1998/0306/sys/src/9/ip/tcp.c:676,682 | ||
| 1997/0327 | csum = ptclcsum(data, TCP_IPLEN, hdrlen+dlen+TCP_PHDRSIZE); hnputs(h->tcpcksum, csum); | |
| 1998/0306 | DBG(h->tcpdst)(Logtcpmsg, "%d > %d s %l8.8ux a %8.8lux %s w %.4ux l %d\n", | |
| 1997/0327 | tcph->source, tcph->dest, tcph->seq, tcph->ack, tcpflag((hdrlen<<10)|tcph->flags), tcph->wnd, dlen); | |
| 1997/1104/sys/src/9/ip/tcp.c:686,692 – 1998/0306/sys/src/9/ip/tcp.c:688,694 | ||
| 1997/0327 | ntohtcp(Tcp *tcph, Block **bpp) { Tcphdr *h; | |
| 1998/0306 | uchar *optr; | |
| 1997/0327 | ushort hdrlen; ushort i, optlen; | |
| 1997/1104/sys/src/9/ip/tcp.c:715,721 – 1998/0306/sys/src/9/ip/tcp.c:717,723 | ||
| 1997/0327 | if(*bpp == nil) return -1; | |
| 1998/0306 | DBG(h->tcpsrc)(Logtcpmsg, "%d > %d s %l8.8ux a %8.8lux %s w %.4ux l %d\n", | |
| 1997/0327 | tcph->source, tcph->dest, tcph->seq, tcph->ack, tcpflag((hdrlen<<10)|tcph->flags), tcph->wnd, nhgets(h->length)-hdrlen-TCP_PKT); | |
| 1997/1104/sys/src/9/ip/tcp.c:754,781 – 1998/0306/sys/src/9/ip/tcp.c:756,784 | ||
| 1997/0327 | tcb->sndsyntime = msec; } | |
| 1998/0306 | /* * called with v4 (4 byte) addresses */ | |
| 1997/0327 | void | |
| 1998/0306 | sndrst(uchar *source, uchar *dest, ushort length, Tcp *seg) | |
| 1997/0327 | { | |
| 1998/0306 | uchar rflags; | |
| 1997/0327 | if(seg->flags & RST) return; | |
| 1998/0306 | /* make pseudo header */ memset(&ph, 0, sizeof(ph)); v6tov4(ph.tcpsrc, dest); v6tov4(ph.tcpdst, source); | |
| 1997/0327 | ph.proto = IP_TCPPROTO; hnputs(ph.tcplen, TCP_HDRSIZE); | |
| 1998/0306 | hnputs(ph.tcpsport, seg->dest); hnputs(ph.tcpdport, seg->source); | |
| 1997/0327 |
| |
| 1997/1104/sys/src/9/ip/tcp.c:811,817 – 1998/0306/sys/src/9/ip/tcp.c:814,819 | ||
| 1997/0327 | tcphangup(Conv *s) { Tcp seg; | |
| 1997/1104/sys/src/9/ip/tcp.c:823,830 – 1998/0306/sys/src/9/ip/tcp.c:825,830 | ||
| 1997/0327 | } qlock(tcb); if(s->raddr != 0) { | |
| 1997/1104/sys/src/9/ip/tcp.c:832,846 – 1998/0306/sys/src/9/ip/tcp.c:832,839 | ||
| 1997/0327 | seg.urg = 0; seg.mss = 0; tcb->last_ack = tcb->rcv.nxt; | |
| 1998/0306 | hbp = htontcp(&seg, nil, &tcb->protohdr); | |
| 1997/0327 | ipoput(hbp, 0, s->ttl); } localclose(s, nil); | |
| 1997/1104/sys/src/9/ip/tcp.c:850,859 – 1998/0306/sys/src/9/ip/tcp.c:843,853 | ||
| 1997/0327 | } Conv* | |
| 1998/0306 | tcpincoming(Conv *s, Tcp *segp, uchar *src, uchar *dst) | |
| 1997/0327 | { Conv *new; Tcpctl *tcb; | |
| 1998/0306 | Tcphdr *h; | |
| 1997/0327 | new = Fsnewcall(&fs, s, src, segp->source, dst, segp->dest); if(new == nil) | |
| 1997/1104/sys/src/9/ip/tcp.c:867,872 – 1998/0306/sys/src/9/ip/tcp.c:861,874 | ||
| 1997/0327 | tcb->acktimer.arg = new; tcb->acktimer.state = TimerOFF; | |
| 1998/0306 | h = &tcb->protohdr; memset(h, 0, sizeof(*h)); h->proto = IP_TCPPROTO; hnputs(h->tcpsport, new->lport); hnputs(h->tcpdport, new->rport); v6tov4(h->tcpsrc, dst); v6tov4(h->tcpdst, src); | |
| 1997/0327 | return new; } | |
| 1997/1104/sys/src/9/ip/tcp.c:1030,1036 – 1998/0306/sys/src/9/ip/tcp.c:1032,1038 | ||
| 1997/0327 | } void | |
| 1997/0423 |
| |
| 1998/0306 | tcpiput(uchar*, Block *bp) | |
| 1997/0327 | { Tcp seg; Tcphdr *h; | |
| 1997/1104/sys/src/9/ip/tcp.c:1037,1050 – 1998/0306/sys/src/9/ip/tcp.c:1039,1051 | ||
| 1997/0327 | int hdrlen; Tcpctl *tcb; ushort length; | |
| 1998/0306 | uchar source[IPaddrlen], dest[IPaddrlen]; | |
| 1997/0327 | Conv *spec, *gen, *s, **p; | |
| 1997/0423 |
| |
| 1997/0327 | h = (Tcphdr*)(bp->rp); | |
| 1998/0306 | v4tov6(dest, h->tcpdst); v4tov6(source, h->tcpsrc); | |
| 1997/0327 | length = nhgets(h->length); h->Unused = 0; | |
| 1997/1104/sys/src/9/ip/tcp.c:1076,1083 – 1998/0306/sys/src/9/ip/tcp.c:1077,1085 | ||
| 1997/0327 | /* Look for a connection. failing that look for a listener. */ for(p = tcp.conv; *p; p++) { s = *p; | |
| 1998/0306 | if(s->rport == seg.source) if(s->lport == seg.dest) if(ipcmp(s->raddr, source) == 0) | |
| 1997/0327 | break; } s = *p; | |
| 1997/1104/sys/src/9/ip/tcp.c:1116,1122 – 1998/0306/sys/src/9/ip/tcp.c:1118,1124 | ||
| 1997/0327 | continue; if(tcb->state != Listen) continue; | |
| 1998/0306 | if(s->rport == 0 && ipcmp(s->raddr, IPnoaddr) == 0) { | |
| 1997/0327 | if(s->lport == seg.dest){ spec = s; break; | |
| 1997/1104/sys/src/9/ip/tcp.c:1414,1420 – 1998/0306/sys/src/9/ip/tcp.c:1416,1421 | ||
| 1997/0327 | int x; Tcp seg; int msgs; | |
| 1997/1104/sys/src/9/ip/tcp.c:1547,1563 – 1998/0306/sys/src/9/ip/tcp.c:1548,1555 | ||
| 1997/0327 | if(seq_gt(tcb->snd.ptr,tcb->snd.nxt)) tcb->snd.nxt = tcb->snd.ptr; | |
| 1998/0306 | hbp = htontcp(&seg, bp, &tcb->protohdr); | |
| 1997/0327 | if(hbp == nil) { freeblist(bp); return; | |
| 1997/1104/sys/src/9/ip/tcp.c:1588,1600 – 1998/0306/sys/src/9/ip/tcp.c:1580,1591 | ||
| 1997/0327 | } /* | |
| 1998/0306 | * the BSD convention (hack?) for keep alives. resend last uchar acked. | |
| 1997/0327 | */ void tcpkeepalive(Conv *s) { Tcp seg; | |
| 1997/1104/sys/src/9/ip/tcp.c:1618,1633 – 1998/0306/sys/src/9/ip/tcp.c:1609,1616 | ||
| 1997/0327 | dbp->wp++; } | |
| 1998/0306 | hbp = htontcp(&seg, dbp, &tcb->protohdr); | |
| 1997/0327 | if(hbp == nil) { freeblist(dbp); return; | |
| 1997/1104/sys/src/9/ip/tcp.c:1792,1798 – 1998/0306/sys/src/9/ip/tcp.c:1775,1781 | ||
| 1997/0327 | { ushort len; Block *nbp; | |
| 1998/0306 | uchar accept; | |
| 1997/0327 | int dupcnt, excess; accept = 0; | |
| 1997/1104/sys/src/9/ip/tcp.c:1866,1879 – 1998/0306/sys/src/9/ip/tcp.c:1849,1863 | ||
| 1997/0327 | { Tcphdr *h; Tcpctl *tcb; | |
| 1998/0306 | uchar source[IPaddrlen]; uchar dest[IPaddrlen]; | |
| 1997/0327 | ushort psource, pdest; Conv *s, **p; h = (Tcphdr*)(bp->rp); | |
| 1998/0306 | v4tov6(dest, h->tcpdst); v4tov6(source, h->tcpsrc); | |
| 1997/0327 | psource = nhgets(h->tcpsport); pdest = nhgets(h->tcpdport); | |
| 1997/1104/sys/src/9/ip/tcp.c:1880,1887 – 1998/0306/sys/src/9/ip/tcp.c:1864,1873 | ||
| 1997/0327 | /* Look for a connection */ for(p = tcp.conv; *p; p++) { s = *p; | |
| 1998/0306 | if(s->rport == pdest) if(s->lport == psource) if(ipcmp(s->raddr, dest) == 0) if(ipcmp(s->laddr, source) == 0){ | |
| 1997/0327 | tcb = (Tcpctl*)s->ptcl; qlock(tcb); switch(tcb->state){ | |
| 1997/1104/sys/src/9/ip/tcp.c:1896,1901 – 1998/0306/sys/src/9/ip/tcp.c:1882,1888 | ||
| 1997/0327 | freeblist(bp); } | |
| 1998/0306 | /* called with c->car qlocked */ | |
| 1997/0327 | char* tcpctl(Conv* c, char** f, int n) { | |
| 1997/1104/sys/src/9/ip/tcp.c:1907,1913 – 1998/0306/sys/src/9/ip/tcp.c:1894,1907 | ||
| 1997/0916 | int tcpstats(char *buf, int len) { | |
| 1998/0306 | int n; n = snprint(buf, len, "tcp: csum %d hlen %d len %d order %d rexmit %d", tcp.csumerr, tcp.hlenerr, tcp.lenerr, tcp.order, tcp.rexmit); n += snprint(buf+n, len-n, " dupp %d dupb %d\n", tstats.dup, tstats.dupb); return n; | |
| 1997/0916 | } | |
| 1997/0327 | void | |
| 1997/1104/sys/src/9/ip/tcp.c:1924,1929 – 1998/0306/sys/src/9/ip/tcp.c:1918,1924 | ||
| 1997/0327 | tcp.rcv = tcpiput; tcp.advise = tcpadvise; | |
| 1997/0916 | tcp.stats = tcpstats; | |
| 1998/0306 | tcp.inuse = tcpinuse; | |
| 1997/0327 | tcp.ipproto = IP_TCPPROTO; tcp.nc = Nchans; tcp.ptclsize = sizeof(Tcpctl); | |
| 1997/1104/sys/src/9/ip/tcp.c:1932,1934 – 1998/0306/sys/src/9/ip/tcp.c:1927,1930 | ||
| 1997/0327 | Fsproto(fs, &tcp); } | |
| 1998/0306 | ||
| 1998/0306/sys/src/9/ip/tcp.c:180,204 – 1998/0313/sys/src/9/ip/tcp.c:180,231 (short | long) | ||
| 1998/0306 | Tcphdr protohdr; /* prototype header */ | |
| 1997/0327 | }; | |
| 1998/0306 |
| |
| 1997/0327 |
| |
| 1997/0916 |
| |
| 1998/0313 | /* MIB II counters */ typedef struct Tcpstats Tcpstats; struct Tcpstats | |
| 1997/0916 | { | |
| 1998/0306 |
| |
| 1997/0916 |
| |
| 1998/0313 | ulong tcpRtoAlgorithm; ulong tcpRtoMin; ulong tcpRtoMax; ulong tcpMaxConn; ulong tcpActiveOpens; ulong tcpPassiveOpens; ulong tcpAttemptFails; ulong tcpEstabResets; ulong tcpCurrEstab; ulong tcpInSegs; ulong tcpOutSegs; ulong tcpRetransSegs; ulong InErrs; ulong OutRsts; }; | |
| 1997/0916 | ||
| 1998/0313 | typedef struct Tcppriv Tcppriv; struct Tcppriv { Timer *timers; /* List of active timers */ QLock tl; /* Protect timer list */ Rendez tcpr; /* used by tcpackproc */ /* MIB stats */ Tcpstats tstats; /* non-MIB stats */ ulong csumerr; /* checksum errors */ ulong hlenerr; /* header length error */ ulong lenerr; /* short packet */ ulong order; /* out of order */ }; | |
| 1997/0327 | void addreseq(Tcpctl*, Tcp*, Block*, ushort); void getreseq(Tcpctl*, Tcp*, Block**, ushort*); void localclose(Conv*, char*); void procsyn(Conv*, Tcp*); | |
| 1998/0306 |
| |
| 1998/0313 | void tcpiput(Proto*, uchar*, Block*); | |
| 1997/0327 | void tcpoutput(Conv*); int tcptrim(Tcpctl*, Tcp*, Block**, ushort*); void tcpstart(Conv*, int, ushort); | |
| 1998/0306/sys/src/9/ip/tcp.c:212,218 – 1998/0313/sys/src/9/ip/tcp.c:239,248 | ||
| 1997/0327 | { Tcpctl *tcb; | |
| 1998/0306 | uchar oldstate; | |
| 1998/0313 | Tcppriv *tpriv; | |
| 1997/0327 | ||
| 1998/0313 | tpriv = s->p->priv; | |
| 1997/0327 | tcb = (Tcpctl*)s->ptcl; oldstate = tcb->state; | |
| 1998/0306/sys/src/9/ip/tcp.c:219,224 – 1998/0313/sys/src/9/ip/tcp.c:249,259 | ||
| 1997/0327 | if(oldstate == newstate) return; | |
| 1998/0313 | if(oldstate == Established) tpriv->tstats.tcpCurrEstab--; if(newstate == Established) tpriv->tstats.tcpCurrEstab++; | |
| 1997/0327 | /* print("%d/%d %s->%s\n", s->lport, s->rport, tcpstates[oldstate], tcpstates[newstate]); | |
| 1998/0306/sys/src/9/ip/tcp.c:241,247 – 1998/0313/sys/src/9/ip/tcp.c:276,282 | ||
| 1997/0327 | } | |
| 1997/0515 | if(oldstate == Syn_sent && newstate != Closed) | |
| 1997/0327 |
| |
| 1998/0313 | Fsconnected(s, nil); | |
| 1997/0327 | } static char* | |
| 1998/0306/sys/src/9/ip/tcp.c:288,294 – 1998/0313/sys/src/9/ip/tcp.c:323,329 | ||
| 1997/0403 | if(e != nil) return e; | |
| 1997/0327 | tcpstart(c, TCP_LISTEN, QMAX); | |
| 1998/0313 | Fsconnected(c, nil); | |
| 1997/0403 | return nil; | |
| 1997/0327 | } | |
| 1998/0306/sys/src/9/ip/tcp.c:311,317 – 1998/0313/sys/src/9/ip/tcp.c:346,352 | ||
| 1997/0327 | /* * reset any incoming calls to this listener */ | |
| 1998/0313 | Fsconnected(c, "Hangup"); | |
| 1997/0327 | qlock(tcb); localclose(c, nil); | |
| 1998/0306/sys/src/9/ip/tcp.c:376,385 – 1998/0313/sys/src/9/ip/tcp.c:411,420 | ||
| 1997/0327 | * get remote sender going if it was flow controlled due to a closed window */ static void | |
| 1998/0313 | deltimer(Tcppriv *tpriv, Timer *t) | |
| 1997/0327 | { | |
| 1998/0313 | if(tpriv->timers == t) tpriv->timers = t->next; | |
| 1997/0327 | if(t->next) t->next->prev = t->prev; if(t->prev) | |
| 1998/0306/sys/src/9/ip/tcp.c:423,444 – 1998/0313/sys/src/9/ip/tcp.c:458,483 | ||
| 1997/0327 | } void | |
| 1998/0313 | tcpackproc(void *a) | |
| 1997/0327 | { Timer *t, *tp, *timeo; | |
| 1998/0313 | Proto *tcp; Tcppriv *tpriv; | |
| 1997/0327 | ||
| 1998/0313 | tcp = a; tpriv = tcp->priv; | |
| 1997/0327 | for(;;) { | |
| 1998/0313 | tsleep(&tpriv->tcpr, return0, 0, MSPTICK); | |
| 1997/0327 |
| |
| 1998/0313 | qlock(&tpriv->tl); | |
| 1997/0327 | timeo = nil; | |
| 1998/0313 | for(t = tpriv->timers; t != nil; t = tp) { | |
| 1997/0327 | tp = t->next; if(t->state == TimerON) { t->count--; if(t->count == 0) { | |
| 1998/0313 | deltimer(tpriv, t); | |
| 1997/0327 | t->state = TimerDONE; t->next = timeo; timeo = t; | |
| 1998/0306/sys/src/9/ip/tcp.c:445,451 – 1998/0313/sys/src/9/ip/tcp.c:484,490 | ||
| 1997/0327 | } } } | |
| 1998/0313 | qunlock(&tpriv->tl); | |
| 1997/0327 | for(;;) { t = timeo; | |
| 1998/0306/sys/src/9/ip/tcp.c:460,494 – 1998/0313/sys/src/9/ip/tcp.c:499,533 | ||
| 1997/0327 | } void | |
| 1998/0313 | tcpgo(Tcppriv *tpriv, Timer *t) | |
| 1997/0327 | { if(t == nil || t->start == 0) return; | |
| 1998/0313 | qlock(&tpriv->tl); | |
| 1997/0327 | t->count = t->start; if(t->state != TimerON) { t->state = TimerON; t->prev = nil; | |
| 1998/0313 | t->next = tpriv->timers; | |
| 1997/0327 | if(t->next) t->next->prev = t; | |
| 1998/0313 | tpriv->timers = t; | |
| 1997/0327 | } | |
| 1998/0313 | qunlock(&tpriv->tl); | |
| 1997/0327 | } void | |
| 1998/0313 | tcphalt(Tcppriv *tpriv, Timer *t) | |
| 1997/0327 | { if(t == nil) return; | |
| 1998/0313 | qlock(&tpriv->tl); | |
| 1997/0327 | if(t->state == TimerON) | |
| 1998/0313 | deltimer(tpriv, t); | |
| 1997/0327 | t->state = TimerOFF; | |
| 1998/0313 | qunlock(&tpriv->tl); | |
| 1997/0327 | } int | |
| 1998/0306/sys/src/9/ip/tcp.c:505,515 – 1998/0313/sys/src/9/ip/tcp.c:544,556 | ||
| 1997/0327 | { Tcpctl *tcb; Reseq *rp,*rp1; | |
| 1998/0313 | Tcppriv *tpriv; | |
| 1997/0327 | ||
| 1998/0313 | tpriv = s->p->priv; | |
| 1997/0327 | tcb = (Tcpctl*)s->ptcl; | |
| 1998/0313 | tcphalt(tpriv, &tcb->timer); tcphalt(tpriv, &tcb->rtt_timer); | |
| 1997/0327 | /* Flush reassembly queue; nothing more can arrive */ for(rp = tcb->reseq; rp != nil; rp = rp1) { | |
| 1998/0306/sys/src/9/ip/tcp.c:519,525 – 1998/0313/sys/src/9/ip/tcp.c:560,566 | ||
| 1997/0327 | } if(tcb->state == Syn_sent) | |
| 1998/0313 | Fsconnected(s, reason); | |
| 1997/0327 | qhangup(s->rq, reason); qhangup(s->wq, reason); | |
| 1998/0306/sys/src/9/ip/tcp.c:553,559 – 1998/0313/sys/src/9/ip/tcp.c:594,600 | ||
| 1998/0306 | /* create a prototype(pseudo) header */ if(ipcmp(s->laddr, IPnoaddr) == 0) | |
| 1998/0313 | findlocalip(s->p->f, s->laddr, s->raddr); | |
| 1998/0306 | h = &tcb->protohdr; memset(h, 0, sizeof(*h)); h->proto = IP_TCPPROTO; | |
| 1998/0306/sys/src/9/ip/tcp.c:571,577 – 1998/0313/sys/src/9/ip/tcp.c:612,618 | ||
| 1997/0327 | int mtu; mtu = 0; | |
| 1998/0306 |
| |
| 1998/0313 | ifc = findipifc(s->p->f, s->raddr, 0); | |
| 1998/0306 | if(ifc != nil) mtu = ifc->maxmtu - ifc->m->hsize - (TCP_PKT + TCP_HDRSIZE); | |
| 1997/0327 | if(mtu < 4) | |
| 1998/0306/sys/src/9/ip/tcp.c:583,589 – 1998/0313/sys/src/9/ip/tcp.c:624,633 | ||
| 1997/0327 | tcpstart(Conv *s, int mode, ushort window) { Tcpctl *tcb; | |
| 1998/0313 | Tcppriv *tpriv; | |
| 1997/0327 | ||
| 1998/0313 | tpriv = s->p->priv; | |
| 1997/0327 | tcb = (Tcpctl*)s->ptcl; inittcpctl(s); | |
| 1998/0306/sys/src/9/ip/tcp.c:592,602 – 1998/0313/sys/src/9/ip/tcp.c:636,648 | ||
| 1997/0327 | switch(mode) { case TCP_LISTEN: | |
| 1998/0313 | tpriv->tstats.tcpPassiveOpens++; | |
| 1997/0327 | tcb->flags |= CLONE; tcpsetstate(s, Listen); break; case TCP_CONNECT: | |
| 1998/0313 | tpriv->tstats.tcpActiveOpens++; | |
| 1997/0327 | /* Send SYN, go into SYN_SENT state */ qlock(tcb); tcb->flags |= ACTIVE; | |
| 1998/0306/sys/src/9/ip/tcp.c:676,685 – 1998/0313/sys/src/9/ip/tcp.c:722,731 | ||
| 1997/0327 | csum = ptclcsum(data, TCP_IPLEN, hdrlen+dlen+TCP_PHDRSIZE); hnputs(h->tcpcksum, csum); | |
| 1998/0306 |
| |
| 1998/0313 | /* netlog(f, Logtcpmsg, "%d > %d s %l8.8ux a %8.8lux %s w %.4ux l %d\n", | |
| 1997/0327 | tcph->source, tcph->dest, tcph->seq, tcph->ack, tcpflag((hdrlen<<10)|tcph->flags), | |
| 1998/0313 | tcph->wnd, dlen); */ | |
| 1997/0327 | return data; } | |
| 1998/0306/sys/src/9/ip/tcp.c:717,726 – 1998/0313/sys/src/9/ip/tcp.c:763,772 | ||
| 1997/0327 | if(*bpp == nil) return -1; | |
| 1998/0306 |
| |
| 1998/0313 | /* netlog(Logtcpmsg, "%d > %d s %l8.8ux a %8.8lux %s w %.4ux l %d\n", | |
| 1997/0327 | tcph->source, tcph->dest, tcph->seq, tcph->ack, tcpflag((hdrlen<<10)|tcph->flags), | |
| 1998/0313 | tcph->wnd, nhgets(h->length)-hdrlen-TCP_PKT); */ | |
| 1997/0327 | optr = h->tcpopt; for(i = TCP_HDRSIZE; i < hdrlen;) { | |
| 1998/0306/sys/src/9/ip/tcp.c:761,772 – 1998/0313/sys/src/9/ip/tcp.c:807,821 | ||
| 1998/0306 | * called with v4 (4 byte) addresses */ | |
| 1997/0327 | void | |
| 1998/0306 |
| |
| 1998/0313 | sndrst(Proto *tcp, uchar *source, uchar *dest, ushort length, Tcp *seg) | |
| 1997/0327 | { Tcphdr ph; Block *hbp; | |
| 1998/0306 | uchar rflags; | |
| 1998/0313 | Tcppriv *tpriv; | |
| 1997/0327 | ||
| 1998/0313 | tpriv = tcp->priv; | |
| 1997/0327 | if(seg->flags & RST) return; | |
| 1998/0306/sys/src/9/ip/tcp.c:779,784 – 1998/0313/sys/src/9/ip/tcp.c:828,834 | ||
| 1998/0306 | hnputs(ph.tcpsport, seg->dest); hnputs(ph.tcpdport, seg->source); | |
| 1997/0327 | ||
| 1998/0313 | tpriv->tstats.OutRsts++; | |
| 1997/0327 | rflags = RST; /* convince the other end that this reset is in band */ | |
| 1998/0306/sys/src/9/ip/tcp.c:804,810 – 1998/0313/sys/src/9/ip/tcp.c:854,860 | ||
| 1997/0327 | if(hbp == nil) return; | |
| 1998/0313 | ipoput(tcp->f, hbp, 0, MAXTTL); | |
| 1997/0327 | } /* | |
| 1998/0306/sys/src/9/ip/tcp.c:821,827 – 1998/0313/sys/src/9/ip/tcp.c:871,877 | ||
| 1997/0327 | tcb = (Tcpctl*)s->ptcl; if(waserror()){ qunlock(tcb); | |
| 1998/0313 | return commonerror(); | |
| 1997/0327 | } qlock(tcb); if(s->raddr != 0) { | |
| 1998/0306/sys/src/9/ip/tcp.c:834,840 – 1998/0313/sys/src/9/ip/tcp.c:884,890 | ||
| 1997/0327 | tcb->last_ack = tcb->rcv.nxt; hnputs(ph.tcplen, TCP_HDRSIZE); | |
| 1998/0306 | hbp = htontcp(&seg, nil, &tcb->protohdr); | |
| 1997/0327 |
| |
| 1998/0313 | ipoput(s->p->f, hbp, 0, s->ttl); | |
| 1997/0327 | } localclose(s, nil); poperror(); | |
| 1998/0306/sys/src/9/ip/tcp.c:849,855 – 1998/0313/sys/src/9/ip/tcp.c:899,905 | ||
| 1997/0327 | Tcpctl *tcb; | |
| 1998/0306 | Tcphdr *h; | |
| 1997/0327 |
| |
| 1998/0313 | new = Fsnewcall(s, src, segp->source, dst, segp->dest); | |
| 1997/0327 | if(new == nil) return nil; | |
| 1998/0306/sys/src/9/ip/tcp.c:919,926 – 1998/0313/sys/src/9/ip/tcp.c:969,978 | ||
| 1997/0327 | { Tcpctl *tcb; int delta; | |
| 1998/0313 | Tcppriv *tpriv; | |
| 1997/0327 | tcb = (Tcpctl*)s->ptcl; | |
| 1998/0313 | tpriv = s->p->priv; | |
| 1997/0327 | delta = msec - tcb->sndsyntime; tcb->srtt = delta<<LOGAGAIN; | |
| 1998/0306/sys/src/9/ip/tcp.c:927,933 – 1998/0313/sys/src/9/ip/tcp.c:979,985 | ||
| 1997/0327 | tcb->mdev = delta<<LOGDGAIN; /* halt round trip timer */ | |
| 1998/0313 | tcphalt(tpriv, &tcb->rtt_timer); | |
| 1997/0327 | } void | |
| 1998/0306/sys/src/9/ip/tcp.c:936,942 – 1998/0313/sys/src/9/ip/tcp.c:988,996 | ||
| 1997/0327 | int rtt, delta; Tcpctl *tcb; ushort acked, expand; | |
| 1998/0313 | Tcppriv *tpriv; | |
| 1997/0327 | ||
| 1998/0313 | tpriv = s->p->priv; | |
| 1997/0327 | tcb = (Tcpctl*)s->ptcl; tcb->kacounter = MAXBACKOFF; /* keep alive count down */ | |
| 1998/0306/sys/src/9/ip/tcp.c:983,989 – 1998/0313/sys/src/9/ip/tcp.c:1037,1043 | ||
| 1997/0327 | /* Adjust the timers according to the round trip time */ if(tcb->rtt_timer.state == TimerON && seq_ge(seg->ack, tcb->rttseq)) { | |
| 1998/0313 | tcphalt(tpriv, &tcb->rtt_timer); | |
| 1997/0327 | if((tcb->flags&RETRAN) == 0) { tcb->backoff = 0; rtt = tcb->rtt_timer.start - tcb->rtt_timer.count; | |
| 1998/0306/sys/src/9/ip/tcp.c:1020,1028 – 1998/0313/sys/src/9/ip/tcp.c:1074,1082 | ||
| 1997/0327 | if(seq_gt(seg->ack, tcb->snd.urg)) tcb->snd.urg = seg->ack; | |
| 1998/0313 | tcphalt(tpriv, &tcb->timer); | |
| 1997/0327 | if(tcb->snd.una != tcb->snd.nxt) | |
| 1998/0313 | tcpgo(tpriv, &tcb->timer); | |
| 1997/0327 | if(seq_lt(tcb->snd.ptr, tcb->snd.una)) tcb->snd.ptr = tcb->snd.una; | |
| 1998/0306/sys/src/9/ip/tcp.c:1032,1038 – 1998/0313/sys/src/9/ip/tcp.c:1086,1092 | ||
| 1997/0327 | } void | |
| 1998/0306 |
| |
| 1998/0313 | tcpiput(Proto *tcp, uchar*, Block *bp) | |
| 1997/0327 | { Tcp seg; Tcphdr *h; | |
| 1998/0306/sys/src/9/ip/tcp.c:1041,1047 – 1998/0313/sys/src/9/ip/tcp.c:1095,1108 | ||
| 1997/0327 | ushort length; | |
| 1998/0306 | uchar source[IPaddrlen], dest[IPaddrlen]; | |
| 1997/0327 | Conv *spec, *gen, *s, **p; | |
| 1998/0313 | Fs *f; Tcppriv *tpriv; | |
| 1997/0327 | ||
| 1998/0313 | f = tcp->f; tpriv = tcp->priv; tpriv->tstats.tcpInSegs++; | |
| 1997/0327 | h = (Tcphdr*)(bp->rp); | |
| 1998/0306 | v4tov6(dest, h->tcpdst); | |
| 1998/0306/sys/src/9/ip/tcp.c:1051,1058 – 1998/0313/sys/src/9/ip/tcp.c:1112,1119 | ||
| 1997/0327 | h->Unused = 0; hnputs(h->tcplen, length-TCP_PKT); if(ptclcsum(bp, TCP_IPLEN, length-TCP_IPLEN)) { | |
| 1998/0313 | tpriv->csumerr++; netlog(f, Logtcp, "bad tcp proto cksum\n"); | |
| 1997/0327 | freeblist(bp); return; } | |
| 1998/0306/sys/src/9/ip/tcp.c:1059,1066 – 1998/0313/sys/src/9/ip/tcp.c:1120,1127 | ||
| 1997/0327 | hdrlen = ntohtcp(&seg, &bp); if(hdrlen < 0){ | |
| 1998/0313 | tpriv->hlenerr++; netlog(f, Logtcp, "bad tcp hdr len\n"); | |
| 1997/0327 | return; } | |
| 1998/0306/sys/src/9/ip/tcp.c:1068,1081 – 1998/0313/sys/src/9/ip/tcp.c:1129,1142 | ||
| 1997/0327 | length -= hdrlen+TCP_PKT; bp = trimblock(bp, hdrlen+TCP_PKT, length); if(bp == nil){ | |
| 1998/0313 | tpriv->lenerr++; netlog(f, Logtcp, "tcp len < 0 after trim\n"); | |
| 1997/0327 | return; } /* Look for a connection. failing that look for a listener. */ | |
| 1998/0313 | for(p = tcp->conv; *p; p++) { | |
| 1997/0327 | s = *p; | |
| 1998/0306 | if(s->rport == seg.source) if(s->lport == seg.dest) | |
| 1998/0306/sys/src/9/ip/tcp.c:1100,1106 – 1998/0313/sys/src/9/ip/tcp.c:1161,1167 | ||
| 1997/0327 | return; } if(seg.flags & ACK) { | |
| 1998/0313 | sndrst(tcp, source, dest, length, &seg); | |
| 1997/0327 | freeblist(bp); return; } | |
| 1998/0306/sys/src/9/ip/tcp.c:1111,1117 – 1998/0313/sys/src/9/ip/tcp.c:1172,1178 | ||
| 1997/0327 | */ gen = nil; spec = nil; | |
| 1998/0313 | for(p = tcp->conv; *p; p++) { | |
| 1997/0327 | s = *p; tcb = (Tcpctl*)s->ptcl; if((tcb->flags & CLONE) == 0) | |
| 1998/0306/sys/src/9/ip/tcp.c:1136,1142 – 1998/0313/sys/src/9/ip/tcp.c:1197,1203 | ||
| 1997/0327 | } if(s == nil) { freeblist(bp); | |
| 1998/0313 | sndrst(tcp, source, dest, length, &seg); | |
| 1997/0327 | return; } | |
| 1998/0306/sys/src/9/ip/tcp.c:1149,1155 – 1998/0313/sys/src/9/ip/tcp.c:1210,1216 | ||
| 1997/0327 | switch(tcb->state) { case Closed: | |
| 1998/0313 | sndrst(tcp, source, dest, length, &seg); | |
| 1997/0327 | goto raise; case Listen: if(seg.flags & SYN) { | |
| 1998/0306/sys/src/9/ip/tcp.c:1163,1169 – 1998/0313/sys/src/9/ip/tcp.c:1224,1230 | ||
| 1997/0327 | case Syn_sent: if(seg.flags & ACK) { if(!seq_within(seg.ack, tcb->iss+1, tcb->snd.nxt)) { | |
| 1998/0313 | sndrst(tcp, source, dest, length, &seg); | |
| 1997/0327 | goto raise; } } | |
| 1998/0306/sys/src/9/ip/tcp.c:1203,1214 – 1998/0313/sys/src/9/ip/tcp.c:1264,1275 | ||
| 1997/0327 | /* Cut the data to fit the receive window */ if(tcptrim(tcb, &seg, &bp, &length) == -1) { | |
| 1998/0313 | netlog(f, Logtcp, "tcp len < 0, %lux\n", seg.seq); | |
| 1997/0327 | update(s, &seg); if(tcb->sndcnt == 0 && tcb->state == Closing) { tcpsetstate(s, Time_wait); tcb->timer.start = MSL2*(1000 / MSPTICK); | |
| 1998/0313 | tcpgo(tpriv, &tcb->timer); | |
| 1997/0327 | } if(!(seg.flags & RST)) { tcb->flags |= FORCE; | |
| 1998/0306/sys/src/9/ip/tcp.c:1220,1226 – 1998/0313/sys/src/9/ip/tcp.c:1281,1287 | ||
| 1997/0327 | /* Cannot accept so answer with a rst */ if(length && tcb->state == Closed) { | |
| 1998/0313 | sndrst(tcp, source, dest, length, &seg); | |
| 1997/0327 | goto raise; } | |
| 1998/0306/sys/src/9/ip/tcp.c:1230,1236 – 1998/0313/sys/src/9/ip/tcp.c:1291,1297 | ||
| 1997/0327 | if(seg.seq != tcb->rcv.nxt) if(length != 0 || (seg.flags & (SYN|FIN))) { update(s, &seg); | |
| 1997/0916 |
| |
| 1998/0313 | tpriv->order++; | |
| 1997/0327 | addreseq(tcb, &seg, bp, length); tcb->flags |= FORCE; goto output; | |
| 1998/0306/sys/src/9/ip/tcp.c:1242,1247 – 1998/0313/sys/src/9/ip/tcp.c:1303,1310 | ||
| 1997/0327 | */ for(;;) { if(seg.flags & RST) { | |
| 1998/0313 | if(tcb->state == Established) tpriv->tstats.tcpEstabResets++; | |
| 1997/0327 | localclose(s, Econrefused); goto raise; } | |
| 1998/0306/sys/src/9/ip/tcp.c:1252,1258 – 1998/0313/sys/src/9/ip/tcp.c:1315,1321 | ||
| 1997/0327 | switch(tcb->state) { case Syn_received: if(!seq_within(seg.ack, tcb->snd.una+1, tcb->snd.nxt)){ | |
| 1998/0313 | sndrst(tcp, source, dest, length, &seg); | |
| 1997/0327 | goto raise; } update(s, &seg); | |
| 1998/0306/sys/src/9/ip/tcp.c:1267,1273 – 1998/0313/sys/src/9/ip/tcp.c:1330,1336 | ||
| 1997/0327 | tcb->f2counter = MAXBACKOFF; tcpsetstate(s, Finwait2); tcb->timer.start = MSL2 * (1000 / MSPTICK); | |
| 1998/0313 | tcpgo(tpriv, &tcb->timer); | |
| 1997/0327 | } break; case Finwait2: | |
| 1998/0306/sys/src/9/ip/tcp.c:1278,1284 – 1998/0313/sys/src/9/ip/tcp.c:1341,1347 | ||
| 1997/0327 | if(tcb->sndcnt == 0) { tcpsetstate(s, Time_wait); tcb->timer.start = MSL2*(1000 / MSPTICK); | |
| 1998/0313 | tcpgo(tpriv, &tcb->timer); | |
| 1997/0327 | } break; case Last_ack: | |
| 1998/0306/sys/src/9/ip/tcp.c:1290,1296 – 1998/0313/sys/src/9/ip/tcp.c:1353,1359 | ||
| 1997/0327 | case Time_wait: tcb->flags |= FORCE; if(tcb->timer.state != TimerON) | |
| 1998/0313 | tcpgo(tpriv, &tcb->timer); | |
| 1997/0327 | } if((seg.flags&URG) && seg.urg) { | |
| 1998/0306/sys/src/9/ip/tcp.c:1328,1334 – 1998/0313/sys/src/9/ip/tcp.c:1391,1397 | ||
| 1997/0327 | tcb->rcv.nxt += length; tcprcvwin(s); if(tcb->acktimer.state != TimerON) | |
| 1998/0313 | tcpgo(tpriv, &tcb->acktimer); | |
| 1997/0327 | /* force an ack if there's a lot of unacked data */ if(tcb->rcv.nxt-tcb->last_ack > (QMAX>>4)) | |
| 1998/0306/sys/src/9/ip/tcp.c:1339,1345 – 1998/0313/sys/src/9/ip/tcp.c:1402,1408 | ||
| 1997/0327 | /* no process to read the data, send a reset */ if(bp != nil) freeblist(bp); | |
| 1998/0313 | sndrst(tcp, source, dest, length, &seg); | |
| 1997/0327 | qunlock(tcb); return; } | |
| 1998/0306/sys/src/9/ip/tcp.c:1359,1365 – 1998/0313/sys/src/9/ip/tcp.c:1422,1428 | ||
| 1997/0327 | if(tcb->sndcnt == 0) { tcpsetstate(s, Time_wait); tcb->timer.start = MSL2*(1000/MSPTICK); | |
| 1998/0313 | tcpgo(tpriv, &tcb->timer); | |
| 1997/0327 | } else tcpsetstate(s, Closing); | |
| 1998/0306/sys/src/9/ip/tcp.c:1368,1374 – 1998/0313/sys/src/9/ip/tcp.c:1431,1437 | ||
| 1997/0327 | tcb->rcv.nxt++; tcpsetstate(s, Time_wait); tcb->timer.start = MSL2 * (1000/MSPTICK); | |
| 1998/0313 | tcpgo(tpriv, &tcb->timer); | |
| 1997/0327 | break; case Close_wait: case Closing: | |
| 1998/0306/sys/src/9/ip/tcp.c:1375,1381 – 1998/0313/sys/src/9/ip/tcp.c:1438,1444 | ||
| 1997/0327 | case Last_ack: break; case Time_wait: | |
| 1998/0313 | tcpgo(tpriv, &tcb->timer); | |
| 1997/0327 | break; } } | |
| 1998/0306/sys/src/9/ip/tcp.c:1420,1426 – 1998/0313/sys/src/9/ip/tcp.c:1483,1494 | ||
| 1997/0327 | Block *hbp, *bp; int sndcnt, n, first; ulong ssize, dsize, usable, sent; | |
| 1998/0313 | Fs *f; Tcppriv *tpriv; | |
| 1997/0327 | ||
| 1998/0313 | f = s->p->f; tpriv = s->p->priv; | |
| 1997/0327 | tcb = (Tcpctl*)s->ptcl; switch(tcb->state) { | |
| 1998/0306/sys/src/9/ip/tcp.c:1489,1495 – 1998/0313/sys/src/9/ip/tcp.c:1557,1563 | ||
| 1997/0327 | if((tcb->flags&FORCE) == 0) break; | |
| 1998/0313 | tcphalt(tpriv, &tcb->acktimer); | |
| 1997/0327 | tcb->flags &= ~FORCE; tcprcvwin(s); | |
| 1998/0306/sys/src/9/ip/tcp.c:1525,1531 – 1998/0313/sys/src/9/ip/tcp.c:1593,1599 | ||
| 1997/0327 | seg.flags |= FIN; dsize--; } | |
| 1998/0313 | netlog(f, Logtcp, "qcopy: dlen %d blen %d sndcnt %d qlen %d sent %d rp[0] %d\n", | |
| 1997/0327 | dsize, BLEN(bp), sndcnt, qlen(s->wq), sent, bp->rp[0]); } | |
| 1998/0306/sys/src/9/ip/tcp.c:1566,1581 – 1998/0313/sys/src/9/ip/tcp.c:1634,1650 | ||
| 1997/0327 | tcb->timer.start = x; if(tcb->timer.state != TimerON) | |
| 1998/0313 | tcpgo(tpriv, &tcb->timer); | |
| 1997/0327 | /* If round trip timer isn't running, start it */ if(tcb->rtt_timer.state != TimerON) { | |
| 1998/0313 | tcpgo(tpriv, &tcb->rtt_timer); | |
| 1997/0327 | tcb->rttseq = tcb->snd.ptr; } } | |
| 1998/0313 | tpriv->tstats.tcpOutSegs++; ipoput(f, hbp, 0, s->ttl); | |
| 1997/0327 | } } | |
| 1998/0306/sys/src/9/ip/tcp.c:1616,1622 – 1998/0313/sys/src/9/ip/tcp.c:1685,1691 | ||
| 1997/0327 | return; } | |
| 1998/0313 | ipoput(s->p->f, hbp, 0, s->ttl); | |
| 1997/0327 | } void | |
| 1998/0306/sys/src/9/ip/tcp.c:1623,1632 – 1998/0313/sys/src/9/ip/tcp.c:1692,1702 | ||
| 1997/0327 | tcprxmit(Conv *s) { Tcpctl *tcb; | |
| 1998/0313 | Tcppriv *tpriv; | |
| 1997/0327 | ||
| 1998/0313 | tpriv = s->p->priv; | |
| 1997/0327 | tcb = (Tcpctl*)s->ptcl; | |
| 1998/0306/sys/src/9/ip/tcp.c:1642,1649 – 1998/0313/sys/src/9/ip/tcp.c:1712,1718 | ||
| 1997/0327 | tcb->cwind = tcb->mss; tcpoutput(s); | |
| 1998/0313 | tpriv->tstats.tcpRetransSegs++; | |
| 1997/0327 | qunlock(tcb); } | |
| 1998/0306/sys/src/9/ip/tcp.c:1678,1684 – 1998/0313/sys/src/9/ip/tcp.c:1747,1753 | ||
| 1997/0327 | qlock(tcb); tcpkeepalive(s); qunlock(tcb); | |
| 1998/0313 | tcpgo(s->p->priv, &tcb->timer); | |
| 1997/0327 | } break; case Time_wait: | |
| 1998/0306/sys/src/9/ip/tcp.c:1807,1814 – 1998/0313/sys/src/9/ip/tcp.c:1876,1881 | ||
| 1997/0327 | dupcnt = tcb->rcv.nxt - seg->seq; if(dupcnt > 0){ tcb->rerecv += dupcnt; | |
| 1997/0916 |
| |
| 1997/0327 | if(seg->flags & SYN){ seg->flags &= ~SYN; seg->seq++; | |
| 1998/0306/sys/src/9/ip/tcp.c:1845,1851 – 1998/0313/sys/src/9/ip/tcp.c:1912,1918 | ||
| 1997/0327 | } void | |
| 1998/0313 | tcpadvise(Proto *tcp, Block *bp, char *msg) | |
| 1997/0327 | { Tcphdr *h; Tcpctl *tcb; | |
| 1998/0306/sys/src/9/ip/tcp.c:1862,1868 – 1998/0313/sys/src/9/ip/tcp.c:1929,1935 | ||
| 1997/0327 | pdest = nhgets(h->tcpdport); /* Look for a connection */ | |
| 1998/0313 | for(p = tcp->conv; *p; p++) { | |
| 1997/0327 | s = *p; | |
| 1998/0306 | if(s->rport == pdest) if(s->lport == psource) | |
| 1998/0306/sys/src/9/ip/tcp.c:1892,1930 – 1998/0313/sys/src/9/ip/tcp.c:1959,2012 | ||
| 1997/0327 | } | |
| 1997/0916 | int | |
| 1998/0313 | tcpstats(Proto *tcp, char *buf, int len) | |
| 1997/0916 | { | |
| 1998/0306 |
| |
| 1998/0313 | Tcpstats *tstats; | |
| 1998/0306 |
| |
| 1998/0313 | tstats = tcp->priv; return snprint(buf, len, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d", tstats->tcpRtoAlgorithm, tstats->tcpRtoMin, tstats->tcpRtoMax, tstats->tcpMaxConn, tstats->tcpActiveOpens, tstats->tcpPassiveOpens, tstats->tcpAttemptFails, tstats->tcpEstabResets, tstats->tcpCurrEstab, tstats->tcpInSegs, tstats->tcpOutSegs, tstats->tcpRetransSegs, tstats->InErrs, tstats->OutRsts); | |
| 1997/0916 | } | |
| 1997/0327 | void tcpinit(Fs *fs) { | |
| 1997/0916 |
| |
| 1998/0306 |
| |
| 1997/0327 |
| |
| 1998/0313 | Proto *tcp; Tcppriv *tpriv; | |
| 1997/0327 |
| |
| 1998/0313 | tcp = smalloc(sizeof(Proto)); tpriv = tcp->priv = smalloc(sizeof(Tcppriv)); tcp->name = "tcp"; tcp->kick = tcpkick; tcp->connect = tcpconnect; tcp->announce = tcpannounce; tcp->ctl = tcpctl; tcp->state = tcpstate; tcp->create = tcpcreate; tcp->close = tcpclose; tcp->rcv = tcpiput; tcp->advise = tcpadvise; tcp->stats = tcpstats; tcp->inuse = tcpinuse; tcp->ipproto = IP_TCPPROTO; tcp->nc = Nchans; tcp->ptclsize = sizeof(Tcpctl); tpriv->tstats.tcpMaxConn = Nchans; | |
| 1997/0327 |
| |
| 1998/0313 | Fsproto(fs, tcp); | |
| 1998/0306 | ||
| 1998/0313 | kproc("tcpack", tcpackproc, tcp); } | |
| 1998/0313/sys/src/9/ip/tcp.c:37,43 – 1998/0421/sys/src/9/ip/tcp.c:37,43 (short | long) | ||
|
TCP tuning: increase DEF_RTT and set tcb->mdev.
rsc Fri Mar 4 12:44:25 2005 | ||
| 1997/0327 | MSL2 = 10, MSPTICK = 50, /* Milliseconds per timer tick */ DEF_MSS = 1024, /* Default mean segment */ | |
| 1998/0421 | DEF_RTT = 500, /* Default round trip */ | |
| 1997/0327 | TCP_LISTEN = 0, /* Listen connection */ TCP_CONNECT = 1, /* Outgoing connection */ | |
| 1998/0313/sys/src/9/ip/tcp.c:583,588 – 1998/0421/sys/src/9/ip/tcp.c:583,589 | ||
| 1997/0327 | tcb->mss = tcp_mss; tcb->ssthresh = 65535; tcb->srtt = 0; | |
| 1998/0421 | tcb->mdev = tcp_irtt << LOGDGAIN; | |
| 1997/0327 | tcb->timer.start = tcp_irtt / MSPTICK; tcb->timer.func = tcptimeout; | |
| 1998/0421/sys/src/9/ip/tcp.c:37,43 – 1998/0630/sys/src/9/ip/tcp.c:37,43 (short | long) | ||
| 1997/0327 | MSL2 = 10, MSPTICK = 50, /* Milliseconds per timer tick */ DEF_MSS = 1024, /* Default mean segment */ | |
| 1998/0421 |
| |
| 1998/0630 | DEF_RTT = 150, /* Default round trip */ | |
| 1997/0327 | TCP_LISTEN = 0, /* Listen connection */ TCP_CONNECT = 1, /* Outgoing connection */ | |
| 1998/0421/sys/src/9/ip/tcp.c:254,263 – 1998/0630/sys/src/9/ip/tcp.c:254,263 | ||
| 1998/0313 | if(newstate == Established) tpriv->tstats.tcpCurrEstab++; | |
| 1997/0327 |
| |
| 1998/0630 | /** print( "%d/%d %s->%s CurrEstab=%d\n", s->lport, s->rport, tcpstates[oldstate], tcpstates[newstate], tpriv->tstats.tcpCurrEstab ); **/ | |
| 1997/0327 | tcb->state = newstate; | |
| 1998/0421/sys/src/9/ip/tcp.c:583,589 – 1998/0630/sys/src/9/ip/tcp.c:583,588 | ||
| 1997/0327 | tcb->mss = tcp_mss; tcb->ssthresh = 65535; tcb->srtt = 0; | |
| 1998/0421 |
| |
| 1997/0327 | tcb->timer.start = tcp_irtt / MSPTICK; tcb->timer.func = tcptimeout; | |
| 1998/0421/sys/src/9/ip/tcp.c:1962,1985 – 1998/0630/sys/src/9/ip/tcp.c:1961,1987 | ||
| 1997/0916 | int | |
| 1998/0313 | tcpstats(Proto *tcp, char *buf, int len) | |
| 1997/0916 | { | |
| 1998/0313 |
| |
| 1998/0630 | Tcppriv *tpriv; | |
| 1998/0306 | ||
| 1998/0313 |
| |
| 1998/0630 | tpriv = tcp->priv; | |
| 1998/0313 | return snprint(buf, len, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d", | |
| 1998/0630 | tpriv->tstats.tcpRtoAlgorithm, tpriv->tstats.tcpRtoMin, tpriv->tstats.tcpRtoMax, tpriv->tstats.tcpMaxConn, tpriv->tstats.tcpActiveOpens, tpriv->tstats.tcpPassiveOpens, tpriv->tstats.tcpAttemptFails, tpriv->tstats.tcpEstabResets, tpriv->tstats.tcpCurrEstab, tpriv->tstats.tcpInSegs, tpriv->tstats.tcpOutSegs, tpriv->tstats.tcpRetransSegs, tpriv->tstats.InErrs, tpriv->tstats.OutRsts); | |
| 1997/0916 | } | |
| 1997/0327 | void | |
| 1998/0630/sys/src/9/ip/tcp.c:266,274 – 1998/0724/sys/src/9/ip/tcp.c:266,274 (short | long) | ||
| 1997/0327 | qclose(s->rq); qclose(s->wq); qclose(s->eq); | |
| 1998/0306 |
| |
| 1998/0724 | // s->lport = 0; /* This connection is toast */ // s->rport = 0; // ipmove(s->raddr, IPnoaddr); | |
| 1997/0327 | case Close_wait: /* Remote closes */ qhangup(s->rq, nil); | |
| 1998/0630/sys/src/9/ip/tcp.c:1138,1145 – 1998/0724/sys/src/9/ip/tcp.c:1138,1147 | ||
| 1997/0327 | /* Look for a connection. failing that look for a listener. */ | |
| 1998/0313 | for(p = tcp->conv; *p; p++) { | |
| 1997/0327 | s = *p; | |
| 1998/0724 | tcb = (Tcpctl*)s->ptcl; | |
| 1998/0306 | if(s->rport == seg.source) if(s->lport == seg.dest) | |
| 1998/0724 | if(tcb->state != Closed) | |
| 1998/0306 | if(ipcmp(s->raddr, source) == 0) | |
| 1997/0327 | break; } | |
| 1998/0630/sys/src/9/ip/tcp.c:1931,1941 – 1998/0724/sys/src/9/ip/tcp.c:1933,1944 | ||
| 1997/0327 | /* Look for a connection */ | |
| 1998/0313 | for(p = tcp->conv; *p; p++) { | |
| 1997/0327 | s = *p; | |
| 1998/0724 | tcb = (Tcpctl*)s->ptcl; | |
| 1998/0306 | if(s->rport == pdest) if(s->lport == psource) | |
| 1998/0724 | if(tcb->state != Closed) | |
| 1998/0306 | if(ipcmp(s->raddr, dest) == 0) if(ipcmp(s->laddr, source) == 0){ | |
| 1997/0327 |
| |
| 1998/0724/sys/src/9/ip/tcp.c:1794,1799 – 1998/0808/sys/src/9/ip/tcp.c:1794,1800 (short | long) | ||
|
Debugging: print for very long TCP resequence queue.
rsc Fri Mar 4 12:44:25 2005 | ||
| 1997/0327 | addreseq(Tcpctl *tcb, Tcp *seg, Block *bp, ushort length) { Reseq *rp, *rp1; | |
| 1998/0808 | int i; | |
| 1997/0327 | rp = malloc(sizeof(Reseq)); if(rp == nil){ | |
| 1998/0724/sys/src/9/ip/tcp.c:1813,1819 – 1998/0808/sys/src/9/ip/tcp.c:1814,1822 | ||
| 1997/0327 | return; } | |
| 1998/0808 | for(i = 0;; i++) { if(i > 100) print("very long tcp resequence queue\n"); | |
| 1997/0327 | if(rp1->next == nil || seq_lt(seg->seq, rp1->next->seg.seq)) { rp->next = rp1->next; rp1->next = rp; | |
| 1998/0808/sys/src/9/ip/tcp.c:266,274 – 1998/0813/sys/src/9/ip/tcp.c:266,271 (short | long) | ||
| 1997/0327 | qclose(s->rq); qclose(s->wq); qclose(s->eq); | |
| 1998/0724 |
| |
| 1997/0327 | case Close_wait: /* Remote closes */ qhangup(s->rq, nil); | |
| 1998/0808/sys/src/9/ip/tcp.c:1573,1583 – 1998/0813/sys/src/9/ip/tcp.c:1570,1590 | ||
| 1997/0327 | switch(tcb->state){ case Syn_sent: seg.flags = 0; | |
| 1998/0813 | seg.mss = tcpmtu(s); } break; case Syn_received: /* * don't send any data with a SYN/ACK packet * because Linux rejects the packet in its * attempt to solve the SYN attack problem */ if(tcb->snd.ptr == tcb->iss){ seg.flags |= SYN; dsize = 0; | |
| 1997/0327 | seg.mss = tcpmtu(s); } break; | |
| 1998/0813/sys/src/9/ip/tcp.c:1980,1986 – 1998/0825/sys/src/9/ip/tcp.c:1980,1986 (short | long) | ||
|
Bug fix: print format.
rsc Fri Mar 4 12:44:25 2005 | ||
| 1998/0630 | ||
| 1998/0313 |
| |
| 1998/0825 | return snprint(buf, len, "%lud %lud %lud %lud %lud %lud %lud %lud %lud %lud %lud %lud %lud %lud", | |
| 1998/0630 | tpriv->tstats.tcpRtoAlgorithm, tpriv->tstats.tcpRtoMin, tpriv->tstats.tcpRtoMax, | |
| 1998/0825/sys/src/9/ip/tcp.c:1585,1590 – 1998/0831/sys/src/9/ip/tcp.c:1585,1591 (short | long) | ||
| 1998/0813 | if(tcb->snd.ptr == tcb->iss){ seg.flags |= SYN; dsize = 0; | |
| 1998/0831 | ssize = 1; | |
| 1997/0327 | seg.mss = tcpmtu(s); } break; | |
| 1998/0831/sys/src/9/ip/tcp.c:1509,1515 – 1998/0901/sys/src/9/ip/tcp.c:1509,1515 (short | long) | ||
| 1997/0327 | sent = tcb->snd.ptr - tcb->snd.una; /* Don't send anything else until our SYN has been acked */ | |
| 1998/0901 | if(tcb->snd.ptr != tcb->iss && (tcb->flags & SYNACK) == 0) | |
| 1997/0327 | break; /* Compute usable segment based on offered window and limit | |
| 1998/0901/sys/src/9/ip/tcp.c:20,26 – 1998/0918/sys/src/9/ip/tcp.c:20,26 (short | long) | ||
| 1997/0327 | TimerON = 1, TimerDONE = 2, MAX_TIME = (1<<20), /* Forever */ | |
| 1998/0918 | TCP_ACK = 200, /* Timed ack sequence in ms */ | |
| 1997/0327 | URG = 0x20, /* Data marked urgent */ ACK = 0x10, /* Acknowledge is valid */ | |
| 1998/0901/sys/src/9/ip/tcp.c:1384,1400 – 1998/0918/sys/src/9/ip/tcp.c:1384,1404 | ||
| 1997/0327 | * receive queue */ if(bp) { | |
| 1998/0918 | qpassnolim(s->rq, packblock(bp)); | |
| 1997/0327 | bp = nil; } tcb->rcv.nxt += length; tcprcvwin(s); | |
| 1998/0313 |
| |
| 1997/0327 |
| |
| 1998/0918 | /* * force an ack if we've got 2 segs * and the user isn't backing up */ if(tcb->rcv.nxt - tcb->last_ack >= 2*tcb->mss && qlen(s->rq) < 8*tcb->mss) | |
| 1997/0327 | tcb->flags |= FORCE; | |
| 1998/0918 | else if(tcb->acktimer.state != TimerON) tcpgo(tpriv, &tcb->acktimer); | |
| 1997/0327 | break; case Finwait2: | |
| 1998/0901/sys/src/9/ip/tcp.c:1637,1644 – 1998/0918/sys/src/9/ip/tcp.c:1641,1655 | ||
| 1997/0327 | * expect acknowledges */ if(ssize != 0){ | |
| 1998/0918 | /* round trip depenency */ | |
| 1997/0327 | x = backoff(tcb->backoff) * (tcb->mdev + (tcb->srtt>>LOGAGAIN) + MSPTICK) / MSPTICK; | |
| 1998/0918 | /* take into account delayed ack */ if(sent <= 2*tcb->mss) x += TCP_ACK/MSPTICK; /* sanity check */ | |
| 1997/0327 | if(x > (10000/MSPTICK)) x = 10000/MSPTICK; tcb->timer.start = x; | |
| 1998/0918/sys/src/9/ip/tcp.c:1384,1390 – 1998/0923/sys/src/9/ip/tcp.c:1384,1393 (short | long) | ||
| 1997/0327 | * receive queue */ if(bp) { | |
| 1998/0918 |
| |
| 1998/0923 | bp = packblock(bp); if(bp == nil) panic("tcp packblock"); qpassnolim(s->rq, bp); | |
| 1997/0327 | bp = nil; } tcb->rcv.nxt += length; | |
| 1998/0923/sys/src/9/ip/tcp.c:219,224 – 1998/0924/sys/src/9/ip/tcp.c:219,227 (short | long) | ||
| 1998/0313 | ulong lenerr; /* short packet */ ulong order; /* out of order */ | |
| 1998/0924 | /* for keeping track of tcpackproc */ int ackprocstarted; QLock apl; | |
| 1998/0313 | }; | |
| 1997/0327 | void addreseq(Tcpctl*, Tcp*, Block*, ushort); | |
| 1998/0923/sys/src/9/ip/tcp.c:622,630 – 1998/0924/sys/src/9/ip/tcp.c:625,644 | ||
| 1997/0327 | { Tcpctl *tcb; | |
| 1998/0313 | Tcppriv *tpriv; | |
| 1998/0924 | char kpname[NAMELEN]; | |
| 1997/0327 | ||
| 1998/0313 | tpriv = s->p->priv; | |
| 1998/0924 | if(tpriv->ackprocstarted == 0){ qlock(&tpriv->apl); if(tpriv->ackprocstarted == 0){ sprint(kpname, "#I%dtcpack", s->p->f->dev); kproc(kpname, tcpackproc, s->p); tpriv->ackprocstarted = 1; } qunlock(&tpriv->apl); } | |
| 1997/0327 | tcb = (Tcpctl*)s->ptcl; inittcpctl(s); | |
| 1998/0923/sys/src/9/ip/tcp.c:2038,2043 – 1998/0924/sys/src/9/ip/tcp.c:2052,2055 | ||
| 1998/0313 | tpriv->tstats.tcpMaxConn = Nchans; | |
| 1997/0327 | ||
| 1998/0313 | Fsproto(fs, tcp); | |
| 1998/0306 | ||
| 1998/0313 |
| |
| 1998/0924/sys/src/9/ip/tcp.c:76,81 – 1998/0925/sys/src/9/ip/tcp.c:76,82 (short | long) | ||
| 1997/0327 | { Timer *next; Timer *prev; | |
| 1998/0925 | Timer *readynext; | |
| 1997/0327 | int state; int start; int count; | |
| 1998/0924/sys/src/9/ip/tcp.c:262,274 – 1998/0925/sys/src/9/ip/tcp.c:263,274 | ||
| 1998/0630 | tcpstates[oldstate], tcpstates[newstate], tpriv->tstats.tcpCurrEstab ); **/ | |
| 1997/0327 |
| |
| 1998/0925 | break; | |
| 1997/0327 | case Close_wait: /* Remote closes */ qhangup(s->rq, nil); | |
| 1998/0924/sys/src/9/ip/tcp.c:275,280 – 1998/0925/sys/src/9/ip/tcp.c:275,282 | ||
| 1997/0327 | break; } | |
| 1998/0925 | tcb->state = newstate; | |
| 1997/0515 | if(oldstate == Syn_sent && newstate != Closed) | |
| 1998/0313 | Fsconnected(s, nil); | |
| 1997/0327 | } | |
| 1998/0924/sys/src/9/ip/tcp.c:419,424 – 1998/0925/sys/src/9/ip/tcp.c:421,427 | ||
| 1997/0327 | t->next->prev = t->prev; if(t->prev) t->prev->next = t->next; | |
| 1998/0925 | t->next = t->prev = nil; | |
| 1997/0327 | } void | |
| 1998/0924/sys/src/9/ip/tcp.c:463,468 – 1998/0925/sys/src/9/ip/tcp.c:466,472 | ||
| 1997/0327 | Timer *t, *tp, *timeo; | |
| 1998/0313 | Proto *tcp; Tcppriv *tpriv; | |
| 1998/0925 | int loop; | |
| 1997/0327 | ||
| 1998/0313 | tcp = a; tpriv = tcp->priv; | |
| 1998/0924/sys/src/9/ip/tcp.c:472,478 – 1998/0925/sys/src/9/ip/tcp.c:476,485 | ||
| 1997/0327 | ||
| 1998/0313 | qlock(&tpriv->tl); | |
| 1997/0327 | timeo = nil; | |
| 1998/0925 | loop = 0; | |
| 1998/0313 | for(t = tpriv->timers; t != nil; t = tp) { | |
| 1998/0925 | if(loop++ > 10000) panic("tcpackproc1"); | |
| 1997/0327 | tp = t->next; if(t->state == TimerON) { t->count--; | |
| 1998/0924/sys/src/9/ip/tcp.c:479,485 – 1998/0925/sys/src/9/ip/tcp.c:486,492 | ||
| 1997/0327 | if(t->count == 0) { | |
| 1998/0313 | deltimer(tpriv, t); | |
| 1997/0327 | t->state = TimerDONE; | |
| 1998/0925 | t->readynext = timeo; | |
| 1997/0327 | timeo = t; } } | |
| 1998/0924/sys/src/9/ip/tcp.c:486,497 – 1998/0925/sys/src/9/ip/tcp.c:493,502 | ||
| 1997/0327 | } | |
| 1998/0313 | qunlock(&tpriv->tl); | |
| 1997/0327 |
| |
| 1998/0925 | loop = 0; for(t = timeo; t != nil; t = t->readynext) { if(loop++ > 10000) panic("tcpackproc2"); | |
| 1997/0327 | if(t->state == TimerDONE && t->func != nil) (*t->func)(t->arg); } | |
| 1998/0924/sys/src/9/ip/tcp.c:551,556 – 1998/0925/sys/src/9/ip/tcp.c:556,562 | ||
| 1997/0327 | ||
| 1998/0313 | tcphalt(tpriv, &tcb->timer); tcphalt(tpriv, &tcb->rtt_timer); | |
| 1998/0925 | tcphalt(tpriv, &tcb->acktimer); | |
| 1997/0327 | /* Flush reassembly queue; nothing more can arrive */ for(rp = tcb->reseq; rp != nil; rp = rp1) { | |
| 1998/0924/sys/src/9/ip/tcp.c:1412,1421 – 1998/0925/sys/src/9/ip/tcp.c:1418,1431 | ||
| 1998/0918 | * and the user isn't backing up */ if(tcb->rcv.nxt - tcb->last_ack >= 2*tcb->mss && | |
| 1998/0925 | qlen(s->rq) < 8*tcb->mss){ | |
| 1997/0327 | tcb->flags |= FORCE; | |
| 1998/0918 |
| |
| 1998/0925 | if(tcb->acktimer.state == TimerON) tcphalt(tpriv, &tcb->acktimer); } else { if(tcb->acktimer.state != TimerON) tcpgo(tpriv, &tcb->acktimer); } | |
| 1997/0327 | break; case Finwait2: | |
| 1998/0925/sys/src/9/ip/tcp.c:409,422 – 1998/0927/sys/src/9/ip/tcp.c:409,419 (short | long) | ||
| 1997/0327 | } } | |
| 1998/0313 |
| |
| 1998/0927 | deltimer(Tcppriv *priv, Timer *t) | |
| 1997/0327 | { | |
| 1998/0313 |
| |
| 1998/0927 | if(priv->timers == t) priv->timers = t->next; | |
| 1997/0327 | if(t->next) t->next->prev = t->prev; if(t->prev) | |
| 1998/0925/sys/src/9/ip/tcp.c:465,483 – 1998/0927/sys/src/9/ip/tcp.c:462,480 | ||
| 1997/0327 | { Timer *t, *tp, *timeo; | |
| 1998/0313 | Proto *tcp; | |
| 1998/0927 | Tcppriv *priv; | |
| 1998/0925 | int loop; | |
| 1997/0327 | ||
| 1998/0313 | tcp = a; | |
| 1998/0927 | priv = tcp->priv; | |
| 1998/0313 | ||
| 1997/0327 | for(;;) { | |
| 1998/0313 |
| |
| 1998/0927 | tsleep(&priv->tcpr, return0, 0, MSPTICK); | |
| 1997/0327 | ||
| 1998/0313 |
| |
| 1998/0927 | qlock(&priv->tl); | |
| 1997/0327 | timeo = nil; | |
| 1998/0925 | loop = 0; | |
| 1998/0313 |
| |
| 1998/0927 | for(t = priv->timers; t != nil; t = tp) { | |
| 1998/0925 | if(loop++ > 10000) panic("tcpackproc1"); | |
| 1997/0327 | tp = t->next; | |
| 1998/0925/sys/src/9/ip/tcp.c:484,490 – 1998/0927/sys/src/9/ip/tcp.c:481,487 | ||
| 1997/0327 | if(t->state == TimerON) { t->count--; if(t->count == 0) { | |
| 1998/0313 |
| |
| 1998/0927 | deltimer(priv, t); | |
| 1997/0327 | t->state = TimerDONE; | |
| 1998/0925 | t->readynext = timeo; | |
| 1997/0327 | timeo = t; | |
| 1998/0925/sys/src/9/ip/tcp.c:491,497 – 1998/0927/sys/src/9/ip/tcp.c:488,494 | ||
| 1997/0327 | } } } | |
| 1998/0313 |
| |
| 1998/0927 | qunlock(&priv->tl); | |
| 1997/0327 | ||
| 1998/0925 | loop = 0; for(t = timeo; t != nil; t = t->readynext) { | |
| 1998/0925/sys/src/9/ip/tcp.c:504,538 – 1998/0927/sys/src/9/ip/tcp.c:501,535 | ||
| 1997/0327 | } void | |
| 1998/0313 |
| |
| 1998/0927 | tcpgo(Tcppriv *priv, Timer *t) | |
| 1997/0327 | { if(t == nil || t->start == 0) return; | |
| 1998/0313 |
| |
| 1998/0927 | qlock(&priv->tl); | |
| 1997/0327 | t->count = t->start; if(t->state != TimerON) { t->state = TimerON; t->prev = nil; | |
| 1998/0313 |
| |
| 1998/0927 | t->next = priv->timers; | |
| 1997/0327 | if(t->next) t->next->prev = t; | |
| 1998/0313 |
| |
| 1998/0927 | priv->timers = t; | |
| 1997/0327 | } | |
| 1998/0313 |
| |
| 1998/0927 | qunlock(&priv->tl); | |
| 1997/0327 | } void | |
| 1998/0313 |
| |
| 1998/0927 | tcphalt(Tcppriv *priv, Timer *t) | |
| 1997/0327 | { if(t == nil) return; | |
| 1998/0313 |
| |
| 1998/0927 | qlock(&priv->tl); | |
| 1997/0327 | if(t->state == TimerON) | |
| 1998/0313 |
| |
| 1998/0927 | deltimer(priv, t); | |
| 1997/0327 | t->state = TimerOFF; | |
| 1998/0313 |
| |
| 1998/0927 | qunlock(&priv->tl); | |
| 1997/0327 | } int | |
| 1998/0927/sys/src/9/ip/tcp.c:20,26 – 1998/1008/sys/src/9/ip/tcp.c:20,26 (short | long) | ||
| 1997/0327 | TimerON = 1, TimerDONE = 2, MAX_TIME = (1<<20), /* Forever */ | |
| 1998/0918 |
| |
| 1998/1008 | TCP_ACK = 50, /* Timed ack sequence in ms */ | |
| 1997/0327 | URG = 0x20, /* Data marked urgent */ ACK = 0x10, /* Acknowledge is valid */ | |
| 1998/0927/sys/src/9/ip/tcp.c:1417,1428 – 1998/1008/sys/src/9/ip/tcp.c:1417,1425 | ||
| 1998/0918 | if(tcb->rcv.nxt - tcb->last_ack >= 2*tcb->mss && | |
| 1998/0925 | qlen(s->rq) < 8*tcb->mss){ | |
| 1997/0327 | tcb->flags |= FORCE; | |
| 1998/0925 |
| |
| 1998/1008 | if(tcb->acktimer.state != TimerON) tcpgo(tpriv, &tcb->acktimer); | |
| 1997/0327 | break; case Finwait2: | |
| 1998/0927/sys/src/9/ip/tcp.c:1556,1573 – 1998/1008/sys/src/9/ip/tcp.c:1553,1570 | ||
| 1997/0327 | if(tcb->snd.wnd < usable) usable = tcb->snd.wnd; usable -= sent; | |
| 1998/1008 | * and send if any of the following: * - there's no unacked packets outstanding | |
| 1997/0327 | * - we've forced to send anyways * - we've just gotten an ACK for a previous packet | |
| 1998/1008 | * - there's more than 5 bytes queued | |
| 1997/0327 | */ if(!first) if(!(tcb->flags&(FORCE|ACKED))) | |
| 1998/1008 | if((sndcnt-sent) < 5) | |
| 1997/0327 | usable = 0; } tcb->flags &= ~ACKED; | |
| 1998/1008/sys/src/9/ip/tcp.c:38,43 – 1998/1118/sys/src/9/ip/tcp.c:38,44 (short | long) | ||
| 1997/0327 | MSPTICK = 50, /* Milliseconds per timer tick */ DEF_MSS = 1024, /* Default mean segment */ | |
| 1998/0630 | DEF_RTT = 150, /* Default round trip */ | |
| 1998/1118 | DEF_KAT = 10000, /* Default keep alive trip in ms */ | |
| 1997/0327 | TCP_LISTEN = 0, /* Listen connection */ TCP_CONNECT = 1, /* Outgoing connection */ | |
| 1998/1008/sys/src/9/ip/tcp.c:171,181 – 1998/1118/sys/src/9/ip/tcp.c:172,182 | ||
| 1997/0327 | Timer timer; /* Activity timer */ Timer acktimer; /* Acknowledge timer */ Timer rtt_timer; /* Round trip timer */ | |
| 1998/1118 | Timer katimer; /* keep alive timer */ | |
| 1997/0327 | ulong rttseq; /* Round trip sequence */ int srtt; /* Shortened round trip */ int mdev; /* Mean deviation of round trip */ int kacounter; /* count down for keep alive */ | |
| 1998/0306 | Tcphdr protohdr; /* prototype header */ | |
| 1998/1008/sys/src/9/ip/tcp.c:237,242 – 1998/1118/sys/src/9/ip/tcp.c:238,244 | ||
| 1997/0327 | void tcpsndsyn(Tcpctl*); void tcprcvwin(Conv*); void tcpacktimer(Conv*); | |
| 1998/1118 | void tcpkeepalive(Conv*); | |
| 1997/0327 | void | |
| 1998/0306 | tcpsetstate(Conv *s, uchar newstate) | |
| 1998/1008/sys/src/9/ip/tcp.c:554,559 – 1998/1118/sys/src/9/ip/tcp.c:556,562 | ||
| 1998/0313 | tcphalt(tpriv, &tcb->timer); tcphalt(tpriv, &tcb->rtt_timer); | |
| 1998/0925 | tcphalt(tpriv, &tcb->acktimer); | |
| 1998/1118 | tcphalt(tpriv, &tcb->katimer); | |
| 1997/0327 | /* Flush reassembly queue; nothing more can arrive */ for(rp = tcb->reseq; rp != nil; rp = rp1) { | |
| 1998/1008/sys/src/9/ip/tcp.c:594,599 – 1998/1118/sys/src/9/ip/tcp.c:597,606 | ||
| 1997/0327 | tcb->acktimer.start = TCP_ACK / MSPTICK; tcb->acktimer.func = tcpacktimer; tcb->acktimer.arg = s; | |
| 1998/1118 | tcb->kacounter = 0; tcb->katimer.start = DEF_KAT / MSPTICK; tcb->katimer.func = tcpkeepalive; tcb->katimer.arg = s; | |
| 1998/0306 | /* create a prototype(pseudo) header */ if(ipcmp(s->laddr, IPnoaddr) == 0) | |
| 1998/1008/sys/src/9/ip/tcp.c:1007,1014 – 1998/1118/sys/src/9/ip/tcp.c:1014,1019 | ||
| 1998/0313 | tpriv = s->p->priv; | |
| 1997/0327 | tcb = (Tcpctl*)s->ptcl; | |
| 1998/1008/sys/src/9/ip/tcp.c:1224,1229 – 1998/1118/sys/src/9/ip/tcp.c:1229,1237 | ||
| 1997/0327 | tcb = (Tcpctl*)s->ptcl; qlock(tcb); | |
| 1998/1118 | if(tcb->kacounter > 0) tcb->kacounter = MAXBACKOFF; | |
| 1997/0327 | switch(tcb->state) { case Closed: | |
| 1998/0313 | sndrst(tcp, source, dest, length, &seg); | |
| 1998/1008/sys/src/9/ip/tcp.c:1343,1351 – 1998/1118/sys/src/9/ip/tcp.c:1351,1359 | ||
| 1997/0327 | case Finwait1: update(s, &seg); if(tcb->sndcnt == 0){ | |
| 1998/1118 | tcb->kacounter = MAXBACKOFF; | |
| 1997/0327 | tcpsetstate(s, Finwait2); | |
| 1998/1118 | tcb->katimer.start = MSL2 * (1000 / MSPTICK); | |
| 1998/0313 | tcpgo(tpriv, &tcb->timer); | |
| 1997/0327 | } break; | |
| 1998/1008/sys/src/9/ip/tcp.c:1686,1691 – 1998/1118/sys/src/9/ip/tcp.c:1694,1701 | ||
| 1997/0327 | } | |
| 1998/0313 | tpriv->tstats.tcpOutSegs++; | |
| 1998/1118 | if(tcb->kacounter > 0) tcpgo(tpriv, &tcb->katimer); | |
| 1998/0313 | ipoput(f, hbp, 0, s->ttl); | |
| 1997/0327 | } } | |
| 1998/1008/sys/src/9/ip/tcp.c:1694,1700 – 1998/1118/sys/src/9/ip/tcp.c:1704,1710 | ||
| 1998/0306 | * the BSD convention (hack?) for keep alives. resend last uchar acked. | |
| 1997/0327 | */ void | |
| 1998/1118 | tcpsendka(Conv *s) | |
| 1997/0327 | { Tcp seg; Tcpctl *tcb; | |
| 1998/1008/sys/src/9/ip/tcp.c:1730,1736 – 1998/1118/sys/src/9/ip/tcp.c:1740,1787 | ||
| 1998/0313 | ipoput(s->p->f, hbp, 0, s->ttl); | |
| 1997/0327 | } | |
| 1998/1118 | /* * if we've timed out, close the connection * otherwise, send a keepalive and restart the timer */ | |
| 1997/0327 | void | |
| 1998/1118 | tcpkeepalive(Conv *s) { Tcpctl *tcb; tcb = (Tcpctl*)s->ptcl; if(--(tcb->kacounter) <= 0) localclose(s, Etimedout); else { qlock(tcb); tcpsendka(s); qunlock(tcb); tcpgo(s->p->priv, &tcb->katimer); } } /* * start keepalive timer */ char* tcpstartka(Conv *s, char **f, int n) { Tcpctl *tcb; int x; tcb = (Tcpctl*)s->ptcl; if(n > 1){ x = atoi(f[1]); if(x >= MSPTICK) tcb->katimer.start = x/MSPTICK; } tcb->kacounter = MAXBACKOFF; tcpgo(s->p->priv, &tcb->katimer); return nil; } void | |
| 1997/0327 | tcprxmit(Conv *s) { Tcpctl *tcb; | |
| 1998/1008/sys/src/9/ip/tcp.c:1782,1797 – 1998/1118/sys/src/9/ip/tcp.c:1833,1838 | ||
| 1997/0327 | } tcprxmit(s); break; | |
| 1998/0313 |
| |
| 1997/0327 |
| |
| 1998/1008/sys/src/9/ip/tcp.c:2001,2006 – 1998/1118/sys/src/9/ip/tcp.c:2042,2049 | ||
| 1997/0327 | { if(n == 1 && strcmp(f[0], "hangup") == 0) return tcphangup(c); | |
| 1998/1118 | if(n >= 1 && strcmp(f[0], "keepalive") == 0) return tcpstartka(c, f, n); | |
| 1997/0327 | return "unknown control request"; } | |
| 1998/1118/sys/src/9/ip/tcp.c:567,572 – 1998/1127/sys/src/9/ip/tcp.c:567,574 (short | long) | ||
| 1997/0327 | if(tcb->state == Syn_sent) | |
| 1998/0313 | Fsconnected(s, reason); | |
| 1998/1127 | if(s->state == Announced) wakeup(&s->listenr); | |
| 1997/0327 | qhangup(s->rq, reason); qhangup(s->wq, reason); | |
| Too many diffs (26 > 25). Stopping. | ||