Computer Networks
Sina Keshvadi
Fall 2021
University of Calgary
Lecture No. 14
Oct 08, 2021
Principles of Reliable Data Transfer (Part 1)
Transport Layer: 3-1
Today’s Agenda:
Principles of reliable data transfer
Transport Layer: 3-2
sending process
data
receiving process
data
reliable channel
application
transport
reliable service abstraction
Principles of reliable data transfer
Transport Layer: 3-3
sending process
data
receiving process
data
application
transport
reliable service implementation
unreliable channel
network
transport
sender-side of
reliable data transfer protocol
receiver-side
of reliable data transfer protocol
sending process
data
receiving process
data
reliable channel
application
transport
reliable service abstraction
Principles of reliable data transfer
Transport Layer: 3-4
sending process
data
receiving process
data
application
transport
reliable service implementation
unreliable channel
network
transport
sender-side of
reliable data transfer protocol
receiver-side
of reliable data transfer protocol
Complexity of reliable data transfer protocol will depend (strongly) on characteristics of unreliable channel (lose, corrupt, reorder data?)
Principles of reliable data transfer
Transport Layer: 3-5
sending process
data
receiving process
data
application
transport
reliable service implementation
unreliable channel
network
transport
sender-side of
reliable data transfer protocol
receiver-side
of reliable data transfer protocol
Sender, receiver do not know the “state” of each other, e.g., was a message received?
Reliable data transfer protocol (rdt): interfaces
Transport Layer: 3-6
sending process
data
receiving process
data
unreliable channel
sender-side
implementation of rdt reliable data transfer protocol
receiver-side
implementation of rdt reliable data transfer protocol
rdt_send()
udt_send()
rdt_rcv()
deliver_data()
data
Header
data
Header
rdt_send(): called from above, (e.g., by app.). Passed data to deliver to receiver upper layer
udt_send(): called by rdt
to transfer packet over
unreliable channel to receiver
rdt_rcv(): called when packet arrives on receiver side of channel
deliver_data(): called by rdt to deliver data to upper layer
Bi-directional communication over unreliable channel
data
packet
Reliable data transfer: getting started
Transport Layer: 3-7
We will:
state
1
state
2
event causing state transition
actions taken on state transition
state: when in this “state” next state uniquely determined by next event
event
actions
Transport Layer: 3-8
rdt1.0: reliable transfer over a reliable channel
Transport Layer: 3-9
packet = make_pkt(data)
udt_send(packet)
rdt_send(data)
extract (packet,data)
deliver_data(data)
rdt_rcv(packet)
Wait for call from below
receiver
sender
Wait for call from above
rdt2.0: channel with bit errors
Transport Layer: 3-10
How do humans recover from “errors” during conversation?
rdt2.0: channel with bit errors
Transport Layer: 3-11
stop and wait
sender sends one packet, then waits for receiver response
rdt2.0: FSM specifications
Transport Layer: 3-12
Wait for call from above
udt_send(sndpkt)
Wait for ACK or NAK
udt_send(NAK)
rdt_rcv(rcvpkt) && corrupt(rcvpkt)
Wait for call from below
extract(rcvpkt,data)
deliver_data(data)
udt_send(ACK)
rdt_rcv(rcvpkt) && notcorrupt(rcvpkt)
snkpkt = make_pkt(data, checksum)
udt_send(sndpkt)
rdt_send(data)
rdt_rcv(rcvpkt) && isACK(rcvpkt)
Λ
sender
receiver
rdt_rcv(rcvpkt) &&
isNAK(rcvpkt)
rdt2.0: FSM specification
Transport Layer: 3-13
Wait for call from above
udt_send(sndpkt)
Wait for ACK or NAK
udt_send(NAK)
rdt_rcv(rcvpkt) && corrupt(rcvpkt)
Wait for call from below
extract(rcvpkt,data)
deliver_data(data)
udt_send(ACK)
rdt_rcv(rcvpkt) && notcorrupt(rcvpkt)
snkpkt = make_pkt(data, checksum)
udt_send(sndpkt)
rdt_send(data)
rdt_rcv(rcvpkt) && isACK(rcvpkt)
Λ
sender
receiver
Note: “state” of receiver (did the receiver get my message correctly?) isn’t known to sender unless somehow communicated from receiver to sender
rdt_rcv(rcvpkt) &&
isNAK(rcvpkt)
isNAK(rcvpkt)
isACK(rcvpkt)
rdt2.0: operation with no errors
Transport Layer: 3-14
Wait for call from above
snkpkt = make_pkt(data, checksum)
udt_send(sndpkt)
udt_send(sndpkt)
udt_send(NAK)
Wait for ACK or NAK
Wait for call from below
rdt_send(data)
rdt_rcv(rcvpkt) && corrupt(rcvpkt)
rdt_rcv(rcvpkt) && isACK(rcvpkt)
Λ
extract(rcvpkt,data)
deliver_data(data)
udt_send(ACK)
rdt_rcv(rcvpkt) && notcorrupt(rcvpkt)
sender
receiver
rdt_rcv(rcvpkt) &&
isNAK(rcvpkt)
rdt2.0: corrupted packet scenario
Transport Layer: 3-15
Wait for call from above
snkpkt = make_pkt(data, checksum)
udt_send(sndpkt)
udt_send(sndpkt)
rdt_rcv(rcvpkt) &&
isNAK(rcvpkt)
Wait for ACK or NAK
Wait for call from below
rdt_send(data)
udt_send(NAK)
rdt_rcv(rcvpkt) && corrupt(rcvpkt)
extract(rcvpkt,data)
deliver_data(data)
udt_send(ACK)
rdt_rcv(rcvpkt) && notcorrupt(rcvpkt)
rdt_rcv(rcvpkt) && isACK(rcvpkt)
Λ
sender
receiver
rdt2.0 has a fatal flaw!
Transport Layer: 3-16
what happens if ACK/NAK corrupted?
handling duplicates:
stop and wait
sender sends one packet, then waits for receiver response
rdt2.1: sender, handling garbled ACK/NAKs
Transport Layer: 3-17
Wait for call 0 from above
Wait for ACK or NAK 0
sndpkt = make_pkt(0, data, checksum)
udt_send(sndpkt)
rdt_send(data)
udt_send(sndpkt)
rdt_rcv(rcvpkt) && (corrupt(rcvpkt) ||
isNAK(rcvpkt) )
sndpkt = make_pkt(1, data, checksum)
udt_send(sndpkt)
rdt_send(data)
udt_send(sndpkt)
rdt_rcv(rcvpkt)
&& (corrupt(rcvpkt) ||
isNAK(rcvpkt) )
Wait for
call 1 from above
Wait for ACK or NAK 1
rdt_rcv(rcvpkt)
&& notcorrupt(rcvpkt)
&& isACK(rcvpkt)
Λ
rdt_rcv(rcvpkt)
&& notcorrupt(rcvpkt) && isACK(rcvpkt)
Λ
rdt2.1: receiver, handling garbled ACK/NAKs
Transport Layer: 3-18
Wait for
0 from below
rdt_rcv(rcvpkt) && notcorrupt(rcvpkt)
&& has_seq1(rcvpkt)
extract(rcvpkt,data)
deliver_data(data)
sndpkt = make_pkt(ACK, chksum)
udt_send(sndpkt)
Wait for
1 from below
rdt_rcv(rcvpkt) && notcorrupt(rcvpkt)
&& has_seq0(rcvpkt)
extract(rcvpkt,data)
deliver_data(data)
sndpkt = make_pkt(ACK, chksum)
udt_send(sndpkt)
sndpkt = make_pkt(NAK, chksum)
udt_send(sndpkt)
rdt_rcv(rcvpkt) && (corrupt(rcvpkt)
rdt_rcv(rcvpkt) &&
not corrupt(rcvpkt) &&
has_seq0(rcvpkt)
sndpkt = make_pkt(ACK, chksum)
udt_send(sndpkt)
rdt_rcv(rcvpkt) &&
not corrupt(rcvpkt) &&
has_seq1(rcvpkt)
sndpkt = make_pkt(ACK, chksum)
udt_send(sndpkt)
rdt_rcv(rcvpkt) && (corrupt(rcvpkt)
sndpkt = make_pkt(NAK, chksum)
udt_send(sndpkt)
What do you call a running turkey?
Fast food :)
Transport Layer: 3-19
rdt2.1: discussion
Transport Layer: 3-20
sender:
receiver:
rdt2.2: a NAK-free protocol
Transport Layer: 3-21
As we will see, TCP uses this approach to be NAK-free
rdt2.2: sender, receiver fragments
Transport Layer: 3-24
Wait for call 0 from above
sndpkt = make_pkt(0, data, checksum)
udt_send(sndpkt)
rdt_send(data)
udt_send(sndpkt)
rdt_rcv(rcvpkt) &&
( corrupt(rcvpkt) ||
isACK(rcvpkt,1) )
rdt_rcv(rcvpkt)
&& notcorrupt(rcvpkt)
&& isACK(rcvpkt,0)
Wait for ACK
0
sender FSM
fragment
rdt_rcv(rcvpkt) && notcorrupt(rcvpkt)
&& has_seq1(rcvpkt)
extract(rcvpkt,data)
deliver_data(data)
sndpkt = make_pkt(ACK1, chksum)
udt_send(sndpkt)
Wait for
0 from below
rdt_rcv(rcvpkt) &&
(corrupt(rcvpkt) ||
has_seq1(rcvpkt))
udt_send(sndpkt)
receiver FSM
fragment
Λ
What do you call a running turkey?
Fast food :)
Transport Layer: 3-25