Enterprise Networking Week 13

Spring 2021, Mondays 5:30-8:00

April 26

Final exam



BGP stuck routes

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.


Cubic vs BBR

1. Basic run as in renocubic2.py

2. What would give Cubic a leg up?


TLS


TCP implementation

    wireshark 2 and wireshark 3


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

       

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