pete > courses > CS 431 Spring 25 > lecture 17: TCP windows


Lecture 17: TCP windows

Goals


in shell snippets below, "local\(" indicates commands run on "this" machine and "remote\)" indicates commands run on "that" machine

we have to run the tests between different machines because often operating systems play games with interprocess communication between processes on the same machine (including VMs)

nc (netcat) on Linux uses different parameters to nc on FreeBSD

remote$ nc -l -p 4000

can use netstat (previously used to inspect the routing table) to see the state of sockets: -t for TCP, -n for no DNS, -l for listeners:

remote$ netstat -tnl

note that the entry for port 4000 is in state LISTEN

local$ nc remote-ip 4000

in Wireshark, observe SYN, SYN-ACK, ACK packets

review corresponding ladder diagram

review sequence numbers: random-ish ISN, refer to octets, separate streams for each direction within connection (hence the second SYN in reverse direction)

can use netstat again, this time not limited to listening sockets:

remote: netstat -tn

see that the connection is now ESTABLISHED

type something at netcat, see it printed by the other netcat; in wireshark, see the data packet and the corresponding ACK

what is receiving netcat doing here? it’s calling recv(2), one argument to which is buffer size, probably much larger than amount of text sent; so why is recv(2) returning right away? PSH flag tells kernel "when you get this data, deliver it right away, don’t wait for full buffer"

what do you think would happen without the PSH flag? the kernel might save the data until enough arrives to satisfy the full amount requested with recv

this suggests that the kernel needs to store some information pertaining to the connection, which is perhaps obvious but merits explicit mention

before we dig into that, press ^C on one, note FIN and… RST?

run the client again with no server running:

local$ nc remote-ip 4000

see the SYN go out, and the response is not a SYN-ACK, but a RST

this is to indicate that there is no process listening (bound to) that port

back to the previous topic: what if the local process doesn’t call recv? (whether or not the PSH flag is set) the kernel will just let the data sit in that buffer until recv is called

but kernel memory is finite; what happens if the sender keeps sending more and more data without the local process calling recv? the kernel can’t store it all… can it?

let’s test it

sender.c & receiver.c

the sender will listen for an incoming connection; the receiver will make that connection

the sender runs an infinite loop that asks how many bytes to send and then call send for that many

the receiver runs an infinite loop that asks how many bytes to receive and then calls recv for that many

run both

remote$ ./sender 4000
local$ ./receiver remote 4000

also run wireshark with the capture filter "ip host remote and not tcp port 22" to capture only packets to/from remote but not ssh

tell the sender to send 100 bytes, we see a single 100-byte packet and its ACK

tell the sender to send 10000 bytes, we see several packets, and their corresponding ACKs

note that all these ACKs have been sent without the process having called recv! so the kernel is acknowledging all this stuff without any interaction from the process.

tell the sender to send 100000 bytes, we see several packets and their ACKs, but then we see some bad stuff: the receiver sends back a TCP Window Full packet, which is evidently worrisome because wireshark shows it with a black background

what is this window thing? it’s an indication of how much kernel buffer space is remaining on the receiver: by sending TCP Window Full, the receiver is telling the sender: "I have no more kernel buffer space for more data, so you should probably stop sending"

if we look back at the preceding ACK packets, we can see the window size decreasing (in the "WIN=" part of the Info column in wireshark)

as we let it sit there, the sender keeps sending checks about every 2 minutes (120 seconds) to see if the situation has changed

if we tell the receiver to recv a few bytes, it does so, but it still sends back the TCP Window Full message in response to the sender’s checks

it’s only until we tell the receiver to recv more bytes than are currently in the kernel buffer that the receiver responds with an ACK that indicates enough (window) buffer space available, at which point the rest of the data is sent

we can also see this in the output of netcat on both systems: the Send-Q and Recv-Q columns indicate how many bytes are in each buffer

if we tell the receiver to recv a ton of bytes, we can also see the window size increase—it seems like the kernel might choose to increase the buffer size because the corresponding process has shown that it wants more data at once

for every TCP socket, the kernel maintains a send buffer and a receive buffer

it also has to remember information like what it’s expecting next (eg, "I just send a SYN, I expect a receive a SYN-ACK soon, with ack_num=XYZ")

it makes sense that all this information would be stored in a struct; typically, this struct is called a Transmission Control Block (TCB)

the "what it’s expecting next" information is reminiscent of the state machine we talked about a few weeks ago

and, on page 23 of the RFC, the exact state machine is specified

the square blocks are states (whose names exactly match the State column in the netstat outout)

each transition has a two-part label: the top part indicates what external stimulus causes the transition to be taken and the bottom part indicates what action should be taken along with transitioning to the new state

so if we’re currently in the CLOSED state and an active OPEN happens (ie, the process calls connect(2)), the TCP subsystem must create a TCB and send a SYN packet before it transitions the connection to the SYN_SENT state

if we’re currently in the SYN_SENT state and we receive a SYN/ACK packet, we send back an ACK and transition to the ESTABLISHED state

we’ll see all this in more detail over the next couple lectures

next time we’ll look at other kinds of bad things that can happen and see how systems respond

Last modified: