Open In App

Find the final size of Congestion Window in TCP Tahoe

Improve
Improve
Like Article
Like
Save
Share
Report

Given the initial congestion window size cwnd, threshold value ssthresh, connection time rtt and an array arr where arr[i] implies the time when a packet loss is detected. The task is to find the final congestion window size when all the packet drops are being encountered by the sender.

The TCP Tahoe follows below conditions:

  • The initial value of cwnd is 10.
  • Before reaching ssthresh, double cwnd per unit of time. By doubling the value, cwnd can’t cross ssthresh value, it can almost go up to ssthresh value.
  • After reaching ssthresh, increase cwnd by 1 per unit of time.
  • When there is packet loss, reduce the ssthresh to half of cwnd value (50%), reset cwnd to initial value of 10 and no other updation happens.
  • The connection will be active until rtt unit of time.

Examples:

Input arr[] = {16, 25}, ssthresh = 320, rtt = 28
Output: 80
Explanation:
Time = 0: cwnd = 10
Time = 1: cwnd = 20
Time = 2, 3, 4, 5: cwnd = 40, 80, 160, 320
cwnd=ssthresh at time=5, so now onwards cwnd increases by 1 per unit of time.
Time = 6-15: cwnd = 321-330
Time = 16: packet loss is detected, so ssthresh will become half of current cwnd value.
ssthresh = 330/2=165, cwnd = 10 (reseted), Note: cwnd is not increased by 1 or doubled in this case. 
Time = 17, cwnd = 20
Time = 18, cwnd = 40
Time = 19, cwnd = 80
Time = 20, cwnd = 160
Time = 21, cwnd = 165 {cwnd can’t get doubled because 320>165, it will cross the ssthresh. It can go max upto ssthresh}
Time = 22, cwnd = 166,  so now onwards cwnd increases by 1 per unit of time.
Time = 23, cwnd = 167
Time = 24, cwnd = 168,  
Time = 25:  packet loss is detected, so ssthresh will become half of current cwnd value, 
ssthresh = 168/2=84, cwnd=10 (reseted)
Time = 26: cwnd = 20
Time = 27, cwnd = 40
Time = 28, cwnd = 80
Final cwnd is = 80

Input arr[] = {12, 20, 31, 45}, ssthresh = 300, rtt = 50
Output: The final cwnd value is= 29
Explanation:
Time = 0: cwnd = 10
Time = 1: cwnd = 20
Time = 2, 3, 4: cwnd = 40, 80, 160
Time = 5: cwnd = 300 {cwnd can’t get doubled because 320>300, it will cross the ssthresh. It can go max upto ssthresh}
Time = 6-11: cwnd = 301-306
Time = 12: cwnd = 10 (reseted), and ssthresh = 306/2=153 {Packet loss}
Time = 13: cwnd = 20
Time = 14: cwnd = 40
Time = 15: cwnd = 80
Time = 16: cwnd = 153, {cwnd can’t get doubled because 160>153, it will cross the ssthresh. It can go max upto ssthresh}
Time = 17: cwnd = 154
Time = 18: cwnd = 155
Time = 19: cwnd = 156
Time = 20:  cwnd = 10 (reseted), ssthresh = 156/2 = 78   {Packet loss}
Time = 21: cwnd = 20
Time = 22: cwnd = 20
Time = 23: cwnd = 40
Time = 24: cwnd = 78, {cwnd can’t get doubled because 80>78, it will cross the ssthresh. It can go max upto ssthresh}
Time = 25-30: cwnd = (78+1=79) – (78+6=84) 
Time = 31: cwnd = 10 (reseted), ssthresh = 84/2 = 42   {Packet loss}
Time = 32: cwnd = 20
Time = 33, cwnd = 40
Time = 34, cwnd = 42, {cwnd can’t get doubled because 80>42, it will cross the ssthresh. It can go max upto ssthresh}
Time = 35-44: cwnd = 43 – 52
Time = 45: cwnd = 10 (reseted), ssthresh = 52/2 = 26   {Packet loss}
Time = 46: cwnd = 20
Time = 47: cwnd = 26 {cwnd can’t get doubled because 40>26, it will cross the ssthresh. It can go max upto ssthresh}
Time = 48-50: cwnd = 27-29
The final cwnd value is= 29

 

Approach: The idea is to keep all the constraints in mind and write the code to run in minimum time and space complexity.Follow below steps:

  • Traverse through all the time units when the connection is alive.
  • Store the next packet loss time in variable timeout
  • Check if the current time is equal to timeout. if it is, then reduce the ssthresh = cwnd/2 and reset cwnd to 10.
    • If cwnd is less than ssthresh, then double the cwnd value.
    • If by double of cwnd is greater than ssthresh then set cwnd=ssthresh.
    • If cwnd is greater than ssthresh then increment cwnd by 1 per time.
  • Return final cwnd value after the loop terminates.

Below is the implementation of the above approach.

C++




// C++ code to find the final size
// of congestion window in TCP TAHOE
 
#include <bits/stdc++.h>
using namespace std;
 
// TCP Tahoe Utility function
int tcpTahoeCongestionWindow(
    int initcwnd, int cwnd,
    int ssthresh, int rtt,
    vector<int> time)
{
    int ind = 0, timeout = time[ind];
    for (int t = 1; t <= rtt; t++) {
 
        // Packet loss occurs.
        // Reduce ssthresh to half of
        // current cwnd value.
        // Reset cwnd to 10
        if (t == timeout) {
            ssthresh = cwnd / 2;
            cwnd = initcwnd;
            timeout = time[++ind];
            continue;
        }
 
        // Threshold is not reached.
        // Keep doubling
        if (cwnd < ssthresh)
            cwnd = min(2 * cwnd,
                       ssthresh);
 
        // Threshold is reached.
        // Increase additively.
        else
            cwnd += 1;
    }
 
    // Return final cwnd value.
    return cwnd;
}
 
// Driver code
int main()
{
    int initcwnd = 10, cwnd = 10;
    int ssthresh = 300;
    int rtt = 50;
    vector<int> time{ 12, 20, 31, 45 };
 
    // Function call
    cwnd = tcpTahoeCongestionWindow(
        initcwnd, cwnd,
        ssthresh, rtt, time);
    cout << cwnd;
    return 0;
}


Java




import java.util.*;
 
public class Main {
    // TCP Tahoe Utility function
    static int tcpTahoeCongestionWindow(
        int initcwnd, int cwnd, int ssthresh, int rtt, ArrayList<Integer> time)
    {
        int ind = 0, timeout = time.get(ind);
        for (int t = 1; t <= rtt; t++) {
            // Packet loss occurs.
            // Reduce ssthresh to half of
            // current cwnd value.
            // Reset cwnd to 10
            if (t == timeout) {
                ssthresh = cwnd / 2;
                cwnd = initcwnd;
                if (ind + 1 < time.size()) {
                    timeout = time.get(++ind);
                }
                continue;
            }
 
            // Threshold is not reached.
            // Keep doubling
            if (cwnd < ssthresh) {
                cwnd = Math.min(2 * cwnd, ssthresh);
            }
 
            // Threshold is reached.
            // Increase additively.
            else {
                cwnd += 1;
            }
        }
 
        // Return final cwnd value.
        return cwnd;
    }
 
    // Driver code
    public static void main(String[] args) {
        int initcwnd = 10, cwnd = 10;
        int ssthresh = 300;
        int rtt = 50;
        ArrayList<Integer> time = new ArrayList<Integer>(Arrays.asList(12, 20, 31, 45));
 
        // Function call
        cwnd = tcpTahoeCongestionWindow(initcwnd, cwnd, ssthresh, rtt, time);
        System.out.println(cwnd);
    }
}


Python3




from typing import List
 
# TCP Tahoe Utility function
def tcpTahoeCongestionWindow(initcwnd, cwnd, ssthresh, rtt, time):
    ind = 0 # initialize ind to 0
    timeout = time[ind]
    for t in range(1, rtt+1):
 
        # Packet loss occurs.
        # Reduce ssthresh to half of
        # current cwnd value.
        # Reset cwnd to 10
        if t == timeout:
            ssthresh = cwnd // 2
            cwnd = initcwnd
            ind += 1
            timeout = time[ind] if ind < len(time) else float('inf')
            continue
 
        # Threshold is not reached.
        # Keep doubling
        if cwnd < ssthresh:
            cwnd = min(2 * cwnd, ssthresh)
 
        # Threshold is reached.
        # Increase additively.
        else:
            cwnd += 1
 
    # Return final cwnd value.
    return cwnd
 
# Driver code
if __name__ == '__main__':
    initcwnd = 10
    cwnd = 10
    ssthresh = 300
    rtt = 50
    time = [12, 20, 31, 45]
 
    # Function call
    cwnd = tcpTahoeCongestionWindow(initcwnd, cwnd, ssthresh, rtt, time)
    print(cwnd)


C#




using System;
using System.Collections.Generic;
 
namespace TCP_Tahoe_CongestionWindow
{
    class Program
    {
        static void Main(string[] args)
        {
            // TCP Tahoe Utility function
            int tcpTahoeCongestionWindow(
                int initcwnd, int cwnd,
                int ssthresh, int rtt,
                List<int> time)
            {
                int ind = 0, timeout = time[ind];
                for (int t = 1; t <= rtt; t++)
                {
                    // Packet loss occurs.
                    // Reduce ssthresh to half of
                    // current cwnd value.
                    // Reset cwnd to 10
                    if (t == timeout)
                    {
                        ssthresh = cwnd / 2;
                        cwnd = initcwnd;
                        timeout = time[++ind];
                        continue;
                    }
 
                    // Threshold is not reached.
                    // Keep doubling
                    if (cwnd < ssthresh)
                        cwnd = Math.Min(2 * cwnd, ssthresh);
 
                    // Threshold is reached.
                    // Increase additively.
                    else
                        cwnd += 1;
                }
 
                // Return final cwnd value.
                return cwnd;
            }
 
            // Driver code
            int initcwnd = 10, cwnd = 10;
            int ssthresh = 300;
            int rtt = 50;
            List<int> time = new List<int> { 12, 20, 31, 45 };
 
            // Function call
            cwnd = tcpTahoeCongestionWindow(
                initcwnd, cwnd,
                ssthresh, rtt, time);
            Console.WriteLine(cwnd);
            Console.ReadLine();
        }
    }
}


Javascript




<script>
    // JavaScript code for the above approach
 
    // TCP Tahoe Utility function
    function tcpTahoeCongestionWindow(
        initcwnd, cwnd,
        ssthresh, rtt,
        time) {
        let ind = 0, timeout = time[ind];
        for (let t = 1; t <= rtt; t++) {
 
            // Packet loss occurs.
            // Reduce ssthresh to half of
            // current cwnd value.
            // Reset cwnd to 10
            if (t == timeout) {
                ssthresh = Math.floor(cwnd / 2);
                cwnd = initcwnd;
                timeout = time[++ind];
                continue;
            }
 
            // Threshold is not reached.
            // Keep doubling
            if (cwnd < ssthresh)
                cwnd = Math.min(2 * cwnd,
                    ssthresh);
 
            // Threshold is reached.
            // Increase additively.
            else
                cwnd += 1;
        }
 
        // Return final cwnd value.
        return cwnd;
    }
 
    // Driver code
    let initcwnd = 10, cwnd = 10;
    let ssthresh = 300;
    let rtt = 50;
    let time = [12, 20, 31, 45];
 
    // Function call
    cwnd = tcpTahoeCongestionWindow(
        initcwnd, cwnd,
        ssthresh, rtt, time);
    document.write(cwnd);
 
 // This code is contributed by Potta Lokesh
</script>


Output

Final congestion window size = 29

Time complexity: O(N), N is the time of connection activeness.
Auxiliary Space: O(1) 



Last Updated : 27 Feb, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads