루프백 인터페이스를 사용할 때 재전송된/비순차적인 패킷이 표시되며 이 사실에 놀랐는지(저는 그렇습니다) 또는 다른 사람이 보고 있지만 저는 본 적이 없는지 결정하기 위해 며칠 동안 인터넷 검색을 해왔습니다. 아직 답변을 찾지 못했습니다. 제가 뭔가를 놓쳤다면 죄송합니다. 누군가 루프백 사양을 언급했지만 찾을 수 없습니다. 루프백 인터페이스 사양을 아는 사람이 있습니까?
ACK 손실로 인한 재전송의 예:
/root
root@cmsstor911 :^| tshark -nr/tmp/t.tcpdump -te | egrep -i 'retrans|out.of.order' -B3 -A2
Running as user "root" and group "root". This could be dangerous.
54 1582904297 127.0.0.1 -> 127.0.0.1 TCP 66 7001 > 45529 [ACK] Seq=449 Ack=917399 Win=2752512 Len=0 TSval=3255514024 TSecr=3255514024
55 1582904297 127.0.0.1 -> 127.0.0.1 TCP 65549 45529 > 7001 [ACK] Seq=982882 Ack=449 Win=49152 Len=65483 TSval=3255514024 TSecr=3255514024
56 1582904297 127.0.0.1 -> 127.0.0.1 TCP 278 45529 > 7001 [PSH, ACK] Seq=1048365 Ack=449 Win=49152 Len=212 TSval=3255514024 TSecr=3255514024
57 1582904297 127.0.0.1 -> 127.0.0.1 TCP 278 [TCP Retransmission] 45529 > 7001 [PSH, ACK] Seq=1048365 Ack=449 Win=49152 Len=212 TSval=3255514034 TSecr=3255514024
58 1582904297 127.0.0.1 -> 127.0.0.1 TCP 78 7001 > 45529 [ACK] Seq=449 Ack=1048577 Win=2686976 Len=0 TSval=3255514034 TSecr=3255514024 SLE=1048365 SRE=1048577
59 1582904297 127.0.0.1 -> 127.0.0.1 TCP 178 7001 > 45529 [PSH, ACK] Seq=449 Ack=1048577 Win=2686976 Len=112 TSval=3255514224 TSecr=3255514024
tshark가 마이크로초를 훌륭하게 인쇄하도록 하는 것은 어렵지만 무슨 일이 일어나고 있는 것처럼 보이는 것은 패킷 56이 (내 응용 프로그램에서) 한동안 마지막 패킷이라는 것입니다. Acknowledge 이전에 2개의 패킷이 발생하였으므로 1개를 보냈어야 했는데 그렇지 않았습니다. 에 대한. 9.056밀리초가 지나고 발신자는 재전송을 결정합니다. 수신자는 즉시 SACK를 보냅니다.
내가 하고 있는 일은 다음과 같습니다(5.5.4를 포함한 여러 최신 Linux 커널에서 시도).
sudo tcpdump -s78 -wt.tcpdump -ilo port 7001 & tcpdump_pid=$!; \
taskset -c 1 ./tcp_loopback.py -s -b1048576 & sleep .5; taskset -c 2 ./tcp_loopback.py -c -b1048576 --count=8192; \
sudo kill $tcpdump_pid; \
tshark -r t.tcpdump | egrep -i 'retrans|out.of.order' | tail
tcp_loopback.py 스크립트는 home.fnal.gov/~ron/tcp_loopback.py에서 찾을 수 있습니다.
서버 부분(-s)의 핵심은 다음과 같습니다.
sock = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
sock.setsockopt( socket.SOL_SOCKET, socket.SO_REUSEADDR, 1 )
sock.bind( ('127.0.0.1', port) )
sock.listen( 4 )
sockconn,address = sock.accept()
while 1:
data = sockconn.recv(bs)
if opargs['-v']=='': print('received: '+str(len(data)))
if len(data) == 0:
if opargs['-v']=='': print('0 data, closing')
break
클라이언트 부분(-s)의 핵심은 다음과 같습니다.
sock = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
sock.connect( ('127.0.0.1',port) )
for xx in range(cnt): sock.send( '*'*bs )
재전송 확률은 쓰기/읽기가 더 클수록(예: 2M, 4M) 증가하는 것으로 보입니다.
다른 코어의 스케줄링과 관련된 순서가 잘못된 문제에 대해 읽었습니다(예: Documentation/networking/scaling.rst). 따라서 위에서 "작업 세트"를 사용합니다.
tcpdump에서 세그먼트가 두 번 전송된 것을 확인했기 때문에 재전송이 실제라고 믿습니다. 또한 전송이 진행되는 동안 재전송 정보를 얻기 위해 NETLINK_SOCK_DIAG 소켓을 사용하는 사용자 지정 응용 프로그램이 있습니다. 이를 사용할 때 로컬 호스트/루프백에 대한 재전송이 표시됩니다. 전송의 대부분(아마도 모두)이 순서가 잘못된 현상으로 인해 발생하는 것 같습니다. 따라서 다음과 같은 질문이 실제로 있을 수 있습니다. 루프백을 사용할 때 패킷 순서를 보장하기 위해 내가 할 수 있는 트릭(작업 세트 제외)이 있습니까? 상호 작용?
루프백을 사용하면 송신 프로세스에서 잘못된 내용을 보내는 것인지, 아니면 수신 프로세스에서 잘못된 내용을 수신하는 것인지 알 수 없습니다. 나의 궁극적인 목표는 100Gi, 높은 혼잡(다대일) 환경에서 낮은 대기 시간의 노드 간 전송을 위한 기준을 설정하는 것입니다. 재전송 정보를 얻기 위해 "디버그 소켓"을 사용하는 애플리케이션을 개발했는데, 로컬 호스트에서 재전송되는 것을 보고 놀랐습니다.
무슨 일이 일어나고 있는지 이해하는 데 도움을 줄 수 있는 사람이 있습니까? 손잡이(예: sysctl)가 있는 경우 데이터 속도를 최대화하면서 재전송을 제거할 수 있습니까?
고마워요, 론
추신: 이 작업을 수행했을 때도 결국 이 문제가 발생했습니다.
while true;do
sudo tcpdump -s78 -w/tmp/t.tcpdump -ilo port 7001 & tcpdump_pid=$!
ncat -4l localhost 7001 > /dev/null & ncat_pid=$!
sleep .5
dd if=/dev/zero bs=1048576 count=2048 | ncat localhost 7001
sudo kill $tcpdump_pid
tshark -r /tmp/t.tcpdump | egrep -i 'retrans|out.of.order' && break
done
출력 예:
/home/ron/notes
ron@ronlap77 :^) sudo tcpdump -s78 -wt.tcpdump -ilo port 7001 & tcpdump_pid=$!; \
> taskset -c 1 ./tcp_loopback.py -s -b1048576 & sleep .5; taskset -c 2 ./tcp_loopback.py -c -b1048576 --count=8192; \
> sudo kill $tcpdump_pid; \
> tshark -r t.tcpdump | egrep -i 'retrans|out.of.order' | tail
[1] 29066
[2] 29067
tcpdump: listening on lo, link-type EN10MB (Ethernet), capture size 78 bytes
191379 packets captured
383230 packets received by filter
0 packets dropped by kernel
[2]+ Done taskset -c 1 ./tcp_loopback.py -s -b1048576
189947 1.092534 127.0.0.1 → 127.0.0.1 TCP 65549 [TCP Out-Of-Order] 46988 → 7001 [ACK] Seq=4203412074 Ack=1 Win=65536 Len=65483 TSval=2693245609 TSecr=2693245609
189948 1.092535 127.0.0.1 → 127.0.0.1 TCP 65549 [TCP Out-Of-Order] 46988 → 7001 [ACK] Seq=4203477557 Ack=1 Win=65536 Len=65483 TSval=2693245609 TSecr=2693245609
189949 1.092536 127.0.0.1 → 127.0.0.1 TCP 65549 [TCP Out-Of-Order] 46988 → 7001 [ACK] Seq=4203543040 Ack=1 Win=65536 Len=65483 TSval=2693245609 TSecr=2693245609
189950 1.092536 127.0.0.1 → 127.0.0.1 TCP 65549 [TCP Out-Of-Order] 46988 → 7001 [ACK] Seq=4203608523 Ack=1 Win=65536 Len=65483 TSval=2693245609 TSecr=2693245609
189951 1.092537 127.0.0.1 → 127.0.0.1 TCP 65549 [TCP Out-Of-Order] 46988 → 7001 [ACK] Seq=4203674006 Ack=1 Win=65536 Len=65483 TSval=2693245609 TSecr=2693245609
189962 1.092594 127.0.0.1 → 127.0.0.1 TCP 65549 [TCP Spurious Retransmission] 46988 → 7001 [ACK] Seq=4203674006 Ack=1 Win=65536 Len=65483 TSval=2693245609 TSecr=2693245609
190115 1.093456 127.0.0.1 → 127.0.0.1 TCP 65549 [TCP Out-Of-Order] 46988 → 7001 [ACK] Seq=4211997131 Ack=1 Win=65536 Len=65483 TSval=2693245610 TSecr=2693245610
190116 1.093457 127.0.0.1 → 127.0.0.1 TCP 65549 [TCP Out-Of-Order] 46988 → 7001 [ACK] Seq=4212062614 Ack=1 Win=65536 Len=65483 TSval=2693245610 TSecr=2693245610
190117 1.093457 127.0.0.1 → 127.0.0.1 TCP 1762 [TCP Out-Of-Order] 46988 → 7001 [PSH, ACK] Seq=4212128097 Ack=1 Win=65536 Len=1696 TSval=2693245610 TSecr=2693245610
190138 1.093547 127.0.0.1 → 127.0.0.1 TCP 1762 [TCP Out-Of-Order] 46988 → 7001 [PSH, ACK] Seq=4212128097 Ack=1 Win=65536 Len=1696 TSval=2693245610 TSecr=2693245610
[1]+ Done sudo tcpdump -s78 -wt.tcpdump -ilo port 7001
--2020-02-25_11:27:17--