21

I have an application that receives relatively sparse traffic over TCP with no application-level responses. I believe the TCP stack is sending delayed ACKs (based on glancing at a network packet capture). What is the recommended way to disable delayed-ACK in the network stack for a single socket? I've looked at TCP_QUICKACK, but it seems that the stack will change it under my feet anyways.

This is running on a Linux 2.6 kernel, and I am not worried about portability.

Tom
  • 10,689
  • 4
  • 41
  • 50

3 Answers3

17

You could setsockopt(sockfd, IPPROTO_TCP, TCP_QUICKACK, (int[]){1}, sizeof(int)) after every recv you perform. It appears that TCP_QUICKACK is only reset when there is data being sent or received; if you're not sending any data, then it will only get reset when you receive data, in which case you can simply set it again.

You can check this in the 14th field of /proc/net/tcp; if it is not 1, ACKs should be sent immediately... if I'm reading the TCP code correctly. (I'm not an expert at this either.)

ephemient
  • 198,619
  • 38
  • 280
  • 391
  • I believe he has done that already based on his question and he says the value is being reset. – Nikolaos Oct 23 '09 at 20:02
  • Setting `TCP_QUICKACK` immediately sends an ACK if there is anything that needs to be ACK'ed, so I think this is sufficient. – ephemient Oct 23 '09 at 20:11
  • I am still `send()`ing on that socket. But as I said, I am not responding to messages I receive. I'll check out `/proc/net/tcp`. – Tom Oct 23 '09 at 23:34
  • Is it really the 14th field? See [here](https://askubuntu.com/questions/243435/not-able-to-understand-and-map-output-of-proc-net-tcp) and [the explanations of all fields in the kernel documentation](https://www.kernel.org/doc/Documentation/networking/proc_net_tcp.txt). Looks more like the 19th field to me. – nh2 Apr 13 '17 at 16:37
  • 1
    @nh2 That diagram counts `010310AC:9C4C` as two fields, while I was counting it as one and skipping the initial `46:` identifier. – ephemient Apr 13 '17 at 16:53
  • the 14th field of `/proc/net/tcp`...I assume you are talking about the `timeout` column on the 14th line? That's all zeroes for me so. – Alexander Mills Jun 02 '18 at 20:16
1

I believe using the setsockopt() function you can use the TCP_NODELAY which will disable the Nagle algorithm.

Edit Found a link: http://www.ibm.com/developerworks/linux/library/l-hisock.html

Edit 2 Tom is correct. Nagle does not affect Delayed ACKs.

Russ
  • 10,835
  • 12
  • 42
  • 57
CoryC
  • 469
  • 1
  • 6
  • 13
  • 5
    Disabling Nagle's algorithm won't impact delayed acknowledgements (at least, not on any implementation I know of). – Tom Sep 01 '10 at 02:46
  • No, disabling nagle impacts delayed ack, at least I can confirm in linux's very recent 3.17 kernel. – Timir Aug 28 '14 at 19:05
  • 1
    It depends on what do you mean "nagle does not impact Delayed ACKs"? They are independent options, that is true, but the combination of the two can have quite a big impact, which can cause unnecessary stalling in a TCP network, please read more, by Nagel himself - https://news.ycombinator.com/item?id=10608356 and here fora more formal discussion: https://www.extrahop.com/company/blog/2016/tcp-nodelay-nagle-quickack-best-practices/#2 – Mindaugas Bernatavičius Jan 07 '18 at 19:29
0

The accepted answer has a bug, it should be

flags = 0;
flglen = sizeof(flags);
setsockopt(sfd, SOL_TCP, TCP_QUICKACK, &flags, flglen)

(SOL_TCP, not IPPROTO_TCP)

Post here in case someone need it.

As @damolp suggested, it is not a bug. Keep it here for record.

Alt Eisen
  • 598
  • 6
  • 9
  • Both macros are actually the same value on linux [```SOL_TCP```](https://github.com/torvalds/linux/blob/6f0d349d922ba44e4348a17a78ea51b7135965b1/include/linux/socket.h#L309)[```IPPROTO_TCP```](https://github.com/torvalds/linux/blob/6f0d349d922ba44e4348a17a78ea51b7135965b1/include/uapi/linux/in.h#L37-L38). I wouldn't call this a bug, as the man page (```man tcp```) states ```call getsockopt(2) to read or setsockopt(2) to write the option with the option level argument set to IPPROTO_TCP```. – damolp Oct 08 '18 at 05:54