M port/devip.c => port/devip.c +34 -14
@@ 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++;
M port/devmnt.c => port/devmnt.c +0 -1
@@ 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);
}
}
M port/ipdat.h => port/ipdat.h +3 -1
@@ 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,
M port/page.c => port/page.c +109 -24
@@ 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<<PGSHIFT);
+ region[Nregion-1].start = conf.base1;
+ region[Nregion-1].end = conf.base1 + (conf.npage1<<PGSHIFT);
+
+ palloc.addr0 = region[Nregion-2].start;
+ palloc.addr1 = region[Nregion-1].start;
}
/*
- * try first bank
+ * alignment also applies to length
*/
- p = align ? PGROUND(palloc.addr0) : palloc.addr0;
- if(p+n > conf.base0 + (conf.npage0<<PGSHIFT)){
- /*
- * no room in first bank, try second bank
- */
- if(conf.npage1 <= 0)
- panic("keep bill joy away 1");
- p = align ? PGROUND(palloc.addr1) : palloc.addr1;
- ap = &palloc.addr1;
- } else
- ap = &palloc.addr0;
-
- if(p >= 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<<PGSHIFT))
+ palloc.addr0 = r->start;
+ else if(palloc.addr1 < r->start && r->start <= conf.base1+(conf.npage1<<PGSHIFT))
+ palloc.addr1 = r->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)
{
M port/portfns.h => port/portfns.h +1 -0
@@ 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*);
M port/tcpinput.c => port/tcpinput.c +17 -45
@@ 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;
}
@@ 358,42 362,6 @@ done:
}
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)
{
Block *hbp;
@@ 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 {
M port/tcpoutput.c => port/tcpoutput.c +8 -3
@@ 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++;