从Linux内核看TCP重传机制

从Linux内核看TCP重传机制

0. 工作计划

2023.05.15~19

本周工作:

  • 会议决议每人负责一个底层方向,目前我的方向为TCP重传与丢包
  • 查找TCP重传机制的相关资料

下一步计划:

  • 分析TCP重传的三种机制及在Linux中的实现
  • 使用传统工具以及现有的eBPF工具,观测性能参数
  • 分析/proc/sys/net/ipv4/下面涉及TCP的参数含义,以及了解如何通过参数配置进行网络调优(特化)

1. TCP重传机制原理简述

关于TCP重传机制的阐述,网络上有大量的优质文章,读者可以搜索查阅。为了文章的完整性,本文仅做概述。

TCP重传机制具有以下几种方法:

  • 基于计时器的重传(超时重传)

  • 快重传(Fast Retransmit)

  • 选择重传

    • 选择性确认方法(Selective Acknowledgment,SACK)
    • Duplicate SACK

1.1 超时重传

关于超时重传,即数据发送时计时,若指定超时重传时间(Retransmission Timeout,RTO)范围内,没有收到ACK确认应答报文,将触发超时重传机制,重新发送该数据包。

  • RTO不固定,根据网络延迟,动态调整
  • 调整与RTT(Round Trip Time)往返时间有关
image-20230518093143094

1.2 快重传

快重传是TCP协议在特定情况下的一种优化重传机制,当TCP发送方连续收到三个相同的确认,就会认为这个报文是丢失了而不是延迟,此时会立即进行重传,从而减少等待超时时间的长短,提高重传的速度和效率。

1.3 选择重传

SACK是TCP协议引入的一种优化重传的机制,它可以在数据包中带上一个SACK选项,记录已经成功接收的数据及缺失的数据段的起止位置。这样当TCP重传时,可以精确指定要重传的数据包,从而避免重传已经成功接收的数据包,减少网络拥塞和提高传输效率。

D-SACK(Duplicate SACK)是SACK的一个改进,它可以记录重复的SACK块,即探测到的丢失数据块的段在后续的确认中又会出现。D-SACK在与SACK一起使用时,主要解决某些复杂情况下SACK的不足,例如在网络重传造成新段落结构时,SACK存在可能会指示不正确的段。

2. Linux内核网络协议栈重传机制实现

2.1 TCP关键参数

SYN重传次数tcp_syn_retries

SYN-ACK重传次数tcp_synack_retries

SYN包队列tcp_max_syn_backlog

丢包率

超时重传时间

重传队列

2.2 TCP重传机制的实现

通过跟踪数据包重传的路线,理解Linux网络协议栈的具体实现。

Linux内核版本:5.10.104

2.2.1 超时重传

2.2.1.1 RTO的范围

超时重传时间最大最小值的计算与HZ有关。HZ的由CONFIG_HZ设置,如下所示,目前这台X64主机的CONFIG_HZ为250,可以修改设置为100,300以及1000等。若用户不设置,则默认是100。

1
2
3
4
5
6
7
8
fzy@fzy-Lenovo:~$ cat /boot/config-5.15.0-72-generic | grep CONFIG_HZ
# CONFIG_HZ_PERIODIC is not set
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250

因此, 超时重传时间的最小值为50ms,最大为30s。

1
2
3
// include/net/tcp.h
#define TCP_RTO_MAX ((unsigned)(120*HZ))
#define TCP_RTO_MIN ((unsigned)(HZ/5))
2.2.1.2 重传计时器
1
2
3
4
5
6
7
8
9
/*!
创建流程图, from 内核之旅
sk->sk_prot->init --指向--> tcp_v4_init_sock(这里以tcp v4 为例)
|--->tcp_init_sock
|--->tcp_init_xmit_timers
|----->inet_csk_init_xmit_timers
| |------timer_setup
|----->hrtimer_init
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// net/ipv4/tcp_timer.c
static void tcp_write_timer(struct timer_list *t)
{
struct inet_connection_sock *icsk =
from_timer(icsk, t, icsk_retransmit_timer);
struct sock *sk = &icsk->icsk_inet.sk;

bh_lock_sock(sk);
if (!sock_owned_by_user(sk)) {
tcp_write_timer_handler(sk);
} else {
/* delegate our work to tcp_release_cb() */
if (!test_and_set_bit(TCP_WRITE_TIMER_DEFERRED, &sk->sk_tsq_flags))
sock_hold(sk);
}
bh_unlock_sock(sk);
sock_put(sk);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// include/net/inet_connection_sock.h
/** inet_connection_sock - INET connection oriented sock
*
* @icsk_accept_queue: FIFO of established children
* @icsk_bind_hash: Bind node
* @icsk_timeout: Timeout
* @icsk_retransmit_timer: Resend (no ack)
* @icsk_rto: Retransmit timeout
* @icsk_pmtu_cookie Last pmtu seen by socket
* @icsk_ca_ops Pluggable congestion control hook
* @icsk_af_ops Operations which are AF_INET{4,6} specific
* @icsk_ulp_ops Pluggable ULP control hook
* @icsk_ulp_data ULP private data
* @icsk_clean_acked Clean acked data hook
* @icsk_listen_portaddr_node hash to the portaddr listener hashtable
* @icsk_ca_state: Congestion control state
* @icsk_retransmits: Number of unrecovered [RTO] timeouts
* @icsk_pending: Scheduled timer event
* @icsk_backoff: Backoff
* @icsk_syn_retries: Number of allowed SYN (or equivalent) retries
* @icsk_probes_out: unanswered 0 window probes
* @icsk_ext_hdr_len: Network protocol overhead (IP/IPv6 options)
* @icsk_ack: Delayed ACK control data
* @icsk_mtup; MTU probing control data
* @icsk_probes_tstamp: Probe timestamp (cleared by non-zero window ack)
* @icsk_user_timeout: TCP_USER_TIMEOUT value
*/
struct inet_connection_sock {
/* inet_sock has to be the first member! */
struct inet_sock icsk_inet;
struct request_sock_queue icsk_accept_queue;
struct inet_bind_bucket *icsk_bind_hash;
unsigned long icsk_timeout;
struct timer_list icsk_retransmit_timer;
}

2.2.2 快重传

2.2.3 SACK与D-SACK

3. 如何观测重传关键参数

3.1 传统工具

3.2 现有eBPF技术工具

3.3 开发采用eBPF技术的小工具

==若有必要==

4. 总结

5. 参考资料

  1. 详解 TCP 超时与重传机制
  2. TCP超时重传定时器【内核之旅,推荐】
  3. TCP连接延时
  4. linux协议栈 TCP定时器之超时重传定时器
  5. 详说TCP重传问题的排查思路与实践

从Linux内核看TCP重传机制
http://ziyangfu.github.io/2023/05/16/从Linux内核看TCP重传机制/
作者
FZY
发布于
2023年5月16日
许可协议