编辑:实际上存在 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 最终会跟随发送的序列号)。
有人知道可能导致接收器行为的原因吗?
编辑:您没有看到来自发件人的快速重传,因为我将它们关闭以证明流没有丢失数据(这样做会使吞吐量大大提高)。一种解释是 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
出于某种原因,
.250
正在为它已经收到的 SEQ 发送旧的 ACK 值。见数据包#551:.1
状态SEQ=290541
。在数据包 #552 中,.250
说ACK=267181
. 因此,由于.250
确认号 (267181) 低于.1
序列号 (290541),因此.1
假设.250
丢失了 #551,因为 #552 和 #558 之间的所有数据包都使用过时SEQ=267181
的数据包,并为它接收到的每个数据包发送另一个 ACK 带有过期的 ACK 号。如果 RTOS 没有报告丢失,我们只能假设它的调度程序优先推送数据而不是处理确认。