无数据包丢失的 TCP 重复确认

无数据包丢失的 TCP 重复确认

编辑:实际上有 2 个问题,运行 RTOS 的设备上 TCP 实现存在错误,以及当有超过 1 个核心处于活动状态时导致 Linux 网络堆栈无序接收 TCP 片段的问题。

我有一个在 IP 192.168.2.250 上运行一些嵌入式 RTOS 的发送器和一个在 IP 192.168.2.1 上运行 Linux 4.9.x 的接收器

接收器配置为无线接入点,发送器通过 WiFi 直接连接到接收器。

我在 TCP 数据传输期间在接收端进行了 tcpdump,我注意到接收器发送了相当多的重复 ACK,而实际上并没有发生数据包丢失(或者至少我是这样认为的,因为我没有看到重新传输并且 ACK 最终遵循发送的序列号)。

wireshark 跟踪 tcp 重复确认

有人知道是什么原因导致了接收者的行为吗?

编辑:您没有看到来自发送方的快速重传,因为我关闭了它们以证明流没有丢失数据(这样做吞吐量大大提高)。一种解释是,TCP 堆栈认为数据包是无序的。我可以让 Linux 更能容忍无序数据包吗?例如不立即发送重复确认。

输出sysctl net | grep tcp

net.ipv4.tcp_abort_on_overflow=0
net.ipv4.tcp_adv_win_scale=1
net.ipv4.tcp_allowed_congestion_control=cubic reno
net.ipv4.tcp_app_win=31
net.ipv4.tcp_autocorking=1
net.ipv4.tcp_available_congestion_control=cubic reno
net.ipv4.tcp_base_mss=1024
net.ipv4.tcp_challenge_ack_limit=1000
net.ipv4.tcp_congestion_control=cubic
net.ipv4.tcp_delack_seg=1
net.ipv4.tcp_dsack=1
net.ipv4.tcp_early_retrans=3
net.ipv4.tcp_ecn=2
net.ipv4.tcp_ecn_fallback=1
net.ipv4.tcp_fack=1
net.ipv4.tcp_fastopen=1
net.ipv4.tcp_fin_timeout=60
net.ipv4.tcp_frto=2
net.ipv4.tcp_fwmark_accept=0
net.ipv4.tcp_invalid_ratelimit=500
net.ipv4.tcp_keepalive_intvl=75
net.ipv4.tcp_keepalive_probes=9
net.ipv4.tcp_keepalive_time=7200
net.ipv4.tcp_limit_output_bytes=262144
net.ipv4.tcp_low_latency=0
net.ipv4.tcp_max_orphans=16384
net.ipv4.tcp_max_reordering=300
net.ipv4.tcp_max_syn_backlog=128
net.ipv4.tcp_max_tw_buckets=16384
net.ipv4.tcp_mem=332494433366498
net.ipv4.tcp_min_rtt_wlen=300
net.ipv4.tcp_min_tso_segs=2
net.ipv4.tcp_moderate_rcvbuf=1
net.ipv4.tcp_mtu_probing=0
net.ipv4.tcp_no_metrics_save=0
net.ipv4.tcp_notsent_lowat=4294967295
net.ipv4.tcp_orphan_retries=0
net.ipv4.tcp_pacing_ca_ratio=120
net.ipv4.tcp_pacing_ss_ratio=200
net.ipv4.tcp_probe_interval=600
net.ipv4.tcp_probe_threshold=8
net.ipv4.tcp_recovery=1
net.ipv4.tcp_reordering=3
net.ipv4.tcp_retrans_collapse=1
net.ipv4.tcp_retries1=3
net.ipv4.tcp_retries2=15
net.ipv4.tcp_rfc1337=0
net.ipv4.tcp_rmem=4096873806291456
net.ipv4.tcp_sack=1
net.ipv4.tcp_slow_start_after_idle=1
net.ipv4.tcp_stdurg=0
net.ipv4.tcp_syn_retries=6
net.ipv4.tcp_synack_retries=5
net.ipv4.tcp_syncookies=1
net.ipv4.tcp_thin_dupack=0
net.ipv4.tcp_thin_linear_timeouts=0
net.ipv4.tcp_timestamps=0
net.ipv4.tcp_tso_win_divisor=3
net.ipv4.tcp_tw_recycle=0
net.ipv4.tcp_tw_reuse=0
net.ipv4.tcp_use_userconfig=0
net.ipv4.tcp_window_scaling=1
net.ipv4.tcp_wmem=4096163844194304
net.ipv4.tcp_workaround_signed_windows=0

答案1

由于某种原因,.250正在发送已收到的 SEQ 的旧 ACK 值。参见数据包 #551:.1状态SEQ=290541。在数据包 #552 中,.250表示ACK=267181。因此,由于.250确认号 (267181) 低于.1序列号 (290541),.1因此假设.250丢失了 #551,因为 #552 和 #558 之间的所有数据包都使用过时的 ACK 号SEQ=267181,并为每个收到的带有过时 ACK 号的数据包发送另一个 ACK​​。

如果 RTOS 报告没有丢失,我们只能假设它的调度程序优先推送数据而不是处理确认。

相关内容