Spring 2021, Mondays 5:30-8:00
April 26
Final exam
This is a fascinating network puzzle with real-world consequences:
blog.benjojo.co.uk/post/bgp-stuck-routes-tcp-zero-window
First off, let's look at Ben's actual data for stuck routes, and his BGP trace information.
Second, let's look at his TCP-zero-winsize theory. This is a little more speculative. There may be some other BGP flaw.
Followups:
Nobody really is sure what is going on. Note the email from Alexandre Snarskii
The third issue is whether a BGP timer that detects a non-reading connection would really fix anything.
1. Basic run as in renocubic2.py
2. What would give Cubic a leg up?
wireshark 2 and wireshark 3
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
Issues with checksums and layers
How timeouts work" emd pf altsockettcp.py file
Issues with locking: do you have to lock queues?
FIN_WAIT1, etc
TCP congestion plugin (struct
How would you implement data with the first SYN? How about with the second SYN (first SYN-ACK)?
T/TCP and SYN+data+FIN
ConnectionCount
Predicting CC value, to spoof connections
Morris spoofing on steroids