|
packetdrill_ requires root privileges since it inject raw IP packets. The easiest way to install it is to use a virtualbox image with a Linux kernel 4.x or 5.x. You can clone its git repository from https://github.com/google/packetdrill and follow the instructions in https://github.com/google/packetdrill/tree/master/gtests/net/packetdrill. The packetdrill_ scripts used in this section are available from https://github.com/cnp3/ebook/tree/master/exercises/packetdrill_scripts
|
|
|
packetdrill_ writes 10 bytes of data through the :manpage:`write` system call. The stack immediately sends these 10 bytes inside a segment whose ``Push`` flag is set [#fpush]_. The payload starts at sequence number ``1`` and ends at sequence number ``10``. packetdrill_ replies by injecting an acknowledgment for the entire data after 100 milliseconds.
|
|
|
Redraw the same figure assuming that the second segment that was delivered by the sender in the figure experienced congestion. In a network that uses Explicit Congestion Notification, this segment would be marked by routers and the receiver would return the congestion mark in the corresponding acknowledgment.
|
|
|
Same question as above but now with a small variation. Recent TCP implementations use a large initial value for the congestion window. Draw the time-sequence diagram that corresponds to an initial value of 10000 bytes for this congestion window.
|
|
|
Same question as the first one, but consider that the MSS on the sender is set to 500 bytes. How does this modification affect the entire delay ?
|
|
|
Same question, but assume now that the fourth segment delivered by the sender experienced congestion (but was not discarded).
|
|
|
Some TCP clients use delayed acknowledgments and send a TCP acknowledgment after after second in-sequence segment. This behavior is illustrated in the script below. This script is available from :download:`/exercises/packetdrill_scripts/slow-start-delayed.pkt`.
|
|
|
TCP always acknowledges each received segment
|
|
|
The ``0`` indicates that the system call must be issued immediately. packetdrill_ then executes the system call and verifies that it returns ``3```. If yes, the processing continues. Otherwise the script stops and indicates an error.
|
|
|
The complete packetdrill_ script is available from :download:`/exercises/packetdrill_scripts/connect.pkt`.
|
|
|
the delay required to transmit a single TCP segment containing MSS bytes is small and set to 1 milliseconds, independently of the MSS size
|
|
|
The description of TCP packets in packetdrill_ uses a syntax that is very close to the tcpdump_ one. The ``+0`` timing indicates that the line is executed immediately after the previous event. The ``<`` sign indicates that packetdrill_ injects a TCP segment and the ``S`` character indicates that the ``SYN`` flag must be set. Like tcpdump_, packetdrill_ uses sequence numbers that are relative to initial sequence number. The three numbers that follow are the sequence number of the first byte of the payload of the segment (``0``), the sequence number of the last byte of the payload of the segment (``0`` after the semi-column) and the length of the payload (``0`` between brackets) of the ``SYN`` segment. This segment does not contain a valid acknowledgment but advertises a window of 1000 bytes. All ``SYN`` segments must also include the ``MSS`` option. In this case, we set the MSS to 1000 bytes. The next line of the packetdrill_ script verifies the reply sent by the instrumented Linux kernel.
|
|
|
The examples above have demonstrated how TCP retransmits lost segments. However, they did not consider the interactions with the congestion control scheme since the use a large initial congestion window. We now set the initial congestion window to two MSS-sized segments and use the ``tcpi_snd_cwnd`` and ``tcpi_snd_ssthresh`` variables from ``TCP_INFO`` to explore the evolution of the TCP congestion control scheme. Our first script looks at the evolution of the congestion window during a slow-start when there are no losses. This script is available from :download:`/exercises/packetdrill_scripts/slow-start.pkt`.
|
|
|
the initial value of the congestion window is one MSS-sized segment
|
|
|
The :manpage:`accept` system call returns a new file descriptor, in this case value ``4``. At this point, packetdrill_ can write data on the socket or inject packets.
|
|
|
The `Push` flag is one of the TCP flags defined in :rfc:`793`. TCP stacks usually set this flag when transmitting a segment that empties the send buffer. This is the reason why we observe this push flag in our example.
|
|
|
the round-trip-time is fixed and does not change during the lifetime of the TCP connection. We assume a fixed value of 100 milliseconds for the round-trip-time and a fixed value of 200 milliseconds for the retransmission timer.
|
|
|
the sender/receiver performs a single :manpage:`send(3)` of `x` bytes
|
|
|
These states are defined in https://github.com/torvalds/linux/blob/master/include/net/tcp_states.h
|
|
|
The ``tcpi_state`` variable used in this script is returned by ``TCP_INFO`` [#ftcpinfo]_. It tracks the state of the TCP connection according to TCP's finite state machine [#fstates]_. This script is available from :download:`/exercises/packetdrill_scripts/client.pkt`.
|
|