Tcp

沒有丟包的 TCP 重複確認

  • September 15, 2020

編輯:實際上存在 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 重複 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 中,.250ACK=267181. 因此,由於.250確認號 (267181) 低於.1序列號 (290541),因此.1假設.250失去了 #551,因為 #552 和 #558 之間的所有數據包都使用過時SEQ=267181的數據包,並為它接收到的每個數據包發送另一個 ACK,其中包含過期的 ACK 編號。

如果 RTOS 沒有報告失去,我們只能假設它的調度程序優先推送數據而不是處理確認。

引用自:https://serverfault.com/questions/1013408