Finding throughput from Congestion window - tcp

I am trying to understand TCP protocol with different simulation scenarios. I have to find out the throughput theoretically by just seeing the congestion window of the TCP.
Simulation scenario,
RTT= 100min (6000sec)
Data rate= 10Mbps
Loss=0;
MSS=1460bytes
SImulation Time= 11445005s
I got this congestion window after simulating. . The TCP is always in the Congestion Avoidance phase.
What I tried is to take the current maximum congestion window value which is in bytes and divide it by the RTT value which is 6000s. is it right? or do you have any suggestions? Please help.

Related

Why isn't cwnd restricted by rwnd in a TCP connection?

I'm trying to understand how TCP works and I'm a bit surprised by the (absence of) effect of the receiver window (rwnd) on the congestion window (cwnd).
From what I've read (mainly wikipedia and RFC5681) I understand that if the slow start threshold (ssthresh) has not been reached but the transmission rate is restricted by rwnd (since it is the minimum value between rwnd and cwnd) then cwnd continues to increase during the slow start phase (and even during congestion avoidance) if there are no loss or timeout. Meaning that cwnd could potentially reach a very high value since the initial value of ssthresh is extremely big.
See the following citation to confirm my deduction :
Implementation Note: An easy mistake to make is to simply use cwnd,
rather than FlightSize, which in some implementations may
incidentally increase well beyond rwnd.
[from RFC5681 (this part of the RFC is about setting a new value for ssthresh after a loss)]
In this case wouldn't it be possible to :
keep a connection with a relatively low transmission rate (e.g. setting rwnd to 10mss in every ack) to have no loss and hence keep the connection in the slow start phase,
wait enough time to allow cwnd to be extremely big (like 10 times what the link can handle) and then
set rwnd to an even bigger value to let the transmission rate be restricted only by cwnd ?
This would lead to a massive amount of congestion on the link, especially since it will take quite a lot of time for the server to notice the loss with a timeout and reset cwnd back to its initial value... and this may have a huge impact on other connections using the same link, or at least the same bottleneck link.
I would have imagined that once rcwnd is reached, slow start algorithm stops and congestion avoidance would begin to react to any new change in the network (or an increase in rwnd).
According to https://stackoverflow.com/a/21775731/20003316, Linux implementation of TCP does not allow cwnd to increase when the sending rate is application-controlled (= sending rate is controlled by rwnd and not cwnd).
By looking more in depth into this, I've found that in fact there is an RFC handling this question : https://www.rfc-editor.org/rfc/rfc7661#page-10
When in slow start :
if the number of ACK in the current window is smaller than 0.5*cwnd, then a TCP implementation must not increase the value of cwnd.
if the number of ACK in the current window is greater or equal than 0.5*cwnd, then a TCP implementation must increase the value of cwnd as it would normally do.
When not in slow start:
if the sending rate is restricted by rwnd and not cwnd and the number of ACK in the current window is smaller than 0.5*cwnd, then a TCP implementation must not increase cwnd.
otherwise proceed as usual

Stumbling on a Reliable UDP implementation

I received an assignment from the College where I have to implement a reliable transfer through UDP aka. TCP Over UDP (I know, reinvent the wheel since this has already been implemented on TCP) to know in deep how TCP works. Some of the requirements are: 3-Way Handshake, Congestion Control (TCP Tahoe, in particular) and Waved Hands. I think about doing this with Java or Python.
Some more specific requirements are:
After each ACK is received:
(Slow start) If CWND < SS-THRESH: CWND += 512
(Congestion Avoidance) If CWND >= SS-THRESH: CWND += (512 * 512) / CWND
After timeout, set SS-THRESH -> CWND / 2, CWND -> 512, and retransmit data after the last acknowledged byte.
I couldn't find more specific information about the TCP Tahoe implementation. But from what I understand, TCP Tahoe is based on Go-Back-N, so I found the following pseudo algorithm for sender and receiver:
My question is the Slow Start and Congestion Avoidance phase should happen right after if sendbase == nextseqnum? That is, right after confirming the receipt of an expected ACK?
My other question is about the Window Size, Go-Back-N uses a fixed window whereas TCP Tahoe uses a dynamic window. How can I calculate window size based on cwnd?
Note: your pictures are unreadable, please provide a higher resolution images
I don't think that algorithm is correct. A timer should be associated with each packet and stopped when ACK for this packet is received. Congestion control is triggered when the timer for any of the packets fires.
TCP is not exactly Go-Back-N receiver. In TCP receiver has a buffer too. This does not require any changes at the sender Go-Back-N. However, TCP is also supposed to implement flow control, in which the receiver tells the sender how much space in its buffer remains, and the sender adjusts its window accordingly.
Note, that Go-Back-N sequence number count packets, and TCP sequence numbers count bytes in the packets, you have to change your algorithm accordingly.
I would advice to get somewhat familiar with rfc793. It does not have congestion control, but it specifies how other TCP mechanics is supposed to work. Also this link has a nice illustration of TCP window and all variables associated with it.
My question is the Slow Start and Congestion Avoidance phase should happen right after if sendbase == nextseqnum? That is, right after confirming the receipt of an expected ACK?
your algorithm only does something when it receives ACK for the last packet. As I said, this is incorrect.
Regardless. Every ACK that acknowledges new packet shoult trigger window increase. You can do check this by checking if send_base was increased as the result of an ACK.
Dunno if every Tahoe implementation does this, but you may need this also. After three consequtive duplicate ACKs, i.e., ACKs that do not increase send_base you trigger congestion response.
My other question is about the Window Size, Go-Back-N uses a fixed window whereas TCP Tahoe uses a dynamic window. How can I calculate window size based on cwnd?
you make the N variable instead of constant, and assign congestion window to it.
in a real TCP with flow control you do N = min (cwnd, receiver_window).

How to increase TCP bandwidth in Iperf

In IPERF we have a option to increase the target bandwidth with the option "-b 100m" but in TCP i dont see a option in both JPERF 2.0.2 and also in cli command. Please let me know how can i increase the bandwidth for my throughput testing since i can only receive the traffic at a rate of 20mbps .
Try setting the TCP window with -w. Multiply your desired throughput by the latency to get a starting point for the window value. If you wanted to get 50mbps on a link with 40ms rtt:
50000000 * .04 = 2000000 bytes
For TCP, you cannot set target bandwidth. As for TCP, its sending rate is regulated by flow and congestion control which is determined by RTT and loss. For example, in slow-start phase, the sender can send double number of packets every RTT. In congestion-avoidance state, the congestion window size will be cut by half (or 1/3 in TCP Cubic) once a loss detected.
However, -w can set the sending/receiving window size. If your window size is too small, the total throughput may be bottle-necked by it. So, usually try a large window size, e.g. 65535. Remember a large window size just makes sure your TCP rate would not be bottle-necked by window size, it does not "guarantee" a large throughput.

TCP Congestion Window Size

I'm going through some revision and I've been stumped by a TCP question. Maybe someone can give me a quick hint or push in the right direction, just so I can get passed this section.
"Why does the sending entity in TCP need to consider the size of the congestion window when determining the sliding window size? "
"Why does the sending entity in TCP need to consider the size of the congestion window when determining the sliding window size? "
This is because the size of the congestion window represents the possible congestion in the network. This is one of the key features offered by TCP. This window is updated in three stages.
In the first stage, when TCP starts, it starts with congestion windows as 1 MSS (Max Segment Size) and then ramps it up in a slow-start manner. TCP sender starts with this value because it is "estimating" how many packets it can send in the network. This phase is also known as slow-start phase. Btw, even though it is called slow-start, TCP increases the packet by doubling the congestion window and the increase happens upon reception of ACKs.
In the second stage, when the congestion window reaches slow-start (ss) threshold (yep, there is one!), TCP sender grows its cogestion window additively -- this is congestion avoidance phase. Here, the sender becomes more cautious. Once again, the increase happens upon reception of ACKs.
In the third stage, when a packet is dropped (one reason would be that a retransmission timeout happened), then TCP cuts its congestion window back to 1 MSS and restarts to grow it again. This is done because a likely congestion was encountered and so cutting back the congestion window would likely freeup the congestion situation along the path. Unlike other stages, the decrease happens due to lack of reception of ACKs.
TCP can use sliding window method to regulate the packets which need to be sent to the receiver. The receiver can also preserve a sliding window to keep track of which packets have been received and which have acked. When determining the sliding window size at the sender side, we should take the congestion window size into account, as we don't want to overwhelm the network channel. The actual traffic in the network is min{awnd,cwnd}, where awnd is the window size which is advertised by the receiver to the receiver, cwnd stands for the congestion window size, whose maximum value will change according to the network condition.

What is the maximum window size in segments of a TCP connection?

Consider a single TCP (Reno) connection that uses a 10 Mbps link.
Assume this link does not buffer data and that the receiver's receive buffer is much larger than the congestion window.
Let each TCP segment be of size 1500 bytes and the two-way propagation delay of the connection between sender and receiver be 200 msec.
Also, assume that the TCP connection is always in congestion avoidance phase (ignore slow start).
What is the maximum window size in segments that this TCP connection can achieve?
So we know the throughput of the connection and the delay,
I think we can should be able to manipulate the following formula so that we are able to find the Window Size.
Throughput = Window Size / RTT
Throughput * RTT = Window Size
10 Mbps * 200 msec = Window Size
I am not sure if this is correct. I am having a hard time finding anything else that relates in finding Window Size other than this formula.
The Maximum windows size in terms of segments can be up to 2^30/ MSS, where MSS is the maximum segment size. The 2^30 = (2^16*2^14) comes through this as Michael mentioned you in his answer. If your network bandwidth and delay product exceeds than the TCP receiver window size than the window scaling option is enabled for the TCP connection and most OS support this features. The scaling supports up to 14-bit multiplicative shift for the window size. You can read following for the better explanation:
http://en.wikipedia.org/wiki/TCP_window_scale_option
http://www.ietf.org/rfc/rfc1323.txt
I think what you are asking is how data can I get end to end on the wire. In that case you are close. Throughput*RTT [units: B/S * S] is how much the wire holds. Ignoring PMTU, packet overhead, hardware encoding, etc. then Throughput*RTT/PacketSize would give you the estimate. But hold on, I used RTT. My receive window is really about how much can fit on the wire in one direction so divide that in half.
If your implementation doesn't support window scaling then min that with 2^16. If it does then you min it with 2^30.
A packets will be dropped if the maximum sending rate exceeds link capacity
(max window size*size of 1 segment) / RTT = link capacity
(max window size * 1500*8) / 200*10^-3 = 10 * 10^-6
you can solve this for max window size.
We divide by the RTT because after this time an ACK will be received so the sender can send more segments without the need to increase the window size.

Resources