Spring 2021, Mondays 5:30-8:00
April 19
Project 5 discussion
UDP implementation
TCP implementation
How do you assess competing traffic? PROBE_RTT
BWE as max rather than mean
Reno: increase cwnd as a way of probing for more BW
BBR: PROBE_BW. When cwnd < queuesize, MAX feature works to keep
increasing cwnd.
cwnd grows 25% every 8 RTTs, or approx 3% per RTT, or faster than Reno as
soon as cwnd > 30 packets
As soon as cwnd >= queuesize, the MAX feature works to ensure no
further increases.
BBR typically does better when the queue size is not so large
BBR currently sets cwnd to 2*bdp. This leads to huge packet losses if the queue is less than bdp.
As RTTactual increases, BBR's rate (equal to cwnd/RTTactual) falls. Also, as Reno's relative queue utilization grows, BBR's falls. These together are why BBR's throughput falls so precipitously at the start of the Reno-BBR graph. Once the first PROBE_BW event occurs, BBR has a better idea of the actual bandwidth.
My own TCP
RCV_NXT: number of next byte we expect to receive;
sent in each packet in the ACK field
SND_NXT: number of next byte we expect to send; sent in
each packet in the SEQ field
class tcpsocket methods, used on local side
tcp_handle_packet, used for arriving packets
How do you write this so there is no waiting needed?
tcp_handle_packet and RFC 793
Demo: wireshark traces showing failure at final ACK.
Two Generals and the final ACK
class tcpsocket:
def __init__(self):
self.localport=0
self.remoteport= None
self.localaddr = None
self.localaddrb = None
self.remoteaddr = None
self.remoteaddrb= None
self.ipheader = None
self.tcpheader= None
self.state =
CLOSED
self.isbound=False
self.sockettimeout =
0 # in seconds; floating-point
value. This is the time a reading socket will wait before throwing a
sockettimeout exception.
self.socknum =
nextsocketnum() # internal identifier
self.isclosed = False
self.shadowsocket =
None # The idea was to open "real"
sockets with the same port, to reserve it
self.arrivelist
= [] #
pkt_bufs that have arrived but cannot yet be ACKed because earlier data
has not arrived.
# Kept in order of increasing
startseq > self.snd_una. May overlap.
# NOT A QUEUE
self.readqueue
= queue.Queue() # holds pkt_bufs from received packets
that have been ACKed, but have not yet been read.
# entries are in order of arrival time; each entry strictly extends
read_maxSEQ,
# because otherwise it would be discarded.
self.read_relSEQ =
1 # Relative seqnum of next byte of
data to be read by application; relative offset from beginning of stream
self.read_maxSEQ =
-1 # Seqnum of next byte of data
AFTER all data in readqueue
self.writequeue
= queue.Queue() # data (as pkt_buf) that has been written by
application, but not yet sent, because of cwnd limits
# Must be strictly non-overlapping
self.sentqueue
= queue.Queue() # pkt_bufs for packets that have been
sent, but not ACKed. Again, must be non-overlapping. Includes SYN/FIN
self.readevent
= None # we are waiting to read
from this socket
self.connectevent
= None # wait on this until the connection reaches
ESTABLISHED. Used for both directions.
self.connectstatus =
0 # 0 for success; -1 for failure
self.childsocket
= None # when a connection is accepted, this is the
socket. SHOULD REALLY BE A QUEUE.
self.parentsocket =
None # when we create the child socket, we will
eventually need to NOTIFY the parent
self.lock =
None # a mutex lock
self.localISN
= 0 # the one we choose, used for
sending
self.remoteISN
= 0 # from other side's arriving
SYN, used for *receiving*
# sender sliding-window
parameters. These are all RELATIVE sequence numbers.
self.snd_una =
-1 # smallest unacknowledged sender
sequence number; lastACKed +1; bottom of sender window
self.lastACKed =
-1 # deprecated
self.snd_nxt
= -1 # next sequence number we will
send, = currentSEQ
# self.currentSEQ = -1
self.snd_max =
-1 # maximum seq number sent, +1.
If packets are lost, snd_next may be less.
self.cwnd =
MIN_CWND # sending
winsize.
# receiver sliding-window
parameters
self.remote_adv_wnd =
-1 # received advertised winsize, taken from packet
window advertisements, max value of cwnd
self.local_adv_wnd =
ADV_WIN # our own advertised winsize
self.rcv_wnd =
self.local_adv_wnd # ACTUAL receive winsize; may be
reduced. Our own advertised window
self.rcv_nxt
= 0 # next seq# we expect to
receive; = current ACK number
#self.rcv_wup #
highest seq# for which we have actually sent an ACK; <= rcv_nxt.
self.est_rtt = 0.5
self.RTO =
2.0 # initial
Retransmission TimeOut, in seconds
self.cwnd =
MIN_CWND #
self.timeout_time =
0 # time of next packet timeout;
incremented on every receive. Set to 0 to disable.
self.finseqnum
= None # relative sequence number when we sent our FIN
self.receivedFIN =
False # did other side send us a
FIN? NOT USED
self.TWend = 0
# time TIME_WAIT ends
TLS