- 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 New Reno Algorithm
TCP New Reno is an improved version of the TCP Reno algorithm. It has extended fast recovery phase that can handle multiple packet losses within a single window. TCP Reno suffered from the disadvantage that it could handle only single packet loss in the same window.
On multiple packet losses, TCP New Reno does not exit fast recovery phase after retransmitting single lost packet. It identifies and retransmits all the lost packets in the same window before returning to the congestion avoidance phase using partial acknowledgments (partial ACKs). It reduces the data transmission delay.
Characteristics of TCP New Reno Algorithm
The characteristics of TCP New Reno algorithm are mentioned below −
- It handles multiple packet losses within a single window efficiently.
- It uses partial acknowledgments to detect additional lost packets.
- It maintains fast recovery until all packets are acknowledged.
- It provides better throughput than TCP Reno in lossy networks.
Working of TCP New Reno Algorithm
TCP New Reno works in four main phases −
Slow Start Phase
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 Phase
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 Phase
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 Phase
- After fast retransmit, it sets the ssthresh to half of the current cwnd and sets cwnd to ssthresh plus 3 MSS. TCP New Reno remains in fast recovery and monitors incoming acknowledgments.
- If a partial ACK is received, it indicates another lost packet in the same window. TCP New Reno retransmits the next unacknowledged packet and remains in fast recovery. It only exits fast recovery when a full ACK is received.
- This is the main improvement of TCP New Reno over TCP Reno, which would exit fast recovery on the first new ACK. 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 New Reno algorithm works −
Example
Here is an example based on the above working of TCP New Reno algorithm. Initially, cwnd = 1 MSS, ssthresh = 8 MSS, and multiple packet losses occur when cwnd = 10 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 cwnd = 9 -> cwnd = 10 3. Multiple Packet Losses at cwnd = 10 (3 duplicate ACKs) => New ssthresh = (cwnd / 2) = (10 / 2) = 5 => cwnd = ssthresh + 3 = 5 + 3 = 8 (Fast Recovery) => Retransmit first lost packet 4. Partial ACK received (not all packets acknowledged) => Another packet lost, retransmit next lost packet => Remain in Fast Recovery 5. Full ACK received (all packets acknowledged) => Exit Fast Recovery => cwnd = ssthresh = 5 6. Continue in Congestion Avoidance cwnd = 5, increase slowly: cwnd = 6 cwnd = 6 -> cwnd = 7 => Continue from congestion avoidance.
Steps to Implement TCP New Reno Algorithm
Here are the steps to implement TCP New 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.
- Set ssthresh = cwnd / 2, set cwnd = ssthresh + 3, and enter Fast Recovery.
- While in Fast Recovery, check for partial ACKs and retransmit next lost packet if detected.
- Exit Fast Recovery only when full ACK is received, then set cwnd = ssthresh.
- 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 New 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 = 18; // total RTT rounds to simulate
int lossRound = 7; // first loss occurs in this round
int partialAckRound = 8; // partial ACK received in this round
int fullAckRound = 9; // full ACK received 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
int recoverPoint = 0; // highest seq sent before entering fast recovery
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);
recoverPoint = cwnd; // mark recovery point
cwnd = ssthresh + 3;
phase = FAST_RECOVERY;
cout << "=> Triple duplicate ACKs: ssthresh=" << ssthresh
<< ", \n \t cwnd=" << cwnd << " (enter Fast Recovery)\n";
cout << "=> Retransmit first lost packet\n";
continue;
}
}
// Simulate partial ACK in Fast Recovery
if (r == partialAckRound && phase == FAST_RECOVERY)
{
cout << "=> Partial ACK received (multiple losses detected)\n";
cout << "=> Retransmit next lost packet, remain in Fast Recovery\n";
continue;
}
// Simulate full ACK to exit Fast Recovery
if (r == fullAckRound && phase == FAST_RECOVERY)
{
cwnd = ssthresh;
phase = CONGESTION_AVOIDANCE;
cout << "=> Full ACK received: exit Fast Recovery,"
<< "\n\tcwnd set to ssthresh=" << cwnd << "\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)
{
// Stay in fast recovery, inflate cwnd for each duplicate ACK
cwnd = cwnd + 1;
}
// 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) => Retransmit first lost packet 8 Fast Recov 8 5 => Partial ACK received (multiple losses detected) => Retransmit next lost packet, remain in Fast Recovery 9 Fast Recov 8 5 => Full ACK received: exit Fast Recovery, cwnd set to ssthresh=5 10 Cong Avoid 5 5 11 Cong Avoid 6 5 12 Cong Avoid 7 5 13 Cong Avoid 8 5 14 Cong Avoid 9 5 15 Cong Avoid 10 5 16 Cong Avoid 11 5 17 Cong Avoid 12 5 18 Cong Avoid 13 5
public class Main {
enum Phase { SLOW_START, CONGESTION_AVOIDANCE, FAST_RECOVERY }
public static void main(String[] args) {
int maxRTT = 18; // total RTT rounds to run
int lossRound = 7; // first loss occurs in this round
int partialAckRound = 8; // partial ACK received in this round
int fullAckRound = 9; // full ACK received 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
int recoverPoint = 0; // highest seq sent before entering fast recovery
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);
recoverPoint = cwnd; // mark recovery point
cwnd = ssthresh + 3;
phase = Phase.FAST_RECOVERY;
System.out.println("=> Triple duplicate ACKs: ssthresh=" + ssthresh
+ ", \n \t cwnd=" + cwnd + " (enter Fast Recovery)");
System.out.println("=> Retransmit first lost packet");
continue;
}
}
// Simulate partial ACK in Fast Recovery
if (r == partialAckRound && phase == Phase.FAST_RECOVERY) {
System.out.println("=> Partial ACK received (multiple losses detected)");
System.out.println("=> Retransmit next lost packet, remain in Fast Recovery");
continue;
}
// Simulate full ACK to exit Fast Recovery
if (r == fullAckRound && phase == Phase.FAST_RECOVERY) {
cwnd = ssthresh;
phase = Phase.CONGESTION_AVOIDANCE;
System.out.println("=> Full ACK received: exit Fast Recovery,"
+ "\n\tcwnd set to ssthresh=" + cwnd);
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) {
// Stay in fast recovery, inflate cwnd for each duplicate ACK
cwnd = cwnd + 1;
}
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) => Retransmit first lost packet 8 Fast Recov 8 5 => Partial ACK received (multiple losses detected) => Retransmit next lost packet, remain in Fast Recovery 9 Fast Recov 8 5 => Full ACK received: exit Fast Recovery, cwnd set to ssthresh=5 10 Cong Avoid 5 5 11 Cong Avoid 6 5 12 Cong Avoid 7 5 13 Cong Avoid 8 5 14 Cong Avoid 9 5 15 Cong Avoid 10 5 16 Cong Avoid 11 5 17 Cong Avoid 12 5 18 Cong Avoid 13 5
def simulate(max_rtt=18, loss_round=7, partial_ack_round=8, full_ack_round=9, loss_is_timeout=False):
cwnd = 1
ssthresh = 8
recover_point = 0 # highest seq sent before entering fast recovery
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)
recover_point = cwnd # mark recovery point
cwnd = ssthresh + 3
phase = "FAST_RECOVERY"
print(f"=> Triple duplicate ACKs: ssthresh={ssthresh}, \n \t cwnd={cwnd} (enter Fast Recovery)")
print("=> Retransmit first lost packet")
continue
# Simulate partial ACK in Fast Recovery
if r == partial_ack_round and phase == "FAST_RECOVERY":
print("=> Partial ACK received (multiple losses detected)")
print("=> Retransmit next lost packet, remain in Fast Recovery")
continue
# Simulate full ACK to exit Fast Recovery
if r == full_ack_round and phase == "FAST_RECOVERY":
cwnd = ssthresh
phase = "CONGESTION_AVOIDANCE"
print(f"=> Full ACK received: exit Fast Recovery,\n \t cwnd set to ssthresh={cwnd}")
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":
# Stay in fast recovery, inflate cwnd for each duplicate ACK
cwnd = cwnd + 1
if cwnd < 1:
cwnd = 1
if __name__ == "__main__":
simulate(max_rtt=18, loss_round=7, partial_ack_round=8, full_ack_round=9, 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) => Retransmit first lost packet 8 Fast Recov 8 5 => Partial ACK received (multiple losses detected) => Retransmit next lost packet, remain in Fast Recovery 9 Fast Recov 8 5 => Full ACK received: exit Fast Recovery, cwnd set to ssthresh=5 10 Cong Avoid 5 5 11 Cong Avoid 6 5 12 Cong Avoid 7 5 13 Cong Avoid 8 5 14 Cong Avoid 9 5 15 Cong Avoid 10 5 16 Cong Avoid 11 5 17 Cong Avoid 12 5 18 Cong Avoid 13 5
Pros and Cons of TCP New Reno Algorithm
The advantages of TCP New Reno algorithm are as follows −
- It handles multiple packet losses efficiently within a single window.
- It provides better throughput than TCP Reno in lossy networks.
- It avoids multiple reductions of congestion window for losses in the same window.
- It maintains higher network utilization during recovery.
- It reduces unnecessary slow start invocations.
Here are the limitations of TCP New Reno algorithm −
- It still performs poorly when many packets are lost in a single window.
- Slow recovery when too many packets are lost.
- Complex to implement.
Difference between TCP Reno and New Reno Algorithm
The following table highlights the major differences between TCP Reno and New Reno algorithms −
| TCP Reno Algorithm | TCP New Reno Algorithm |
|---|---|
| It can only handle a single packet loss in same window. | It can handles multiple packet losses in a single window. |
| Simple to implement. | It is more complex than TCP reno. |
| It exits the fast recovery phase on receiving the first new ACK, even if other packets are still lost in the same window. | It remains in fast recovery phase until all packets in the window are acknowledged. It uses partial ACKs to find packet losses. |
| It may enter slow start phase multiple times even for losses in the same window. | It remains in fast recovery phase and avoids entering slow start phase multiple times. |
| Less throughput. | Higher throughput than TCP Reno. |
Conclusion
TCP New Reno is an improved congestion control algorithm that provides a reliable, ordered, and error-checked delivery of data packets with better performance than TCP Reno. The most important feature of TCP New Reno is its enhanced fast recovery phase that can handle multiple packet losses in a single window using partial acknowledgments.