15
votes

Since Kernel 3.14 I see there is another TCP optimization called tcp_autocorking.

What is the actual difference between tcp_cork and tcp_autocorking?

Is it just an automated version of tcp_cork? I couldnĀ“t find any valuable information except this link:

http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=f54b311142a92ea2e42598e347b84e1655caf8e3

1

1 Answers

10
votes

Short answer: TCP_CORK is a socket option, used in setsockopt() function for forcing TCP corking. tcp_autocorking is a flag for the kernel for checking specific conditions and perform corking when these conditions are met.

Bottom line: Corking would be performed for every packet when TCP_CORK is enabled, might be performed on packets when tcp_autocorking is enabled and TCP_CORK is disabled and would not be performed on any packets if both options are disabled. Data aggregation might still happen even when both options are disabled if Nagle's algorithm is enabled.

More details: TCP corking is described (and criticized) in this post: on TCP_CORK.

Also, see this detailed explanation about TCP_CORK and TCP_NODELAY by Appleman1234

By forcing TCP_CORK, data would be aggregated to the same buffer (SKB) until the buffer is filled. This option is stronger than TCP_NODELAY (i.e. disable Nagle's algorithm) so it would still work even when TCP_NODELAY option is set. The meaning behind aggregating to the same buffer is that calls for tcp_push() function (net/include/tcp.c) will not result in calls to __tcp_push_pending_frames() function (net/include/tcp_output.c), which result (eventually) in calls to the NIC's driver xmit functions. Instead, the payload of the next message arriving from the application would be copied to the same buffer as the last one. See tcp_sendmsg() function (net/include/tcp.c) for messages processing.

tcp_autocorking, on the other hand, wouldn't force aggregation until the buffer is full, but rather check specific conditions for continuing aggregation on current buffer. The tcp_push() function calls tcp_should_autocork() function (net/include/tcp.c) in order to check if current buffer should be sent:

static bool tcp_should_autocork(struct sock *sk, struct sk_buff *skb,
                                int size_goal)
{
        return skb->len < size_goal &&
               sysctl_tcp_autocorking &&
               skb != tcp_write_queue_head(sk) &&
               refcount_read(&sk->sk_wmem_alloc) > skb->truesize;
}

In English - should cork if (buffer isn't full) and (autocorking is enabled) and (there's at least one packet in Qdisc or NIC queues) and (not all packets in Qdisc/NIC queues are ACKs)

tcp_push() function checks additional conditions which might abort corking even when tcp_should_autocork() returned "true".

Hope this helps.