How to set ssthresh value in tcp - tcp

I am trying to start TCP slow start congestion algoritham in my raspberry device. As it documented in RFC 2581, it needs to set ssthresh value greater than the congestion window (cwnd). So I have chnaged /sys/module/tcp_cubic/parameters# sudo nano initial_ssthresh value to 65000 and cwnd was set to 10 ( checked with ss -i). After this settings I tried to send big packet from raspberry of size 19000 bytes. According to slow start it first needs to send to the destination device 2 packtes and then 4, then 8 ..etc.
But its not happening at raspberry. it sending me 10 packtes. Did I do something worng ?. In this case How can i start slow start algoritham.
Thanks

When CWND is less than ssthresh, the connection is in slowstart. When the CWND becomes greater than the ssthresh, the connection goes into congestion avoidance.
What you're seeing is that newer versions of linux have the initial congestion window set to 10. Before it was the default setting, you could change your initial congestion window from 3 through an ip route command. I haven't tried it, but I'm guessing you can do the opposite here.
Long story short, your machine is doing slow start. It is just starting with a larger initial congestion window.

Related

TCP avoid delayed acknowledge

I'm having an application on a micro controller with a small TCP/IP stack. This application waits for a connection on a specific TCP port. As soon as the TCP connection is established the micro controller need to send 8 KB of data. Because the TX buffer of the TCP socket is only 1 KB tall I will need to send 8 segments of data. The TX buffer size can't be changed!
But now I have the problem, that after every segment a delay of 200 ms occurs. I know that this is caused by the delayed ack (which is on Windows 200 ms). But in my use case this means the whole process includes 1400 ms of delay time, which is just wasted time.
Is there any possibility that I can force the PC to acknowledge the data instantly (maybe a bit in the TCP header)? I can't change anything on the PC side.
Or should I instead sent two 512 byte tall segments instead of the 1 KB segment? Would this fix / trick out the issue? I have read that the PC will acknowledge the data if a second segement arrives.
What is the right way to solve such a usecase?

TCP Connection window size

A 10 Mbps congested non-buffered link is used to send a huge file between two hosts. The receiving host has a large buffer than the congestion window. Assume the turnaround time is 100 ms, and the TCP Reno connection is always in congestion avoidance phase
what is the max window size (in segment) that this TCP connection can achieve?
Im using the formula W*MSS/RTT=10Mbps
I have RTT which is 100ms but im not sure where to get the MSS(maximum segment size) to be able to solve for W

TCP congestion window size in slow start phase

I have a question about the increasing rate of TCP sender's congestion window during the slow start phase.
Traditionally, the size of cwnd exponentially increases for every RTT. For instance, if the initial cwnd value is 1, it increases 2->4->8->16->.... .
In my case, since the sender uses linux kernel 3.5, the initial cwnd is 10.
I expected the cwnd increases as 10->20->40->... without delayed ACK (I turned it off at the receiver). However, when the receiver downloads a large size (over 1MB) of object from the sender over HTTP, cwnd increases as 10->12->19->29->.... I cannot understand this sequence.
I set RTT to 100ms and the link bandwidth is high enough. There is no loss during a session. I estimated the sender's cwnd by counting the number of packet the receiver received within one RTT.
Does anyone have idea for this behavior?
Thanks.
The dafault congestion control algorithm in kernel 3.5 is not TCP Reno, but CUBIC.
CUBIC has different behavior. It stems from BIC, and I know that CUBIC share slow start phase of BIC. Just see codes of BIC and CUBIC at /usr/src/yourkernelname/net/ipv4/tcp_cubic.c.
Moreover, delayed ack MAY result in such sequences. You know, 'traditional' TCP congestion control behavior is TCP reno without DACK nor SACK.
Know that even current TCP reno in Linux is not reno but new reno (reno with SACK).
Check the options of Delayed ack and Seletive ack using sysctl command.

Serial driver hw fifo overrun at 460800 baud rate

I am using 2.6.32 OMAP based linux kernel. I have observed that at high speed data rate (Serial port set to 460800 baud rate) serial port HW fifo overflow happens.
The serial port is configured to generate interrupt at every 8 bytes in rx and tx both direction (i.e when the serial port HW fifo is 8 byte full serial interrupt is generated which reads the data from the serial port at once).
I am transmitting 114 bytes packet continuously (Serial driver has no clue about the packet mode, it receives data in raw mode). Based on calculations,
460800 bits/sec => 460800/10 = 46080 bytes/sec (Where 1 stop bit and 1 start bit) so in 1 second I can transmit under worst case 46080/114 => 404.21 packets without any issue.
But, I expect the serial port to handle at least 1000 packets per second as such I have configured serial driver to generate interrupt every 8 bytes.
I tried the same using windows XP and I am able to read upto 600 packets / second.
Do you think this is feasible on linux under above circumstances? or I am missing something? Let me know your comments.
could someone also, send some important configuration settings that needs to be configured in .config file. I am unable to attach .config file otherwise, I can share it.
There are two kind of overflows that can occur for a serial port. The first one is the one you are talking about, the driver not responding to the interrupt fast enough to empty the FIFO. They are typically around 16 bytes deep so getting a fifo overflow requires the interrupt handler to be unresponsive for 1 / (46080 / 16) = 347 microseconds. That's a really, really long time. You have to have a pretty drastically screwed up driver with a higher priority interrupt to trip that.
The second kind is the one you didn't consider and offers more hope for a logical explanation. The driver copies the bytes from the fifo into a receive buffer. Where they will sit until the user mode program calls read() to read them. Getting an overflow on that buffer will happen when don't configure any kind of handshaking with the device and the user mode program is not calling read() often enough. It looks exactly like a fifo buffer overflow, bytes just disappear. There are status bits to warn about these problems but not checking them is a frequent oversight. You didn't mention doing that either.
So start by improving the diagnostics, do check the overflow status bits to know what's going on. Then do consider enabling handshaking if you find out that it is actually a buffer overflow issue. Increasing the buffer size is possible but not a solution if this is a fire-hose problem. Getting the user mode program to call read() more often is a fix but not an easy one. Just lowering the baud rate, yeah, that always works.

TCP Socket no connection timeout

I open a TCP socket and connect it to another socket somewhere else on the network. I can then successfully send and receive data. I have a timer that sends something to the socket every second.
I then rudely interrupt the connection by forcibly losing the connection (pulling out the Ethernet cable in this case). My socket is still reporting that it is successfully writing data out every second. This continues for approximately 1hour and 30 minutes, where a write error is eventually given.
What specifies this time-out where a socket finally accepts the other end has disappeared? Is it the OS (Ubuntu 11.04), is it from the TCP/IP specification, or is it a socket configuration option?
Pulling the network cable will not break a TCP connection(1) though it will disrupt communications. You can plug the cable back in and once IP connectivity is established, all back-data will move. This is what makes TCP reliable, even on cellular networks.
When TCP sends data, it expects an ACK in reply. If none comes within some amount of time, it re-transmits the data and waits again. The time it waits between transmissions generally increases exponentially.
After some number of retransmissions or some amount of total time with no ACK, TCP will consider the connection "broken". How many times or how long depends on your OS and its configuration but it typically times-out on the order of many minutes.
From Linux's tcp.7 man page:
tcp_retries2 (integer; default: 15; since Linux 2.2)
The maximum number of times a TCP packet is retransmitted in
established state before giving up. The default value is 15, which
corresponds to a duration of approximately between 13 to 30 minutes,
depending on the retransmission timeout. The RFC 1122 specified
minimum limit of 100 seconds is typically deemed too short.
This is likely the value you'll want to adjust to change how long it takes to detect if your connection has vanished.
(1) There are exceptions to this. The operating system, upon noticing a cable being removed, could notify upper layers that all connections should be considered "broken".
If want a quick socket error propagation to your application code, you may wanna try this socket option:
TCP_USER_TIMEOUT (since Linux 2.6.37)
This option takes an unsigned int as an argument. When the
value is greater than 0, it specifies the maximum amount of
time in milliseconds that transmitted data may remain
unacknowledged before TCP will forcibly close the
corresponding connection and return ETIMEDOUT to the
application. If the option value is specified as 0, TCP will
use the system default.
See full description on linux/man/tcp(7). This option is more flexible (you can set it on the fly, just right after a socket creation) than tcp_retries2 editing and exactly applies to a situation when you client's socket doesn't aware about server's one state and may get into so called half-closed state.
Two excellent answers are here and here.
TCP user timeout may work for your case: The TCP user timeout controls how long transmitted data may remain unacknowledged before a connection is forcefully closed.
there are 3 OS dependent TCP timeout parameters.
On Linux the defaults are:
tcp_keepalive_time default 7200 seconds
tcp_keepalive_probes default 9
tcp_keepalive_intvl default 75 sec
Total timeout time is tcp_keepalive_time + (tcp_keepalive_probes * tcp_keepalive_intvl), with these defaults 7200 + (9 * 75) = 7875 secs
To set these parameters on Linux:
sysctl -w net.ipv4.tcp_keepalive_time=1800 net.ipv4.tcp_keepalive_probes=3 net.ipv4.tcp_keepalive_intvl=20

Resources