Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 
(연관된 글이 1개 있습니다.)
(시리즈 글이 8개 있습니다.)
개발 환경 구성: 533. Wireshark + C#으로 확인하는 TCP 통신의 MSS(Maximum Segment Size) - 리눅스 환경
; https://www.sysnet.pe.kr/2/0/12527

개발 환경 구성: 534. Wireshark + C#으로 확인하는 TCP 통신의 MSS(Maximum Segment Size) - 윈도우 환경
; https://www.sysnet.pe.kr/2/0/12528

개발 환경 구성: 535. Wireshark + C#으로 확인하는 TCP 통신의 MIN RTO
; https://www.sysnet.pe.kr/2/0/12529

개발 환경 구성: 536. Wireshark + C#으로 확인하는 TCP 통신의 Receive Window
; https://www.sysnet.pe.kr/2/0/12530

개발 환경 구성: 538. Wireshark + C#으로 확인하는 ReceiveBufferSize(SO_RCVBUF), SendBufferSize(SO_SNDBUF)
; https://www.sysnet.pe.kr/2/0/12532

개발 환경 구성: 539. Wireshark + C/C++로 확인하는 TCP 연결에서의 shutdown 동작
; https://www.sysnet.pe.kr/2/0/12533

개발 환경 구성: 540. Wireshark + C/C++로 확인하는 TCP 연결에서의 closesocket 동작
; https://www.sysnet.pe.kr/2/0/12534

개발 환경 구성: 541.  Wireshark로 확인하는 LSO(Large Send Offload), RSC(Receive Segment Coalescing) 옵션
; https://www.sysnet.pe.kr/2/0/12535




Wireshark로 확인하는 LSO(Large Send Offload), RSC(Receive Segment Coalescing) 옵션

지난번에 윈도우 환경에서 MSS 패킷 테스트를 하면서,

Wireshark + C#으로 확인하는 TCP 통신의 MSS(Maximum Segment Size) - 윈도우 환경
; https://www.sysnet.pe.kr/2/0/12528#lso_option

가령, send(10KB)를 하면 다음과 같이 MSS=1460 크기를 (리눅스와는 달리) 무시하고,

// 3-way handshake
1   0.000000    ..client_ip...  ..server_ip...  TCP 66  2872 → 15000 [SYN] Seq=0 Win=64240 Len=0 MSS=1460 WS=256 SACK_PERM=1
2   0.004824    ..server_ip...  ..client_ip...  TCP 66  15000 → 2872 [SYN, ACK] Seq=0 Ack=1 Win=65535 Len=0 MSS=1460 WS=256 SACK_PERM=1
3   0.004898    ..client_ip...  ..server_ip...  TCP 54  2872 → 15000 [ACK] Seq=1 Ack=1 Win=262656 Len=0

// send(10KB)
4   1.722068    ..client_ip...  ..server_ip...  TCP 10294   2872 → 15000 [PSH, ACK] Seq=1 Ack=1 Win=262656 Len=10240
5   1.726845    ..server_ip...  ..client_ip...  TCP 60  15000 → 2872 [ACK] Seq=1 Ack=2921 Win=131328 Len=0
6   1.726845    ..server_ip...  ..client_ip...  TCP 60  15000 → 2872 [ACK] Seq=1 Ack=5841 Win=131328 Len=0
7   1.728553    ..server_ip...  ..client_ip...  TCP 60  15000 → 2872 [ACK] Seq=1 Ack=8761 Win=131328 Len=0
8   1.728553    ..server_ip...  ..client_ip...  TCP 60  15000 → 2872 [ACK] Seq=1 Ack=10241 Win=131328 Len=0

10KB 데이터를 통째로 하나의 패킷으로 캡처되는 것을 확인할 수 있었습니다. 원인이 뭘까 궁금해서 네트워크 어댑터의 옵션 창을 살펴봤더니 왠지 느낌이 오는 옵션이 하나 있습니다. ^^

rsc_network_setting_0.png

"Large Send Offload Version 2"라는 이름에서 벌써 신뢰를 주는데요, 설명을 보면 정확히 저 현상으로 해석이 됩니다.

LSO is a technology in which the work of segmenting data into network frames is performed by the network adapter instead of by the TCP/IP stack. With LSO, TCP/IP sends very large data packets down to the network adapter driver and the network adapter hardware. The network adapter separates the data into smaller network-sized frames.


즉, TCP/IP 스택을 구현한 device driver는 (MSS 단위로 분할하지 않은) 대형 TCP 패킷을 NIC 장치로 내려보낼 수 있다는 것으로, 따라서 NIC 장치가 MSS 단위로 분할해 송신하는 작업을 대행해 주기 때문에 CPU의 부담을 덜어줄 수 있는 기술입니다.

정말 그런지 테스트를 해봐야겠지요. ^^

이 옵션을 네트워크 속성 창에서 제어하는 것도 가능하지만 PowerShell을 이용할 수도 있습니다.

Enable-NetAdapterLso
; https://learn.microsoft.com/en-us/powershell/module/netadapter/enable-netadapterlso

Disable-NetAdapterLso
; https://learn.microsoft.com/en-us/powershell/module/netadapter/disable-netadapterlso

Get-NetAdapterLso
; https://learn.microsoft.com/en-us/powershell/module/netadapter/get-netadapterlso

따라서 다음과 같이 비활성화시키면,

PS C:\WINDOWS\system32> Get-NetAdapterLso -Name "*"

Name                           Version         V1IPv4Enabled  IPv4Enabled  IPv6Enabled
----                           -------         -------------  -----------  -----------
Ethernet                       LSO Version 2   False          True         True
vEthernet (MyTestHyperVsw)     LSO Version 2   False          True         True


PS C:\WINDOWS\system32> Disable-NetAdapterLso -Name "vEthernet (MyTestHyperVsw)"

PS C:\WINDOWS\system32> Get-NetAdapterLso -Name "*"

Name                           Version         V1IPv4Enabled  IPv4Enabled  IPv6Enabled
----                           -------         -------------  -----------  -----------
Ethernet                       LSO Version 2   False          True         True
vEthernet (MyTestHyperVsw)     LSO Version 2   False          False        False

잠깐 네트워크 연결이 리셋되고는, 이후 동일하게 send(10KB)하면 다음과 같이 MSS 단위로 보기 좋게 패킷이 캡처되는 것을 확인할 수 있습니다.

1   0.000000    ..client_ip...  ..server_ip...  TCP 66  2606 → 15000 [SYN] Seq=0 Win=64240 Len=0 MSS=1460 WS=256 SACK_PERM=1
2   0.004987    ..server_ip...  ..client_ip...  TCP 66  15000 → 2606 [SYN, ACK] Seq=0 Ack=1 Win=65535 Len=0 MSS=1460 WS=256 SACK_PERM=1
3   0.005055    ..client_ip...  ..server_ip...  TCP 54  2606 → 15000 [ACK] Seq=1 Ack=1 Win=262656 Len=0

4   1.266381    ..client_ip...  ..server_ip...  TCP 1514    2606 → 15000 [ACK] Seq=1 Ack=1 Win=262656 Len=1460
5   1.266381    ..client_ip...  ..server_ip...  TCP 1514    2606 → 15000 [ACK] Seq=1461 Ack=1 Win=262656 Len=1460
6   1.266381    ..client_ip...  ..server_ip...  TCP 1514    2606 → 15000 [ACK] Seq=2921 Ack=1 Win=262656 Len=1460
7   1.266381    ..client_ip...  ..server_ip...  TCP 1514    2606 → 15000 [ACK] Seq=4381 Ack=1 Win=262656 Len=1460
8   1.266381    ..client_ip...  ..server_ip...  TCP 1514    2606 → 15000 [ACK] Seq=5841 Ack=1 Win=262656 Len=1460
9   1.266381    ..client_ip...  ..server_ip...  TCP 1514    2606 → 15000 [ACK] Seq=7301 Ack=1 Win=262656 Len=1460
10  1.266381    ..client_ip...  ..server_ip...  TCP 1514    2606 → 15000 [ACK] Seq=8761 Ack=1 Win=262656 Len=1460
11  1.266381    ..client_ip...  ..server_ip...  TCP 74  2606 → 15000 [PSH, ACK] Seq=10221 Ack=1 Win=262656 Len=20
12  1.273309    ..server_ip...  ..client_ip...  TCP 60  15000 → 2606 [ACK] Seq=1 Ack=2921 Win=131328 Len=0
13  1.273309    ..server_ip...  ..client_ip...  TCP 60  15000 → 2606 [ACK] Seq=1 Ack=5841 Win=131328 Len=0
14  1.273309    ..server_ip...  ..client_ip...  TCP 60  15000 → 2606 [ACK] Seq=1 Ack=8761 Win=131328 Len=0
15  1.273309    ..server_ip...  ..client_ip...  TCP 60  15000 → 2606 [ACK] Seq=1 Ack=10241 Win=131328 Len=0

테스트가 끝나면 돌려놓는 것도 잊지 마시고. ^^

PS C:\WINDOWS\system32> Enable-NetAdapterLso -Name "vEthernet (MyTestHyperVsw)"

그러고 보니, 리눅스에서는 그냥 MSS 단위로 보냈던 것은 아마도 해당 PC가 구형이어서 그 시절의 NIC 카드에는 LSO 기능이 없어서 그런 것 같습니다.




기왕 시작했으니 네트워크 설정 창에 있는 다른 옵션도 살펴보겠습니다.

Receive Segment Coalescing (RSC)
; https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-r2-and-2012/hh997024(v=ws.11)

RSC in the vSwitch
; https://learn.microsoft.com/en-us/windows-server/networking/technologies/hpn/rsc-in-the-vswitch

rsc_network_setting_1.png

전송 시에 LSO가 있다면 수신 시에 RSC가 있는 듯한데요, 다음의 문서를 보면,

Windows 가상 시스템의 VMXNET3 어댑터에서 LRO 사용 또는 사용 안 함
; https://docs.vmware.com/kr/VMware-vSphere/7.0/com.vmware.vsphere.networking.doc/GUID-ECC80415-442C-44E9-BA7A-852DDB174B9F.html

다른 환경에서는 RSC라는 이름 대신 LRO라고 알려진 기술이라고 소개합니다. 실제로 설명을 보면, LSO의 대칭인 기술로 보입니다. ^^

Receive segment coalescing (RSC). RSC takes multiple packets received within the same interrupt period and combines the packets into a single large package to be processed by the network stack.


이 옵션도 Powershell로 제어 가능하고,

Get-NetAdapterRsc
; https://learn.microsoft.com/en-us/powershell/module/netadapter/get-netadapterrsc

Disable-NetAdapterRsc
; https://learn.microsoft.com/en-us/powershell/module/netadapter/disable-netadapterrsc

Enable-NetAdapterRsc
; https://learn.microsoft.com/en-us/powershell/module/netadapter/enable-netadapterrsc

(disable/enable은 네트워크가 리셋되니 유의하시고) 사용법은 LSO 제어와 옵션 설정 방식이 같습니다.

PS C:\WINDOWS\system32> Get-NetAdapterRsc -Name "*"

Name                           IPv4Enabled  IPv6Enabled  IPv4Operational IPv6Operational IPv4FailureReason IPv6FailureR
                                                         State           State                             eason
----                           -----------  -----------  --------------- --------------- ----------------- ------------
vEthernet (Default Switch)     True         True         True            True            NoFailure         NoFailure
vEthernet (MyTestHyperVsw)     True         True         True            True            NoFailure         NoFailure

기본값으로는 enable 상태인데, 실제로 테스트를 하면 wireshark에서 LSO처럼 합쳐진 패킷으로 안 보이고 MSS 단위로 개별 패킷이 캡처됩니다. 이상하군요, 약간의 짐작을 더해 보면 100%라고 말할 수는 없으나, 이 옵션의 활성 상태와 상관없이 해당 NIC 장치에서 이것을 지원해야만 하는 것으로 보입니다.

다음의 글을 보면,

Performance Tuning Windows 2012: Network Subsystem Part 1
; https://www.monitis.com/blog/performance-tuning-windows-2012-network-subsystempart-1/

RSC 관련 통계 값을 구하는 방법이 나오는데,

PS C:\WINDOWS\system32> $x = Get-NetAdapterStatistics  "vEthernet (MyTestHyperVsw)"
PS C:\WINDOWS\system32> $x.rscstatistics

CoalescedBytes       : 0
CoalescedPackets     : 0
CoalescingEvents     : 0
CoalescingExceptions : 0
PSComputerName       :

제 컴퓨터에서는 0으로만 나오고 있으므로 NIC 장치가 RSC를 지원하는 유형은 아닌 것 같습니다. 참고로, 윈도우에 hyper-v가 설치되어 있으면 그런 경우에도 RSC 지원이 호스트와 VM 머신 간에 달라지는 경우가 있다고 합니다.

If the host adapter is not bound to the virtual switch, RSC is supported on the physical host. If the adapter is bound to the virtual switch, Windows 2012 will disable RSC on the physical host. RSC can be enabled for a virtual machine when SR-IOV is enabled. In this case, virtual functions will support RSC capability; hence, virtual machines will also get the benefit of RSC.


아쉽지만 wireshark에서의 재현은 나중으로 미뤄야겠습니다. ^^




근래에는 CPU의 부하를 줄이기 위해 어떻게든 통신 부하를 NIC(Network Interface Controller)에 전가하는 offload 기능들이 나오고 있습니다. 아래의 문서에서 이에 대한 설명을 담고 있으며,

Performance in Network Adapters
; https://learn.microsoft.com/en-us/windows-hardware/drivers/network/performance-in-network-adapters

TCP/IP Offload Overview
; https://learn.microsoft.com/en-us/windows-hardware/drivers/network/tcp-ip-offload

TCP/IP Task Offload Overview
; https://learn.microsoft.com/en-us/windows-hardware/drivers/network/task-offload

리눅스의 경우 다음과 같은 명령어로 기능의 on/off를 확인할 수 있습니다.

$ ethtool -k eth0 | grep offload
tcp-segmentation-offload: on
generic-segmentation-offload: on
generic-receive-offload: on
large-receive-offload: off
rx-vlan-offload: on [fixed]
tx-vlan-offload: on [fixed]
l2-fwd-offload: off [fixed]
hw-tc-offload: off [fixed]
esp-hw-offload: off [fixed]
esp-tx-csum-hw-offload: off [fixed]
rx-udp_tunnel-port-offload: off [fixed]
tls-hw-tx-offload: off [fixed]
tls-hw-rx-offload: off [fixed]
macsec-hw-offload: off [fixed]
hsr-tag-ins-offload: off [fixed]
hsr-tag-rm-offload: off [fixed]
hsr-fwd-offload: off [fixed]
hsr-dup-offload: off [fixed]




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]

[연관 글]






[최초 등록일: ]
[최종 수정일: 3/19/2024]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 




... 91  92  93  94  95  96  97  98  99  100  101  102  103  [104]  105  ...
NoWriterDateCnt.TitleFile(s)
11325정성태10/14/201719252.NET Framework: 689. CLR 4.0 환경에서 DLL 모듈의 로드 주소(Base address) 알아내는 방법
11324정성태10/13/201720846디버깅 기술: 101. windbg - "*** WARNING: Unable to verify checksum for" 경고 없애는 방법
11322정성태10/13/201718267디버깅 기술: 100. windbg - .NET 4.0 응용 프로그램의 Main 메서드에 Breakpoint 걸기
11321정성태10/11/201719784.NET Framework: 688. NGen 모듈과 .NET Profiler
11320정성태10/11/201720570.NET Framework: 687. COR_PRF_USE_PROFILE_IMAGES 옵션과 NGen의 "profiler-enhanced images" [1]
11319정성태10/11/201728159.NET Framework: 686. C# - string 배열을 담은 구조체를 직렬화하는 방법
11318정성태10/7/201720923VS.NET IDE: 122. 비주얼 스튜디오에서 관리자 권한을 요구하는 C# 콘솔 프로그램 제작 [1]
11317정성태10/4/201726091VC++: 120. std::copy 등의 함수 사용 시 _SCL_SECURE_NO_WARNINGS 에러 발생
11316정성태9/30/201724135디버깅 기술: 99. (닷넷) 프로세스(EXE)에 디버거가 연결되어 있는지 아는 방법 [4]
11315정성태9/29/201740215기타: 68. "시작하세요! C# 6.0 프로그래밍: 기본 문법부터 실전 예제까지" 구매하신 분들을 위한 C# 7.0/7.1 추가 문법 PDF [8]
11314정성태9/28/201721996디버깅 기술: 98. windbg - 덤프 파일로부터 닷넷 버전 확인하는 방법
11313정성태9/25/201719291디버깅 기술: 97. windbg - 메모리 덤프로부터 DateTime 형식의 값을 알아내는 방법파일 다운로드1
11312정성태9/25/201722365.NET Framework: 685. C# - 구조체(값 형식)의 필드를 리플렉션을 이용해 값을 바꾸는 방법파일 다운로드1
11311정성태9/20/201716831.NET Framework: 684. System.Diagnostics.Process 객체의 명시적인 해제 권장
11310정성태9/19/201720247.NET Framework: 683. WPF의 Window 객체를 생성했는데 GC 수집 대상이 안 되는 이유 [3]
11309정성태9/13/201718371개발 환경 구성: 335. Octave의 명령 창에서 실행한 결과를 복사하는 방법
11308정성태9/13/201719430VS.NET IDE: 121. 비주얼 스튜디오에서 일부 텍스트 파일을 무조건 메모장으로만 여는 문제파일 다운로드1
11307정성태9/13/201721951오류 유형: 421. System.Runtime.InteropServices.SEHException - 0x80004005
11306정성태9/12/201720004.NET Framework: 682. 아웃룩 사용자를 위한 중국어 스팸 필터 Add-in
11305정성태9/12/201721511개발 환경 구성: 334. 기존 프로젝트를 Visual Studio를 이용해 Github의 신규 생성된 repo에 올리는 방법 [1]
11304정성태9/11/201718638개발 환경 구성: 333. 3ds Max를 Hyper-V VM에서 실행하는 방법
11303정성태9/11/201721938개발 환경 구성: 332. Inno Setup 파일의 관리자 권한을 제거하는 방법
11302정성태9/11/201718168개발 환경 구성: 331. SQL Server Express를 위한 방화벽 설정
11301정성태9/11/201717062오류 유형: 420. SQL Server Express 연결 오류 - A network-related or instance-specific error occurred while establishing a connection to SQL Server.
11300정성태9/10/201720917.NET Framework: 681. dotnet.exe - run, exec, build, restore, publish 차이점 [3]
11299정성태9/9/201719663개발 환경 구성: 330. Hyper-V VM의 Internal Network를 Private 유형으로 만드는 방법
... 91  92  93  94  95  96  97  98  99  100  101  102  103  [104]  105  ...