From f230709ddb4b27d7766f25d41d42b5ef0a27c32e Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 13 Mar 1992 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1992-03-13 --- port/devip.c | 48 ++++++++++++----- port/devmnt.c | 1 - port/ipdat.h | 4 +- port/page.c | 133 ++++++++++++++++++++++++++++++++++++++--------- port/portfns.h | 1 + port/tcpinput.c | 62 ++++++---------------- port/tcpoutput.c | 11 ++-- 7 files changed, 172 insertions(+), 88 deletions(-) diff --git a/port/devip.c b/port/devip.c index cc6627a5f3359f259b0b7d2c897d7b47b96e6734..ef454344e7cc231123c4bea7cce46134212775f0 100644 --- a/port/devip.c +++ b/port/devip.c @@ -160,18 +160,18 @@ ipincoming(Ipconv *base, Ipconv *from) etab = &base[conf.ip]; for(new = base; new < etab; new++) { if(new->ref == 0 && canqlock(new)) { - if(new->ref || - (new->stproto == &tcpinfo && new->tcpctl.state != Closed) || - (new->stproto == &ilinfo && new->ilctl.state != Ilclosed)) { + if(new->ref || ipconbusy(new)) { qunlock(new); continue; } if(from) /* copy ownership from listening channel */ - netown(new->net, new->index, new->net->prot[from->index].owner, 0); + netown(new->net, new->index, + new->net->prot[from->index].owner, 0); else /* current user becomes owner */ netown(new->net, new->index, u->p->user, 0); + new->ref = 1; new->newcon = 0; qunlock(new); @@ -242,9 +242,8 @@ ipwrite(Chan *c, char *a, long n, ulong offset) error(Ebadarg); if(strcmp(field[0], "connect") == 0) { - if((cp->stproto == &tcpinfo && cp->tcpctl.state != Closed) || - (cp->stproto == &ilinfo && cp->ilctl.state != Ilclosed)) - error(Enetbusy); + if(ipconbusy(cp)) + error(Enetbusy); if(m != 2) error(Ebadarg); @@ -284,9 +283,8 @@ ipwrite(Chan *c, char *a, long n, ulong offset) cp->pdst = 0; } else if(strcmp(field[0], "announce") == 0) { - if((cp->stproto == &tcpinfo && cp->tcpctl.state != Closed) || - (cp->stproto == &ilinfo && cp->ilctl.state != Ilclosed)) - error(Enetbusy); + if(ipconbusy(cp)) + error(Enetbusy); if(m != 2) error(Ebadarg); @@ -325,6 +323,19 @@ ipwrite(Chan *c, char *a, long n, ulong offset) return n; } +int +ipconbusy(Ipconv *cp) +{ + if(cp->stproto == &tcpinfo) + if(cp->tcpctl.state != Closed) + return 1; + + if(cp->stproto == &ilinfo) + if(cp->ilctl.state != Ilclosed) + return 1; + + return 0; +} void udpstiput(Queue *q, Block *bp) @@ -369,8 +380,9 @@ udprcvmsg(Ipconv *muxed, Block *bp) /* Look for a conversation structure for this port */ etab = &muxed[conf.ip]; for(ifc = muxed; ifc < etab; ifc++) { - if(ifc->psrc == dport && ifc->ref && - (ifc->pdst == 0 || ifc->pdst == sport)) { + if(ifc->ref) + if(ifc->psrc == dport) + if(ifc->pdst == 0 || ifc->pdst == sport) { /* Trim the packet down to data size */ len = len - (UDP_HDRSIZE-UDP_PHDRSIZE); bp = btrim(bp, UDP_EHSIZE+UDP_HDRSIZE, len); @@ -512,6 +524,7 @@ tcpstoput(Queue *q, Block *bp) tcb->flags |= ACTIVE; send_syn(tcb); setstate(s, Syn_sent); + /* No break */ case Syn_sent: case Syn_received: @@ -530,6 +543,7 @@ tcpstoput(Queue *q, Block *bp) tcp_output(s); qunlock(tcb); break; + default: freeb(bp); error(Ehungup); @@ -629,8 +643,12 @@ iplisten(Chan *c) s = &ipconv[c->dev][connection]; base = ipconv[c->dev]; - if((s->stproto == &tcpinfo && s->tcpctl.state != Listen) || - (s->stproto == &ilinfo && s->ilctl.state != Illistening)) + if(s->stproto == &tcpinfo) + if(s->tcpctl.state != Listen) + error(Enolisten); + + if(s->stproto == &ilinfo) + if(s->ilctl.state != Illistening) error(Enolisten); qlock(&s->listenq); @@ -677,12 +695,14 @@ tcpstclose(Queue *q) case Syn_sent: close_self(s, 0); break; + case Syn_received: case Established: tcb->sndcnt++; tcb->snd.nxt++; setstate(s, Finwait1); goto output; + case Close_wait: tcb->sndcnt++; tcb->snd.nxt++; diff --git a/port/devmnt.c b/port/devmnt.c index 823825784bfeb0459688c4c3fc5ba1b16c279f55..59c2bd3cb25881e3d5b45fc34bbe4046f72bb06b 100644 --- a/port/devmnt.c +++ b/port/devmnt.c @@ -516,7 +516,6 @@ mountrpc(Mnt *m, Mntrpc *r) if(r->reply.type != r->request.type+1) { print("devmnt: mismatched reply 0x%lux T%d R%d tags req %d fls %d rep %d\n", r, r->request.type, r->reply.type, r->request.tag, r->flushtag, r->reply.tag); - mntdump(); error(Emountrpc); } } diff --git a/port/ipdat.h b/port/ipdat.h index 56f4e08d6a8485da0724f16f8de033464e478c76..f131f20f7248ee573256c4f15707ad9e187171d8 100644 --- a/port/ipdat.h +++ b/port/ipdat.h @@ -499,6 +499,7 @@ void ipremotefill(Chan*, char*, int); void ipstatusfill(Chan*, char*, int); int ipforme(uchar*); void ipsetaddrs(void); +int ipconbusy(Ipconv*); #define fmtaddr(xx) (xx>>24)&0xff,(xx>>16)&0xff,(xx>>8)&0xff,xx&0xff #define MIN(a, b) ((a) < (b) ? (a) : (b)) @@ -525,7 +526,8 @@ extern Qinfo arpinfo; extern Queue *Ipoutput; /* offsets into Myip */ -enum { +enum +{ Myself= 0, Mybcast= 1, Mynet= 3, diff --git a/port/page.c b/port/page.c index fadebba1b99159b1b694aeffea1887c8a4132bb6..7d8cc78c7b2a5d7e2bcb7d76f244d8d2e0fea3f0 100644 --- a/port/page.c +++ b/port/page.c @@ -49,56 +49,141 @@ unlockpage(Page *p) p->lock = 0; } +typedef struct Region Region; +struct Region +{ + ulong start; + ulong end; +}; + +enum +{ + Nregion= 10, +}; +Region region[Nregion]; + + /* * Called to allocate permanent data structures, before calling pageinit(). * We assume all of text+data+bss is in the first memory bank. + * + * alignment is in number of bytes + * + * WARNING: You can't cross a crevasse! */ +void +addsplit(Region *r, ulong start, ulong end) +{ + Region *rr; + int len = end - start; + + /* first look for an unused one */ + for(rr = region; rr < ®ion[Nregion]; rr++){ + if(rr == r) + continue; + if(rr->end - rr->start == 0){ + rr->start = start; + rr->end = end; + return; + } + } + + /* then look for a smaller one */ + for(rr = region; rr < ®ion[Nregion]; rr++){ + if(rr == r) + continue; + if(rr->end - rr->start < len){ + rr->start = start; + rr->end = end; + return; + } + } +} void* -ialloc(ulong n, int align) +iallocspan(ulong n, int align, ulong crevasse) { ulong p; - ulong *ap; + Region *r; + int m; + int ledge; if(palloc.active && n!=0) print("ialloc bad\n"); if(palloc.addr0 == 0){ - /* addr0 and addr1 are physical addresses */ - palloc.addr0 = (((ulong)&end)&~KZERO) + conf.base0; - palloc.addr1 = conf.base1; + region[Nregion-2].start = (((ulong)&end)&~KZERO) + conf.base0; + region[Nregion-2].end = conf.base0 + (conf.npage0< conf.base0 + (conf.npage0<= conf.maxialloc) - panic("keep bill joy away 2"); + if(align){ + m = n % align; + if(m) + n += align - m; + } + + p = 0; + for(r = region; r < ®ion[Nregion]; r++){ + /* allign region */ + p = r->start; + if(align){ + m = p % align; + if(m) + p += align - m; + } + + /* check for crossing a crevasse */ + if(crevasse){ + ledge = p / crevasse; + if(ledge != ((p+n-1) / crevasse)) + p = ((p+n-1) / crevasse) * crevasse; + } + + /* see if it fits */ + if(p + n > r->end) + continue; + + /* split the region */ + if(p != r->start) + addsplit(r, r->start, p); + r->start = p + n; + break; + } + if(r == ®ion[Nregion]) + panic("out of memory"); /* - * zero it + * remember high water marks */ - memset((void*)(p|KZERO), 0, n); + if(palloc.addr0 < r->start && r->start <= conf.base0+(conf.npage0<start; + else if(palloc.addr1 < r->start && r->start <= conf.base1+(conf.npage1<start; /* - * don't put anything else into a page aligned ialloc + * zero it */ - *ap = align ? PGROUND(p+n) : (p+n); + memset((void*)(p|KZERO), 0, n); return (void*)(p|KZERO); } +/* + * allocate with possible page alignment + */ +void* +ialloc(ulong n, int align) +{ + return iallocspan(n, align ? BY2PG : 0, 0); +} + void pageinit(void) { diff --git a/port/portfns.h b/port/portfns.h index 6f9faab488cf5d7ba9af8c551b2deffb86f141b7..46c18206f3053739c85aeb615bded0670589c37c 100644 --- a/port/portfns.h +++ b/port/portfns.h @@ -88,6 +88,7 @@ void grpinit(void); int hwcursmove(int, int); int hwcursset(uchar*, uchar*, int, int); void* ialloc(ulong, int); +void* iallocspan(ulong, int, ulong); long ibrk(ulong, int); int incref(Ref*); void initq(IOQ*); diff --git a/port/tcpinput.c b/port/tcpinput.c index d190ba3f888547f76e94137d233e406a99d9714d..60af142bfcba658c51040dee18e8ac180d1a9176 100644 --- a/port/tcpinput.c +++ b/port/tcpinput.c @@ -156,11 +156,13 @@ process: goto done; } - if((seg.flags & ACK) && PREC(tos) != PREC(tcb->tos)){ + if(seg.flags & ACK) + if(PREC(tos) != PREC(tcb->tos)){ freeb(bp); reset(source, dest, tos, length, &seg); goto done; } + if(seg.flags & SYN) { proc_syn(s, tos, &seg); if(seg.flags & ACK){ @@ -193,7 +195,8 @@ process: /* If we have no opens and the other end is sending data then * reply with a reset */ - if(s->readq == 0 && length) { + if(length) + if(s->readq == 0) { freeb(bp); reset(source, dest, tos, length, &seg); goto done; @@ -293,7 +296,8 @@ process: case Finwait2: /* Place on receive queue */ tcb->rcvcnt += blen(bp); - if(s->readq && bp) { + if(bp) + if(s->readq) { PUTNEXT(s->readq, bp); bp = 0; } @@ -357,42 +361,6 @@ done: qunlock(tcb); } -void -tcp_icmp(Ipconv *ipc, Ipaddr source, Ipaddr dest, char type, char code, Block **bpp) -{ - Tcp seg; - Tcpctl *tcb; - Ipconv *s; - - ntohtcp(&seg, bpp); - if(!(s = ip_conn(ipc, seg.source, seg.dest, dest, IP_TCPPROTO))) - return; - - tcb = &s->tcpctl; - - if(!seq_within(seg.seq, tcb->snd.una, tcb->snd.nxt)) - return; - - switch((uchar)type) { - case ICMP_UNREACH: - tcb->type = type; - tcb->code = code; - if(tcb->state == Syn_sent || tcb->state == Syn_received) - close_self(s, Enetunreach); - break; - case ICMP_TIMXCEED: - tcb->type = type; - tcb->code = code; - if(tcb->state == Syn_sent || tcb->state == Syn_received) - close_self(s, Etimedout); - break; - case ICMP_SOURCEQUENCH: - tcb->cwind = tcb->cwind/2; - tcb->cwind = MAX(tcb->mss,tcb->cwind); - break; - } -} - void reset(Ipaddr source, Ipaddr dest, char tos, ushort length, Tcp *seg) { @@ -455,10 +423,12 @@ update(Ipconv *s, Tcp *seg) return; } - if(seq_gt(seg->seq,tcb->snd.wl1) || ((seg->seq == tcb->snd.wl1) - && seq_ge(seg->ack,tcb->snd.wl2))) { - if(tcb->snd.wnd == 0 && seg->wnd != 0) + if(seq_ge(seg->ack,tcb->snd.wl2)) + if(seq_gt(seg->seq,tcb->snd.wl1) || (seg->seq == tcb->snd.wl1)) { + if(seg->wnd != 0) + if(tcb->snd.wnd == 0) tcb->snd.ptr = tcb->snd.una; + tcb->snd.wnd = seg->wnd; tcb->snd.wl1 = seg->seq; tcb->snd.wl2 = seg->ack; @@ -483,10 +453,11 @@ update(Ipconv *s, Tcp *seg) } /* Round trip time estimation */ - if(run_timer(&tcb->rtt_timer) && seq_ge(seg->ack, tcb->rttseq)) { + if(run_timer(&tcb->rtt_timer)) + if(seq_ge(seg->ack, tcb->rttseq)) { stop_timer(&tcb->rtt_timer); - if(!(tcb->flags & RETRAN)) { + if(!(tcb->flags & RETRAN)) { rtt = tcb->rtt_timer.start - tcb->rtt_timer.count; rtt *= MSPTICK; if(rtt > tcb->srtt && @@ -654,7 +625,8 @@ trim(Tcpctl *tcb, Tcp *seg, Block **bp, ushort *length) len++; if(tcb->rcv.wnd == 0) { - if(seg->seq == tcb->rcv.nxt && len == 0) + if(len == 0) + if(seg->seq == tcb->rcv.nxt) return 0; } else { diff --git a/port/tcpoutput.c b/port/tcpoutput.c index 23d7589351a8c0f454479ea97109e2ab9c8d1277..1bd5e5a028871efe966355349ab8b5b038d0025d 100644 --- a/port/tcpoutput.c +++ b/port/tcpoutput.c @@ -36,7 +36,8 @@ tcp_output(Ipconv *s) sndq = tcb->sndq; /* Don't send anything else until our SYN has been acked */ - if(sent != 0 && !(tcb->flags & SYNACK)) + if(sent != 0) + if((tcb->flags & SYNACK) == 0) break; if(tcb->snd.wnd == 0){ @@ -50,7 +51,8 @@ tcp_output(Ipconv *s) * limited by the congestion window */ usable = MIN(tcb->snd.wnd,tcb->cwind) - sent; - if(sent != 0 && qlen - sent < tcb->mss) + if(sent != 0) + if(qlen - sent < tcb->mss) usable = 0; } @@ -60,7 +62,8 @@ tcp_output(Ipconv *s) seg.up = 0; DPRINT("tcp_out: ssize = %lux\n", ssize); - if(ssize == 0 && (tcb->flags & FORCE) == 0) + if(ssize == 0) + if((tcb->flags & FORCE) == 0) break; /* Stop ack timer if one will be piggy backed on data */ @@ -175,9 +178,11 @@ tcp_timeout(void *arg) switch(tcb->state){ case Closed: panic("tcptimeout"); + case Time_wait: close_self(s, 0); break; + case Established: if(tcb->backoff < MAXBACKOFF) tcb->backoff++;