CompSci 356: Computer Network Architectures Lecture 5: Reliable Transmission and Multi-access links Chapter 2.4, 2.5, 2.6 Xiaowei Yang xwy@cs.duke.edu
Overview • Link layer functions – Encoding • NRZ, NRZI, Manchester, 4B/5B – Framing • Byte-oriented, bit-oriented, time-based • Bit stuffing – Error detection • Parity, checkshum, CRC – Reliability • FEC, sliding window • Multi-access links
Error detection • Error detection code adds redundancy – Analogy: sending two copies – Parity – Checksum – CRC • Error correcting code
Two-dimensional parity A sample frame of six bytes • Even parity bit – Make an even number of 1s in each row and column • Detect all 1,2,3-bit errors, and most 4-bit errors
Internet checksum algorithm • Basic idea (for efficiency) – Add all the words transmitted and then send the sum. – Receiver does the same computation and compares the sums • IP checksum – Adding 16-bit short integers using 1’s complement arithmetic – Take 1’s complement of the result • Used by lab 2 to detect errors
1 ’ s complement arithmetic • -x is each bit of x inverted • If there is a carry bit, add 1 to the sum • [-2^(n-1)-1, 2^(n-1)-1] • Example: 4-bit integer – -5 + -2 – +5: 0101; -5: 1010; – +2: 0010; -2: 1101; – -5 + -2 = 1010+1101 = 0111 + one carrier bit; – à 1000 = -7
Calculating the Internet checksum • u_short cksum (u_short *buf, int count) { register u_long sum = 0; while (count--) { sum += *buf++; if (sum & 0xFFFF0000) { /* carry occurred. So wrap around */ sum &= 0xFFFF; sum++; } } // one’s complement sum return ~(sum & 0xFFFF); // one’s complement of the sum }
Verifying the checksum • Adds all 16-bit words together, including the checksum • 0: correct • 1: errors
Remarks • Can detect 1 bit error • Not all two-bits • Efficient for software implementation
Cyclic Redundancy Check • Cyclic error-correcting codes • High-level idea: – Represent an n+1-bit message with an n degree polynomial M(x) – Divide the polynomial by a degree-k divisor polynomial C(x) – k-bit CRC: remainder – Send Message + CRC that is dividable by C(x)
Polynomial arithmetic modulo 2 – B(x) can be divided by C(x) if B(x) has higher degree – B(x) can be divided once by C(x) if of same degree • x^3 + 1 can be divided by x^3 + x^2 + 1 • The remainder would be 0*x^3 + 1*x^2 + 0*x^1 + 0*x^0 (obtained by XORing the coefficients of each term) – Remainder of B(x)/C(x) = B(x) – C(x) – Substraction is done by XOR each pair of matching coefficients
CRC algorithm 1. Multiply M(x) by x^k. Add k zeros to Message. Call it T(x) 2. Divide T(x) by C(x) and find the remainder 3. Send P(x) = T(x) – remainder • Append remainder to T(x) • P(x) dividable by C(x)
An example • 8-bit msg – 10011010 • Divisor (3bit CRC) – 1101 Msg sent: 11111001101
How to choose a divisor • Arithmetic of a finite field • Intuition: unlikely to be divided evenly by an error • Corrupted msg is P(x) + E(x) • If E(x) is single bit, then E(x) = x i • If C(x) has the first and last term nonzero, then detects all single bit errors • Find C(x) by looking it up in a book
Hardware implementation • Very efficient: XOR operations • Number of bits = k • 0 to k-1 registers (k-bit shift registers) • If n th (n < k) term is not zero, places an XOR gate • x 3 + x 2 + 1
Overview • Link layer functions – Encoding • NRZ, NRZI, Manchester, 4B/5B – Framing • Byte-oriented, bit-oriented, time-based • Bit stuffing – Error detection • Parity, checkshum, CRC – Reliability • FEC, sliding window • Multi-access links
Reliable transmission • What to do if a receiver detects bit errors? • Two high-level approaches – Forward error correction (FEC) – Retransmission • Acknowledgements – Can be “piggybacked” on data packets • Timeouts • Also called Automatic repeat request (ARQ)
Stop-and-wait • Send one frame, wait for an ack, and send the next • Retransmit if times out • Note in the last figure (d), there might be confusion: a new frame, or a duplicate?
Sequence number • Add a sequence number to each frame to avoid the ambiguity
Stop-and-wait drawback • Revisiting bandwidth-delay product – Total delay/latency = transmission delay + propagation delay + queuing • Queuing is the time packet sent waiting at a router’s buffer • Will revisit later (no sweat if you don’t get it now)
Delay * bandwidth product • For a 1Mbps pipe, it takes 8 seconds to transmit 1MB. If the link latency is less than 8 seconds, the pipe is full before all data are pumped into the pipe • For a 1Gbps pipe, it takes 8 ms to transmit 1MB.
Stop-and-wait drawback • A 1Mbps link with a 100ms two-way delay (round trip time, RTT) • 1KB frame size • Throughput = 1KB/ (1KB/1Mbps + 100ms) = 74Kbps << 1Mbps • Delay * bandwidth = 100Kb • So we could send ~12 frames before the pipe is full! • Throughput = 100Kb/(1KB/1Mbps + 100ms) = 926Kbps
Sliding window • Key idea: allowing multiple outstanding (unacked) frames to keep the pipe full
Sliding window on sender • Assign a sequence number (SeqNum) to each frame • Maintains three variables – Send Window Size (SWS) – Last Ack Received (LAR) – Last Frame Sent (LFS) • Invariant: LFS – LAR ≤ SWS
Slide window this way when an ACK arrives • Sender actions – When an ACK arrives, moves LAR to the right, opening the window to allow the sender to send more frames – If a frame times out before an ACK arrives, retransmit
Sliding window on receiver • Maintains three window variables – Receive Window Size (RWS) – Largest Acceptable Frame (LAF) – Last frame received (LFR) • Invariant – LAF – LFR ≤ RWS
• When a frame with SeqNum arrives – Discards it if out of window • Seq ≤ LFR or Seq > LAF – If in window, decides what to ACK • Cumulative ack • Acks SeqNumToAck even if higher-numbered packets have been received • Sets LFR = SeqNumToAck-1, LAF = LFR + RWS • Updates SeqNumToAck
Finite sequence numbers • Things may go wrong when SWS=RWS, SWS too large • Example – 3-bit sequence number, SWS=RWS=7 – Sender sends 0, …, 6; receiver acks, expects (7,0, …, 5), but all acks lost – Sender retransmits 0,…,6; receiver thinks they are new • SWS < (MaxSeqNum+1)/2 – Alternates between first half and second half of sequence number space as stop-and-wait alternates between 0 and 1
Sliding window protocol (SWP) implementation typedef u_char SwpSeqno; typedef struct { SwpSeqno SeqNum; /* sequence number of this frame */ SwpSeqno AckNum; /* ack of received frame */ u_char Flags; /* up to 8 bits' worth of flags. An ack or data */ } SwpHdr; Your code will look very different!
typedef struct { /* sender side state: */ SwpSeqno LAR; /* seqno of last ACK received */ SwpSeqno LFS; /* last frame sent */ Semaphore sendWindowNotFull; SwpHdr hdr; /* preinitialized header */ struct sendQ_slot { Event timeout; /* event associated with send-timeout */ Msg msg; } sendQ[SWS]; /* receiver side state: */ SwpSeqno NFE; /* seqno of next frame expected */ struct recvQ_slot { int received; /* is msg valid? */ Msg msg; } recvQ[RWS]; } SwpState;
static int sendSWP(SwpState *state, Msg *frame) { struct sendQ_slot *slot; hbuf[HLEN]; /* wait for send window to open */ semWait(&state->sendWindowNotFull); state->hdr.SeqNum = ++state->LFS; slot = &state->sendQ[state->hdr.SeqNum % SWS]; store_swp_hdr(state->hdr, hbuf); msgAddHdr(frame, hbuf, HLEN); msgSaveCopy(&slot->msg, frame); slot->timeout = evSchedule(swpTimeout, slot, SWP_SEND_TIMEOUT); return sendLINK(frame); }
static int deliverSWP(SwpState state, Msg *frame) { SwpHdr hdr; char *hbuf; hbuf = msgStripHdr(frame, HLEN); load_swp_hdr(&hdr, hbuf) if (hdr->Flags & FLAG_ACK_VALID) { /* received an acknowledgment---do SENDER side */ if (swpInWindow(hdr.AckNum, state->LAR + 1, state->LFS)) { do { struct sendQ_slot *slot; slot = &state->sendQ[++state->LAR % SWS]; evCancel(slot->timeout); msgDestroy(&slot->msg); semSignal(&state->sendWindowNotFull); } while (state->LAR != hdr.AckNum); } }
if (hdr.Flags & FLAG_HAS_DATA) { struct recvQ_slot *slot; /* received data packet---do RECEIVER side */ slot = &state->recvQ[hdr.SeqNum % RWS]; if (!swpInWindow(hdr.SeqNum, state->NFE, state->NFE + RWS - 1)) { /* drop the message */ return SUCCESS; } msgSaveCopy(&slot->msg, frame); slot->received = TRUE; if (hdr.SeqNum == state->NFE) { Msg m; while (slot->received) { deliverHLP(&slot->msg); msgDestroy(&slot->msg); slot->received = FALSE; slot = &state->recvQ[++state->NFE % RWS]; } /* send ACK: */ prepare_ack(&m, state->NFE - 1); sendLINK(&m); msgDestroy(&m); }} return SUCCESS; }
static bool swpInWindow(SwpSeqno seqno, SwpSeqno min, SwpSeqno max) { SwpSeqno pos, maxpos; pos = seqno - min; /* pos *should* be in range [0..MAX)*/ maxpos = max - min + 1; /* maxpos is in range [0..MAX]*/ return pos < maxpos; }
Recommend
More recommend