2019년 11월 4일 월요일

IBM POWER 가상머신에서의 RPS(Receive Packet Steering)을 이용한 network performance tuning


IBM Virtual Machine에서는 다음과 같이 RSS(Receive Side Scaling)가 receive (input) queue 1개로 제한됩니다.  아래는 POWER8 KVM 환경입니다.

[user607@p607-kvm2 ~]$ egrep 'CPU|virtio0' /proc/interrupts
           CPU0       CPU1       CPU2       CPU3       CPU4       CPU5       CPU6       CPU7       CPU8       CPU9       CPU10      CPU11      CPU12      CPU13      CPU14      CPU15
 47:          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0          0      XICS 4126 Edge      virtio0-config
 48:         48          0          0          0          0          0          0          0          0   57548404          0          0          0          0          0          0      XICS 4127 Edge      virtio0-input.0
 49:          1          0          0          0          0          0          0       4414          0          0          0          0          0          0          0          0      XICS 4128 Edge      virtio0-output.0


이 queue의 interrupt를 어떤 CPU가 처리하는지는 아래와 같이 찾을 수도 있습니다.

[user607@p607-kvm2 ~]$ sudo find /sys/devices -name "*eth0*"
/sys/devices/pci0000:00/0000:00:01.0/virtio0/net/eth0

[user607@p607-kvm2 ~]$ ls -l /sys/devices/pci0000:00/0000:00:01.0/msi_irqs
total 0
-r--r--r-- 1 root root 65536 Oct 31 22:47 47
-r--r--r-- 1 root root 65536 Oct 31 22:47 48
-r--r--r-- 1 root root 65536 Oct 31 22:47 49

virtio0-input.0, 즉 48번의 interrupt를 처리하는 CPU를 찾기 위해 /proc/irq/해당번호/smp_affinity 파일을 확인합니다.

[user607@p607-kvm2 ~]$ cat /proc/irq/48/smp_affinity
0200


위 숫자 string은 각 숫자 하나가 CPU 4개를 가리키는 16진수이며, 이를 2진수로 풀어놓으면 다음과 같습니다.   (16진수 2은 2^1이므로 2진수로는 0010 입니다)

(16진수) 0200
(2진수) 0000 0010 0000 0000 

각각의 2진수 숫자는 CPU 1개를 뜻하며, 뒤쪽부터 CPU0, CPU1, CPU2...를 표시합니다.  1로 표시된 CPU가 이 interrupt를 처리하는데 사용되는 CPU를 뜻합니다.
즉 총 16개의 CPU 중에서 (뒤쪽부터 셉니다) 10번째의 CPU가 이 interrupt를 처리한다는 뜻입니다.   맨 위에서 /proc/interrupts로 확인한 정보와 일치합니다.

이렇게 receive side queue가 1개 뿐이라면 혹시 heavy network traffic이 몰려들어올 때 해당 interrupt를 처리하는 CPU가 100% 차서 병목이 되는 일이 없을까요 ?   그 부분을 확인해보기 위해 network 부하 테스트 tool인 iperf를 설치하겠습니다.

[user607@p607-kvm2 ~]$ sudo yum groupinstall "Development Tools"

[user607@p607-kvm2 ~]$ wget https://iperf.fr/download/source/iperf-3.1.3-source.tar.gz

[user607@p607-kvm2 ~]$ tar -xf iperf-3.1.3-source.tar.gz

[user607@p607-kvm2 ~]$ cd iperf-3.1.3

[user607@p607-kvm2 iperf-3.1.3]$ ./configure

[user607@p607-kvm2 iperf-3.1.3]$ make -j8 && sudo make install

[user607@p607-kvm2 iperf-3.1.3]$ iperf3 -s -p 5021
-----------------------------------------------------------
Server listening on 5201
-----------------------------------------------------------

충분한 부하를 주기 위해, 이것 외에도 다음과 같이 5022~5024 port를 이용해 총 4개의 iperf3 server process를 구동해놓습니다.

[user607@p607-kvm2 iperf-3.1.3]$ iperf3 -s -p 5022
[user607@p607-kvm2 iperf-3.1.3]$ iperf3 -s -p 5023
[user607@p607-kvm2 iperf-3.1.3]$ iperf3 -s -p 5024


그리고 다른 서버에서 다음과 같이 이 4개 port에 대해 iperf3 client를 구동하여 작은 size의 packet들을 30초간 보냅니다.

user607@p607-kvm1:~$ user607@p607-kvm1:~$ for i in 1 2 3 4
> do
> iperf3 -c 129.40.252.107 -P 6 -t 30 -N -l 16 -p 502${i} &
> done

이렇게 해보면 다음과 같이 10번째 CPU가 정말 거의 95%에 달하는 것을 보실 수 있습니다.   다른 CPU들은 iperf3 server process들이 CPU를 100%씩 쓰고 있는 것입니다.




이 문제를 해결할 방법이 없을까요 ?  있습니다.  RPS(Receive Packet Steering)가 그것인데, 이는 쉽게 말해 RSS와 같은 것이지만 RSS가 HW적인 구현인 것에 비해 RPS는 SW적인 구현이라는 것입니다.  이건 기본적으로는 disable 처리되어 있습니다.  Disable 처리 여부는 다음과 같이 "...eth#/queues/rx-0/rps_cpus 파일에 할당된 CPU를 보고 확인하실 수 있습니다. 

[user607@p607-kvm2 ~]$ sudo find / -name queues
/sys/devices/pci0000:00/0000:00:01.0/virtio0/net/eth0/queues
/sys/devices/virtual/net/lo/queues

[user607@p607-kvm2 ~]$ ls -l /sys/devices/pci0000:00/0000:00:01.0/virtio0/net/eth0/queues/
total 0
drwxr-xr-x. 3 root root 0 Oct 29 18:57 rx-0
drwxr-xr-x. 3 root root 0 Oct 29 18:57 tx-0

[user607@p607-kvm2 ~]$ ls -l /sys/devices/pci0000:00/0000:00:01.0/virtio0/net/eth0/queues/rx-0
total 0
-rw-r--r--. 1 root root 65536 Oct 31 02:18 rps_cpus
-rw-r--r--. 1 root root 65536 Oct 31 02:18 rps_flow_cnt
drwxr-xr-x. 2 root root     0 Oct 29 18:58 virtio_net

[user607@p607-kvm2 ~]$ cat /sys/devices/pci0000:00/0000:00:01.0/virtio0/net/eth0/queues/rx-0/rps_cpus
0000

이렇게 0000이 들어있는 것은 disable되어 있다는 것입니다.   기본적으로 disable 처리가 된 것은 RSS로 multi-queue 처리가 된다면 굳이 RPS까지 함께 구현할 필요가 없기 떄문입니다.  그러나 Virtual 환경처럼 RSS에서 single-queue로만 처리가 되는 경우에는 도움이 될 수도 있습니다. 

RPS를 enable하기 위해서는 다음과 같이 그 처리를 해줄 CPU를 지정해주면 됩니다.

[root@p607-kvm2 user607]# echo "1001" > /sys/devices/pci0000:00/0000:00:01.0/virtio0/net/eth0/queues/rx-0/rps_cpus

[root@p607-kvm2 user607]# cat /sys/devices/pci0000:00/0000:00:01.0/virtio0/net/eth0/queues/rx-0/rps_cpus
1001

위와 같이 넣으면 16진수로 1001은 2진수로는 다음과 같이 표현됩니다. 

0001 0000 0000 0001

즉 전체 16개 CPU 중 첫번째 CPU와 13번째 CPU의 2개 CPU로 Receive packet들을 처리한다는 뜻입니다. 

이렇게 구성을 해놓고 위와 동일한게 4개 port에 대해 iperf3 server/client를 구동하여 작은 size의 packet들을 30초간 보냅니다.

user607@p607-kvm1:~$ user607@p607-kvm1:~$ for i in 1 2 3 4
> do
> iperf3 -c 129.40.252.107 -P 6 -t 30 -N -l 16 -p 502${i} &
> done

그 결과를 보면, 다음과 같이 RSS를 처리하는 10번 CPU의 사용률이 대폭 떨어지고, 대신 첫번째 CPU와 13번째 CPU의 사용률이 꽤 높이, 각각 약 35% 정도로 올라간 것을 보실 수 있습니다.





그리고 RSS만 이용했을 때와 RPS까지 함께 이용했을 때의 iperf 성능 결과는 아래와 같습니다.  4개 session을 사용했기 때문에 각각의 합을 비교했습니다.



보시는 바와 같이 network 처리 성능도 약~간 상승한 것을 보실 수 있습니다.  다만 이 가상머신 환경은 16개 CPU가 있기는 하지만 실제 물리적 CPU core는 2개 밖에 없고, 각 CPU core당 8개의 SMT(hyperthread)가 있는 것이라서, CPU 자원이 워낙 작습니다.  그런 상황에서 iperf server process도 CPU를 많이 사용하다보니, 정확한 성능 측정은 어려운 상황이라는 것은 감안하셔야 합니다.


RSS와 RPS에 대한 좀더 자세한 설명은 아래 URL을 참조하시기 바랍니다.

http://balodeamit.blogspot.com/2013/10/receive-side-scaling-and-receive-packet.html


댓글 없음:

댓글 쓰기