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
tcp_wmem (since Linux 2.4) This is a vector of 3 integers: [min, default, max]. These parameters are used by TCP to regulate send buffer sizes. TCP dynamically adjusts the size of the send buffer from the default values listed below, in the range of these values, depending on memory available.
The TCP layer builds packets when data is available in the send buffer or ACK packets in response to data packets received. Each packet is pushed down to the IP layer for transmission. The IP layer enqueues each packet in an output queue (qdisc) associated with the NIC.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With