TCP Congestion Window Size - tcp

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.

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.

Benefit of small TCP receive window?

I am trying to learn how TCP Flow Control works when I came across the concept of receive window.
My question is, why is the TCP receive window scale-able? Are there any advantages from implementing a small receive window size?
Because as I understand it, the larger the receive window size, the higher the throughput. While the smaller the receive window, the lower the throughput, since TCP will always wait until the allocated buffer is not full before sending more data. So doesn't it make sense to have the receive window at the maximum at all times to have maximum transfer rate?
My question is, why is the TCP receive window scale-able?
There are two questions there. Window scaling is the ability to multiply the scale by a power of 2 so you can have window sizes > 64k. However the rest of your question indicates that you are really asking why it is resizeable, to which the answer is 'so the application can choose its own receive window size'.
Are there any advantages from implementing a small receive window size?
Not really.
Because as I understand it, the larger the receive window size, the higher the throughput.
Correct, up to the bandwidth-delay product. Beyond that, increasing it has no effect.
While the smaller the receive window, the lower the throughput, since TCP will always wait until the allocated buffer is not full before sending more data. So doesn't it make sense to have the receive window at the maximum at all times to have maximum transfer rate?
Yes, up to the bandwidth-delay product (see above).
A small receive window ensures that when a packet loss is detected (which happens frequently on high collision network),
No it doesn't. Simulations show that if packet loss gets above a few %, TCP becomes unusable.
the sender will not need to resend a lot of packets.
It doesn't happen like that. There aren't any advantages to small window sizes except lower memory occupancy.
After much reading around, I think I might just have found an answer.
Throughput is not just a function of receive window. Both small and large receive windows have their own benefits and harms.
A small receive window ensures that when a packet loss is detected (which happens frequently on high collision network), the sender will not need to resend a lot of packets.
A large receive window ensures that the sender will not be idle a most of the time as it waits for the receiver to acknowledge that a packet has been received.
The receive window needs to be adjustable to get the optimal throughput for any given network.

TCP - difference between Congestion window and Receive window

I try to understand the difference between Congestion window and Receive window.
As I understand, the receiver window is a buffer where the receiver can get the packets. The same is with the Congestion window which tell us the bound of the Receiver's abilities, and change according to lost packets, etc.
So what is the diffrence between them?
To give a short answer: the receive window is managed by the receiver, who sends out window sizes to the sender. The window sizes announce the number of bytes still free in the receiver buffer, i.e. the number of bytes the sender can still send without needing an acknowledgement from the receiver.
The congestion window is a sender imposed window that was implemented to avoid overrunning some routers in the middle of the network path. The sender, with each segment sent, increases the congestion window slightly, i.e. the sender will allow itself more outstanding sent data. But if the sender detects packet loss, it will cut the window in half. The rationale behind this is that the sender assumes that packet loss has occurred because of a buffer overflow somewhere (which is almost always true), so the sender wants to keep less data "in flight" to avoid further packet loss in the future.
For more, start here: http://en.wikipedia.org/wiki/Slow-start
Initially, CongWindow is set equal to one packet. It then sends the first packet into the network and waits for an acknowledgment. If the acknowledgment for this packet arrives before the timer runs out, the sender increases CongWindow by one packet and sends out two packets. Once all of these packets are acknowledged before their timeouts, CongWindow is increased by two—one for each of the acknowledged segments. Now the size of CongWindow is four packets, and thus, the sender transmits four packets. Such an exponential increase continues as long as the size of CongWindow is below the threshold and acknowledgments are received before their corresponding timeouts expire.One important difference is that CongWindow changes in size but receive window size is always constant.

Resources