- Data Comm & Networks Home
- DCN - Overview
- DCN - What is Computer Network
- DCN - Uses of Computer Network
- DCN - Computer Network Types
- DCN - Network LAN Technologies
- DCN - Computer Network Models
- DCN - Computer Network Security
- DCN - Components
- DCN - Connectors
- DCN - Switches
- DCN - Repeaters
- DCN - Gateways
- DCN - Bridges
- DCN - Socket
- DCN - Network Interface Card
- DCN - NIC: Pros and Cons
- DCN - Network Hardware
- DCN - Network Port
- Computer Network Topologies
- DCN - Computer Network Topologies
- DCN - Point-to-point Topology
- DCN - Bus Topology
- DCN - Star Topology
- DCN - Ring Topology
- DCN - Mesh Topology
- DCN - Tree Topology
- DCN - Hybrid Topology
- Physical Layer
- DCN - Physical Layer Introduction
- DCN - Digital Transmission
- DCN - Analog Transmission
- DCN - Transmission media
- DCN - Wireless Transmission
- DCN - Transmission Impairments
- DCN - Multiplexing
- DCN - Network Switching
- DCN - Circuit Switching
- DCN - Packet Switching
- DCN - Message Switching
- Data Link Layer
- DCN - Data Link Layer Introduction
- DCN - Data Link Control & Protocols
- DCN - RMON
- DCN - Token Ring Network
- DCN - Hamming Code
- DCN - Byte Stuffing
- DCN - Channel Allocation
- DCN - MAC Address
- DCN - Address Resolution Protocol
- DCN - Cyclic Redundancy Checks
- DCN - Error Control
- DCN - Flow Control
- DCN - Framing
- DCN - Error Detection & Correction
- DCN - Error Correcting Codes
- DCN - Parity Bits
- Network Layer
- DCN - Network Layer Introduction
- DCN - Network Addressing
- DCN - Routing
- DCN - Routing Table
- DCN - Internetworking
- DCN - Network Layer Protocols
- DCN - Routing Information Protocol
- DCN - Border Gateway Protocol
- DCN - OSPF Protocol
- DCN - Network Address Translation
- DCN - Network Address Translation Types
- Transport Layer
- DCN - Transport Layer Introduction
- DCN - Transmission Control Protocol
- DCN - User Datagram Protocol
- DCN - Congestion Control
- DCN - Open Loop Congestion Control
- DCN - Closed Loop Congestion Control
- DCN - Congestion Control Algorithms
- DCN - Token Bucket Algorithm
- DCN - TCP Tahoe Algorithm
- DCN - TCP Reno Algorithm
- DCN - TCP New Reno Algorithm
- DCN - TCP BIC Algorithm
- DCN - TCP CUBIC Algorithm
- DCN - TCP Service Model
- DCN - TLS Handshake
- DCN - TCP Vs. UDP
- Application Layer
- DCN - Application Layer Introduction
- DCN - Client-Server Model
- DCN - Application Protocols
- DCN - Network Services
- DCN - Virtual Private Network
- DCN - Load Shedding
- DCN - Optimality Principle
- DCN - Service Primitives
- DCN - Services of Network Security
- DCN - Hypertext Transfer Protocol
- DCN - File Transfer Protocol
- DCN - Secure Socket Layer
- Network Protocols
- DCN - ALOHA Protocol
- DCN - Pure ALOHA Protocol
- DCN - Sliding Window Protocol
- DCN - Stop and Wait Protocol
- DCN - Link State Routing
- DCN - Link State Routing Protocol
- Network Algorithms
- DCN - Shortest Path Algorithm
- DCN - Routing Algorithm
- DCN - Leaky Bucket Algorithm
- Wireless Networks
- DCN - Wireless Networks
- DCN - Wireless LANs
- DCN - Wireless LAN & IEEE 802.11
- DCN - IEEE 802.11 Wireless LAN Standards
- DCN - IEEE 802.11 Networks
- Multiplexing
- DCN - Multiplexing & Its Types
- DCN - Time Division Multiplexing
- DCN - Synchronous TDM
- DCN - Asynchronous TDM
- DCN - Synchronous Vs. Asynchronous TDM
- DCN - Frequency Division Multiplexing
- DCN - TDM Vs. FDM
- DCN - Code Division Multiplexing
- DCN - Wavelength Division Multiplexing
- Miscellaneous
- DCN - Shortest Path Routing
- DCN - B-ISDN Reference Model
- DCN - Design Issues For Layers
- DCN - Selective-repeat ARQ
- DCN - Flooding
- DCN - E-Mail Format
- DCN - Cryptography
- DCN - Unicast, Broadcast, & Multicast
- DCN - Network Virtualization
- DCN - Flow Vs. Congestion Control
- DCN - Asynchronous Transfer Mode
- DCN - ATM Networks
- DCN - Synchronous Vs. Asynchronous Transmission
- DCN - Network Attacks
- DCN - WiMax
- DCN - Buffering
- DCN - Authentication
- DCN Useful Resources
- DCN - Quick Guide
- DCN - Useful Resources
- DCN - Discussion
TCP Reno Algorithm
TCP Reno algorithm is an improved congestion control algorithm by which TCP controls the amount of data that can be sent over a network for avoiding network congestion.
What is TCP Reno Algorithm?
TCP Reno is an improved version of the TCP Tahoe algorithm. One major feature of TCP Reno is its fast recovery phase from packet loss using 3 duplicate ACKs. When a packet loss occurs, it does not retransmitting all unacknowledged packets. It only retransmits the lost packets with new packets. This reduces the delays in data transmission and improves network throughput.
The primary aim of TCP Reno algorithm is to provide a fast and efficient data transfer over congested networks. It improves the throughput of network as it avoids restarting slow start phase on minor packet losses.
Characteristics of TCP Reno Algorithm
The characteristics of TCP Reno algorithm are mentioned below −
- It provides faster recovery from packet loss compared to TCP Tahoe.
- It distinguishes between timeout and duplicate ACKs.
- It is suitable for moderate to high-bandwidth networks.
- It maintains better throughput than TCP Tahoe.
Working of TCP Reno Algorithm
TCP Reno works in four main phases −
- Slow start − In slow start phase, the congestion window (cwnd) starts with a small value and then increases exponentially with each acknowledgment received. It keeps increasing until it reaches a threshold (ssthresh) or packet loss occurs.
- Congestion avoidance − It uses the AIMD (Additive Increase Multiplicative Decrease) method. Once the cwnd reaches the ssthresh, the congestion avoidance phase starts. In this phase, the cwnd increases linearly (earlier it was increasing exponentially) with each acknowledgment received.
- Fast retransmit − When three duplicate ACKs are received, it means that the packet has been lost. It then immediately retransmits the missing packet without waiting for a timeout.
- Fast recovery − After fast retransmit, it sets the ssthresh to half of the current cwnd and sets cwnd to ssthresh plus 3 MSS. Then it enters the congestion avoidance phase directly without entering slow start phase. It is the main improvement of TCP Reno over TCP Tahoe as TCP Tahoe would reset cwnd to 1 MSS. Here, if a timeout occurs, then cwnd is reset to 1 MSS and the slow start phase begins again.
The following image depicts how the TCP Reno algorithm works −
Here is an example based on the above working of TCP Reno algorithm. Initially, cwnd = 1 MSS, ssthresh = 8 MSS, and a packet loss occurs when cwnd = 9 MSS
1. Start in Slow Start, cwnd = 1 Receive ACK -> cwnd = 2 Receive ACK -> cwnd = 4 Receive ACK -> cwnd = 8 cwnd = ssthresh = 8 => stop exponential growth. 2. Congestion Avoidance Phase: cwnd = 8, increase slowly (approx +1 per RTT): cwnd = 9 3. Packet Loss at cwnd = 9 (3 duplicate ACKs) => New ssthresh = (cwnd / 2) = (9 / 2) = 4 => cwnd = ssthresh + 3 = 4 + 3 = 7 (Fast Recovery) 4. Lost packet gets acknowledged => Exit Fast Recovery => cwnd = ssthresh = 4 5. Continue in Congestion Avoidance cwnd = 4, increase slowly: cwnd = 5 cwnd = 5 -> cwnd = 6 => Continue from congestion avoidance.
Steps to Implement TCP Reno Algorithm
Here are the steps to implement TCP Reno algorithm −
- Set the cwnd = 1 MSS and initial value of ssthresh and the number of iterations.
- In Slow Start phase increase cwnd by 1 MSS for every ACK received.
- When cwnd reaches ssthresh, switch to Congestion Avoidance phase and increase cwnd slowly.
- On receiving 3 duplicate ACKs, trigger Fast Retransmit and Fast Recovery.
- Now, set ssthresh = cwnd / 2, set cwnd = ssthresh, and continue in Congestion Avoidance.
- On timeout, reset cwnd to 1 MSS and go back to Slow Start.
Code Implementation
Here is the code implementation of the above steps for TCP Reno algorithm in C++, Java, and python −
#include <iostream>
#include <algorithm>
using namespace std;
enum Phase
{
SLOW_START,
CONGESTION_AVOIDANCE,
FAST_RECOVERY
};
int main()
{
int maxRTT = 15; // total RTT rounds to simulate
int lossRound = 7; // a loss occurs in this round
// set true to simulate timeout
// false for triple duplicate ACKs
bool lossIsTimeout = false;
int cwnd = 1; // in MSS units
int ssthresh = 8; // initial slow start threshold
Phase phase = SLOW_START;
cout << "RTT\tPhase\t\tcwnd\tssthresh\n";
for (int r = 1; r <= maxRTT; ++r)
{
// Print current state at start of RTT
string ph = (phase == SLOW_START) ? "Slow Start" : (phase == CONGESTION_AVOIDANCE) ? "Cong Avoid"
: "Fast Recov";
cout << r << "\t" << ph << "\t" << cwnd << "\t" << ssthresh << "\n";
// Simulate loss event
if (r == lossRound)
{
if (lossIsTimeout)
{
// Timeout => go to slow start
ssthresh = max(cwnd / 2, 1);
cwnd = 1;
phase = SLOW_START;
cout << "=> Timeout detected: ssthresh=" << ssthresh
<< ", \n \t cwnd=" << cwnd << " (enter Slow Start)\n";
continue;
}
else
{
// Triple duplicate ACKs => Fast Recovery
ssthresh = max(cwnd / 2, 1);
// cwnd = ssthresh + 3
cwnd = ssthresh + 3;
phase = FAST_RECOVERY;
cout << "=> Triple duplicate ACKs: ssthresh=" << ssthresh
<< ", \n \t cwnd=" << cwnd << " (enter Fast Recovery)\n";
continue;
}
}
// In no loss
if (phase == SLOW_START)
{
// Exponential growth
cwnd = cwnd * 2;
if (cwnd >= ssthresh)
{
// Crossing ssthresh => move to congestion avoidance
phase = CONGESTION_AVOIDANCE;
}
}
else if (phase == CONGESTION_AVOIDANCE)
{
// Linear increase => cwnd += 1 MSS per RTT
cwnd = cwnd + 1;
}
else if (phase == FAST_RECOVERY)
{
cwnd = ssthresh;
phase = CONGESTION_AVOIDANCE;
cout << "=> New ACK received: exit Fast Recovery,"
<< "\n\tcwnd set to ssthresh=" << cwnd << "\n";
}
// keep values same
if (cwnd < 1)
cwnd = 1;
}
return 0;
}
The output of the above code is as follows −
RTT Phase cwnd ssthresh 1 Slow Start 1 8 2 Slow Start 2 8 3 Slow Start 4 8 4 Cong Avoid 8 8 5 Cong Avoid 9 8 6 Cong Avoid 10 8 7 Cong Avoid 11 8 => Triple duplicate ACKs: ssthresh=5, cwnd=8 (enter Fast Recovery) 8 Fast Recov 8 5 => New ACK received: exit Fast Recovery, cwnd set to ssthresh=5 9 Cong Avoid 5 5 10 Cong Avoid 6 5 11 Cong Avoid 7 5 12 Cong Avoid 8 5 13 Cong Avoid 9 5 14 Cong Avoid 10 5 15 Cong Avoid 11 5
public class Main {
enum Phase { SLOW_START, CONGESTION_AVOIDANCE, FAST_RECOVERY }
public static void main(String[] args) {
int maxRTT = 15; // total RTT rounds to run
int lossRound = 7; // a loss occurs in this round
// set true to simulate timeout
// false for triple duplicate ACKs
boolean lossIsTimeout = false;
int cwnd = 1;
int ssthresh = 8; // initial slow start threshold
Phase phase = Phase.SLOW_START;
System.out.println("RTT\tPhase\t\tcwnd\tssthresh");
for (int r = 1; r <= maxRTT; r++) {
String ph = (phase == Phase.SLOW_START) ? "Slow Start"
: (phase == Phase.CONGESTION_AVOIDANCE) ? "Cong Avoid" : "Fast Recov";
System.out.println(r + "\t" + ph + "\t" + cwnd + "\t" + ssthresh);
// Simulate loss event
if (r == lossRound) {
if (lossIsTimeout) {
// Timeout => go to slow start
ssthresh = Math.max(cwnd / 2, 1);
cwnd = 1;
phase = Phase.SLOW_START;
System.out.println("=> Timeout detected: ssthresh=" + ssthresh
+ ", \n \t cwnd=" + cwnd + " (enter Slow Start)");
continue;
} else {
// Triple duplicate ACKs => Fast Recovery
ssthresh = Math.max(cwnd / 2, 1);
// cwnd = ssthresh + 3
cwnd = ssthresh + 3;
phase = Phase.FAST_RECOVERY;
System.out.println("=> Triple duplicate ACKs: ssthresh=" + ssthresh
+ ", \n \t cwnd=" + cwnd + " (enter Fast Recovery)");
continue;
}
}
// In no loss
if (phase == Phase.SLOW_START) {
// Exponential growth
cwnd = cwnd * 2;
if (cwnd >= ssthresh) {
// Crossing ssthresh => move to congestion avoidance
phase = Phase.CONGESTION_AVOIDANCE;
}
} else if (phase == Phase.CONGESTION_AVOIDANCE) {
// Linear increase => cwnd += 1 MSS per RTT
cwnd = cwnd + 1;
} else if (phase == Phase.FAST_RECOVERY) {
cwnd = ssthresh;
phase = Phase.CONGESTION_AVOIDANCE;
System.out.println("=> New ACK received: exit Fast Recovery,"
+ "\n\tcwnd set to ssthresh=" + cwnd);
}
if (cwnd < 1)
cwnd = 1;
}
}
}
The output of the above code is as follows −
RTT Phase cwnd ssthresh 1 Slow Start 1 8 2 Slow Start 2 8 3 Slow Start 4 8 4 Cong Avoid 8 8 5 Cong Avoid 9 8 6 Cong Avoid 10 8 7 Cong Avoid 11 8 => Triple duplicate ACKs: ssthresh=5, cwnd=8 (enter Fast Recovery) 8 Fast Recov 8 5 => New ACK received: exit Fast Recovery, cwnd set to ssthresh=5 9 Cong Avoid 5 5 10 Cong Avoid 6 5 11 Cong Avoid 7 5 12 Cong Avoid 8 5 13 Cong Avoid 9 5 14 Cong Avoid 10 5 15 Cong Avoid 11 5
def simulate(max_rtt=15, loss_round=7, loss_is_timeout=False):
cwnd = 1
ssthresh = 8
phase = "SLOW_START" # "SLOW_START", "CONGESTION_AVOIDANCE", "FAST_RECOVERY"
print("RTT\tPhase\t\tcwnd\tssthresh")
for r in range(1, max_rtt + 1):
ph = "Slow Start" if phase == "SLOW_START" else ("Cong Avoid" if phase == "CONGESTION_AVOIDANCE" else "Fast Recov")
print(f"{r}\t{ph}\t{cwnd}\t{ssthresh}")
# In loss event
if r == loss_round:
if loss_is_timeout:
# Timeout => go to slow start
ssthresh = max(cwnd // 2, 1)
cwnd = 1
phase = "SLOW_START"
print(f"=> Timeout detected: ssthresh={ssthresh}, cwnd={cwnd} (enter Slow Start)")
continue
else:
# Triple duplicate ACKs => Fast Recovery
ssthresh = max(cwnd // 2, 1)
# cwnd = ssthresh + 3
cwnd = ssthresh + 3
phase = "FAST_RECOVERY"
print(f"=> Triple duplicate ACKs: ssthresh={ssthresh}, \n \t cwnd={cwnd} (enter Fast Recovery)")
continue
# In no loss
if phase == "SLOW_START":
# Exponential growth
cwnd = cwnd * 2
if cwnd >= ssthresh:
# crossing ssthresh => move to congestion avoidance
phase = "CONGESTION_AVOIDANCE"
elif phase == "CONGESTION_AVOIDANCE":
# Linear increase
cwnd = cwnd + 1
elif phase == "FAST_RECOVERY":
cwnd = ssthresh
phase = "CONGESTION_AVOIDANCE"
print(f"=> New ACK received: exit Fast Recovery,\n \t cwnd set to ssthresh={cwnd}")
if cwnd < 1:
cwnd = 1
if __name__ == "__main__":
simulate(max_rtt=15, loss_round=7, loss_is_timeout=False)
The output of the above code is as follows −
RTT Phase cwnd ssthresh 1 Slow Start 1 8 2 Slow Start 2 8 3 Slow Start 4 8 4 Cong Avoid 8 8 5 Cong Avoid 9 8 6 Cong Avoid 10 8 7 Cong Avoid 11 8 => Triple duplicate ACKs: ssthresh=5, cwnd=8 (enter Fast Recovery) 8 Fast Recov 8 5 => New ACK received: exit Fast Recovery, cwnd set to ssthresh=5 9 Cong Avoid 5 5 10 Cong Avoid 6 5 11 Cong Avoid 7 5 12 Cong Avoid 8 5 13 Cong Avoid 9 5 14 Cong Avoid 10 5 15 Cong Avoid 11 5
Pros and Cons of TCP Reno Algorithm
The following list highlights the advantages of TCP Reno algorithm −
- It provides better throughput than TCP Tahoe.
- It recovers faster from packet loss using fast recovery.
- It maintains higher network utilization.
- It is more efficient in handling isolated packet losses.
- It reduces the recovery time significantly.
Here are the limitations of TCP Reno algorithm −
- It cannot handle multiple packet losses in a single window.
- Its throughput decreases in a high loss networks.
Conclusion
TCP Reno is an improved congestion control algorithm that provides a reliable, ordered, and error-checked delivery of data packets with better performance than TCP Tahoe. In this chapter, we covered the features, working, implementation steps, code implementation, advantages, and limitations of the TCP Reno algorithm.