我想问一个基本问题:Linux 上默认启用 TCP PACING 吗?我现在使用的是Ubuntu,内核4.4.0。
我看到可以使用 TC-FQ 启用/禁用它,但是默认情况下仅使用 TC 启用它,还是默认禁用它?
答案1
简短回答:对于内核 4.4.0,TCP PACING 默认启用,并设置为每个套接字 ~34.36Gb/s。从内核 4.13.0-rc1 开始,TCP PACING 默认被禁用。在这两种情况下,由于 TSO 已启用,因此当调步速率设置为默认值时,TCP PACING 将不起作用。
使用 sock_setsockopt() 函数 (net/core/sock.c) 为套接字设置 TCP PACING。这样做的标志是SO_MAX_PACING_RATE,处理代码如下:
case SO_MAX_PACING_RATE:
sk->sk_max_pacing_rate = val;
sk->sk_pacing_rate = min(sk->sk_pacing_rate,
sk->sk_max_pacing_rate);
break;
创建套接字时,相关字段在 sock_init_data() (net/core/sock.c) 中设置为 ~0U:
sk->sk_max_pacing_rate = ~0U;
sk->sk_pacing_rate = ~0U;
因此,调步速率和最大调步速率的默认值为 max unsigned int value,即 (2^32 - 1),或每秒 4,294,967,295 字节,即 34.36Gb/s。
然而,通过使用 TCP 分段卸载 (TSO),即使使用单个套接字也可以获得更高的速率。 TSO 考虑了调步率,但实际上不受默认率的限制。在 tcp_tso_autosize() 函数 (net/ipv4/tcp_output.c) 中,调步速率可能会减少 TSO 会话的大小,但由于默认值约为 4.3GB,即使右移 10 后,您仍然会获得约 4MB,因此比典型的 TSO 会话大得多。
static u32 tcp_tso_autosize(const struct sock *sk, unsigned int mss_now)
{
u32 bytes, segs;
bytes = min(sk->sk_pacing_rate >> 10,
sk->sk_gso_max_size - 1 - MAX_TCP_HEADER);
/* Goal is to send at least one packet per ms,
* not one big TSO packet every 100 ms.
* This preserves ACK clocking and is consistent
* with tcp_tso_should_defer() heuristic.
*/
segs = max_t(u32, bytes / mss_now, sysctl_tcp_min_tso_segs);
return min_t(u32, segs, sk->sk_gso_max_segs);
}
我尝试实际达到 34Gb/s 限制,但不幸的是,如果 TX 端没有 TSO CPU 利用率,则将单插槽 BW 限制为 ~23Gb/s。
Eric Dumazet 的补丁tcp:节奏的内部实现在内核 4.13.0-rc1 上引入。该补丁增强了 TCP PACING 能力。这一次,它允许在不使用 TC-FQ 的情况下进行调步。如果 sk_pacing_rate 字段设置为 0 或 ~0U(默认),它还会完全禁用调步。有关更多详细信息,请参阅补丁封面和代码。