M port/devip.c => port/devip.c +21 -0
@@ 604,6 604,11 @@ tcpstiput(Queue *q, Block *bp)
PUTNEXT(q, bp);
}
+tcproominq(void *a)
+{
+ return !((Tcpctl *)a)->sndfull;
+}
+
void
tcpstoput(Queue *q, Block *bp)
{
@@ 638,6 643,20 @@ tcpstoput(Queue *q, Block *bp)
case Established:
case Close_wait:
/*
+ * Process flow control
+ */
+ if(tcb->sndfull){
+ qlock(&tcb->sndrlock);
+ if(waserror()) {
+ qunlock(&tcb->sndrlock);
+ nexterror();
+ }
+ sleep(&tcb->sndr, tcproominq, tcb);
+ poperror();
+ qunlock(&tcb->sndrlock);
+ }
+
+ /*
* Push data
*/
qlock(tcb);
@@ 646,6 665,8 @@ tcpstoput(Queue *q, Block *bp)
nexterror();
}
tcb->sndcnt += blen(bp);
+ if(tcb->sndcnt > Streamhi)
+ tcb->sndfull = 1;
if(tcb->sndq == 0)
tcb->sndq = bp;
else {
M port/devscsi.c => port/devscsi.c +1 -1
@@ 8,7 8,7 @@
#define DPRINT if(debug)kprint
-#define DATASIZE (32*512)
+#define DATASIZE (64*512)
static Scsi staticcmd; /* BUG: should be one per scsi device */
M port/ipdat.h => port/ipdat.h +3 -0
@@ 240,6 240,9 @@ struct Tctl
Block *sndq; /* List of data going out */
ulong sndcnt; /* Amount of data in send queue */
+ Rendez sndr; /* process flow control */
+ QLock sndrlock;
+ int sndfull;
Reseq *reseq; /* Resequencing queue */
Timer timer; /* Activity timer */
M port/tcpinput.c => port/tcpinput.c +5 -0
@@ 559,6 559,11 @@ update(Ipconv *s, Tcp *seg)
tcb->flags &= ~RETRAN;
tcb->backoff = 0;
+
+ if(tcb->sndfull && tcb->sndcnt < Streamhi/2){
+ wakeup(&tcb->sndr);
+ tcb->sndfull = 0;
+ }
}
int