(FILECREATED "29-May-85 14:20:46" {ERIS}<LISP>INTERMEZZO>PATCHES>BSPPATCH.;1 6655 changes to: (VARS BSPPATCHCOMS)) (* Copyright (c) 1985 by Xerox Corporation. All rights reserved.) (PRETTYCOMPRINT BSPPATCHCOMS) (RPAQQ BSPPATCHCOMS ((FNS \BSP.HANDLE.ACK) (INITVARS (\BSP.MIN.ADATA.TIMEOUT 500) (\BSP.MAX.ADATA.TIMEOUT 10000)) (GLOBALVARS \BSP.MIN.ADATA.TIMEOUT \BSP.MAX.ADATA.TIMEOUT))) (DEFINEQ (\BSP.HANDLE.ACK [LAMBDA (PUP SOCKET) (* bvm: "29-May-85 14:12") (* * Handle an ACK pup. This is a little messy. The ACK's id tells how far partner has gotten in the stream. Assuming this ack was in response to an ADATA of ours, we need to retransmit anything that we sent before that ADATA which isn't acknowledged in this ack. Finally, the body of the ack gives us an update of partner's allocation) (PROG (THISID NEXTPUP OLDPUP ADATACOUNT ACKDATA OUTQUEUE INTERRUPTPUP) (COND ((OR (NOT (\RTP.FILTER SOCKET PUP T)) (ILESSP (SETQ THISID (fetch PUPID of PUP)) (fetch LASTACKID of SOCKET))) (* not for us, or is a duplicate/delayed ack) (RELEASE.PUP PUP) (RETURN))) [COND ((fetch ACKREQUESTED of SOCKET) (* This is presumably in response to our last ADATA, so notice how long it took. Update our timeout = 2 * avg round trip delay, exponentially aged over the last 8 samples) (replace ADATATIMEOUT of SOCKET with (LRSH [IPLUS (ITIMES 7 (fetch ADATATIMEOUT of SOCKET)) (IMAX \BSP.MIN.ADATA.TIMEOUT (IMIN \BSP.MAX.ADATA.TIMEOUT (LLSH (CLOCKDIFFERENCE (fetch LASTADATATIME of SOCKET)) 1] 3] (replace LASTACKID of SOCKET with THISID) (SETQ OUTQUEUE (fetch BSPOUTPUTQ of SOCKET)) (* Now figure out who is acked and who needs retransmitting) [COND ((fetch INTERRUPTOUT of SOCKET) (SETQ INTERRUPTPUP (\SEARCH.OUTPUTQ SOCKET T] (UNINTERRUPTABLY (SETQ OLDPUP (fetch SYSQUEUEHEAD of OUTQUEUE)) (* Empty out the queue and refill it below) (replace SYSQUEUEHEAD of OUTQUEUE with (replace SYSQUEUETAIL of OUTQUEUE with NIL))) (COND (INTERRUPTPUP (* Retransmit interrupts immediately) (replace EPREQUEUE of INTERRUPTPUP with OUTQUEUE) (SENDPUP (fetch PUPSOC of SOCKET) INTERRUPTPUP))) (COND ((fetch ACKREQUESTED of SOCKET) (SETQ ADATACOUNT (fetch ADATACOUNT of SOCKET)) (* This lets us know whether a pup was sent before or after last adata) (replace ACKREQUESTED of SOCKET with NIL))) (while OLDPUP do (SETQ NEXTPUP (fetch QLINK of OLDPUP)) (replace QLINK of OLDPUP with NIL) (COND ((EQ (fetch PUPTYPE of OLDPUP) \PT.INTERRUPT) (* We retransmitted it above, so we should not be seeing this!) (\ENQUEUE OUTQUEUE OLDPUP)) ((IGEQ (IDIFFERENCE THISID (fetch PUPID of OLDPUP)) (IDIFFERENCE (fetch PUPLENGTH of OLDPUP) \PUPOVLEN)) (* has been acked, release it) (add (fetch #UNACKEDPUPS of SOCKET) -1) (add (fetch #UNACKEDBYTES of SOCKET) (IDIFFERENCE \PUPOVLEN (fetch PUPLENGTH of OLDPUP))) (add (fetch PUPALLOCCOUNT of SOCKET) 1) (* one more pup successfully received) (RELEASE.PUP OLDPUP)) ((AND ADATACOUNT (IGREATERP ADATACOUNT (fetch AUXWORD of OLDPUP))) (* This pup was originally sent before our last ADATA, so retransmit it) [\TRANSMIT.STRATEGY SOCKET OLDPUP (COND ([AND (fetch QLINK of OLDPUP) (ILEQ ADATACOUNT (fetch AUXWORD of (fetch QLINK of OLDPUP] (SETQ ADATACOUNT NIL)) (T (QUOTE NO] (* Maybe make it an ADATA if this is the last thing we're retransmitting, else make it just DATA) (replace EPREQUEUE of OLDPUP with OUTQUEUE) (SENDPUP (fetch PUPSOC of SOCKET) OLDPUP)) (T (\ENQUEUE OUTQUEUE OLDPUP))) (SETQ OLDPUP NEXTPUP)) (* * Now update allocations) [COND ((IGREATERP (fetch PUPALLOCCOUNT of SOCKET) \BSP.ALLOCHYSTERESIS) (* We've been doing okay for a while with no congestion, so increase our max pup allocation) (replace PUPALLOCCOUNT of SOCKET with 0) (COND ((ILESSP (fetch MAXPUPALLOC of SOCKET) \BSP.MAXPUPALLOC) (add (fetch MAXPUPALLOC of SOCKET) 1] (SETQ ACKDATA (fetch PUPCONTENTS of PUP)) (replace BYTESPERPUP of SOCKET with (IMIN (fetch ACKBYTESPERPUP of ACKDATA) \MAX.PUPLENGTH)) (replace PUPALLOC of SOCKET with (IMAX (IMIN (fetch MAXPUPALLOC of SOCKET) (IDIFFERENCE (fetch ACKPUPS of ACKDATA) (fetch #UNACKEDPUPS of SOCKET))) 0)) (* number of pups we can still send) (replace BYTEALLOC of SOCKET with (IMAX (IDIFFERENCE (fetch ACKBYTES of ACKDATA) (fetch #UNACKEDBYTES of SOCKET)) 0)) (RELEASE.PUP PUP) (NOTIFY.EVENT (fetch BSPINPUTEVENT of SOCKET)) (* Actually, notifying that allocation may have changed) (\SETBSPTIMEOUT SOCKET) (SETUPTIMER \BSP.INACTIVITY.TIMEOUT (fetch INACTIVITYTIMER of SOCKET]) ) (RPAQ? \BSP.MIN.ADATA.TIMEOUT 500) (RPAQ? \BSP.MAX.ADATA.TIMEOUT 10000) (DECLARE: DOEVAL@COMPILE DONTCOPY (GLOBALVARS \BSP.MIN.ADATA.TIMEOUT \BSP.MAX.ADATA.TIMEOUT) ) (PUTPROPS BSPPATCH COPYRIGHT ("Xerox Corporation" 1985)) (DECLARE: DONTCOPY (FILEMAP (NIL (435 6398 (\BSP.HANDLE.ACK 445 . 6396))))) STOP