TCP
- Sliding Window for Flow Control
- Nagle algorithm
The need for Flow Control
- IP gives us ability to send end-to-end
- sequence and ack give us ability to reliably (modulo checksum)
deliver data to application
- still missing: flow control, the ability to slow down the sender
if the receiver is slow
- receiver buffers are limited
- why send if the receiver has no space?
TCP flow control
- with each ack, the receiver specifies how many more bytes past the
ack the receiver is willing to accept
- the number of bytes is the window
- the window is sliding every time a new ack pushes its left
edge to the right in sequence space
- the sender may have sent some of those bytes already -- because
they were in the previous window
- when the sender exhaust the window, it must stop sending
TCP window
- the left edge of the TCP window is moved to the right by the receiver
when it acknowledges new data
- the right edge of the TCP window is moved to the right by the receiver
when it sends a window update
- the left edge of the TCP window is communicated to the sender by
the acknowledgement number
- the left edge of the TCP window is communicated to the sender by
the window field
TCP data transfer example
- A to B: seq 1, ack 1000000, window 100, 200 bytes of data
- A to B: seq 201, ack 1000000, window 100, 800 bytes of data
- B to A: seq 1000000, ack 201, window 1000, 0 bytes of data
- A to B: seq 1001, ack 1000000, window 100, 200 bytes of data
Zero windows
- suppose the window size is reduced to zero: receiver acks, and
says it has a window size of zero, since all buffers are full
- later the receiver reopens the window by sending a new ack with
a new window
- that ack is lost!
- deadlock: sender is waiting for window update, receiver is waiting
for new data
- a sender with data to send, and a zero send window, must periodically
send one byte past the window, to elicit an ack in response
Silly Window Syndrome
- receiver will move right edge of window by a small amount when
it receives a small amount of data
- if sender is window-limited, it will then send a small segment
- this is undesirable, because the overhead is lower when larger
segments are sent, and because the receiver is likely to expand the
window more soon
- solution:
- receiver must move right edge of window in increments of at
least 1 MSS or 1/2 the actual window, whichever is less
- sender increment its send window in increments of at
least 1 MSS or 1/2 the estimated receiver's window, whichever is less
- sender needs a timer so it will send less than 1/2 the estimated
window -- this avoids deadlock in case the estimate for the receiver's
window is wrong (for example if the receiver's window got smaller)
Nagle Algorithm and sender SWS
- the usable window is the number of bytes I could send given the
ack, window, and the next sequence number to send:
U = ack + wnd - nxt
- D is the amount of data I am ready to send
- to avoid SWS, the sender sends if it can send one full MSS,
or at least 1/2 the (estimated) receive buffer:
min(D, U) >= MSS or min(D, U) >= rcvbuff / 2
- Nagle suggests, for D < MSS, only sending if the window is
large enough to send everything, and no acks are pending:
nxt = ack and D <= U
- or send if there is data to send, and an override timeout occurs
- in-class exercise: what is the benefit of this, that is, the
benefit of not sending when (a) the
window is large enough to send everything, but (b) acks are pending?
(i.e. if D < MSS and nxt != ack?)