stress-ngコマンドの使い方(UDP編)
- 1 はじめに
- 2 検証環境
- 3 パッケージのインストール方法
- 4 オプション一覧
- 5 送受信のプロセス数を指定する方法(--udp)
- 6 受信待ちのポート番号を指定する方法(--udp-port)
- 7 IPv4またはIPv6を指定する方法(--udp-domain)
- 8 実行回数を指定する方法(--udp-ops)
- 9 UDPパケット送受信するインタフェースを指定する方法(--udp-if)
- 10 受信待ちのポート番号をランダムに指定する方法(--udp-flood)
- 11 UDP-Liteのパケットを送受信する方法(--udp-lite)
- Y 参考図書
- Z 参考情報
1 はじめに
stress-ngコマンドは、CPU、メモリ、ディスク、ネットワークなど、さまざまなリソースに対して負荷テストを行うためのツールです。stressコマンドと比較して、より多くの種類のリソースに対して負荷をかけることができます。本記事ではUDPに関する使い方を説明します。なお、stressコマンド、およびstress-ngコマンドの基本的な使い方は、以下の記事を参照してください。
2 検証環境
AlmaLinuxの版数は以下のとおりです。
[root@server ~]# cat /etc/redhat-release AlmaLinux release 9.2 (Turquoise Kodkod)
カーネル版数は以下のとおりです。
[root@server ~]# uname -r 5.14.0-284.11.1.el9_2.x86_64
3 パッケージのインストール方法
stress-ngパッケージをインストールします。なお、dnfコマンドの使い方は、dnfコマンドの使い方 - hana_shinのLinux技術ブログを参照してください。
[root@server ~]# dnf -y install stress-ng
stress-ngコマンドの版数を確認します。
[root@server ~]# stress-ng -V stress-ng, version 0.15.00 (gcc 11.3, x86_64 Linux 5.14.0-284.11.1.el9_2.x86_64) ?諮
なお、AlmaLinux 9.1以前は、stress-ngパッケージはepelリポジトリにあるので、まずepel-releaseパッケージをインストールします。そのあと、stress-ngパッケージをインストールします。
[root@server ~]# dnf -y install epel-release [root@server ~]# dnf -y install stress-ng
4 オプション一覧
stress-ngコマンドのUDPオプションには以下のものがあります。
[root@server ~]# man stress-ng -snip- --udp N start N workers that transmit data using UDP. This involves a pair of client/server processes perform‐ ing rapid connect, send and receives and disconnects on the local host. --udp-domain D specify the domain to use, the default is ipv4. Currently ipv4, ipv6 and unix are supported. --udp-if NAME use network interface NAME. If the interface NAME does not exist, is not up or does not support the do‐ main then the loopback (lo) interface is used as the default. --udp-gro enable UDP-GRO (Generic Receive Offload) if supported. --udp-lite use the UDP-Lite (RFC 3828) protocol (only for ipv4 and ipv6 domains). --udp-ops N stop udp stress workers after N bogo operations. --udp-port P start at port P. For N udp worker processes, ports P to P - 1 are used. By default, ports 7000 upwards are used. --udp-flood N start N workers that attempt to flood the host with UDP packets to random ports. The IP address of the packets are currently not spoofed. This is only available on systems that support AF_PACKET. --udp-flood-domain D specify the domain to use, the default is ipv4. Currently ipv4 and ipv6 are supported. --udp-flood-if NAME use network interface NAME. If the interface NAME does not exist, is not up or does not support the do‐ main then the loopback (lo) interface is used as the default. --udp-flood-ops N stop udp-flood stress workers after N bogo operations.
5 送受信のプロセス数を指定する方法(--udp)
--udpオプションは、UDPパケットの送受信プロセス数を指定するためのオプションです。1を指定すると、送受信プロセスがそれぞれ1つずつ生成されます。2を指定すると、送受信プロセスがそれぞれ2つずつ生成されます。あとは同様です。また、-kオプションは、親プロセスと子プロセスを同じ名前にするためのオプションです。psコマンドの実行結果を見ると、全てのプロセスの名前がstress-ngであることがわかります。
[root@server ~]# stress-ng -k --udp 1 stress-ng: info: [1541] defaulting to a 86400 second (1 day, 0.00 secs) run per stressor stress-ng: info: [1541] dispatching hogs: 1 udp
psコマンドを使用してプロセスの状態を確認します。また、後述するstraceコマンドの実行結果から分かるように、PID=1542はUDPパケットの受信プロセス、PID=1543はUDPパケットの送信プロセスです。また、PID=1541は送受信プロセスの終了をwaitシステムコールで待機しています。do_waitはwaitシステムコールの延長として呼び出されるカーネル関数です。なお、psコマンドの使い方は、psコマンドの使い方 - hana_shinのLinux技術ブログを参照してください。
[root@server ~]# ps -C stress-ng -o comm,pid,ppid,psr,%cpu,wchan COMMAND PID PPID PSR %CPU WCHAN stress-ng 1541 1515 3 0.0 do_wait stress-ng 1542 1541 1 43.5 - stress-ng 1543 1542 3 49.7 -
次に、lsofコマンドを実行します。PID=1542はUDPパケットの受信プロセスです。UDPの7000番ポートで受信待ちしていることがわかります。そして、PID=1543はUDPパケットの送信プロセスです。UDPパケットをポート番号60301から送信します。また、それぞれのプロセスは、任意のIPアドレス(ポート番号の前のIPアドレスがワイルドカード(*)なので)でUDPパケットの送受信を実行することがわかります。なお、lsofコマンドの使い方は、lsofコマンドの使い方 - hana_shinのLinux技術ブログを参照してください。
[root@server ~]# lsof -c stress-ng -a -i -a -nP COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME stress-ng 1542 root 4u IPv4 21463 0t0 UDP *:7000 stress-ng 1543 root 4u IPv4 23423 0t0 UDP *:60301
PID=1543のプロセスに対して、straceコマンドを実行します。 PID=1543のプロセスはsendtoシステムコールを繰り返し実行しています。宛先UDPポート番号は7000、送信元IPアドレスは任意のIPアドレス(0.0.0.0)であることがわかります。なお、straceコマンドの使い方は、straceコマンドの使い方 - hana_shinのLinux技術ブログを参照してください。
[root@server ~]# strace -e trace=network -p 1543 strace: Process 1543 attached sendto(4, "QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ"..., 304, 0, {sa_family=AF_INET, sin_port=htons(7000), sin_addr=inet_addr("0.0.0.0")}, 16) = 304 sendto(4, "RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR"..., 320, 0, {sa_family=AF_INET, sin_port=htons(7000), sin_addr=inet_addr("0.0.0.0")}, 16) = 320 sendto(4, "SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS"..., 336, 0, {sa_family=AF_INET, sin_port=htons(7000), sin_addr=inet_addr("0.0.0.0")}, 16) = 336 -snip-
PID=1542のプロセスに対して、straceコマンドを実行します。PID=1542のプロセスはrecvfromシステムコールを繰り返し実行しています。送信元UDPポート番号は60301、送信元IPアドレスは127.0.0.1であることがわかります。
[root@server ~]# strace -e trace=network -p 1542 strace: Process 1542 attached recvfrom(4, "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM"..., 1024, 0, {sa_family=AF_INET, sin_port=htons(60301), sin_addr=inet_addr("127.0.0.1")}, [16]) = 960 recvfrom(4, "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN"..., 1024, 0, {sa_family=AF_INET, sin_port=htons(60301), sin_addr=inet_addr("127.0.0.1")}, [16]) = 976 recvfrom(4, "OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO"..., 1024, 0, {sa_family=AF_INET, sin_port=htons(60301), sin_addr=inet_addr("127.0.0.1")}, [16]) = 992 recvfrom(4, "PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP"..., 1024, 0, {sa_family=AF_INET, sin_port=htons(60301), sin_addr=inet_addr("127.0.0.1")}, [16]) = 1008 -snip-
tcpdumpコマンドを実行すると、loデバイスを介してUDPパケットを送受信していることがわかります。なお、tcpdumpコマンドの使い方は、tcpdumpの使い方(基本編) - hana_shinのLinux技術ブログを参照してください。
[root@server ~]# tcpdump -i lo -nn dropped privs to tcpdump tcpdump: verbose output suppressed, use -v[v]... for full protocol decode listening on lo, link-type EN10MB (Ethernet), snapshot length 262144 bytes 20:01:24.361797 IP 127.0.0.1.60301 > 127.0.0.1.7000: rx type 86 (480) 20:01:24.361805 IP 127.0.0.1.60301 > 127.0.0.1.7000: rx type 87 (496) 20:01:24.361813 IP 127.0.0.1.60301 > 127.0.0.1.7000: rx type 88 (512) -snip-
Ctrl+cを押下してstress-ngコマンドを終了します。
[root@server ~]# stress-ng -k --udp 1 stress-ng: info: [1541] defaulting to a 86400 second (1 day, 0.00 secs) run per stressor stress-ng: info: [1541] dispatching hogs: 1 udp ^Cstress-ng: info: [1541] successful run completed in 653.52s (10 mins, 53.52 secs)
6 受信待ちのポート番号を指定する方法(--udp-port)
--udp-port オプションは、UDPパケットの到着を待ち受けるポート番号を指定するためのオプションです。デフォルトではポート番号7000が使用されますが、もし他のプロセスが同じポート番号(7000)をすでに使用している場合、このオプションを使用して、stress-ngプロセスの受信ポート番号を変更することができます。
[root@server ~]# stress-ng -k --udp 1 --udp-port 8000 stress-ng: info: [1790] defaulting to a 86400 second (1 day, 0.00 secs) run per stressor stress-ng: info: [1790] dispatching hogs: 1 udp
lsofコマンドを実行すると、stress-ngプロセスが8000番ポートでUDPパケットの受信待ちをしていることが確認できます。
[root@server ~]# lsof -c stress-ng -a -i -a -nP COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME stress-ng 1791 root 4u IPv4 25883 0t0 UDP *:8000 stress-ng 1792 root 4u IPv4 23820 0t0 UDP *:48625
7 IPv4またはIPv6を指定する方法(--udp-domain)
--udp-domainオプションは、UDPパケットの送受信において、IPv4またはIPv6を使用するかを指定するオプションです。デフォルトでは、UDPパケットの送受信にはIPv4が利用されますが、このオプションを使用することでIPv6を選択することが可能です
送受信するUDPパケットを確認するため、tcpdumpコマンドを実行します。
[root@server ~]# tcpdump -i lo -nn
--udp-domainオプションにipv6を指定して、stress-ngコマンドを実行します。
[root@server ~]# stress-ng -k --udp 1 --udp-domain ipv6 stress-ng: info: [1314] defaulting to a 86400 second (1 day, 0.00 secs) run per stressor stress-ng: info: [1314] dispatching hogs: 1 udp stress-ng: info: [1314] successful run completed in 0.01s
送受信するUDPパケットを確認するため、tcpdumpコマンドを実行すると、ループバックアドレスでIPv6のUDPパケットが送受信されていることが確認できます。
[root@server ~]# tcpdump -i lo -nn dropped privs to tcpdump tcpdump: verbose output suppressed, use -v[v]... for full protocol decode listening on lo, link-type EN10MB (Ethernet), snapshot length 262144 bytes 20:16:11.211740 IP6 ::1.60769 > ::1.7000: [|rx] (16) 20:16:11.211915 IP6 ::1.60769 > ::1.7000: rx type 66 (32) 20:16:11.211938 IP6 ::1.60769 > ::1.7000: rx type 67 (48) 20:16:11.211958 IP6 ::1.60769 > ::1.7000: rx type 68 (64) -snip-
8 実行回数を指定する方法(--udp-ops)
--udp-opsはUDPパケットの送信回数を指定するオプションです。
UDPパケットを5回送信してみます。
[root@server ~]# stress-ng -k --udp 1 --udp-ops 5 stress-ng: info: [1636] defaulting to a 86400 second (1 day, 0.00 secs) run per stressor stress-ng: info: [1636] dispatching hogs: 1 udp stress-ng: info: [1636] successful run completed in 0.00s
tcpdumpコマンドの実行結果を確認すると、UDPパケットが5回送信されているのがわかります。
[root@server ~]# tcpdump -i lo -nn dropped privs to tcpdump tcpdump: verbose output suppressed, use -v[v]... for full protocol decode listening on lo, link-type EN10MB (Ethernet), snapshot length 262144 bytes 20:24:55.105270 IP 127.0.0.1.47176 > 127.0.0.1.7000: [|rx] (16) 20:24:55.105338 IP 127.0.0.1.47176 > 127.0.0.1.7000: rx type 66 (32) 20:24:55.105361 IP 127.0.0.1.47176 > 127.0.0.1.7000: rx type 67 (48) 20:24:55.105380 IP 127.0.0.1.47176 > 127.0.0.1.7000: rx type 68 (64) 20:24:55.105398 IP 127.0.0.1.47176 > 127.0.0.1.7000: rx type 69 (80)
9 UDPパケット送受信するインタフェースを指定する方法(--udp-if)
--udp-ifオプションは、UDPパケットの送受信に使用するインタフェースを指定するオプションですが、実験をしてみると正常に機能していないようにみえます。
--udp-ifオプションにeth0を指定してstress-ngコマンドを実行します。
[root@server ~]# stress-ng -k --udp 1 --udp-if eth0 --udp-ops 3 stress-ng: info: [1235] defaulting to a 86400 second (1 day, 0.00 secs) run per stressor stress-ng: info: [1235] dispatching hogs: 1 udp stress-ng: info: [1235] successful run completed in 0.01s
tcpdumpコマンドの実行結果を確認すると、インタフェースにeth0を指定したにもかかわらず、lo(127.0.0.1)を使用しています。
[root@server ~]# tcpdump -i any udp port 7000 -nn tcpdump: data link type LINUX_SLL2 dropped privs to tcpdump tcpdump: verbose output suppressed, use -v[v]... for full protocol decode listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes 20:03:14.857652 lo In IP 127.0.0.1.51858 > 127.0.0.1.7000: [|rx] (16) 20:03:14.857752 lo In IP 127.0.0.1.51858 > 127.0.0.1.7000: rx type 66 (32) 20:03:14.857768 lo In IP 127.0.0.1.51858 > 127.0.0.1.7000: rx type 67 (48) 20:03:14.857779 lo In IP 127.0.0.1.51858 > 127.0.0.1.7000: rx type 68 (64) 20:03:14.857789 lo In IP 127.0.0.1.51858 > 127.0.0.1.7000: rx type 69 (80) -snip-
10 受信待ちのポート番号をランダムに指定する方法(--udp-flood)
--udp-floodオプションは、UDPパケットの受信ポート番号をランダムに指定するオプションです。
送受信するUDPパケットを確認するため、tcpdumpコマンドを実行します。
[root@server ~]# tcpdump -i any udp -nn
stress-ngコマンドを実行します。
[root@server ~]# stress-ng -k --udp-flood 1 --udp-flood-ops 3 stress-ng: info: [1273] defaulting to a 86400 second (1 day, 0.00 secs) run per stressor stress-ng: info: [1273] dispatching hogs: 1 udp-flood stress-ng: info: [1273] successful run completed in 0.00s
tcpdumpコマンドの実行結果を確認すると、UDPパケットの受信ポート番号が1025,31282,1026と変化していることがわかります。
[root@server ~]# tcpdump -i any udp -nn tcpdump: data link type LINUX_SLL2 dropped privs to tcpdump tcpdump: verbose output suppressed, use -v[v]... for full protocol decode listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes 20:14:23.005442 lo In IP 127.0.0.1.36690 > 127.0.0.1.1025: UDP, length 1 20:14:23.005498 lo In IP 127.0.0.1.36690 > 127.0.0.1.31282: UDP, length 1 20:14:23.005543 lo In IP 127.0.0.1.36690 > 127.0.0.1.1026: UDP, length 2
Y 参考図書
TECHNICAL MASTER はじめてのAlmaLinux 9 & Rocky Linux 9 Linuxサーバエンジニア入門編
Z 参考情報
私が業務や記事執筆で参考にした書籍を以下のページに記載します。
Linux技術のスキルアップをしよう! - hana_shinのLinux技術ブログ