Chapter 3
Transport Layer

Computer Networking:
A Top Down Approach,

4th edition.
Jim Kurose, Keith Ross
Addison-Wesley, July
2007.
Principles of Reliable Data Transfer
• Important in application, transport, link layers
• Top-10 list of important networking topics!
Principles of Reliable Data Transfer (rdt)
• Important in application, transport, link layers
• Top-10 list of important networking topics!
Principles of Reliable Data Transfer
• Important in application, transport, link layers
• Top-10 list of important networking topics!
Reliable Data Transfer: Getting Started
rdt_send(): called from
above, (e.g., by app.). Passed data to
deliver to receiver upper layer

send
side

udt_send(): called by rdt
protocol, to transfer packet over
unreliable channel to receiver

deliver_data(): called by rdt
to deliver data to upper layer

receive
side

rdt_rcv(): called when packet
arrives on rcv-side of channel
Reliable Data Transfer: Getting Started
We’ll:
• Incrementally develop sender, receiver sides of
reliable data transfer protocol (rdt)
• Consider only unidirectional data transfer
– but control info will flow on both directions!

• Use Finite State Machines (FSM) to specify sender,
receiver
event causing state transition
actions taken on state transition
state: When in this “state”
next state uniquely
determined by next
event

state
1

event
actions

state
2
Rdt1.0: Reliable Data Transfer over a Perfectly
Reliable Channel
• Underlying channel perfectly reliable
– no bit errors
– no loss of packets

• Separate FSMs for sender, receiver:
– sender sends data into underlying channel
– receiver reads data from underlying channel

• The initial state of the FSM is indicated by the dashed line
Wait for
call from
above

rdt_send(data)
packet =make_pkt(data)
udt_send(packet)

Sender

Wait for
call from
below

rdt_rcv(packet)
extract (packet,data)
deliver_data(data)

Receiver

Note:Perfectly reliable channel no need for feedback
Rdt2.0: Channel with Bit Errors
• More realistic model
– Underlying channel may flip bits in packet

• How people deal with such a situation
– OK (positive acknowledgment)
– Please repeat that (negative acknowledgements)
– Acknowledgements (ACKs): Receiver explicitly tells sender that pkt
received OK
– Negative acknowledgements (NAKs): Receiver explicitly tells sender
that pkt had errors
– Sender retransmits pkt on receipt of NAK

• These control messages let the sender know
– What has been received in error and requires repetition

• Automatic Repeat reQuest (ARQ) protocols.
Rdt2.0: Channel with Bit Errors
Three capabilities are required in ARQ to handle the presence of bit
errors.
• Error Detection:
– Needed to allow the receiver to detect bit errors
– Checksum field in the header
• Receiver Feed Back
– Receiver provided explicit feedback
– ACK
– NAK
• Retransmission
– A packet that is received in error will be retransmitted
• New mechanisms in rdt2.0 (beyond rdt1.0):
– Error detection
– Receiver feedback: Control msgs (ACK,NAK) Rcvr->Sender
Rdt2.0: FSM Specification
rdt_send(data)
snkpkt = make_pkt(data, checksum)
udt_send(sndpkt)
rdt_rcv(rcvpkt) &&
isNAK(rcvpkt)
Wait for
call from
above

Wait for
ACK or
NAK

udt_send(sndpkt)

rdt_rcv(rcvpkt) && isACK(rcvpkt)

receiver
rdt_rcv(rcvpkt) &&
corrupt(rcvpkt)
udt_send(NAK)
Wait for call
from below

sender
rdt_rcv(rcvpkt) &&
notcorrupt(rcvpkt)
extract(rcvpkt,data)
deliver_data(data)
udt_send(ACK)
Rdt2.0: Operation with No Errors
rdt_send(data)
snkpkt = make_pkt(data, checksum)
udt_send(sndpkt)
rdt_rcv(rcvpkt) &&
isNAK(rcvpkt)

Wait for call
from above

Wait for
ACK or
NAK

udt_send(sndpkt)

rdt_rcv(rcvpkt) && isACK(rcvpkt)

rdt_rcv(rcvpkt) &&
corrupt(rcvpkt)
udt_send(NAK)
Wait for call
from below

rdt_rcv(rcvpkt) &&
notcorrupt(rcvpkt)
extract(rcvpkt,data)
deliver_data(data)
udt_send(ACK)
Rdt2.0: error scenario
rdt_send(data)
snkpkt = make_pkt(data, checksum)
udt_send(sndpkt)
rdt_rcv(rcvpkt) &&
isNAK(rcvpkt)
Wait for

Wait for call
from above

ACK or
NAK

udt_send(sndpkt)

rdt_rcv(rcvpkt) && isACK(rcvpkt)

rdt_rcv(rcvpkt) &&
corrupt(rcvpkt)
udt_send(NAK)
Wait for call
from below

rdt_rcv(rcvpkt) &&
notcorrupt(rcvpkt)
extract(rcvpkt,data)
deliver_data(data)
udt_send(ACK)
Rdt2.0
• rdt2.0 is a stop and wait protocol
– Sender sends one packet, then
waits for receiver response

• rdt2.0 has a fatal flaw
• What happens if ACK/NAK get
corrupted?
–

•

Add checksum bits to ACK/NAK

How the protocol should recover from
errors in ACK/NAK?
– Retransmission on receipt of a
corrupt ACK/NAK
– Retransmission causes duplicates

– Receiver does not know whether
ACK or NAK it sent was received
correctly
– Receiver does not know a priori
whether an arriving packet
contains new data or is a
retransmission

Handling Duplicates:
• Sender retransmits current
packet if ACK/NAK garbled
• Sender adds sequence number
to each packet
• Receiver discards (doesn’t
deliver up) duplicate packet
Rdt2.1: Sender, handles garbled ACK/NAKs
rdt_send(data)
sndpkt = make_pkt(0, data, checksum)
udt_send(sndpkt)

Wait for call
0 from
above

Wait for
ACK or NAK
0

rdt_rcv(rcvpkt)
&& notcorrupt(rcvpkt)
&& isACK(rcvpkt)

rdt_rcv(rcvpkt) &&
( corrupt(rcvpkt) ||
isNAK(rcvpkt) )
udt_send(sndpkt)

rdt_rcv(rcvpkt) &&
( corrupt(rcvpkt) ||
isNAK(rcvpkt) )
udt_send(sndpkt)

rdt_rcv(rcvpkt)
&& notcorrupt(rcvpkt)
&& isACK(rcvpkt)

Wait for
ACK or NAK
1

Wait for
call 1
from
above
rdt_send(data)

sndpkt = make_pkt(1, data, checksum)
udt_send(sndpkt)
Rdt2.1: Receiver, handles garbled ACK/NAKs
rdt_rcv(rcvpkt) && notcorrupt(rcvpkt)
&& has_seq0(rcvpkt)

rdt_rcv(rcvpkt) && (corrupt(rcvpkt))

extract(rcvpkt,data)
deliver_data(data)
sndpkt = make_pkt(ACK, chksum)
udt_send(sndpkt)
rdt_rcv(rcvpkt) && (corrupt(rcvpkt))

sndpkt = make_pkt(NAK, chksum)
udt_send(sndpkt)
rdt_rcv(rcvpkt) &&
not corrupt(rcvpkt) &&
has_seq1(rcvpkt)
sndpkt = make_pkt(ACK, chksum)
udt_send(sndpkt)

sndpkt = make_pkt(NAK, chksum)
udt_send(sndpkt)
Wait for
0 from
below

Wait for
1 from
below

rdt_rcv(rcvpkt) && notcorrupt(rcvpkt)
&& has_seq1(rcvpkt)
extract(rcvpkt,data)
deliver_data(data)
sndpkt = make_pkt(ACK, chksum)
udt_send(sndpkt)

rdt_rcv(rcvpkt) &&
not corrupt(rcvpkt) &&
has_seq0(rcvpkt)
sndpkt = make_pkt(ACK, chksum)
udt_send(sndpkt)
Rdt2.2: a NAK-free protocol
• Same functionality as rdt2.1, using ACKs only
• Instead of NAK, receiver sends ACK for last packet
received OK
– Receiver must explicitly include seq # of the
packet being ACKed
• Duplicate ACK at sender results in same action as
NAK: retransmit current packet
Rdt2.2: Sender, Receiver Fragments
rdt_send(data)

sndpkt = make_pkt(0, data, checksum)
rdt_rcv(rcvpkt) &&
udt_send(sndpkt)
( corrupt(rcvpkt) ||
Wait for
Wait for
isACK(rcvpkt,1) )
ACK

call 0 from
above

0

Sender FSM
Fragment
rdt_rcv(rcvpkt) &&
(corrupt(rcvpkt) ||
has_seq1(rcvpkt))
udt_send(sndpkt)

Wait for
0 from
below

udt_send(sndpkt)

rdt_rcv(rcvpkt)
&& notcorrupt(rcvpkt)
&& isACK(rcvpkt,0)

Receiver FSM
Fragment

rdt_rcv(rcvpkt) && notcorrupt(rcvpkt)
&& has_seq1(rcvpkt)
extract(rcvpkt,data)
deliver_data(data)
sndpkt = make_pkt(ACK,1, chksum)
udt_send(sndpkt)
Rdt3.0: Channels with Errors and Loss
New Assumption: Underlying channel can also lose packets
(data or ACKs)
 What to do when packet loss occurs?
 Retransmissions
 How to detect loss?
 Sender waits “reasonable” amount of time for ACK
 Must wait at least as long as RTT plus processing
delay.
 Retransmits if no ACK received in this time
 If packet (or ACK) just delayed (not lost):
 Retransmission will be duplicate, but use of sequence
numbers can handles this.
Rdt3.0: Channels with Errors and Loss
Implement a Retransmission mechanism using a
 count down timer
 Interrupts the sender after certain
amount of time

The sender will need to be able to:
Start the timer each time a packet is
sent
Respond to a timer interrupt
Stop the timer
Rdt3.0 Sender
rdt_send(data)

rdt_rcv(rcvpkt) &&
( corrupt(rcvpkt) ||
isACK(rcvpkt,1) )

sndpkt = make_pkt(0, data, checksum)
udt_send(sndpkt)
start_timer

rdt_rcv(rcvpkt)

Wait for
call 0 from
above
rdt_rcv(rcvpkt)
&& notcorrupt(rcvpkt)
&& isACK(rcvpkt,1)

rdt_rcv(rcvpkt) &&
( corrupt(rcvpkt) ||
isACK(rcvpkt,0) )

timeout
udt_send(sndpkt)
start_timer
rdt_rcv(rcvpkt)
&& notcorrupt(rcvpkt)
&& isACK(rcvpkt,0)
stop_timer

stop_timer

timeout
udt_send(sndpkt)
start_timer

Wait
for
ACK 0

Wait
for
ACK1

Wait for
call 1 from
above
rdt_send(data)
sndpkt = make_pkt(1, data, checksum)
udt_send(sndpkt)
start_timer

Rdt3.0 Receiver?

rdt_rcv(rcvpkt)
Pipelined Reliable Data Transfer
Protocols
 Rdt3.0 works, but performance is poor

 Poor Performance is due to the fact that

it is a stop and wait protocol


Poor utilization of the resource

 Solution

Sender is allowed to send multiple packets
without waiting for ACKs.
 Pipelining


Since many sender to receiver packets can be
visualized as filling a pipeline
Increase utilization
Pipelined Reliable Data Transfer Protocols
 Pipelining has the following consequences for

reliable data transfer
 Range of sequence numbers must be increased
 Sender and receiver sides may have to buffer
more than one packet.

 Two basic approaches towards pipeline error

recovery:

Go-Back-N, Selective Repeat
Go-Back-N (GBN)
Sender:
 Sender is allowed to transmit multiple packets without waiting

for an acknowledgement
 Constrained to a certain maximum number N.
 Base or send_base
 Sequence number of oldest unacknowledged packet
 Nextseqnum
 Sequence number of next packet to be sent
 The range of sequence numbers for transmitted but not
acknowledged packets can be viewed as a window of size N.
 This window slides forward as the protocol operates
Go-Back-N
GBN sender must respond to three types of events
 Invocation from above (rdt_send() is called):
 If window is full, returns data to upper layer
 Maintain synchronization mechanism
 Receipt of an ACK:
 ACK for packet with seq # n is taken as“Cumulative ACK”
 More shortly in receiver
 Time out event:
 Sender has timer for oldest unacknowledged packet
• If timer expires, retransmit all unacknowledged packets
Go-Back-N
Receiver:
 If a packet with seq # n is received correctly and is in
order


ACK is sent and data is delivered to upper layers

 For all other cases
 Receiver discards the packet and resends ACK for most
recently received in order packet
 Packets are delivered one at a time to upper layers
 If a packet k has been received and delivered, then all
packets with seq # lower than k have also been delivered.
 Receiver discards out of order packets
 No receiver buffering
 Need only remember expectedseqnum
GBN in
action

http://www.eecis.udel.edu/~amer/450/TransportApplets/GBN/GBNindex.html

Week4 lec2-bscs1

  • 1.
    Chapter 3 Transport Layer ComputerNetworking: A Top Down Approach, 4th edition. Jim Kurose, Keith Ross Addison-Wesley, July 2007.
  • 2.
    Principles of ReliableData Transfer • Important in application, transport, link layers • Top-10 list of important networking topics!
  • 3.
    Principles of ReliableData Transfer (rdt) • Important in application, transport, link layers • Top-10 list of important networking topics!
  • 4.
    Principles of ReliableData Transfer • Important in application, transport, link layers • Top-10 list of important networking topics!
  • 5.
    Reliable Data Transfer:Getting Started rdt_send(): called from above, (e.g., by app.). Passed data to deliver to receiver upper layer send side udt_send(): called by rdt protocol, to transfer packet over unreliable channel to receiver deliver_data(): called by rdt to deliver data to upper layer receive side rdt_rcv(): called when packet arrives on rcv-side of channel
  • 6.
    Reliable Data Transfer:Getting Started We’ll: • Incrementally develop sender, receiver sides of reliable data transfer protocol (rdt) • Consider only unidirectional data transfer – but control info will flow on both directions! • Use Finite State Machines (FSM) to specify sender, receiver event causing state transition actions taken on state transition state: When in this “state” next state uniquely determined by next event state 1 event actions state 2
  • 7.
    Rdt1.0: Reliable DataTransfer over a Perfectly Reliable Channel • Underlying channel perfectly reliable – no bit errors – no loss of packets • Separate FSMs for sender, receiver: – sender sends data into underlying channel – receiver reads data from underlying channel • The initial state of the FSM is indicated by the dashed line Wait for call from above rdt_send(data) packet =make_pkt(data) udt_send(packet) Sender Wait for call from below rdt_rcv(packet) extract (packet,data) deliver_data(data) Receiver Note:Perfectly reliable channel no need for feedback
  • 8.
    Rdt2.0: Channel withBit Errors • More realistic model – Underlying channel may flip bits in packet • How people deal with such a situation – OK (positive acknowledgment) – Please repeat that (negative acknowledgements) – Acknowledgements (ACKs): Receiver explicitly tells sender that pkt received OK – Negative acknowledgements (NAKs): Receiver explicitly tells sender that pkt had errors – Sender retransmits pkt on receipt of NAK • These control messages let the sender know – What has been received in error and requires repetition • Automatic Repeat reQuest (ARQ) protocols.
  • 9.
    Rdt2.0: Channel withBit Errors Three capabilities are required in ARQ to handle the presence of bit errors. • Error Detection: – Needed to allow the receiver to detect bit errors – Checksum field in the header • Receiver Feed Back – Receiver provided explicit feedback – ACK – NAK • Retransmission – A packet that is received in error will be retransmitted • New mechanisms in rdt2.0 (beyond rdt1.0): – Error detection – Receiver feedback: Control msgs (ACK,NAK) Rcvr->Sender
  • 10.
    Rdt2.0: FSM Specification rdt_send(data) snkpkt= make_pkt(data, checksum) udt_send(sndpkt) rdt_rcv(rcvpkt) && isNAK(rcvpkt) Wait for call from above Wait for ACK or NAK udt_send(sndpkt) rdt_rcv(rcvpkt) && isACK(rcvpkt) receiver rdt_rcv(rcvpkt) && corrupt(rcvpkt) udt_send(NAK) Wait for call from below sender rdt_rcv(rcvpkt) && notcorrupt(rcvpkt) extract(rcvpkt,data) deliver_data(data) udt_send(ACK)
  • 11.
    Rdt2.0: Operation withNo Errors rdt_send(data) snkpkt = make_pkt(data, checksum) udt_send(sndpkt) rdt_rcv(rcvpkt) && isNAK(rcvpkt) Wait for call from above Wait for ACK or NAK udt_send(sndpkt) rdt_rcv(rcvpkt) && isACK(rcvpkt) rdt_rcv(rcvpkt) && corrupt(rcvpkt) udt_send(NAK) Wait for call from below rdt_rcv(rcvpkt) && notcorrupt(rcvpkt) extract(rcvpkt,data) deliver_data(data) udt_send(ACK)
  • 12.
    Rdt2.0: error scenario rdt_send(data) snkpkt= make_pkt(data, checksum) udt_send(sndpkt) rdt_rcv(rcvpkt) && isNAK(rcvpkt) Wait for Wait for call from above ACK or NAK udt_send(sndpkt) rdt_rcv(rcvpkt) && isACK(rcvpkt) rdt_rcv(rcvpkt) && corrupt(rcvpkt) udt_send(NAK) Wait for call from below rdt_rcv(rcvpkt) && notcorrupt(rcvpkt) extract(rcvpkt,data) deliver_data(data) udt_send(ACK)
  • 13.
    Rdt2.0 • rdt2.0 isa stop and wait protocol – Sender sends one packet, then waits for receiver response • rdt2.0 has a fatal flaw • What happens if ACK/NAK get corrupted? – • Add checksum bits to ACK/NAK How the protocol should recover from errors in ACK/NAK? – Retransmission on receipt of a corrupt ACK/NAK – Retransmission causes duplicates – Receiver does not know whether ACK or NAK it sent was received correctly – Receiver does not know a priori whether an arriving packet contains new data or is a retransmission Handling Duplicates: • Sender retransmits current packet if ACK/NAK garbled • Sender adds sequence number to each packet • Receiver discards (doesn’t deliver up) duplicate packet
  • 14.
    Rdt2.1: Sender, handlesgarbled ACK/NAKs rdt_send(data) sndpkt = make_pkt(0, data, checksum) udt_send(sndpkt) Wait for call 0 from above Wait for ACK or NAK 0 rdt_rcv(rcvpkt) && notcorrupt(rcvpkt) && isACK(rcvpkt) rdt_rcv(rcvpkt) && ( corrupt(rcvpkt) || isNAK(rcvpkt) ) udt_send(sndpkt) rdt_rcv(rcvpkt) && ( corrupt(rcvpkt) || isNAK(rcvpkt) ) udt_send(sndpkt) rdt_rcv(rcvpkt) && notcorrupt(rcvpkt) && isACK(rcvpkt) Wait for ACK or NAK 1 Wait for call 1 from above rdt_send(data) sndpkt = make_pkt(1, data, checksum) udt_send(sndpkt)
  • 15.
    Rdt2.1: Receiver, handlesgarbled ACK/NAKs rdt_rcv(rcvpkt) && notcorrupt(rcvpkt) && has_seq0(rcvpkt) rdt_rcv(rcvpkt) && (corrupt(rcvpkt)) extract(rcvpkt,data) deliver_data(data) sndpkt = make_pkt(ACK, chksum) udt_send(sndpkt) rdt_rcv(rcvpkt) && (corrupt(rcvpkt)) sndpkt = make_pkt(NAK, chksum) udt_send(sndpkt) rdt_rcv(rcvpkt) && not corrupt(rcvpkt) && has_seq1(rcvpkt) sndpkt = make_pkt(ACK, chksum) udt_send(sndpkt) sndpkt = make_pkt(NAK, chksum) udt_send(sndpkt) Wait for 0 from below Wait for 1 from below rdt_rcv(rcvpkt) && notcorrupt(rcvpkt) && has_seq1(rcvpkt) extract(rcvpkt,data) deliver_data(data) sndpkt = make_pkt(ACK, chksum) udt_send(sndpkt) rdt_rcv(rcvpkt) && not corrupt(rcvpkt) && has_seq0(rcvpkt) sndpkt = make_pkt(ACK, chksum) udt_send(sndpkt)
  • 16.
    Rdt2.2: a NAK-freeprotocol • Same functionality as rdt2.1, using ACKs only • Instead of NAK, receiver sends ACK for last packet received OK – Receiver must explicitly include seq # of the packet being ACKed • Duplicate ACK at sender results in same action as NAK: retransmit current packet
  • 17.
    Rdt2.2: Sender, ReceiverFragments rdt_send(data) sndpkt = make_pkt(0, data, checksum) rdt_rcv(rcvpkt) && udt_send(sndpkt) ( corrupt(rcvpkt) || Wait for Wait for isACK(rcvpkt,1) ) ACK call 0 from above 0 Sender FSM Fragment rdt_rcv(rcvpkt) && (corrupt(rcvpkt) || has_seq1(rcvpkt)) udt_send(sndpkt) Wait for 0 from below udt_send(sndpkt) rdt_rcv(rcvpkt) && notcorrupt(rcvpkt) && isACK(rcvpkt,0) Receiver FSM Fragment rdt_rcv(rcvpkt) && notcorrupt(rcvpkt) && has_seq1(rcvpkt) extract(rcvpkt,data) deliver_data(data) sndpkt = make_pkt(ACK,1, chksum) udt_send(sndpkt)
  • 18.
    Rdt3.0: Channels withErrors and Loss New Assumption: Underlying channel can also lose packets (data or ACKs)  What to do when packet loss occurs?  Retransmissions  How to detect loss?  Sender waits “reasonable” amount of time for ACK  Must wait at least as long as RTT plus processing delay.  Retransmits if no ACK received in this time  If packet (or ACK) just delayed (not lost):  Retransmission will be duplicate, but use of sequence numbers can handles this.
  • 19.
    Rdt3.0: Channels withErrors and Loss Implement a Retransmission mechanism using a  count down timer  Interrupts the sender after certain amount of time The sender will need to be able to: Start the timer each time a packet is sent Respond to a timer interrupt Stop the timer
  • 20.
    Rdt3.0 Sender rdt_send(data) rdt_rcv(rcvpkt) && (corrupt(rcvpkt) || isACK(rcvpkt,1) ) sndpkt = make_pkt(0, data, checksum) udt_send(sndpkt) start_timer rdt_rcv(rcvpkt) Wait for call 0 from above rdt_rcv(rcvpkt) && notcorrupt(rcvpkt) && isACK(rcvpkt,1) rdt_rcv(rcvpkt) && ( corrupt(rcvpkt) || isACK(rcvpkt,0) ) timeout udt_send(sndpkt) start_timer rdt_rcv(rcvpkt) && notcorrupt(rcvpkt) && isACK(rcvpkt,0) stop_timer stop_timer timeout udt_send(sndpkt) start_timer Wait for ACK 0 Wait for ACK1 Wait for call 1 from above rdt_send(data) sndpkt = make_pkt(1, data, checksum) udt_send(sndpkt) start_timer Rdt3.0 Receiver? rdt_rcv(rcvpkt)
  • 21.
    Pipelined Reliable DataTransfer Protocols  Rdt3.0 works, but performance is poor  Poor Performance is due to the fact that it is a stop and wait protocol  Poor utilization of the resource  Solution Sender is allowed to send multiple packets without waiting for ACKs.  Pipelining  Since many sender to receiver packets can be visualized as filling a pipeline Increase utilization
  • 22.
    Pipelined Reliable DataTransfer Protocols  Pipelining has the following consequences for reliable data transfer  Range of sequence numbers must be increased  Sender and receiver sides may have to buffer more than one packet.  Two basic approaches towards pipeline error recovery: Go-Back-N, Selective Repeat
  • 23.
    Go-Back-N (GBN) Sender:  Senderis allowed to transmit multiple packets without waiting for an acknowledgement  Constrained to a certain maximum number N.  Base or send_base  Sequence number of oldest unacknowledged packet  Nextseqnum  Sequence number of next packet to be sent  The range of sequence numbers for transmitted but not acknowledged packets can be viewed as a window of size N.  This window slides forward as the protocol operates
  • 24.
    Go-Back-N GBN sender mustrespond to three types of events  Invocation from above (rdt_send() is called):  If window is full, returns data to upper layer  Maintain synchronization mechanism  Receipt of an ACK:  ACK for packet with seq # n is taken as“Cumulative ACK”  More shortly in receiver  Time out event:  Sender has timer for oldest unacknowledged packet • If timer expires, retransmit all unacknowledged packets
  • 25.
    Go-Back-N Receiver:  If apacket with seq # n is received correctly and is in order  ACK is sent and data is delivered to upper layers  For all other cases  Receiver discards the packet and resends ACK for most recently received in order packet  Packets are delivered one at a time to upper layers  If a packet k has been received and delivered, then all packets with seq # lower than k have also been delivered.  Receiver discards out of order packets  No receiver buffering  Need only remember expectedseqnum
  • 26.