ネットワークのトラブルシューティングとパフォーマンスチューニング


Red Hat Enterprise Linux 10

ネットワークの問題のデバッグと解決

概要

ネットワーク設定のチューニングは、考慮すべき要素が多数ある複雑なプロセスです。たとえば、これには、CPU からメモリーへのアーキテクチャー、CPU コアの量などが含まれます。Red Hat Enterprise Linux は、ほとんどのシナリオに最適化されたデフォルト設定を使用します。ただし、場合によっては、ネットワーク設定をチューニングして、スループットや遅延を増やしたり、パケットドロップなどの問題を解決したりする必要があります。

Red Hat ドキュメントへのフィードバック (英語のみ)

Red Hat は質の高いドキュメントを提供することに尽力しており、皆様からのフィードバックを大切にしています。改善にご協力いただくため、Red Hat Jira トラッキングシステムを通じてご提案やエラー報告をお寄せください。

手順

  1. Jira の Web サイトにログインします。

    アカウントがない場合、アカウント作成オプションを選択します。

  2. 上部のナビゲーションバーで Create をクリックします。
  3. Summary フィールドにわかりやすいタイトルを入力します。
  4. Description フィールドに、ドキュメントの改善に関するご意見を記入してください。ドキュメントの該当部分へのリンクも追加してください。
  5. ウィンドウ下部の Create をクリックします。

第1章 ネットワークアダプター設定のチューニング

40 Gbps 以上の高速ネットワークでは、ネットワークアダプター関連のカーネル設定の特定のデフォルト値がパケットドロップやパフォーマンス低下の原因となる可能性があります。これらの設定をチューニングすると、このような問題を防ぐことができます。

パケットドロップ率が原因でアプリケーションがデータの損失、タイムアウト、またはその他の問題を報告する場合は、イーサネットデバイスのリングバッファーのサイズを増やします。

受信リングバッファーは、デバイスドライバーとネットワークインターフェイスコントローラー (NIC) の間で共有されます。カードは、送信 (TX) および受信 (RX) リングバッファーを割り当てます。名前が示すように、リングバッファーは循環バッファーであり、オーバーフローによって既存のデータが上書きされます。NIC からカーネルにデータを移動するには、ハードウェア割り込みと、SoftIRQ とも呼ばれるソフトウェア割り込みの 2 つの方法があります。

カーネルは RX リングバッファーを使用して、デバイスドライバーが着信パケットを処理できるようになるまで着信パケットを格納します。デバイスドライバーは、通常は SoftIRQ を使用して RX リングをドレインします。これにより、着信パケットは sk_buff または skb と呼ばれるカーネルデータ構造に配置され、カーネルを経由して関連するソケットを所有するアプリケーションまでの移動を開始します。

カーネルは、ネットワーク宛ての送信パケットを保持するために TX リングバッファーを使用します。このリングバッファーは、スタックの最下層に位置し、パケットドロップが発生しうる重要な箇所です。パケットドロップは、ネットワークパフォーマンスに悪影響を及ぼします。

手順

  1. インターフェイスのパケットドロップ統計を表示します。

    # ethtool -S enp1s0
        ...
        rx_queue_0_drops: 97326
        rx_queue_1_drops: 63783
        ...

    コマンドの出力は、ネットワークカードとドライバーに依存することに注意してください。

    discard または drop カウンターの値が高い場合は、カーネルがパケットを処理できるよりも速く、使用可能なバッファーがいっぱいになることを示します。リングバッファーを増やすと、このような損失を回避できます。

  2. 最大リングバッファーサイズを表示します。

    # ethtool -g enp1s0
     Ring parameters for enp1s0:
     Pre-set maximums:
     RX:             4096
     RX Mini:        0
     RX Jumbo:       16320
     TX:             4096
     Current hardware settings:
     RX:             255
     RX Mini:        0
     RX Jumbo:       0
     TX:             255

    Pre-set maximums セクションの値が Current hardware settings セクションよりも高い場合は、次の手順で設定を変更できます。

  3. このインターフェイスを使用する NetworkManager 接続プロファイルを特定します。

    # nmcli connection show
    NAME                UUID                                  TYPE      DEVICE
    Example-Connection  a5eb6490-cc20-3668-81f8-0314a27f3f75  ethernet  enp1s0
  4. 接続プロファイルを更新し、リングバッファーを増やします。

    • RX リングバッファーを増やすには、次のように実行します。

      # nmcli connection modify Example-Connection ethtool.ring-rx 4096
    • TX リングバッファーを増やすには、次のように実行します。

      # nmcli connection modify Example-Connection ethtool.ring-tx 4096
  5. NetworkManager 接続をリロードします。

    # nmcli connection up Example-Connection
    重要

    NIC が使用するドライバーによっては、リングバッファーを変更すると、ネットワーク接続が短時間中断されることがあります。

パケットドロップ率が原因でアプリケーションがデータの損失、タイムアウト、またはその他の問題を報告する場合は、イーサネットデバイスのリングバッファーのサイズを増やします。

リングバッファーは循環バッファーであり、オーバーフローによって既存のデータが上書きされます。ネットワークカードは、送信 (TX) および受信 (RX) リングバッファーを割り当てます。受信リングバッファーは、デバイスドライバーとネットワークインターフェイスコントローラー (NIC) の間で共有されます。データは、ハードウェア割り込みまたは SoftIRQ とも呼ばれるソフトウェア割り込みによって NIC からカーネルに移動できます。

カーネルは RX リングバッファーを使用して、デバイスドライバーが着信パケットを処理できるようになるまで着信パケットを格納します。デバイスドライバーは、通常は SoftIRQ を使用して RX リングをドレインします。これにより、着信パケットは sk_buff または skb と呼ばれるカーネルデータ構造に配置され、カーネルを経由して関連するソケットを所有するアプリケーションまでの移動を開始します。

カーネルは、ネットワーク宛ての送信パケットを保持するために TX リングバッファーを使用します。このリングバッファーは、スタックの最下層に位置し、パケットドロップが発生しうる重要な箇所です。パケットドロップは、ネットワークパフォーマンスに悪影響を及ぼします。

リングバッファー設定は、NetworkManager 接続プロファイルで設定します。Ansible と network RHEL システムロールを使用すると、このプロセスを自動化し、Playbook で定義されたホスト上の接続プロファイルをリモートで設定できます。

警告

network RHEL システムロールを使用して、既存接続プロファイル内の特定の値だけを更新することはできません。このロールは、接続プロファイルが Playbook の設定と正確に一致するようにします。同じ名前の接続プロファイルがすでに存在する場合、このロールは Playbook の設定を適用し、プロファイル内の他のすべての設定をデフォルトにリセットします。値がリセットされないようにするには、変更しない設定も含め、ネットワーク接続プロファイルの設定全体を Playbook に常に指定してください。

前提条件

  • コントロールノードと管理対象ノードの準備が完了している
  • 管理対象ノードで Playbook を実行できるユーザーとしてコントロールノードにログインしている。
  • 管理対象ノードへの接続に使用するアカウントに、そのノードに対する sudo 権限がある。
  • デバイスがサポートする最大リングバッファーサイズを把握している。

手順

  1. 次の内容を含む Playbook ファイル (例: ~/playbook.yml) を作成します。

    ---
    - name: Configure the network
      hosts: managed-node-01.example.com
      tasks:
        - name: Ethernet connection profile with dynamic IP address setting and increased ring buffer sizes
          ansible.builtin.include_role:
            name: redhat.rhel_system_roles.network
          vars:
            network_connections:
              - name: enp1s0
                type: ethernet
                autoconnect: yes
                ip:
                  dhcp4: yes
                  auto6: yes
                ethtool:
                  ring:
                    rx: 4096
                    tx: 4096
                state: up

    サンプル Playbook で指定されている設定は次のとおりです。

    rx: <value>
    受信するリングバッファーエントリーの最大数を設定します。
    tx: <value>
    送信するリングバッファーエントリーの最大数を設定します。

    Playbook で使用されるすべての変数の詳細は、コントロールノードの /usr/share/ansible/roles/rhel-system-roles.network/README.md ファイルを参照してください。

  2. Playbook の構文を検証します。

    $ ansible-playbook --syntax-check ~/playbook.yml

    このコマンドは構文を検証するだけであり、有効だが不適切な設定から保護するものではないことに注意してください。

  3. Playbook を実行します。

    $ ansible-playbook ~/playbook.yml

検証

  • 最大リングバッファーサイズを表示します。

    # ansible managed-node-01.example.com -m command -a 'ethtool -g enp1s0'
    managed-node-01.example.com | CHANGED | rc=0 >>
    ...
    Current hardware settings:
    RX:             4096
    RX Mini:        0
    RX Jumbo:       0
    TX:             4096

ネットワークカードがパケットを受信し、カーネルプロトコルスタックがこれらのパケットを処理する前に、カーネルはこれらのパケットをバックログキューに保存します。カーネルは、CPU コアごとに個別のキューを維持します。

コアのバックログキューがいっぱいの場合、カーネルは、netif_receive_skb() カーネル関数がこのキューに割り当てるそれ以降の受信パケットをすべてドロップします。サーバーに速度が 10 Gbps 以上のネットワークアダプターまたは複数の 1 Gbps アダプターが含まれている場合は、バックログキューのサイズをチューニングしてこの問題を回避します。

前提条件

  • 速度が 10 Gbps 以上、または複数の 1 Gbps ネットワークアダプター

手順

  1. バックログキューのチューニングが必要かどうかを判断し、/proc/net/softnet_stat ファイル内のカウンターを表示します。

    # awk '{for (i=1; i<=NF; i++) printf strtonum("0x" $i) (i==NF?"\n":" ")}' /proc/net/softnet_stat | column -t
    221951548  0      0  0  0  0  0  0  0  0  0  0  0
    192058677  18862  0  0  0  0  0  0  0  0  0  0  1
    455324886  0      0  0  0  0  0  0  0  0  0  0  2
    ...

    この awk コマンドは、/proc/net/softnet_stat の値を 16 進形式から 10 進形式に変換し、表形式で表示します。各行は、コア 0 から始まる CPU コアを表します。

    関連する列は次のとおりです。

    • 最初の列: 受信フレームの総数
    • 2 番目の列: バックログキューがいっぱいであるためにドロップされたフレームの数
    • 最後の列: CPU コア番号
  2. /proc/net/softnet_stat ファイルの 2 番目の列の値が時間の経過とともに増加する場合は、バックログキューのサイズを増やします。

    1. 現在のバックログキューのサイズを表示します。

      # sysctl net.core.netdev_max_backlog
      net.core.netdev_max_backlog = 1000
    2. 次の内容を含む /etc/sysctl.d/10-netdev_max_backlog.conf ファイルを作成します。

      net.core.netdev_max_backlog = 2000

      net.core.netdev_max_backlog パラメーターを現在の値の 2 倍に設定します。

    3. /etc/sysctl.d/10-netdev_max_backlog.conf ファイルから設定をロードします。

      # sysctl -p /etc/sysctl.d/10-netdev_max_backlog.conf

検証

  • /proc/net/softnet_stat ファイルの 2 番目の列を監視します。

    # awk '{for (i=1; i<=NF; i++) printf strtonum("0x" $i) (i==NF?"\n":" ")}' /proc/net/softnet_stat | column -t

    それでも値が増加する場合は、net.core.netdev_max_backlog 値を再度 2 倍にします。パケットドロップカウンターが増加しなくなるまで、このプロセスを繰り返します。

1.4. NIC の送信キューの長さを増やして送信エラーの数を減らす

カーネルは、パケットを送信する前に送信キューにパケットを格納します。デフォルトのキュー長 (1000 パケット) は、10Gbps ネットワークでは多くの場合十分です。ただし、より高速なネットワークの場合、またはアダプターで送信エラーが増加する場合は、キューの長さを増やしてください。

手順

  1. 現在の送信キューの長さを表示します。

    # ip -s link show enp1s0
    2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
    ...

    この例では、enp1s0 インターフェイスの送信キューの長さ (qlen) は 1000 です。

  2. ネットワークインターフェイスのソフトウェア送信キューのドロップされたパケットカウンターを監視します。

    # tc -s qdisc show dev enp1s0
    qdisc fq_codel 0: root refcnt 2 limit 10240p flows 1024 quantum 1514 target 5ms interval 100ms memory_limit 32Mb ecn drop_batch 64
     Sent 16889923 bytes 426862765 pkt (dropped 191980, overlimits 0 requeues 2)
    ...
  3. 送信エラー数が多い、または増加している場合は、送信キューの長さをより長く設定します。

    1. このインターフェイスを使用する NetworkManager 接続プロファイルを特定します。

      # nmcli connection show
      NAME                UUID                                  TYPE      DEVICE
      Example-Connection  a5eb6490-cc20-3668-81f8-0314a27f3f75  ethernet  enp1s0
    2. 接続プロファイルを更新し、送信キューの長さを増やします。

      # nmcli connection modify Example-Connection link.tx-queue-length 2000

      キューの長さを現在の値の 2 倍に設定します。

    3. 変更を適用します。

      # nmcli connection up Example-Connection

検証

  1. 送信キューの長さを表示します。

    # ip -s link show enp1s0
    2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 2000
    ...
  2. ドロップされたパケットカウンターを監視します。

    # tc -s qdisc show dev enp1s0

    dropped カウンターがまだ増加する場合は、送信キューの長さを再度 2 倍にします。カウンターが増加しなくなるまで、このプロセスを繰り返します。

第2章 IRQ バランシングのチューニング

マルチコアホストでは、Red Hat Enterprise Linux が割り込みキュー (IRQ) のバランスをとり、CPU コア全体に割り込みを分散するようにすることで、パフォーマンスを向上させることができます。

2.1. 割り込みと割り込みハンドラー

パフォーマンスの問題をトラブルシューティングするには、コンピューターがタスクを管理し、イベントに応答する方法を理解する必要があります。このプロセスは、CPU に緊急のタスクを処理するよう信号を送る割り込みと、その要求を処理する特定のルーチンである割り込みハンドラーに依存しています。

ネットワークインターフェイスコントローラー (NIC) が受信データを受信すると、Direct Memory Access (DMA) を使用してそのデータをカーネルバッファーにコピーします。次に、NIC はハード割り込みをトリガーして、このデータについてカーネルに通知します。これらの割り込みは、すでに別のタスクに割り込んでおり、ハンドラー自体は割り込むことができないため、最小限の作業を行う割り込みハンドラーによって処理されます。ハード割り込みは、特にカーネルロックを使用する場合、CPU 使用率の点でコストがかかる可能性があります。

その後、ハード割り込みハンドラーは、パケット受信の大部分をソフトウェア割り込み要求 (SoftIRQ) プロセスに任せます。カーネルは、これらのプロセスをより公平にスケジュールできます。

例2.1 ハードウェア割り込みの表示

カーネルは、割り込みカウンターを /proc/interrupts ファイルに保存します。enp1s0 などの特定の NIC のカウンターを表示するには、次のように入力します。

# grep -E "CPU|enp1s0" /proc/interrupts
         CPU0     CPU1     CPU2    CPU3    CPU4   CPU5
 105:  141606        0        0       0       0      0  IR-PCI-MSI-edge      enp1s0-rx-0
 106:       0   141091        0       0       0      0  IR-PCI-MSI-edge      enp1s0-rx-1
 107:       2        0   163785       0       0      0  IR-PCI-MSI-edge      enp1s0-rx-2
 108:       3        0        0  194370       0      0  IR-PCI-MSI-edge      enp1s0-rx-3
 109:       0        0        0       0       0      0  IR-PCI-MSI-edge      enp1s0-tx

各キューには、最初の列に割り込みベクトルが割り当てられています。カーネルは、システムの起動時、またはユーザーが NIC ドライバーモジュールをロードしたときに、これらのベクトルを初期化します。各受信 (RX) キューと送信 (TX) キューには、どの NIC またはキューから割り込みが発生しているかを割り込みハンドラーに通知する固有のベクトルが割り当てられます。列は、各 CPU コアの受信割り込みの数を表します。

2.2. ソフトウェア割り込み要求

ソフトウェア割り込み要求 (SoftIRQ) は、ネットワークアダプターの受信リングバッファーをクリアします。カーネルは、他のタスクが中断されない時間帯に SoftIRQ ルーチンを実行するようにスケジュールします。RHEL では、ksoftirqd/cpu-number という名前のプロセスがこのルーチンを実行し、ドライバー固有のコード関数を呼び出します。

各 CPU コアの SoftIRQ カウンターを監視するには、次のように入力します。

# watch -n1 'grep -E "CPU|NET_RX|NET_TX" /proc/softirqs'
                    CPU0       CPU1	  CPU2       CPU3	CPU4	   CPU5       CPU6	 CPU7
      NET_TX:	   49672      52610	 28175      97288      12633	  19843      18746     220689
      NET_RX:         96       1615        789         46         31	   1735       1315     470798

このコマンドは出力を動的に更新します。Ctrl+C を押して出力に割り込みます。

2.3. NAPI ポーリング

New API (NAPI) は、受信ネットワークパケットの効率を向上させるためのデバイスドライバーパケット処理フレームワークの拡張機能です。

ハード割り込みは、通常、カーネル空間からユーザー空間へのコンテキストの切り替えを引き起こし、またその逆のコンテキストの切り替えも引き起こし、それ自体を中断することができないため、コストがかかります。割り込み結合を行っても、割り込みハンドラーは CPU コアを完全に独占します。NAPI を使用すると、ドライバーは、パケットを受信するたびにカーネルによってハード割り込みされるのではなく、ポーリングモードを使用できます。

通常の操作では、カーネルは最初のハード割り込みを発行し、続いて NAPI ルーチンを使用してネットワークカードをポーリングするソフト割り込み要求 (SoftIRQ) ハンドラーを発行します。SoftIRQ が CPU コアを独占しないようにするために、ポーリングルーチンには、SoftIRQ が消費できる CPU 時間を決定するバジェットがあります。SoftIRQ ポーリングルーチンが完了すると、カーネルはルーチンを終了し、後で再度実行してネットワークカードからパケットを受信するプロセスを繰り返すようにスケジュールします。

2.4. irqbalance サービス

Non-Uniform Memory Access (NUMA) アーキテクチャーを備えたシステムと備えていないシステムの両方で、irqbalance サービスは、システム条件に基づいて CPU コア間で効果的に割り込みのバランスをとります。

irqbalance サービスはバックグラウンドで実行され、10 秒ごとに CPU 負荷を監視します。CPU の負荷が高すぎる場合、このサービスは割り込みを他の CPU コアに移動します。その結果、システムのパフォーマンスが向上し、負荷がより効率的に処理されます。

irqbalance が実行されていない場合、通常は CPU コア 0 がほとんどの割り込みを処理します。中程度の負荷でも、この CPU コアはシステム内のすべてのハードウェアのワークロードを処理しようとしてビジーになる可能性があります。その結果、割り込みまたは割り込みベースの作業ができなかったり、遅延したりする可能性があります。これにより、ネットワークやストレージのパフォーマンスの低下、パケットロス、その他の問題が発生する可能性があります。

重要

irqbalance を無効にすると、ネットワークのスループットに悪影響を及ぼす可能性があります。

CPU コアが 1 つしかないシステムでは、irqbalance サービスは何のメリットも提供せず、自動的に終了します。

デフォルトでは、irqbalance サービスは有効になっており、Red Hat Enterprise Linux 上で実行されています。サービスを無効にした場合に再度有効にするには、次のように入力します。

# systemctl enable --now irqbalance

2.5. CPU 上で SoftIRQ を実行できる時間の増加

SoftIRQ の実行時間が十分でない場合、受信データの速度が、バッファーを十分な速さでドレインするカーネルの能力を超える可能性があります。その結果、ネットワークインターフェイスコントローラー (NIC) のバッファーがオーバーフローし、パケットが失われます。

softirqd プロセスが 1 回の NAPI ポーリングサイクルでインターフェイスからすべてのパケットを取得できなかった場合、それは SoftIRQ に十分な CPU 時間がないことを示しています。これは、10 Gbps 以上の高速 NIC を備えたホストに当てはまる可能性があります。net.core.netdev_budget および net.core.netdev_budget_usecs カーネルパラメーターの値を増やすと、softirqd がポーリングサイクルで処理できる時間とパケット数を制御できます。

手順

  1. net.core.netdev_budget パラメーターのチューニングが必要かどうかを判断するには、/proc/net/softnet_stat ファイル内のカウンターを表示します。

    # awk '{for (i=1; i<=NF; i++) printf strtonum("0x" $i) (i==NF?"\n":" ")}' /proc/net/softnet_stat | column -t
    221951548  0  0      0  0  0  0  0  0  0  0  0  0
    192058677  0  20380  0  0  0  0  0  0  0  0  0  1
    455324886  0  0      0  0  0  0  0  0  0  0  0  2
    ...

    この awk コマンドは、/proc/net/softnet_stat の値を 16 進形式から 10 進形式に変換し、表形式で表示します。各行は、コア 0 から始まる CPU コアを表します。

    関連する列は次のとおりです。

    • 最初の列: 受信フレームの総数。
    • 3 番目の列: 1 回の NAPI ポーリングサイクルでインターフェイスからすべてのパケットを取得できなかった softirqd プロセスの回数。
    • 最後の列: CPU コア番号。
  2. /proc/net/softnet_stat ファイルの 3 番目の列のカウンターが、時間の経過とともに増加する場合は、システムをチューニングします。

    1. net.core.netdev_budget_usecs および net.core.netdev_budget パラメーターの現在の値を表示します。

      # sysctl net.core.netdev_budget_usecs net.core.netdev_budget
      net.core.netdev_budget_usecs = 2000
      net.core.netdev_budget = 300

      これらの設定を使用すると、softirqd プロセスは、1 回のポーリングサイクルで、NIC から最大 300 個のメッセージを処理するのに最大 2000 マイクロ秒あります。ポーリングは、どの条件が最初に満たされたかに基づいて終了します。

    2. 次の内容を含む /etc/sysctl.d/10-netdev_budget.conf ファイルを作成します。

      net.core.netdev_budget = 600
      net.core.netdev_budget_usecs = 4000

      パラメーターを現在の値の 2 倍に設定します。

    3. /etc/sysctl.d/10-netdev_budget.conf ファイルから設定をロードします。

      # sysctl -p /etc/sysctl.d/10-netdev_budget.conf

検証

  • /proc/net/softnet_stat ファイルの 3 番目の列を監視します。

    # awk '{for (i=1; i<=NF; i++) printf strtonum("0x" $i) (i==NF?"\n":" ")}' /proc/net/softnet_stat | column -t

    それでも値が増加する場合は、net.core.netdev_budget_usecsnet.core.netdev_budget をより高い値に設定します。カウンターが増加しなくなるまで、このプロセスを繰り返します。

第3章 ネットワーク遅延の改善

CPU 電力管理機能により、時間を考慮する必要があるアプリケーション処理に望ましくない遅延が発生する可能性があります。これらの電源管理機能の一部またはすべてを無効にして、ネットワーク遅延を改善できます。

たとえば、サーバーの負荷が高いときよりもアイドル状態のときの遅延が高い場合は、CPU 電源管理設定が遅延に影響を与える可能性があります。

重要

CPU 電源管理機能を無効にすると、電力消費量が増加し、熱損失が発生する可能性があります。

3.1. CPU の電源状態がネットワーク遅延に与える影響

CPU の消費状態 (C ステート) は、コンピューターの電力消費を最適化して削減します。

C ステートには、C0 から始まる番号があります。C0 では、プロセッサーはフルパワーで動作し、実行しています。C1 では、プロセッサーはフルパワーで動作していますが、実行されていません。C ステートの番号が大きいほど、CPU がオフにするコンポーネントの数が多くなります。

CPU コアがアイドル状態のときは、組み込みの省電力ロジックが常に介入し、さまざまなプロセッサーコンポーネントをオフにして、コアを現在の C ステートからより高いステートに移行しようと試みます。CPU コアがデータを処理する必要がある場合、Red Hat Enterprise Linux (RHEL) はプロセッサーに割り込みを送信してコアをウェイクアップし、C ステートを C0 に戻します。

深い C ステートから C0 に戻るには、プロセッサーのさまざまなコンポーネントの電源を再びオンにする必要があるため、時間がかかります。マルチコアシステムでは、多くのコアが同時にアイドル状態になり、より深い C ステートになることもあります。RHEL がそれらを同時にウェイクアップしようとすると、すべてのコアが深い C ステートから戻る間に、カーネルが大量のプロセッサー間割り込み (IPI) を生成する可能性があります。割り込みの処理中にロックが必要となるため、システムはすべての割り込みの処理中にしばらく停止する可能性があります。これにより、イベントに対するアプリケーションの応答が大幅に遅延する可能性があります。

例3.1 コアごとの C ステート時間の表示

PowerTOP アプリケーションの Idle Stats ページには、CPU コアが各 C ステートで費やした時間が表示されます。

           Pkg(HW)  |            Core(HW) |            CPU(OS) 0   CPU(OS) 4
                    |                     | C0 active   2.5%        2.2%
                    |                     | POLL        0.0%    0.0 ms  0.0%    0.1 ms
                    |                     | C1          0.1%    0.2 ms  0.0%    0.1 ms
C2 (pc2)   63.7%    |                     |
C3 (pc3)    0.0%    | C3 (cc3)    0.1%    | C3          0.1%    0.1 ms  0.1%    0.1 ms
C6 (pc6)    0.0%    | C6 (cc6)    8.3%    | C6          5.2%    0.6 ms  6.0%    0.6 ms
C7 (pc7)    0.0%    | C7 (cc7)   76.6%    | C7s         0.0%    0.0 ms  0.0%    0.0 ms
C8 (pc8)    0.0%    |                     | C8          6.3%    0.9 ms  5.8%    0.8 ms
C9 (pc9)    0.0%    |                     | C9          0.4%    3.7 ms  2.2%    2.2 ms
C10 (pc10)  0.0%    |                     |
                    |                     | C10        80.8%    3.7 ms 79.4%    4.4 ms
                    |                     | C1E         0.1%    0.1 ms  0.1%    0.1 ms
...

3.2. EFI ファームウェアの C ステート設定

EFI ファームウェアを備えたほとんどのシステムでは、個々の消費状態 (C ステート) を有効または無効にできます。ただし、RHEL では、アイドルドライバーによって、カーネルがファームウェアの設定を使用するかどうかが決定されます。

以下のドライバーが利用可能です。

  • intel_idle: これは、Intel CPU を搭載したホスト上のデフォルトのドライバーであり、EFI ファームウェアからの C ステート設定を無視します。
  • acpi_idle: RHEL は、Intel 以外のベンダーの CPU を搭載したホスト上、および intel_idle が無効になっている場合に、このドライバーを使用します。デフォルトでは、acpi_idle ドライバーは EFI ファームウェアの C ステート設定を使用します。

詳細は、kernel-doc パッケージによって提供される /usr/share/doc/kernel-doc-<version>/Documentation/admin-guide/pm/cpuidle.rst ファイルを参照してください。

3.3. カスタム TuneD プロファイルを使用した C ステートの無効化

TuneD サービスを使用すると、管理者がカーネルのコマンドラインパラメーターを使用して C ステートの最大値をハードコードする必要がなくなります。

TuneD サービスは、カーネルの Power Management Quality of Service (PMQOS) インターフェイスを使用して、消費状態 (C ステート) のロック設定を行います。カーネルアイドルドライバーは、このインターフェイスと通信して、C ステートを動的に制限できます。

前提条件

  • tuned パッケージがインストールされている。
  • tuned サービスが有効化され、実行されている。

手順

  1. アクティブなプロファイルを表示します。

    # tuned-adm active
    Current active profile: network-latency
  2. カスタム TuneD プロファイル用のディレクトリーを作成します。

    # mkdir /etc/tuned/network-latency-custom/
  3. 次の内容を含む /etc/tuned/network-latency-custom/tuned.conf ファイルを作成します。

    [main]
    include=network-latency
    
    [cpu]
    force_latency=cstate.id:1|2

    このカスタムプロファイルは、network-latency プロファイルからすべての設定を継承します。force_latency TuneD パラメーターは、遅延をマイクロ秒 (µs) 単位で指定します。指定した値よりも C ステートのレイテンシーが高い場合、Red Hat Enterprise Linux のドライバーにより、CPU がより高い C ステートに移行するのが防止されます。force_latency=cstate.id:1|2 を指定すると、TuneD は最初に /sys/devices/system/cpu/cpu_<number>_/cpuidle/state_<cstate.id>_/ ディレクトリーが存在するかどうかを確認します。この場合、TuneD はこのディレクトリー内の latency ファイルからレイテンシー値を読み取ります。ディレクトリーが存在しない場合は、TuneD はフォールバック値として 2 マイクロ秒を使用します。

  4. network-latency-custom プロファイルをアクティブ化します。

    # tuned-adm profile network-latency-custom

3.4. カーネルコマンドラインオプションを使用した C ステートの無効化

ホスト上のアプリケーションのレイテンシーが C ステートによって影響を受けているかどうかをテストするには、カーネルコマンドラインオプションで消費状態 (C ステート) を一時的に無効にします。

processor.max_cstate および intel_idle.max_cstate カーネルコマンドラインパラメーターにより、CPU コアが使用できる最大の C ステートを設定します。たとえば、パラメーターを 1 に設定すると、CPU が C1 より下の C ステートを要求することがなくなります。

特定の状態をハードコーディングしないようにするには、より動的なソリューションの使用を検討してください。カスタム TuneD プロファイルを使用した C-state の無効化 を参照してください。

前提条件

  • tuned サービスが実行されていないか、C ステート設定を更新しないように設定されている。

手順

  1. システムが使用するアイドル状態のドライバーを表示します。

    # cat /sys/devices/system/cpu/cpuidle/current_driver
    intel_idle

    ドライバーの詳細は、kernel-doc パッケージによって提供される /usr/share/doc/kernel-doc-<version>/Documentation/admin-guide/pm/cpuidle.rst ファイルを参照してください。

  2. ホストが intel_idle ドライバーを使用している場合は、intel_idle.max_cstate カーネルパラメーターを設定して、CPU コアが使用できる最大の C ステートを定義します。

    # grubby --update-kernel=ALL --args="intel_idle.max_cstate=0"

    intel_idle.max_cstate=0 を設定すると、intel_idle ドライバーが無効になります。その結果、カーネルが acpi_idle ドライバーを使用するようになります。このドライバーは、EFI ファームウェアに設定されている C ステート値を使用します。そのため、これらの C ステート設定をオーバーライドするには、processor.max_cstate も設定してください。

  3. すべてのホスト上で、CPU ベンダーに関係なく、CPU コアが使用できる最大の C ステートを設定します。

    # grubby --update-kernel=ALL --args="processor.max_cstate=0"
    重要

    intel_idle.max_cstate=0 に加えて processor.max_cstate=0 を設定すると、acpi_idle ドライバーは processor.max_cstate の値をオーバーライドして 1 に設定します。その結果、processor.max_cstate=0 intel_idle.max_cstate=0 の場合、カーネルが使用する最大の C ステートは C0 ではなく C1 になります。

  4. 変更を有効にするためにホストを再起動します。

    # reboot

検証

  1. 最大の C ステートを表示します。

    # cat /sys/module/processor/parameters/max_cstate
    1
  2. ホストが intel_idle ドライバーを使用している場合は、最大の C ステートを表示します。

    # cat /sys/module/intel_idle/parameters/max_cstate
    0

第4章 大量の連続したデータストリームのスループットの向上

大量の連続したデータストリームのスループットを向上させると、1 つのパケットでより多くのデータが送信され、オーバーヘッドが削減されるという利点が得られます。

IEEE 802.3 標準によれば、仮想ローカルエリアネットワーク (VLAN) タグのないデフォルトのイーサネットフレームの最大サイズは 1518 バイトです。これらの各フレームには 18 バイトのヘッダーが含まれて、ペイロード用に 1500 バイトが残されます。したがって、サーバーがネットワーク経由で送信するデータの 1500 バイトごとに、18 バイト (1.2%) のイーサネットフレームヘッダーがオーバーヘッドとなって送信されます。レイヤー 3 およびレイヤー 4 プロトコルのヘッダーにより、パケットあたりのオーバーヘッドがさらに増加します。

ネットワーク上のホストが、多数の連続したデータストリーム (バックアップサーバーや多数の巨大なファイルをホストするファイルサーバーなど) を頻繁に送信する場合は、オーバーヘッドを節約するためにジャンボフレームの採用を検討してください。ジャンボフレームは、標準のイーサネットペイロードサイズである 1500 バイトよりも大きな最大伝送単位 (MTU) を持つ非標準フレームです。たとえば、最大許容 MTU が 9000 バイトのペイロードでジャンボフレームを設定すると、各フレームのオーバーヘッドは 0.2% に減少します。

ネットワークやサービスによっては、クラスターのストレージサーバーなど、ネットワークの特定の部分でのみジャンボフレームを有効にすることが有益な場合があります。これにより、パケットの断片化が回避されます。

4.1. ジャンボフレームを設定する前の考慮事項

ネットワーク内のハードウェア、アプリケーション、サービスに応じて、ジャンボフレームはさまざまな影響を与える可能性があります。ジャンボフレームを有効にすることがシナリオにメリットをもたらすかどうかを慎重に考慮して決定してください。

ジャンボフレームの前提条件:

伝送パス上のすべてのネットワークデバイスはジャンボフレームをサポートし、同じ最大伝送単位 (MTU) サイズを使用する必要があります。逆の場合は、次の問題に直面する可能性があります。

  • ドロップされたパケット
  • 断片化されたパケットが原因の遅延が大きい
  • 断片化によるパケットロスのリスクの増加。たとえば、ルーターが 1 つの 9000 バイトのフレームを 6 つの 1500 バイトのフレームに断片化し、それらの 1500 バイトのフレームのいずれかが失われた場合、フレームを再構築できないため、フレーム全体が失われます。

次の図では、ネットワーク A のホストがネットワーク C のホストにパケットを送信する場合、3 つのサブネット内のすべてのホストが同じ MTU を使用する必要があります。

複数のネットワークを介した通信

ジャンボフレームの利点:

  • より高いスループット: 各フレームにはより多くのユーザーデータが含まれますが、プロトコルオーバーヘッドは固定されています。
  • CPU 使用率の低下: ジャンボフレームにより発生する割り込みが少なくなるため、CPU サイクルが節約されます。

ジャンボフレームの欠点:

  • 遅延が大きい: フレームが大きいと、後続のパケットが遅延します。
  • メモリーバッファーの使用量の増加: フレームが大きくなると、バッファーキューメモリーがより早くいっぱいになる可能性があります。

4.2. 既存の NetworkManager 接続プロファイルでの MTU の設定

ネットワークでデフォルトとは異なる最大伝送単位 (MTU) が必要な場合は、対応する NetworkManager 接続プロファイルでこの設定を設定できます。

ジャンボフレームは、1500 - 9000 バイトのペイロードを持つネットワークパケットです。同じブロードキャストドメイン内のすべてのデバイスは、これらのフレームをサポートする必要があります。

前提条件

  • ブロードキャストドメイン内のすべてのデバイスが同じ MTU を使用している。
  • ネットワークの MTU を把握している。
  • 不一致の MTU を使用するネットワークの接続プロファイルがすでに設定されている。

手順

  1. オプション: 現在の MTU を表示します。

    # ip link show
    ...
    3: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
        link/ether 52:54:00:74:79:56 brd ff:ff:ff:ff:ff:ff
    ...
  2. オプション: NetworkManager 接続プロファイルを表示します。

    # nmcli connection show
    NAME     UUID                                  TYPE      DEVICE
    Example  f2f33f29-bb5c-3a07-9069-be72eaec3ecf  ethernet  enp1s0
    ...
  3. 不一致の MTU を使用してネットワークへの接続を管理するプロファイルに MTU を設定します。

    # nmcli connection modify Example mtu 9000
  4. 接続を再度アクティベートします。

    # nmcli connection up Example

検証

  1. MTU 設定を表示します。

    # ip link show
    ...
    3: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9000 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
        link/ether 52:54:00:74:79:56 brd ff:ff:ff:ff:ff:ff
    ...
  2. 伝送パス上にパケットを断片化するホストがないことを確認します。

    • 受信側で、カーネルの IP 再構築統計を表示します。

      # nstat -az IpReasm*
      #kernel
      IpReasmTimeout 0 0.0
      IpReasmReqds 0 0.0
      IpReasmOKs 0 0.0
      IpReasmFails 0 0.0

      カウンターが 0 を返した場合、パケットは再構築されていません。

    • 送信者側で、prohibit-fragmentation-bit を指定して ICMP リクエストを送信します。

      # ping -c1 -Mdo -s 8972 destination_host

      コマンドが成功した場合、パケットは断片化されていません。

      -s パケットサイズオプションの値を次のように計算します。MTU サイズ - 8 バイト ICMP ヘッダー - 20 バイト IPv4 ヘッダー = パケットサイズ

第5章 高スループットのための TCP 接続のチューニング

Red Hat Enterprise Linux で TCP 関連の設定をチューニングして、スループットを向上させ、レイテンシーを短縮し、パケットロスなどの問題を防止します。

5.1. iperf3 を使用した TCP スループットのテスト

iperf3 ユーティリティーは、サーバーモードとクライアントモードを提供し、2 つのホスト間のネットワークスループットテストを実行します。

注記

アプリケーションのスループットは、アプリケーションが使用するバッファーサイズなどの多くの要因に依存します。したがって、iperf3 などのテストユーティリティーで測定された結果は、実稼働ワークロード下のサーバー上のアプリケーションの結果とは大幅に異なる可能性があります。

前提条件

  • iperf3 パッケージはクライアントとサーバーの両方にインストールされている。
  • どちらかのホスト上の他のサービスによって、テスト結果に大きな影響を与えるネットワークトラフィックが発生することはない。
  • 速度が 40 Gbps 以上の接続の場合、ネットワークカードは Accelerated Receive Flow Steering (ARFS) をサポートし、この機能はインターフェイスで有効になっている。

手順

  1. オプション: サーバーとクライアントの両方のネットワークインターフェイスコントローラー (NIC) の最大ネットワーク速度を表示します。

    # ethtool enp1s0 | grep "Speed"
       Speed: 100000Mb/s
  2. サーバー上では以下の設定になります。

    1. firewalld サービスでデフォルトの iperf3 TCP ポート 5201 を一時的に開きます。

      # firewall-cmd --add-port=5201/tcp
    2. iperf3 をサーバーモードで起動します。

      # iperf3 --server

      サービスは現在、受信クライアント接続を待機しています。

  3. クライアントで以下を実行します。

    1. スループットの測定を開始します。

      # iperf3 --time 60 --zerocopy --client 192.0.2.1
      • --time <seconds>: クライアントが送信を停止する時間を秒単位で定義します。

        このパラメーターを機能すると予想される値に設定し、後の測定で値を増やします。クライアントが送信パス上のデバイスまたはサーバーが処理できる速度よりも速い速度でパケットを送信すると、パケットがドロップされる可能性があります。

      • --zerocopy: write() システムコールを使用する代わりに、ゼロコピーメソッドを有効にします。このオプションは、ゼロコピー対応アプリケーションをシミュレートする場合、または単一ストリームで 40 Gbps 以上に達する場合にのみ必要です。
      • --client <server>: クライアントモードを有効にし、iperf3 サーバーを実行するサーバーの IP アドレスまたは名前を設定します。
  4. iperf3 がテストを完了するまで待ちます。サーバーとクライアントの両方で統計が毎秒表示され、最後に概要が表示されます。たとえば、以下はクライアントに表示される概要です。

    [ ID] Interval         Transfer    Bitrate         Retr
    [  5] 0.00-60.00  sec  101 GBytes   14.4 Gbits/sec   0   sender
    [  5] 0.00-60.04  sec  101 GBytes   14.4 Gbits/sec       receiver

    この例では、平均ビットレートは 14.4 Gbps でした。

  5. サーバー上では以下の設定になります。

    1. Ctrl+C を押して iperf3 サーバーを停止します。
    2. firewalld で TCP ポート 5201 を閉じます。

      # firewall-cmd --remove-port=5201/tcp

5.2. システム全体の TCP ソケットバッファー設定

ソケットバッファーは、カーネルが受信したデータ、または送信待ちのデータを一時的に格納します。

次のバッファーが存在します。

  • 読み取りソケットバッファーには、カーネルが受信したがアプリケーションがまだ読み取っていないパケットが保持されます。
  • 書き込みソケットバッファーには、アプリケーションがバッファーに書き込んだものの、カーネルがまだ IP スタックとネットワークドライバーに渡していないパケットが保持されます。

TCP パケットが大きすぎてバッファーサイズを超えている場合、またはパケットの送受信速度が速すぎる場合、カーネルはデータがバッファーから削除されるまで、新しい受信 TCP パケットをドロップします。この場合、ソケットバッファーを増やすことでパケットロスを防ぐことができます。

net.ipv4.tcp_rmem (読み取り) と net.ipv4.tcp_wmem (書き込み) の両方のソケットバッファーカーネル設定には、次の 3 つの値が含まれます。

net.ipv4.tcp_rmem = 4096  131072  6291456
net.ipv4.tcp_wmem = 4096  16384   4194304

表示される値はバイト単位であり、Red Hat Enterprise Linux はそれらを次の方法で使用します。

  • 最初の値は最小バッファーサイズです。新しいソケットのサイズを小さくすることはできません。
  • 2 番目の値はデフォルトのバッファーサイズです。アプリケーションがバッファーサイズを設定しない場合、これがデフォルト値になります。
  • 3 番目の値は、自動的にチューニングされるバッファーの最大サイズです。アプリケーションで setsockopt() 関数を SO_SNDBUF ソケットオプションとともに使用すると、この最大バッファーサイズが無効になります。

net.ipv4.tcp_rmem および net.ipv4.tcp_wmem パラメーターは、IPv4 プロトコルと IPv6 プロトコルの両方のソケットサイズを設定することに注意してください。

5.3. システム全体の TCP ソケットバッファーの増加

システム全体の TCP ソケットバッファーは、カーネルが受信したデータ、または送信待ちのデータを一時的に保存します。net.ipv4.tcp_rmem (読み取り) と net.ipv4.tcp_wmem (書き込み) の両方のソケットバッファーカーネル設定に、最小値、デフォルト値、最大値の 3 つの設定が含まれています。

重要

バッファーサイズを大きすぎる設定にすると、メモリーが無駄に消費されます。各ソケットはアプリケーションが要求するサイズに設定でき、カーネルはこの値を 2 倍にします。たとえば、アプリケーションが 256 KiB のソケットバッファーサイズを要求し、100 万個のソケットを開く場合、システムは潜在的なソケットバッファースペースとしてのみ最大 512 GB RAM (512 KiB x 100 万) を使用できます。

さらに、最大バッファーサイズの値が大きすぎると、レイテンシーが長くなる可能性があります。

前提条件

  • 著しく高い割合で TCP パケットが破棄されている。

手順

  1. 接続の遅延を決定します。たとえば、クライアントからサーバーに ping を実行して、平均ラウンドトリップ時間 (RTT) を測定します。

    # ping -c 10 server.example.com
    ...
    --- server.example.com ping statistics ---
    10 packets transmitted, 10 received, 0% packet loss, time 9014ms
    rtt min/avg/max/mdev = 17.208/17.056/19.333/0.616 ms

    この例では、レイテンシーは 17 ミリ秒です。

  2. 次の式を使用して、チューニングするトラフィックの帯域幅遅延積 (BDP) を計算します。

    connection speed in bytes * latency in seconds = BDP in bytes

    たとえば、レイテンシーが 17 ミリ秒の 10 Gbps 接続の BDP を計算するには、次のようにします。

    (10 * 1000 * 1000 * 1000 / 8) * 0.017 = 21,250,000 bytes
  3. /etc/sysctl.d/10-tcp-socket-buffers.conf ファイルを作成し、要件に基づいて、最大読み取りバッファーサイズまたは書き込みバッファーサイズ、またはその両方を設定します。

    net.ipv4.tcp_rmem = 4096 262144 42500000
    net.ipv4.tcp_wmem = 4096 262144 42500000

    値をバイト単位で指定します。環境に最適化された値を特定するには、以下の大体の目安を参考にしてください。

    • デフォルトのバッファーサイズ (2 番目の値): この値をわずかに増やすか、最大でも 524288 (512 KiB) に設定します。デフォルトのバッファーサイズが大きすぎると、バッファーのコラプシングが発生し、結果としてレイテンシーが急増する可能性があります。
    • 最大バッファーサイズ (3 番目の値): 多くの場合、BDP の 2 倍から 3 倍の値で十分です。
  4. /etc/sysctl.d/10-tcp-socket-buffers.conf ファイルから設定をロードします。

    # sysctl -p /etc/sysctl.d/10-tcp-socket-buffers.conf
  5. net.ipv4.tcp_rmem または net.ipv4.tcp_wmem パラメーターの 2 番目の値を変更した場合は、新しい TCP バッファーサイズを使用するようにアプリケーションを再起動します。

    3 番目の値のみを変更した場合は、自動チューニングによってこれらの設定が動的に適用されるため、アプリケーションを再起動する必要はありません。

検証

  1. オプション: iperf3 を使用して TCP スループットをテストします
  2. パケットドロップが発生したときに使用したのと同じ方法を使用して、パケットドロップ統計を監視します。

    パケットドロップが依然として発生するが、レートが低い場合は、バッファーサイズをさらに増やします。

5.4. TCP ウィンドウのスケーリング

Red Hat Enterprise Linux でデフォルトで有効になっている TCP ウィンドウスケーリング機能は、スループットを大幅に向上させる TCP プロトコルの拡張機能です。

たとえば、ラウンドトリップ時間 (RTT) が 1.5 ミリ秒の 1 Gbps 接続の場合、次のようになります。

  • TCP ウィンドウスケーリングを有効にすると、約 630 Mbps が現実的になります。
  • TCP ウィンドウスケーリングを無効にすると、スループットは 380 Mbps に低下します。

TCP が提供する機能の 1 つはフロー制御です。フロー制御を使用すると、送信者は受信者が受信可能な量のデータを送信できますが、それ以上のデータは送信できません。これを達成するために、受信者は、送信者が送信できるデータの量である window 値をアドバタイズします。

TCP は当初、最大 64 KiB のウィンドウサイズをサポートしていましたが、帯域幅遅延積 (BDP) が高い場合、送信者が一度に 64 KiB を超えるサイズを送信できないため、この値が制限となります。高速接続では、一度に 64 KiB をはるかに超えるデータを転送できます。たとえば、システム間の遅延が 1 ms の 10 Gbps リンクでは、ある瞬間に 1 MiB 以上のデータが転送中になる可能性があります。ホストが 64 KiB だけを送信し、もう一方のホストがその 64 KiB を受信するまで一時停止して待機するのは非効率的です。

このボトルネックを解消するために、TCP ウィンドウスケーリング拡張機能を使用すると、TCP ウィンドウ値を左算術シフトしてウィンドウサイズを 64 KiB を超えて増やすことができます。たとえば、最大ウィンドウ値 65535 は左に 7 桁シフトし、ウィンドウサイズは 8 MiB 近くになります。これにより、一度により多くのデータを転送できるようになります。

TCP ウィンドウスケーリングは、すべての TCP 接続を開く 3 ウェイ TCP ハンドシェイク中にネゴシエートされます。この機能が動作するには、送信者と受信者の両方が TCP ウィンドウスケーリングをサポートしている必要があります。参加者の一方または両方がハンドシェイクでウィンドウスケーリング機能をアドバタイズしない場合、接続は元の 16 ビット TCP ウィンドウサイズの使用に戻ります。

デフォルトでは、TCP ウィンドウスケーリングは Red Hat Enterprise Linux で有効になっています。

# sysctl net.ipv4.tcp_window_scaling
net.ipv4.tcp_window_scaling = 1

サーバー上で TCP ウィンドウスケーリングが無効 (0) になっている場合は、設定した際と同じ方法で設定を元に戻します。

5.5. TCP SACK がパケットドロップ率を下げる仕組み

RHEL では、TCP Selective Acknowledgment (TCP SACK) 機能がデフォルトで有効になっています。この機能は、TCP プロトコルの拡張機能であり、TCP 接続の効率を向上させます。

TCP 送信では、受信者は受信するパケットごとに ACK パケットを送信者に送信します。たとえば、クライアントは TCP パケット 1 - 10 をサーバーに送信しますが、パケット番号 5 と 6 が失われます。TCP SACK がないと、サーバーはパケット 7 - 10 をドロップし、クライアントは損失点からすべてのパケットを再送信する必要があり、非効率的です。両方のホストで TCP SACK が有効になっている場合、クライアントは失われたパケット 5 と 6 のみを再送信する必要があります。

重要

TCP SACK を無効にするとパフォーマンスが低下し、TCP 接続の受信側でのパケットドロップ率が高くなります。

デフォルトでは、RHEL では TCP SACK が有効になっています。確認するには、以下を実行します。

# sysctl net.ipv4.tcp_sack
1

サーバー上で TCP SACK が無効 (0) になっている場合は、設定した際と同じ方法で設定を元に戻します。

第6章 UDP 接続のチューニング

UDP のスループット向上のために RHEL をチューニングする際は、現実的な期待を持つことが求められます。TCP とは異なり、UDP にはフロー制御や輻輳制御などの機能がありません。そのため、ネットワークインターフェイスコントローラー (NIC) の最大速度に近い、信頼性の高い通信とスループットを実現することは困難です。

6.1. パケットドロップの検出

ネットワークスタックの中には、カーネルによってパケットがドロップされることがある階層が複数あります。RHEL には、これらの階層の統計情報を表示するためのさまざまなユーティリティーがあります。これらのユーティリティーを使用して潜在的な問題を特定してください。

ごくわずかな割合のパケットがドロップされる場合は無視できることに注意してください。ただし、大幅な割合でパケットがドロップされる場合は、チューニング措置を検討してください。

注記

ネットワークスタックが受信トラフィックを処理できない場合、カーネルはネットワークパケットをドロップします。

手順

  • 小さすぎるソケットバッファーまたは遅いアプリケーション処理による UDP プロトコル固有のパケットドロップを特定します。

    # nstat -az UdpSndbufErrors UdpRcvbufErrors
    #kernel
    UdpSndbufErrors           4    0.0
    UdpRcvbufErrors    45716659    0.0

    出力の 2 番目の列にはカウンターがリストされます。

6.2. iperf3 を使用した UDP スループットのテスト

iperf3 ユーティリティーは、サーバーモードとクライアントモードを提供し、2 つのホスト間のネットワークスループットテストを実行します。

注記

アプリケーションのスループットは、アプリケーションが使用するバッファーサイズなど、多くの要因に依存します。したがって、iperf3 などのテストユーティリティーで測定された結果は、実稼働ワークロード下のサーバー上のアプリケーションの結果とは大きく異なる可能性があります。

前提条件

  • iperf3 パッケージはクライアントとサーバーの両方にインストールされている。
  • 両方のホスト上の他のサービスによって、テスト結果に大きな影響を与えるネットワークトラフィックが発生することはない。
  • オプション: サーバーとクライアントの両方で最大 UDP ソケットサイズを増やしている。詳細は、システム全体の UDP ソケットバッファーの増加 を参照してください。

手順

  1. オプション: サーバーとクライアントの両方のネットワークインターフェイスコントローラー (NIC) の最大ネットワーク速度を表示します。

    # ethtool enp1s0 | grep "Speed"
       Speed: 10000Mb/s
  2. サーバー上では以下の設定になります。

    1. UDP ソケット読み取りバッファーの最大サイズを表示し、値をメモします。

      # sysctl net.core.rmem_max
      net.core.rmem_max = 16777216

      表示される値はバイト単位です。

    2. firewalld サービスでデフォルトの iperf3 ポート 5201 を一時的に開きます。

      # firewall-cmd --add-port=5201/tcp --add-port=5201/udp

      iperf3 は、サーバー上の TCP ソケットのみを開くことに注意してください。クライアントが UDP を使用する場合、最初にこの TCP ポートに接続します。その後、サーバーが同じポート番号で UDP ソケットを開いて UDP トラフィックのスループットテストを実行します。このため、ローカルファイアウォールで TCP プロトコルと UDP プロトコルの両方に対してポート 5201 を開く必要があります。

    3. iperf3 をサーバーモードで起動します。

      # iperf3 --server

      サービスは受信クライアント接続を待機するようになります。

  3. クライアントで以下を実行します。

    1. クライアントがサーバーへの接続に使用するインターフェイスの最大伝送単位 (MTU) を表示し、その値をメモします。

      # ip link show enp1s0
      2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
      ...
    2. UDP ソケット書き込みバッファーの最大サイズを表示し、値をメモします。

      # sysctl net.core.wmem_max
      net.core.wmem_max = 16777216

      表示される値はバイト単位です。

    3. スループットの測定を開始します。

      # iperf3 --udp --time 60 --window 16777216 --length 1472 --bitrate 2G --client 192.0.2.1
      • --udp: テストには UDP プロトコルを使用します。
      • --time <seconds>: クライアントが送信を停止する時間を秒単位で定義します。
      • --window <size>: UDP ソケットのバッファーサイズを設定します。理想的には、クライアントとサーバーのサイズが同じです。それらが異なる場合は、このパラメーターを小さい方の値に設定します。クライアントでは net.core.wmem_max、サーバーでは net.core.rmem_max です。
      • --length <size>: 読み取りおよび書き込みを行うバッファーの長さを設定します。このオプションを断片化されていない最大のペイロードに設定します。理想的な値は次のように計算します。MTU - IP ヘッダー (IPv4 の場合は 20 バイト、IPv6 の場合は 40 バイト) - 8 バイトの UDP ヘッダー。
      • --bitrate <rate>: ビットレートをビット/秒単位で指定した値に制限します。2 Gbps の場合は 2G など、単位を指定できます。

        このパラメーターを機能すると予想される値に設定し、後の測定で値を増やします。クライアントが送信パス上のデバイスまたはサーバーが処理できる速度よりも速い速度でパケットを送信すると、パケットがドロップされる可能性があります。

      • --client <server>: クライアントモードを有効にし、iperf3 サーバーを実行するサーバーの IP アドレスまたは名前を設定します。
  4. iperf3 がテストを完了するまで待ちます。サーバーとクライアントの両方で統計が毎秒表示され、最後に概要が表示されます。たとえば、以下はクライアントに表示される概要です。

    [ ID] Interval       Transfer      Bitrate         Jitter    Lost/Total Datagrams
    [ 5] 0.00-60.00 sec  14.0 GBytes   2.00 Gbits/sec  0.000 ms  0/10190216 (0%) sender
    [ 5] 0.00-60.04 sec  14.0 GBytes   2.00 Gbits/sec  0.002 ms  0/10190216 (0%) receiver

    この例では、平均ビットレートは 2 Gbps で、パケットの損失はありませんでした。

  5. サーバー上では以下の設定になります。

    1. Ctrl+C を押して iperf3 サーバーを停止します。
    2. firewalld のポート 5201 を閉じます。

      # firewall-cmd --remove-port=5201/tcp --remove-port=5201/udp

6.3. UDP トラフィックスループットに対する MTU サイズの影響

アプリケーションが大きな UDP メッセージサイズを使用する場合、ジャンボフレームを使用するとスループットを改善できます。

IEEE 802.3 標準によれば、仮想ローカルエリアネットワーク (VLAN) タグのないデフォルトのイーサネットフレームの最大サイズは 1518 バイトです。これらの各フレームには 18 バイトのヘッダーが含まれて、ペイロード用に 1500 バイトが残されます。したがって、サーバーがネットワーク経由で送信するデータの 1500 バイトごとに、18 バイト (1.2%) がオーバーヘッドになります。

ジャンボフレームは、標準のイーサネットペイロードサイズである 1500 バイトよりも大きな最大伝送単位 (MTU) を持つ非標準フレームです。たとえば、最大許容 MTU が 9000 バイトのペイロードでジャンボフレームを設定すると、各フレームのオーバーヘッドは 0.2% に減少します。

重要

伝送パス上のすべてのネットワークデバイスと関連するブロードキャストドメインは、ジャンボフレームをサポートし、同じ MTU を使用する必要があります。伝送パス上の一貫性のない MTU 設定によるパケットの断片化と再構築により、ネットワークスループットが低下します。

接続の種類によっては、特定の MTU 制限があります。

  • イーサネット: MTU は 9000 バイトに制限されます。
  • データグラムモードの IP over InfiniBand (IPoIB): MTU は、InfiniBand MTU より 4 バイト小さい値に制限されます。
  • インメモリーネットワークは通常、より大きな MTU をサポートします。詳細は、それぞれのドキュメントを参照してください。

6.4. UDP トラフィックスループットに対する CPU 速度の影響

パケット集約がないため、UDP は TCP よりもバルク転送の効率が低くなります。CPU 周波数により、高速リンクのスループットが制限される可能性があります。これは、Generic Receive Offload (GRO) と UDP Segmentation Offload (USO) がデフォルトで無効になっているためです。

たとえば、高い最大伝送単位 (MTU) と大きなソケットバッファーを備えたチューニングされたホストでは、3 GHz CPU が、UDP トラフィックをフルスピードで送受信する 10 GBit NIC のトラフィックを処理できます。ただし、UDP トラフィックを送信する場合は、3 GHz 未満の CPU 速度 100 MHz ごとに約 1 - 2 Gbps の速度低下が予想されます。また、3 GHz の CPU 速度がほぼ 10 Gbps に達する場合、同じ CPU は 40 GBit NIC 上の UDP トラフィックを約 20 - 25 Gbps に制限します。

6.5. システム全体の UDP ソケットバッファーの増加

ソケットバッファーは、カーネルが受信したデータ、または送信待ちのデータを一時的に格納します。

次のバッファーが存在します。

  • 読み取りソケットバッファーには、カーネルが受信したがアプリケーションがまだ読み取っていないパケットが保持されます。
  • 書き込みソケットバッファーには、アプリケーションがバッファーに書き込んだものの、カーネルがまだ IP スタックとネットワークドライバーに渡していないパケットが保持されます。

UDP パケットが大きすぎてバッファーサイズを超えている場合、またはパケットの送受信速度が速すぎる場合、カーネルはデータがバッファーから削除されるまで、新しい受信 UDP パケットをドロップします。この場合、ソケットバッファーを増やすことでパケットロスを防ぐことができます。

重要

バッファーサイズを大きすぎる設定にすると、メモリーが無駄に消費されます。各ソケットはアプリケーションが要求するサイズに設定でき、カーネルはこの値を 2 倍にします。たとえば、アプリケーションが 256 KiB のソケットバッファーサイズを要求し、100 万個のソケットを開く場合、システムは潜在的なソケットバッファースペースとしてのみ 512 GB RAM (512 KiB x 100 万) を必要とします。

前提条件

  • かなりの割合で UDP パケットがドロップされました。

手順

  1. /etc/sysctl.d/10-udp-socket-buffers.conf ファイルを作成し、要件に基づいて最大読み取りバッファーサイズまたは書き込みバッファーサイズ、あるいはその両方を設定します。

    net.core.rmem_max = 16777216
    net.core.wmem_max = 16777216

    値をバイト単位で指定します。この例の値は、バッファーの最大サイズを 16 MiB に設定します。両方のパラメーターのデフォルト値は 212992 バイト (208 KiB) です。

  2. /etc/sysctl.d/10-udp-socket-buffers.conf ファイルから設定をロードします。

    # sysctl -p /etc/sysctl.d/10-udp-socket-buffers.conf
  3. より大きなソケットバッファーサイズを使用するようにアプリケーションを設定します。

    net.core.rmem_max および net.core.wmem_max パラメーターは、アプリケーションの setsockopt() 関数が要求できる最大バッファーサイズを定義します。setsockopt() 関数を使用しないようにアプリケーションを設定すると、カーネルは rmem_default および wmem_default パラメーターの値を使用することに注意してください。

    詳細は、アプリケーションのプログラミング言語のドキュメントを参照してください。アプリケーションの開発者ではない場合は、開発者にお問い合わせください。

  4. 新しい UDP バッファーサイズを使用するには、アプリケーションを再起動します。

検証

  • パケットドロップの発生時に使用したものと同じ方法を使用して、パケットドロップの統計情報を監視します。

    パケットドロップが依然として発生するが、レートが低い場合は、バッファーサイズをさらに増やします。

第7章 アプリケーション読み取りソケットバッファーのボトルネックの特定

TCP アプリケーションが読み取りソケットバッファーを十分な頻度でクリアしない場合、パフォーマンスが低下し、パケットが失われる可能性があります。RHEL には、このような問題を特定するためのさまざまなユーティリティーがあります。

7.1. 受信バッファーのコラプシングとプルーニングの特定

受信キュー内のデータが受信バッファーサイズを超えると、TCP スタックはソケットバッファーから不要なメタデータを削除して、スペースを解放しようとします。このステップはコラプシングとして知られています。

コラプシングが追加のトラフィック用に十分なスペースを解放できない場合、カーネルは着信する新しいデータをプルーニングします。これは、カーネルがメモリーからデータを削除し、パケットが失われることを意味します。

操作のコラプシングとプルーニングを回避するには、TCP バッファーのコラプシングとプルーニングがサーバー上で発生するかどうかを監視し、この場合は TCP バッファーをチューニングします。

手順

  1. nstat ユーティリティーを使用して、TcpExtTCPRcvCollapsed カウンターと TcpExtRcvPruned カウンターをクエリーします。

    # nstat -az TcpExtTCPRcvCollapsed TcpExtRcvPruned
    #kernel
    TcpExtRcvPruned            0         0.0
    TcpExtTCPRcvCollapsed      612859    0.0
  2. しばらく待ってから、nstat コマンドを再実行します。

    # nstat -az TcpExtTCPRcvCollapsed TcpExtRcvPruned
    #kernel
    TcpExtRcvPruned            0         0.0
    TcpExtTCPRcvCollapsed      620358    0.0
  3. 最初の実行と比較してカウンターの値が増加している場合は、チューニングが必要です。

    • アプリケーションが setsockopt(SO_RCVBUF) 呼び出しを使用している場合は、それを削除することを検討してください。この呼び出しでは、アプリケーションは呼び出しで指定された受信バッファーサイズのみを使用し、サイズを自動チューニングするソケットの機能をオフにします。
    • アプリケーションが setsockopt(SO_RCVBUF) 呼び出しを使用しない場合は、TCP 読み取りソケットバッファーのデフォルト値と最大値をチューニングします。
  4. 受信バックログキューを表示します (Recv-Q)。

    # ss -nti
    State   Recv-Q   Send-Q   Local Address:Port   Peer Address:Port   Process
    ESTAB   0        0        192.0.2.1:443        192.0.2.125:41574
          :7,7 ... lastrcv:543 ...
    ESTAB   78       0        192.0.2.1:443        192.0.2.56:42612
          :7,7 ... lastrcv:658 ...
    ESTAB   88       0        192.0.2.1:443        192.0.2.97:40313
          :7,7 ... lastrcv:5764 ...
    ...
  5. ss -nt コマンドを、各実行の間に数秒の待ち時間を設けて複数回実行します。

    出力の Recv-Q 列に高い値が 1 件だけリストされている場合、アプリケーションは 2 つの受信操作の間にありました。ただし、lastrcv が継続的に増加する一方で、Recv-Q の値が一定のままである場合、または Recv-Q が時間の経過とともに継続的に増加する場合は、次の問題のいずれかが原因である可能性があります。

    • アプリケーションはソケットバッファーを十分な頻度でチェックしません。この問題の解決方法の詳細は、アプリケーションのベンダーにお問い合わせください。
    • アプリケーションは十分な CPU 時間を取得できません。この問題をさらにデバッグするには、以下を実行します。

      1. アプリケーションが実行されている CPU コアを表示します。

        # ps -eo pid,tid,psr,pcpu,stat,wchan:20,comm
            PID     TID PSR %CPU STAT WCHAN                COMMAND
        ...
          44594   44594   5  0.0 Ss   do_select            httpd
          44595   44595   3  0.0 S    skb_wait_for_more_pa httpd
          44596   44596   5  0.0 Sl   pipe_read            httpd
          44597   44597   5  0.0 Sl   pipe_read            httpd
          44602   44602   5  0.0 Sl   pipe_read            httpd
        ...

        PSR 列には、プロセスが現在割り当てられている CPU コアが表示されます。

      2. 同じコア上で実行されている他のプロセスを特定し、それらを他のコアに割り当てることを検討してください。

第8章 大量のリクエストを受信するアプリケーションのチューニング

Web サーバーなど、大量の受信リクエストを処理するアプリケーションを実行する場合、パフォーマンスを最適化するために Red Hat Enterprise Linux をチューニングすることが必要になる場合があります。

8.1. 多数の TCP 接続試行を処理するための TCP リッスンバックログの調整

アプリケーションが LISTEN 状態で TCP ソケットを開くと、カーネルは、このソケットが処理できる許可されるクライアント接続の数を制限します。アプリケーションが処理できる以上の接続をクライアントが確立しようとすると、新しい接続が破棄されるか、カーネルが SYN Cookie を送信します。

システムが通常のワークロード下にあり、正規のクライアントからの接続が多すぎるためにカーネルが SYN Cookie を送信する場合は、Red Hat Enterprise Linux (RHEL) をチューニングしてこれを回避します。

前提条件

  • RHEL は、possible SYN flooding on port <ip_address>:<port_number> エラーメッセージを Systemd ジャーナルに記録します。
  • 多数の接続試行は有効なソースからのものであり、攻撃によって引き起こされたものではありません。

手順

  1. チューニングが必要かどうかを確認するには、影響を受けるポートの統計を表示します。

    # ss -ntl '( sport = :443 )'
    State    Recv-Q   Send-Q   Local Address:Port   Peer Address:Port  Process
    LISTEN   650      500      192.0.2.1:443        0.0.0.0:*

    バックログ (Recv-Q) 内の現在の接続数がソケットバックログ (Send-Q) より大きい場合、リッスンバックログはまだ十分大きくないため、チューニングが必要です。

  2. オプション: 現在の TCP リッスンバックログ制限を表示します。

    # sysctl net.core.somaxconn
    net.core.somaxconn = 4096
  3. /etc/sysctl.d/10-socket-backlog-limit.conf ファイルを作成し、り大きなリッスンバックログ制限を設定します。

    net.core.somaxconn = 8192

    アプリケーションは net.core.somaxconn カーネルパラメーターで指定したよりも多くのリッスンバックログを要求することができますが、カーネルはこのパラメーターで設定した番号にアプリケーションを制限することに注意してください。

  4. /etc/sysctl.d/10-socket-backlog-limit.conf ファイルから設定をロードします。

    # sysctl -p /etc/sysctl.d/10-socket-backlog-limit.conf
  5. 新しいリッスンバックログ制限を使用するようにアプリケーションを再設定します。

    • アプリケーションが制限の config オプションを提供している場合は、それを更新します。たとえば、Apache HTTP サーバーには、このサービスのリッスンバックログ制限を設定するための ListenBacklog 設定オプションが用意されています。
    • 制限を設定できない場合は、アプリケーションを再コンパイルします。
    重要

    net.core.somaxconn カーネル設定とアプリケーションの設定の両方を常に更新する必要があります。

  6. アプリケーションを再起動します。

検証

  1. Systemd ジャーナルを監視して、possible SYN flooding on port <port_number> エラーメッセージがさらに発生していないかどうかを確認します。
  2. バックログ内の現在の接続数を監視し、ソケットバックログと比較します。

    # ss -ntl '( sport = :443 )'
    State    Recv-Q   Send-Q   Local Address:Port   Peer Address:Port  Process
    LISTEN   0        500      192.0.2.1:443        0.0.0.0:*

    バックログ (Recv-Q) 内の現在の接続数がソケットバックログ (Send-Q) より大きい場合、リッスンバックログが十分に大きくないため、さらなるチューニングが必要です。

第9章 リッスンキューのロック競合の回避

キューロックの競合により、パケットドロップや CPU 使用率の上昇を引き起こす可能性があり、その結果、レイテンシーが長くなる可能性があります。アプリケーションをチューニングし、Transmit Packet Steering を使用することで、受信 (RX) キューと送信 (TX) キューでのキューロックの競合を回避できます。

9.1. RX キューのロック競合の回避: SO_REUSEPORT および SO_REUSEPORT_BPF ソケットオプション

デフォルトでは、マルチスレッドのネットワークアプリケーションは、未接続の UDP または TCP リスナースレッドが受信トラフィックを受信するために、単一のソケットを共有する必要があります。マルチコアシステムでは、SO_REUSEPORT または SO_REUSEPORT_BPF ソケットオプションを使用して負荷を分散することで、アプリケーションのパフォーマンスが向上します。

単一のソケットを使用すると、次のような問題が発生します。

  • パケットドロップや CPU 使用率の上昇を引き起こす可能性のある受信バッファーでの重大な競合。
  • CPU 使用率の大幅な増加
  • パケットドロップの可能性
パケットフロー図: 単一の UDP ソケットのみを使用することで発生するロック競合

SO_REUSEPORT または SO_REUSEPORT_BPF ソケットオプションを使用すると、1 つのホスト上の複数のソケットを同じポートにバインドできます。

パケットフロー図: `SO_REUSEPORT` および `SO_REUSEPORT_BPF` ソケットオプションを使用してロック競合を回避する

詳細は、システム上の socket(7) man ページと /usr/src/debug/kernel-<version>/linux-<version>/tools/testing/selftests/net/reuseport_bpf_cpu.c ファイルを参照してください。

Red Hat Enterprise Linux では、カーネルソースで SO_REUSEPORT ソケットオプションを使用する方法のコードサンプルを提供します。コード例にアクセスするには、以下を実行します。

  1. rhel-10-for-x86_64-baseos-debug-rpms リポジトリーを有効にします。

    # subscription-manager repos --enable rhel-10-for-x86_64-baseos-debug-rpms
  2. kernel-debuginfo-common-x86_64 パッケージをインストールします。

    # dnf install kernel-debuginfo-common-x86_64
  3. コード例が /usr/src/debug/kernel-<version>/linux-<version>/tools/testing/selftests/net/reuseport_bpf_cpu.c ファイルで利用できるようになります。

9.2. TX キューのロック競合の回避: Transmit Packet Steering

マルチキューのネットワークインターフェイスコントローラー (NIC) を備えたホストの場合、Transmit Packet Steering (XPS) によって、送信パケットの処理が複数のキューに分散されます。これにより、複数の CPU がトラフィックを処理できるようになり、送信キューのロック競合やパケットのドロップを防ぐことができます。

ixgbei40emlx5 などの特定のドライバーは、XPS を自動的に設定します。ドライバーがこの機能をサポートしているかどうかを確認するには、NIC ドライバーのドキュメントを参照してください。ドライバーが XPS 自動チューニングをサポートしていない場合は、CPU コアを送信キューに手動で割り当てることができます。

注記

Red Hat Enterprise Linux には、送信キューを CPU コアに永続的に割り当てるオプションがありません。インターフェイスがアクティブ化されたときに実行される NetworkManager ディスパッチャースクリプト内のコマンドを使用してください。詳細は、Red Hat ナレッジベースソリューション How to write a NetworkManager dispatcher script to apply commands on interface start を参照してください。

Linux ネットワークスタックのスケーリングの詳細は、kernel-doc パッケージによって提供される /usr/share/doc/kernel-doc-<version>/Documentation/networking/scaling.rst ファイルを参照してください。

前提条件

  • NIC が複数のキューをサポートする。
  • numactl パッケージがインストールされている。

手順

  1. 使用可能なキューの数を表示します。

    # ethtool -l enp1s0
    Channel parameters for enp1s0:
    Pre-set maximums:
    RX:		0
    TX:		0
    Other:		0
    Combined:	4
    Current hardware settings:
    RX:		0
    TX:		0
    Other:		0
    Combined:	1

    Pre-set maximums セクションにはキューの総数が表示され、Current hardware settings には受信キュー、送信キュー、その他のキュー、または結合されたキューに現在割り当てられているキューの数が表示されます。

  2. オプション: 特定のチャネルにキューが必要な場合は、それに応じてキューを割り当てます。たとえば、4 つのキューを Combined チャネルに割り当てるには、次のように入力します。

    # ethtool -L enp1s0 combined 4
  3. NIC がどの Non-Uniform Memory Access (NUMA) ノードに割り当てられているかを表示します。

    # cat /sys/class/net/enp1s0/device/numa_node
    0

    ファイルが見つからない場合、またはコマンドが -1 を返す場合は、ホストは NUMA システムではありません。

  4. ホストが NUMA システムの場合は、どの CPU がどの NUMA ノードに割り当てられているかを表示します。

    # lscpu | grep NUMA
    NUMA node(s):       2
    NUMA node0 CPU(s):  0-3
    NUMA node1 CPU(s):  4-7
  5. 上の例では、NIC には 4 つのキューがあり、NIC は NUMA ノード 0 に割り当てられています。このノードは CPU コア 0 - 3 を使用します。したがって、各送信キューを 0 - 3 の CPU コアの 1 つにマッピングします。

    # echo 1 > /sys/class/net/enp1s0/queues/tx-0/xps_cpus
    # echo 2 > /sys/class/net/enp1s0/queues/tx-1/xps_cpus
    # echo 4 > /sys/class/net/enp1s0/queues/tx-2/xps_cpus
    # echo 8 > /sys/class/net/enp1s0/queues/tx-3/xps_cpus

    CPU コアと送信 (TX) キューの数が同じ場合は、TX キューで何らかの競合が発生するのを避けるために、1 対 1 マッピングを使用してください。複数の CPU を同じ TX キューにマップすると、各 CPU の送信操作によって TX キューのロック競合が発生し、送信スループットに悪影響が発生します。

    CPU のコア番号を含むビットマップをキューに渡す必要があることに注意してください。次のコマンドを使用してビットマップを計算します。

    # printf %x $((1 << <core_number> ))

検証

  1. トラフィックを送信するサービスのプロセス ID (PID) を特定します。

    # pidof <process_name>
    12345 98765
  2. XPS を使用するコアに PID を固定します。

    # numactl -C 0-3 12345 98765
  3. プロセスがトラフィックを送信している間、requeues カウンターを監視します。

    # tc -s qdisc
    qdisc fq_codel 0: dev enp10s0u1 root refcnt 2 limit 10240p flows 1024 quantum 1514 target 5ms interval 100ms memory_limit 32Mb ecn drop_batch 64
     Sent 125728849 bytes 1067587 pkt (dropped 0, overlimits 0 requeues 30)
     backlog 0b 0p requeues 30
     ...

    requeues カウンターが大幅な速度で増加しなくなると、TX キューロックの競合は発生しなくなります。

9.3. UDP トラフィックが多いサーバーでの Generic Receive Offload 機能の無効化

高速 UDP 一括転送を使用するアプリケーションは、UDP ソケット上で UDP Generic Receive Offload (GRO) を有効にして使用することでメリットが得られます。ただし、GRO を無効にするとスループットを向上させることができます。

次の条件に該当する場合は、GRO を無効にしてください。

  • アプリケーションが GRO をサポートしていないため、機能を追加できない。
  • TCP のスループットが重要ではない。

    警告

    GRO を無効にすると、TCP トラフィックの受信スループットが大幅に低下します。したがって、TCP パフォーマンスが関係するホストでは GRO を無効にしないでください。

前提条件

  • ホストは主に UDP トラフィックを処理している。
  • アプリケーションは GRO を使用していない。
  • ホストは、VXLAN などの UDP トンネルプロトコルを使用していない。
  • ホストは仮想マシン (VM) やコンテナーを実行していない。

手順

  1. オプション: NetworkManager 接続プロファイルを表示します。

    # nmcli connection show
    NAME     UUID                                  TYPE      DEVICE
    example  f2f33f29-bb5c-3a07-9069-be72eaec3ecf  ethernet  enp1s0
  2. 接続プロファイルで GRO サポートを無効にします。

    # nmcli connection modify example ethtool.feature-gro off
  3. 接続プロファイルを再度アクティベートします。

    # nmcli connection up example

検証

  1. GRO が無効になっていることを確認します。

    # ethtool -k enp1s0 | grep generic-receive-offload
    generic-receive-offload: off
  2. サーバー上のスループットを監視します。この設定がホスト上の他のアプリケーションにマイナスの影響を与える場合は、NetworkManager プロファイルで GRO を再度有効にします。

第10章 デバイスドライバーと NIC のチューニング

RHEL では、カーネルモジュールは、ネットワークインターフェイスコントローラー (NIC) 用のドライバーを提供します。これらのモジュールは、デバイスドライバーと NIC をチューニングおよび最適化するためのパラメーターをサポートしています。

たとえば、ドライバーが受信割り込みの生成の遅延をサポートしている場合は、対応するパラメーターの値を減らして、受信記述子の不足を避けることができます。

注記

すべてのモジュールがカスタムパラメーターをサポートしているわけではなく、機能はハードウェア、ドライバーおよびファームウェアのバージョンによって異なります。

10.1. カスタム NIC ドライバーのパラメーターの設定

多くのカーネルモジュールは、ドライバーとネットワークインターフェイスコントローラー (NIC) をチューニングするためのパラメーターの設定をサポートしています。ハードウェアやドライバーに応じて設定をカスタマイズできます。

重要

カーネルモジュールにパラメーターを設定すると、RHEL はこれらの設定をこのドライバーを使用するすべてのデバイスに適用します。

前提条件

  • ホストに NIC がインストールされている。
  • NIC のドライバーを提供するカーネルモジュールは、必要なチューニング機能をサポートしている。
  • ローカルでログインしているか、パラメーターを変更するドライバーを使用するネットワークインターフェイスとは異なるネットワークインターフェイスを使用してログインしている。

手順

  1. ドライバーを特定します。

    # ethtool -i enp0s31f6
    driver: e1000e
    version: ...
    firmware-version: ...
    ...

    特定の機能には、特定のドライバーとファームウェアのバージョンが必要になる場合があることに注意してください。

  2. カーネルモジュールの利用可能なパラメーターを表示します。

    # modinfo -p e1000e
    ...
    SmartPowerDownEnable:Enable PHY smart power down (array of int)
    parm:RxIntDelay:Receive Interrupt Delay (array of int)

    パラメーターの詳細は、カーネルモジュールのドキュメントを参照してください。RHEL のモジュールは、kernel-doc パッケージで提供される /usr/share/doc/kernel-doc-<version>/Documentation/networking/device_drivers/ ディレクトリーにあるドキュメントを参照してください。

  3. /etc/modprobe.d/nic-parameters.conf ファイルを作成し、モジュールのパラメーターを指定します。

    options <module_name> <parameter1>=<value> <parameter2>=<value>

    たとえば、ポートの省電力メカニズムを有効にし、受信割り込みの生成を 4 ユニットに設定するには、次のように入力します。

    options e1000e SmartPowerDownEnable=1 RxIntDelay=4
  4. モジュールをアンロードします。

    # modprobe -r e1000e
    警告

    アクティブなネットワークインターフェイスが使用するモジュールをアンロードすると、接続が即座に終了し、サーバーからロックアウトされる可能性があります。

  5. モジュールをロードします。

    # modprobe e1000e
  6. ネットワーク接続を再アクティブ化します。

    # nmcli connection up <profile_name>

検証

  1. カーネルメッセージを表示します。

    # dmesg
    ...
    [35309.225765] e1000e 0000:00:1f.6: Transmit Interrupt Delay set to 16
    [35309.225769] e1000e 0000:00:1f.6: PHY Smart Power Down Enabled
    ...

    すべてのモジュールがパラメーター設定をカーネルリングバッファーに記録するわけではないことに注意してください。

  2. 特定のカーネルモジュールは、モジュールパラメーターごとに /sys/module/<driver>/parameters/ ディレクトリーにファイルを作成します。これらの各ファイルには、このパラメーターの現在の値が含まれています。これらのファイルを表示して設定を確認できます。

    # cat /sys/module/<driver_name>/parameters/<parameter_name>

第11章 ネットワークアダプターのオフロード設定

CPU 負荷を軽減するために、特定のネットワークアダプターは、ネットワーク処理負荷をネットワークインターフェイスコントローラー (NIC) に移動するオフロード機能を使用します。

たとえば、Encapsulating Security Payload (ESP) オフロードを使用すると、NIC は ESP 操作を実行して、IPsec 接続を高速化し、CPU 負荷を軽減します。

デフォルトでは、Red Hat Enterprise Linux のほとんどのオフロード機能が有効になっています。次の場合にのみ無効にしてください。

  • トラブルシューティングの目的でオフロード機能を一時的に無効にします。
  • 特定の機能がホストに悪影響を与える場合は、オフロード機能を永続的に無効にします。

ネットワークドライバーでパフォーマンス関連のオフロード機能がデフォルトで有効になっていない場合は、手動で有効にすることができます。

11.1. オフロード機能の一時的な設定

オフロード機能によって問題が発生したり、ホストのパフォーマンスが低下したりすると予想される場合は、現在の状態に応じて、オフロード機能を一時的に有効または無効にして、原因の絞り込みを試みることができます。

オフロード機能を一時的に有効または無効にすると、次回の再起動時に以前の値に戻ります。

前提条件

  • ネットワークカードがオフロード機能をサポートしている。

手順

  1. インターフェイスで利用可能なオフロード機能とその現在の状態を表示します。

    # ethtool -k enp1s0
    ...
    esp-hw-offload: on
    ntuple-filters: off
    rx-vlan-filter: off [fixed]
    ...

    出力はハードウェアとそのドライバーの機能によって異なります。[fixed] のフラグが付いている機能の状態は変更できないことに注意してください。

  2. オフロード機能を一時的に無効にします。

    # ethtool -K <interface> <feature> <on|off>
    • たとえば、enp10s0u1 インターフェイスで IPsec Encapsulating Security Payload (ESP) オフロードを一時的に無効にするには、次のように入力します。

      # ethtool -K enp10s0u1 esp-hw-offload off
    • たとえば、enp10s0u1 インターフェイスで Receive Flow Steering (aRFS) フィルタリングを一時的に有効にするには、次のように入力します。

      # ethtool -K enp10s0u1 ntuple-filters on

検証

  1. オフロード機能の状態を表示します。

    # ethtool -k enp1s0
    ...
    esp-hw-offload: off
    ntuple-filters: on
    ...
  2. オフロード機能を変更する前に発生した問題がまだ存在するかどうかをテストします。

    • 特定のオフロード機能を変更した後に問題が解消された場合は、次のようにします。

      1. Red Hat サポート に連絡して問題を報告してください。
      2. 修正が利用可能になるまで、オフロード機能を永続的に設定すること を検討してください。
    • 特定のオフロード機能を無効にしても問題が解決しない場合は、以下を実行します。

      1. ethtool -K <interface> <feature> <on|off> コマンドを使用して、設定を前の状態にリセットします。
      2. 異なるオフロード機能を有効または無効にして、問題を絞り込みます。

11.2. オフロード機能の永続的な設定

ホストのパフォーマンスを制限する特定のオフロード機能を特定した場合は、現在の状態に応じて、それを永続的に有効または無効にすることができます。

オフロード機能を永続的に有効または無効にすると、NetworkManager は再起動後もその機能がこの状態のままであることを確認します。

前提条件

  • ホスト上のパフォーマンスを制限する特定のオフロード機能を特定している。

手順

  1. オフロード機能の状態を変更するネットワークインターフェイスを使用する接続プロファイルを特定します。

    # nmcli connection show
    NAME     UUID                                  TYPE      DEVICE
    Example  a5eb6490-cc20-3668-81f8-0314a27f3f75  ethernet  enp1s0
    ...
  2. オフロード機能の状態を永続的に変更します。

    # nmcli connection modify <connection_name> <feature> <on|off>
    • たとえば、Example 接続プロファイルで IPsec Encapsulating Security Payload (ESP) オフロードを永続的に無効にするには、次のように入力します。

      # nmcli connection modify Example ethtool.feature-esp-hw-offload off
    • たとえば、Example 接続プロファイルでアクセラレート Receive Flow Steering (aRFS) フィルタリングを永続的に有効にするには、次のように入力します。

      # nmcli connection modify Example ethtool.feature-ntuple on
  3. 接続プロファイルを再度アクティベートします。

    # nmcli connection up Example

検証

  • オフロード機能の出力状態を表示します。

    # ethtool -k enp1s0
    ...
    esp-hw-offload: off
    ntuple-filters: on
    ...

第12章 割り込み結合設定のチューニング

割り込み結合は、ネットワークカードによって生成される割り込みの数を減らすためのメカニズムです。一般に、割り込みが少なくなると、ネットワークのレイテンシーと全体的なパフォーマンスが向上します。

割り込み結合設定のチューニングには、以下を制御するパラメーターの調整が含まれます。

  • 1 つの割り込みに結合されるパケットの数。
  • 割り込みを生成するまでの遅延。
重要

最適な結合設定は、特定のネットワーク条件と使用しているハードウェアによって異なります。したがって、環境とニーズに最適な設定を見つけるには、何度か試すことが必要な場合があります。

12.1. 遅延またはスループットの扱いに注意が必要なサービス向けに RHEL を最適化する

割り込み結合のチューニングは、特定のワークロードに対して発生する割り込みを最小限に抑えることを目的としたものです。高スループットが求められる状況では、高いデータ転送速度を維持しながら、割り込みの回数をできるだけ抑えることが目標となります。待ち時間が短い状況では、より多くの割り込みを使用してトラフィックを迅速に処理できます。

ネットワークカードの設定を調整して、1 つの割り込みに結合されるパケットの数を増減できます。その結果、トラフィックのスループットまたは遅延を向上させることができます。

手順

  1. ボトルネックが発生しているネットワークインターフェイスを特定します。

    # ethtool -S enp1s0
    NIC statistics:
         rx_packets: 1234
         tx_packets: 5678
         rx_bytes: 12345678
         tx_bytes: 87654321
         rx_errors: 0
         tx_errors: 0
         rx_missed: 0
         tx_dropped: 0
         coalesced_pkts: 0
         coalesced_events: 0
         coalesced_aborts: 0

    名前に dropdiscard または error を含むパケットカウンターを特定します。これらの特定の統計は、ネットワークインターフェイスコントローラー (NIC) の結合によって発生する可能性がある、NIC のパケットバッファーでの実際のパケットロスを測定します。

  2. 前の手順で特定したパケットカウンターの値を監視します。

    これらをネットワークの予想値と比較して、特定のインターフェイスにボトルネックが発生しているかどうかを判断します。ネットワークのボトルネックの一般的な兆候には次のようなものがありますが、これらに限定されません。

    • ネットワークインターフェイス上での多数のエラー
    • 高いパケットロス
    • ネットワークインターフェイスの多用

      注記

      ネットワークのボトルネックを特定する際のその他の重要な要素としては、CPU 使用率、メモリー使用率、ディスク I/O などがあります。

  3. 現在の割り込み結合設定を確認します。

    # ethtool -c enp1s0
    Coalesce parameters for enp1s0:
            Adaptive RX: off
            Adaptive TX: off
            RX usecs: 100
            RX frames: 8
            RX usecs irq: 100
            RX frames irq: 8
            TX usecs: 100
            TX frames: 8
            TX usecs irq: 100
            TX frames irq: 8
    • usecs 値は、受信機または送信機が割り込みを生成する前に待機するマイクロ秒数を指します。
    • frames 値は、受信機または送信機が割り込みを生成する前に待機するフレーム数を指します。
    • irq 値は、ネットワークインターフェイスがすでに割り込みを処理している場合に、割り込み調整を設定するために使用されます。

      注記

      すべてのネットワークインターフェイスカードが、出力例のすべての値のレポートと変更をサポートしているわけではありません。

    • Adaptive RX/TX 値は、割り込み結合設定を動的に調整する適応割り込み結合メカニズムを表します。Adaptive RX/TX が有効な場合、NIC ドライバーはパケット条件に基づいて、結合値を自動計算します (アルゴリズムは NIC ドライバーごとに異なります)。
  4. 必要に応じて結合設定を変更します。以下に例を示します。

    • ethtool.coalesce-adaptive-rx が無効になっている間に、RX パケットの割り込みを生成するまでの遅延を 100 マイクロ秒に設定するように ethtool.coalesce-rx-usecs を設定します。

      # nmcli connection modify enp1s0 ethtool.coalesce-rx-usecs 100
    • ethtool.coalesce-rx-usecs がデフォルト値に設定されている間、ethtool.coalesce-adaptive-rx を有効にします。

      # nmcli connection modify enp1s0 ethtool.coalesce-adaptive-rx on

      Adaptive-RX 設定を次のように変更します。

      • 低遅延 (50 us 未満) を優先する場合は、Adaptive-RX を有効にしないでください。
      • スループットを優先する場合は、Adaptive-RX を有効にしてもおそらく問題はありません。適応割り込み結合メカニズムを使用しない場合は、ethtool.coalesce-rx-usecs に 100 us や 250 us などの大きな値を設定することをお試しください。
      • ご自身のニーズが明確でない場合は、問題が発生するまでこの設定を変更しないでください。
  5. 接続を再度有効にします。

    # nmcli connection up enp1s0

検証

  • ネットワークパフォーマンスを監視し、ドロップされたパケットを確認します。

    # ethtool -S enp1s0
    NIC statistics:
         rx_packets: 1234
         tx_packets: 5678
         rx_bytes: 12345678
         tx_bytes: 87654321
         rx_errors: 0
         tx_errors: 0
         rx_missed: 0
         tx_dropped: 0
         coalesced_pkts: 12
         coalesced_events: 34
         coalesced_aborts: 56
    ...

    rx_errorsrx_droppedtx_errors、および tx_dropped フィールドの値は、0 またはそれに近い値 (ネットワークトラフィックとシステムリソースに応じて、数百まで) に保ってください。これらのフィールドの値が高い場合は、ネットワークに問題があることを示します。カウンターには異なる名前を付けることができます。名前に "drop"、"discard"、または "error" を含むパケットカウンターを注意深く監視します。

    rx_packetstx_packetsrx_bytes、および tx_bytes の値は、時間の経過とともに増加します。値が増加しない場合は、ネットワークに問題がある可能性があります。パケットカウンターは、NIC ドライバーに応じて異なる名前を持つことができます。

    重要

    ethtool コマンドの出力は、使用している NIC とドライバーによって異なる場合があります。

    極めて低いレイテンシーを重視するユーザーは、監視目的でアプリケーションレベルのメトリクスまたはカーネルパケットタイムスタンプ API を使用できます。

第13章 TCP タイムスタンプの利点

TCP タイムスタンプはオプションの TCP ヘッダー拡張機能です。RHEL ではこの機能がデフォルトで有効になっています。カーネルは TCP タイムスタンプを使用して TCP 接続のラウンドトリップ時間 (RTT) をより正確に推定します。これにより、TCP ウィンドウとバッファーの計算がより正確になります。

さらに、TCP タイムスタンプは、セグメントの寿命と順序を判断し、ラップされたシーケンス番号から保護するための代替方法を提供します。TCP パケットヘッダーは、32 ビットフィールドにシーケンス番号を記録します。10 Gbps 接続では、このフィールドの値は 1.7 秒後にラップされる可能性があります。TCP タイムスタンプがないと、受信側はラップされたシーケンス番号を持つセグメントが新しいセグメントか古い重複かを判断できません。ただし、TCP タイムスタンプを使用すると、受信側はセグメントを受信するか破棄するかを正しく選択できます。したがって、高速ネットワークインターフェイスを備えたシステムでは TCP タイムスタンプを有効にすることが不可欠です。

net.ipv4.tcp_timestamps カーネルパラメーターには、次のいずれかの値を指定できます。

  • 0: TCP タイムスタンプは無効化されています。
  • 1: TCP タイムスタンプは有効化されています (デフォルト)。
  • 2: TCP タイムスタンプは有効ですが、ランダムオフセットはありません。

    重要

    各接続のランダムなオフセットがなければ、ホストの大体の稼働時間とフィンガープリントを決定し、この情報を攻撃に使用することが可能です。

デフォルトでは、Red Hat Enterprise Linux では TCP タイムスタンプが有効になっており、現在の時刻のみを保存するのではなく、接続ごとにランダムなオフセットを使用します。

# sysctl net.ipv4.tcp_timestamps
net.ipv4.tcp_timestamps = 1

net.ipv4.tcp_timestamps パラメーターの値がデフォルト (1) と異なる場合は、設定したときと同じ方法で設定を元に戻します。

第14章 イーサネットネットワークのフロー制御

イーサネットリンクで連続的にデータが送信されると、バッファーがいっぱいになり、ネットワークの輻輳が発生する可能性があります。送信者のレートがレシーバーの処理能力を超えると、スイッチポートのデータ処理能力が低いためにパケットロスが発生する可能性があります。

フロー制御メカニズムは、送信側と受信側の送受信能力がそれぞれ異なるイーサネットリンクを介したデータ送信を管理します。パケットロスを回避するために、イーサネットフロー制御メカニズムはパケット送信を一時的に停止し、スイッチポート側の高い伝送レートを制御します。なお、スイッチがスイッチポートを越えてポーズフレームを転送することはありません。

受信 (RX) バッファーがいっぱいになると、受信側は送信側にポーズフレームを送信します。その後、送信側は、1 秒未満の短い期間、データ送信を停止しますが、この一時停止期間中は受信データのバッファリングを続けます。この期間は、受信側がインターフェイスバッファーを空にして、バッファーオーバーフローを防ぐのに十分な時間を提供します。

注記

イーサネットリンクのどちら側も、ポーズフレームを反対側に送信できます。ネットワークインターフェイスの受信バッファーがいっぱいになると、ネットワークインターフェイスはポーズフレームをスイッチポートに送信します。同様に、スイッチポートの受信バッファーがいっぱいになると、スイッチポートはネットワークインターフェイスにポーズフレームを送信します。

デフォルトでは、Red Hat Enterprise Linux のほとんどのネットワークドライバーではポーズフレームのサポートが有効になっています。ネットワークインターフェイスの現在の設定を表示するには、次のように入力します。

# ethtool --show-pause enp1s0
Pause parameters for enp1s0:
...
RX:     on
TX:     on
...

スイッチのベンダーに問い合わせて、スイッチがポーズフレームをサポートしているかどうかを確認してください。

第15章 NetworkManager 接続プロファイルでの ethtool の設定

NetworkManager は、特定のネットワークドライバー設定とハードウェア設定を永続的に設定できます。ethtool ユーティリティーを使用してこれらの設定を管理する場合と比較して、これには再起動後に設定が失われないという利点があります。

NetworkManager 接続プロファイルでは、次の ethtool 設定を行うことができます。

オフロード機能
ネットワークインターフェイスコントローラーは、TCP オフロードエンジン (TOE) を使用して、特定の操作の処理をネットワークコントローラーにオフロードできます。これにより、ネットワークのスループットが向上します。
割り込み結合設定
割り込み結合を使用すると、システムはネットワークパケットを収集し、複数のパケットに対して割り込みを 1 つ生成します。これにより、1 つのハードウェア割り込みでカーネルに送信されたデータ量が増大し、割り込み負荷が減り、スループットを最大化します。
リングバッファー
これらのバッファーは、送受信ネットワークパケットを保存します。高いパケットドロップ率を下げるためにリングバッファーを増やすことができます。
チャネル設定

ネットワークインターフェイスは、ハードウェア設定およびネットワークドライバーとともに、関連付けられているチャネル数を管理します。ネットワークインターフェイスに関連付けられているデバイスは、すべての割り込み要求 (IRQ) を介して相互に通信します。各デバイスのキューが保留中の IRQ を保持し、チャネルと呼ばれるデータラインを介して相互に通信します。キューのタイプは、特定のチャネルタイプに関連付けられています。このチャネルタイプには次のものがあります。

  • rx: 受信キュー用
  • tx: 送信キュー用
  • other: リンク割り込みまたは single-root input/output virtualization (SR-IOV) 調整用
  • combined: ハードウェア容量ベースの多目的チャネル用

15.1. nmcli を使用して ethtool オフロード機能を設定する

NetworkManager を使用して、接続プロファイルで ethtool オフロード機能を有効または無効にすることができます。

手順

  1. たとえば、RX オフロード機能を有効にし、enp1s0 接続プロファイルで TX オフロードを無効にするには、次のコマンドを実行します。

    # nmcli con modify enp1s0 ethtool.feature-rx on ethtool.feature-tx off

    このコマンドは、RX オフロードを明示的に有効にし、TX オフロードを無効にします。

    設定可能な設定のリストは、システムの nm-settings-nmcli(5) man ページの ethtool setting セクションを参照してください。

  2. 以前に有効または無効にしたオフロード機能の設定を削除するには、機能のパラメーターを null 値に設定します。たとえば、TX オフロードの設定を削除するには、次のコマンドを実行します。

    # nmcli con modify enp1s0 ethtool.feature-tx ""
  3. ネットワークプロファイルを再度アクティブにします。

    # nmcli connection up enp1s0

検証

  • ethtool -k コマンドを使用して、ネットワークデバイスの現在のオフロード機能を表示します。

    # ethtool -k network_device

15.2. network RHEL システムロールを使用した ethtool オフロード機能の設定

network RHEL システムロールを使用すると、特定の操作の処理をネットワークコントローラーにオフロードする TCP オフロードエンジン (TOE) の設定を自動化できます。TOE はネットワークスループットを向上させます。

警告

network RHEL システムロールを使用して、既存接続プロファイル内の特定の値だけを更新することはできません。このロールは、接続プロファイルが Playbook の設定と正確に一致するようにします。同じ名前の接続プロファイルがすでに存在する場合、このロールは Playbook の設定を適用し、プロファイル内の他のすべての設定をデフォルトにリセットします。値がリセットされないようにするには、変更しない設定も含め、ネットワーク接続プロファイルの設定全体を Playbook に常に指定してください。

前提条件

手順

  1. 次の内容を含む Playbook ファイル (例: ~/playbook.yml) を作成します。

    ---
    - name: Configure the network
      hosts: managed-node-01.example.com
      tasks:
        - name: Ethernet connection profile with dynamic IP address settings and offload features
          ansible.builtin.include_role:
            name: redhat.rhel_system_roles.network
          vars:
            network_connections:
              - name: enp1s0
                type: ethernet
                autoconnect: yes
                ip:
                  dhcp4: yes
                  auto6: yes
                ethtool:
                  features:
                    gro: no
                    gso: yes
                    tx_sctp_segmentation: no
                state: up

    サンプル Playbook で指定されている設定は次のとおりです。

    gro: no
    Generic Receive Offload (GRO) を無効にします。
    gso: yes
    Generic Segmentation Offload (GSO) を有効にします。
    tx_sctp_segmentation: no
    TX Stream Control Transmission Protocol (SCTP) セグメンテーションを無効にします。

    Playbook で使用されるすべての変数の詳細は、コントロールノードの /usr/share/ansible/roles/rhel-system-roles.network/README.md ファイルを参照してください。

  2. Playbook の構文を検証します。

    $ ansible-playbook --syntax-check ~/playbook.yml

    このコマンドは構文を検証するだけであり、有効だが不適切な設定から保護するものではないことに注意してください。

  3. Playbook を実行します。

    $ ansible-playbook ~/playbook.yml

検証

  • 管理対象ノードの Ansible fact をクエリーし、オフロード設定を確認します。

    # ansible managed-node-01.example.com -m ansible.builtin.setup
    ...
            "ansible_enp1s0": {
                "active": true,
                "device": "enp1s0",
    	    "features": {
    	        ...
    		"rx_gro_hw": "off,
    	        ...
    		"tx_gso_list": "on,
    	        ...
    		"tx_sctp_segmentation": "off",
    		...
                }
    ...

15.3. nmcli を使用した ethtool coalesce の設定

NetworkManager を使用して、接続プロファイルに ethtool coalesce を設定できます。

手順

  1. たとえば、enp1s0 接続プロファイルで受信パケットの最大数を 128 に設定するには、次のコマンドを実行します。

    # nmcli connection modify enp1s0 ethtool.coalesce-rx-frames 128

    設定可能な設定のリストは、システムの nm-settings-nmcli(5) man ページの ethtool setting セクションを参照してください。

  2. coalesce 設定を削除するには、null 値に設定します。たとえば、ethtool.coalesce-rx-frames 設定を削除するには、次のコマンドを実行します。

    # nmcli connection modify enp1s0 ethtool.coalesce-rx-frames ""
  3. ネットワークプロファイルを再度アクティブにするには、以下を実行します。

    # nmcli connection up enp1s0

検証

  • ethtool -c コマンドを使用して、ネットワークデバイスの現在のオフロード機能を表示します。

    # ethtool -c <network_device>

15.4. network RHEL システムロールを使用した ethtool 結合の設定

割り込み結合は、ネットワークパケットを収集し、複数のパケットに対して単一の割り込みを生成します。これにより割り込みの負荷が軽減され、スループットが最大化されます。network RHEL システムロールを使用すると、NetworkManager 接続プロファイルでのこれらの設定を自動化できます。

警告

network RHEL システムロールを使用して、既存接続プロファイル内の特定の値だけを更新することはできません。このロールは、接続プロファイルが Playbook の設定と正確に一致するようにします。同じ名前の接続プロファイルがすでに存在する場合、このロールは Playbook の設定を適用し、プロファイル内の他のすべての設定をデフォルトにリセットします。値がリセットされないようにするには、変更しない設定も含め、ネットワーク接続プロファイルの設定全体を Playbook に常に指定してください。

前提条件

手順

  1. 次の内容を含む Playbook ファイル (例: ~/playbook.yml) を作成します。

    ---
    - name: Configure the network
      hosts: managed-node-01.example.com
      tasks:
        - name: Ethernet connection profile with dynamic IP address settings and coalesce settings
          ansible.builtin.include_role:
            name: redhat.rhel_system_roles.network
          vars:
            network_connections:
              - name: enp1s0
                type: ethernet
                autoconnect: yes
                ip:
                  dhcp4: yes
                  auto6: yes
                ethtool:
                  coalesce:
                    rx_frames: 128
                    tx_frames: 128
                state: up

    サンプル Playbook で指定されている設定は次のとおりです。

    rx_frames: <value>
    RX フレームの数を設定します。
    tx_frames: <value>
    TX フレームの数を設定します。

    Playbook で使用されるすべての変数の詳細は、コントロールノードの /usr/share/ansible/roles/rhel-system-roles.network/README.md ファイルを参照してください。

  2. Playbook の構文を検証します。

    $ ansible-playbook --syntax-check ~/playbook.yml

    このコマンドは構文を検証するだけであり、有効だが不適切な設定から保護するものではないことに注意してください。

  3. Playbook を実行します。

    $ ansible-playbook ~/playbook.yml

検証

  • ネットワークデバイスの現在のオフロード機能を表示します。

    # ansible managed-node-01.example.com -m command -a 'ethtool -c enp1s0'
    managed-node-01.example.com | CHANGED | rc=0 >>
    ...
    rx-frames:	128
    ...
    tx-frames:	128
    ...

パケットドロップ率が原因でアプリケーションがデータの損失、タイムアウト、またはその他の問題を報告する場合は、イーサネットデバイスのリングバッファーのサイズを増やします。

受信リングバッファーは、デバイスドライバーとネットワークインターフェイスコントローラー (NIC) の間で共有されます。カードは、送信 (TX) および受信 (RX) リングバッファーを割り当てます。名前が示すように、リングバッファーは循環バッファーであり、オーバーフローによって既存のデータが上書きされます。NIC からカーネルにデータを移動するには、ハードウェア割り込みと、SoftIRQ とも呼ばれるソフトウェア割り込みの 2 つの方法があります。

カーネルは RX リングバッファーを使用して、デバイスドライバーが着信パケットを処理できるようになるまで着信パケットを格納します。デバイスドライバーは、通常は SoftIRQ を使用して RX リングをドレインします。これにより、着信パケットは sk_buff または skb と呼ばれるカーネルデータ構造に配置され、カーネルを経由して関連するソケットを所有するアプリケーションまでの移動を開始します。

カーネルは、ネットワーク宛ての送信パケットを保持するために TX リングバッファーを使用します。このリングバッファーは、スタックの最下層に位置し、パケットドロップが発生しうる重要な箇所です。パケットドロップは、ネットワークパフォーマンスに悪影響を及ぼします。

手順

  1. インターフェイスのパケットドロップ統計を表示します。

    # ethtool -S enp1s0
        ...
        rx_queue_0_drops: 97326
        rx_queue_1_drops: 63783
        ...

    コマンドの出力は、ネットワークカードとドライバーに依存することに注意してください。

    discard または drop カウンターの値が高い場合は、カーネルがパケットを処理できるよりも速く、使用可能なバッファーがいっぱいになることを示します。リングバッファーを増やすと、このような損失を回避できます。

  2. 最大リングバッファーサイズを表示します。

    # ethtool -g enp1s0
     Ring parameters for enp1s0:
     Pre-set maximums:
     RX:             4096
     RX Mini:        0
     RX Jumbo:       16320
     TX:             4096
     Current hardware settings:
     RX:             255
     RX Mini:        0
     RX Jumbo:       0
     TX:             255

    Pre-set maximums セクションの値が Current hardware settings セクションよりも高い場合は、次の手順で設定を変更できます。

  3. このインターフェイスを使用する NetworkManager 接続プロファイルを特定します。

    # nmcli connection show
    NAME                UUID                                  TYPE      DEVICE
    Example-Connection  a5eb6490-cc20-3668-81f8-0314a27f3f75  ethernet  enp1s0
  4. 接続プロファイルを更新し、リングバッファーを増やします。

    • RX リングバッファーを増やすには、次のように実行します。

      # nmcli connection modify Example-Connection ethtool.ring-rx 4096
    • TX リングバッファーを増やすには、次のように実行します。

      # nmcli connection modify Example-Connection ethtool.ring-tx 4096
  5. NetworkManager 接続をリロードします。

    # nmcli connection up Example-Connection
    重要

    NIC が使用するドライバーによっては、リングバッファーを変更すると、ネットワーク接続が短時間中断されることがあります。

パケットドロップ率が原因でアプリケーションがデータの損失、タイムアウト、またはその他の問題を報告する場合は、イーサネットデバイスのリングバッファーのサイズを増やします。

リングバッファーは循環バッファーであり、オーバーフローによって既存のデータが上書きされます。ネットワークカードは、送信 (TX) および受信 (RX) リングバッファーを割り当てます。受信リングバッファーは、デバイスドライバーとネットワークインターフェイスコントローラー (NIC) の間で共有されます。データは、ハードウェア割り込みまたは SoftIRQ とも呼ばれるソフトウェア割り込みによって NIC からカーネルに移動できます。

カーネルは RX リングバッファーを使用して、デバイスドライバーが着信パケットを処理できるようになるまで着信パケットを格納します。デバイスドライバーは、通常は SoftIRQ を使用して RX リングをドレインします。これにより、着信パケットは sk_buff または skb と呼ばれるカーネルデータ構造に配置され、カーネルを経由して関連するソケットを所有するアプリケーションまでの移動を開始します。

カーネルは、ネットワーク宛ての送信パケットを保持するために TX リングバッファーを使用します。このリングバッファーは、スタックの最下層に位置し、パケットドロップが発生しうる重要な箇所です。パケットドロップは、ネットワークパフォーマンスに悪影響を及ぼします。

リングバッファー設定は、NetworkManager 接続プロファイルで設定します。Ansible と network RHEL システムロールを使用すると、このプロセスを自動化し、Playbook で定義されたホスト上の接続プロファイルをリモートで設定できます。

警告

network RHEL システムロールを使用して、既存接続プロファイル内の特定の値だけを更新することはできません。このロールは、接続プロファイルが Playbook の設定と正確に一致するようにします。同じ名前の接続プロファイルがすでに存在する場合、このロールは Playbook の設定を適用し、プロファイル内の他のすべての設定をデフォルトにリセットします。値がリセットされないようにするには、変更しない設定も含め、ネットワーク接続プロファイルの設定全体を Playbook に常に指定してください。

前提条件

  • コントロールノードと管理対象ノードの準備が完了している
  • 管理対象ノードで Playbook を実行できるユーザーとしてコントロールノードにログインしている。
  • 管理対象ノードへの接続に使用するアカウントに、そのノードに対する sudo 権限がある。
  • デバイスがサポートする最大リングバッファーサイズを把握している。

手順

  1. 次の内容を含む Playbook ファイル (例: ~/playbook.yml) を作成します。

    ---
    - name: Configure the network
      hosts: managed-node-01.example.com
      tasks:
        - name: Ethernet connection profile with dynamic IP address setting and increased ring buffer sizes
          ansible.builtin.include_role:
            name: redhat.rhel_system_roles.network
          vars:
            network_connections:
              - name: enp1s0
                type: ethernet
                autoconnect: yes
                ip:
                  dhcp4: yes
                  auto6: yes
                ethtool:
                  ring:
                    rx: 4096
                    tx: 4096
                state: up

    サンプル Playbook で指定されている設定は次のとおりです。

    rx: <value>
    受信するリングバッファーエントリーの最大数を設定します。
    tx: <value>
    送信するリングバッファーエントリーの最大数を設定します。

    Playbook で使用されるすべての変数の詳細は、コントロールノードの /usr/share/ansible/roles/rhel-system-roles.network/README.md ファイルを参照してください。

  2. Playbook の構文を検証します。

    $ ansible-playbook --syntax-check ~/playbook.yml

    このコマンドは構文を検証するだけであり、有効だが不適切な設定から保護するものではないことに注意してください。

  3. Playbook を実行します。

    $ ansible-playbook ~/playbook.yml

検証

  • 最大リングバッファーサイズを表示します。

    # ansible managed-node-01.example.com -m command -a 'ethtool -g enp1s0'
    managed-node-01.example.com | CHANGED | rc=0 >>
    ...
    Current hardware settings:
    RX:             4096
    RX Mini:        0
    RX Jumbo:       0
    TX:             4096

15.7. nmcli を使用した ethtool チャネルの設定

ethtool ユーティリティーは、関連デバイスとの IRQ ベースの通信を処理し、接続プロファイル内の関連チャネル設定を管理します。NetworkManager 接続プロファイルで ethtool の設定を行うには、nmcli ユーティリティーを使用します。

手順

  1. ネットワークデバイスに関連付けられているチャネルを表示します。

    # ethtool --show-channels enp1s0
    Channel parameters for enp1s0:
    Pre-set maximums:
    RX:		4
    TX:		3
    Other:	   10
    Combined:  63
    
    Current hardware settings:
    RX:   	 1
    TX:   	 1
    Other:   1
    Combined:  1
  2. ネットワークインターフェイスのチャネル設定を更新します。

    # nmcli connection modify enp1s0 ethtool.channels-rx 4 ethtool.channels-tx 3 ethtool.channels-other 9 ethtool.channels-combined 50
  3. ネットワークプロファイルを再度アクティブにします。

    # nmcli connection up enp1s0

検証

  • ネットワークデバイスに関連付けられている更新されたチャネル設定を確認します。

    # ethtool --show-channels enp1s0
    Channel parameters for enp1s0:
    Pre-set maximums:
    RX:		4
    TX:		3
    Other:	  10
    Combined: 63
    
    Current hardware settings:
    RX:   	 4
    TX:   	 3
    Other:   9
    Combined:  50

第16章 NetworkManager のデバッグの概要

すべてのドメインまたは特定のドメインのログレベルを増やすと、NetworkManager が実行する操作の詳細をログに記録するのに役立ちます。この情報を使用して問題のトラブルシューティングを行うことができます。

NetworkManager は、ロギング情報を生成するさまざまなレベルとドメインを提供します。/etc/NetworkManager/NetworkManager.conf ファイルは、NetworkManager の主な設定ファイルです。ログはジャーナルに保存されます。

16.1. NetworkManager の reapply() メソッドの概要

NetworkManager はプロファイルを使用してデバイス接続設定を管理します。この設定は、D-Bus API を通じて作成、変更、または削除できます。プロファイルが変更されると、D-Bus が設定のクローンを作成します。この変更を適用するには、接続の設定を再アクティブ化するか、reapply() メソッドを使用する必要があります。

reapply() メソッドには次の機能があります。

  • ネットワークインターフェイスの非アクティブ化または再起動を行わずに、変更された接続設定を更新します。
  • 変更された接続設定から保留中の変更を削除します。NetworkManager は、手動による変更を元に戻さないため、デバイスを再設定して外部パラメーターまたは手動パラメーターを元に戻すことができます。
  • 既存の接続設定とは異なる、変更された接続設定を作成します。

また、reapply() メソッドは次の属性をサポートします。

  • bridge.ageing-time
  • bridge.forward-delay
  • bridge.group-address
  • bridge.group-forward-mask
  • bridge.hello-time
  • bridge.max-age
  • bridge.multicast-hash-max
  • bridge.multicast-last-member-count
  • bridge.multicast-last-member-interval
  • bridge.multicast-membership-interval
  • bridge.multicast-querier
  • bridge.multicast-querier-interval
  • bridge.multicast-query-interval
  • bridge.multicast-query-response-interval
  • bridge.multicast-query-use-ifaddr
  • bridge.multicast-router
  • bridge.multicast-snooping
  • bridge.multicast-startup-query-count
  • bridge.multicast-startup-query-interval
  • bridge.priority
  • bridge.stp
  • bridge.VLAN-filtering
  • bridge.VLAN-protocol
  • bridge.VLANs
  • 802-3-ethernet.accept-all-mac-addresses
  • 802-3-ethernet.cloned-mac-address
  • IPv4.addresses
  • IPv4.dhcp-client-id
  • IPv4.dhcp-iaid
  • IPv4.dhcp-timeout
  • IPv4.DNS
  • IPv4.DNS-priority
  • IPv4.DNS-search
  • IPv4.gateway
  • IPv4.ignore-auto-DNS
  • IPv4.ignore-auto-routes
  • IPv4.may-fail
  • IPv4.method
  • IPv4.never-default
  • IPv4.route-table
  • IPv4.routes
  • IPv4.routing-rules
  • IPv6.addr-gen-mode
  • IPv6.addresses
  • IPv6.dhcp-duid
  • IPv6.dhcp-iaid
  • IPv6.dhcp-timeout
  • IPv6.DNS
  • IPv6.DNS-priority
  • IPv6.DNS-search
  • IPv6.gateway
  • IPv6.ignore-auto-DNS
  • IPv6.may-fail
  • IPv6.method
  • IPv6.never-default
  • IPv6.ra-timeout
  • IPv6.route-metric
  • IPv6.route-table
  • IPv6.routes
  • IPv6.routing-rules

16.2. NetworkManager ログレベルの設定

デフォルトでは、すべてのログドメインは INFO ログレベルを記録します。デバッグログを収集する前にレート制限を無効にします。帯域制限により、systemd-journald は、短時間にメッセージが多すぎる場合にメッセージを破棄します。これは、ログレベルが TRACE の場合に発生する可能性があります。

この手順では、レート制限を無効にし、すべての (ALL) ドメインのデバッグログの記録を有効にします。

手順

  1. レート制限を無効にするには、/etc/systemd/journald.conf ファイルを編集し、[Journal] セクションの RateLimitBurst パラメーターのコメントを解除し、その値を 0 に設定します。

    RateLimitBurst=0
  2. systemd-journald サービスを再起動します。

    # systemctl restart systemd-journald
  3. 以下の内容で /etc/NetworkManager/conf.d/95-nm-debug.conf ファイルを作成します。

    [logging]
    domains=ALL:TRACE

    domains パラメーターには、複数のコンマ区切りの domain:level ペアを含めることができます。

  4. NetworkManager サービスを再起動します。

    # systemctl restart NetworkManager

検証

  • systemd ジャーナルにクエリーを実行して、NetworkManager ユニットのジャーナルエントリーを表示します。

    # journalctl -u NetworkManager
    ...
    Jun 30 15:24:32 server NetworkManager[164187]: <debug> [1656595472.4939] active-connection[0x5565143c80a0]: update activation type from assume to managed
    Jun 30 15:24:32 server NetworkManager[164187]: <trace> [1656595472.4939] device[55b33c3bdb72840c] (enp1s0): sys-iface-state: assume -> managed
    Jun 30 15:24:32 server NetworkManager[164187]: <trace> [1656595472.4939] l3cfg[4281fdf43e356454,ifindex=3]: commit type register (type "update", source "device", existing a369f23014b9ede3) -> a369f23014b9ede3
    Jun 30 15:24:32 server NetworkManager[164187]: <info>  [1656595472.4940] manager: NetworkManager state is now CONNECTED_SITE
    ...

16.3. nmcli を使用してランタイム時にログレベルを一時的に設定する

nmcli を使用すると、ランタイム時にログレベルを変更できます。

手順

  1. 必要に応じて、現在のログ設定を表示します。

    # nmcli general logging
      LEVEL  DOMAINS
      INFO   PLATFORM,RFKILL,ETHER,WIFI,BT,MB,DHCP4,DHCP6,PPP,WIFI_SCAN,IP4,IP6,A
    UTOIP4,DNS,VPN,SHARING,SUPPLICANT,AGENTS,SETTINGS,SUSPEND,CORE,DEVICE,OLPC,
    WIMAX,INFINIBAND,FIREWALL,ADSL,BOND,VLAN,BRIDGE,DBUS_PROPS,TEAM,CONCHECK,DC
    B,DISPATCH
  2. ログレベルおよびドメインを変更するには、以下のオプションを使用します。

    • すべてのドメインのログレベルを同じ LEVEL に設定するには、次のコマンドを実行します。

      # nmcli general logging level LEVEL domains ALL
    • 特定のドメインのレベルを変更するには、以下を入力します。

      # nmcli general logging level LEVEL domains DOMAINS

      このコマンドを使用してログレベルを更新すると、他のすべてのドメインのログが無効になることに注意してください。

    • 特定のドメインのレベルを変更し、他のすべてのドメインのレベルを保持するには、次のコマンドを実行します。

      # nmcli general logging level KEEP domains DOMAIN:LEVEL,DOMAIN:LEVEL

16.4. NetworkManager ログの表示

トラブルシューティング用の NetworkManager ログを表示できます。

手順

  • ログを表示するには、以下を入力します。

    # journalctl -u NetworkManager -b

16.5. デバッグレベルおよびドメイン

levels および domains パラメーターを使用して、NetworkManager のデバッグを管理できます。レベルは詳細レベルを定義しますが、ドメインは特定の重大度 (level) でログを記録するメッセージのカテゴリーを定義します。

Expand
ログレベル説明

OFF

NetworkManager に関するメッセージをログに記録しません。

ERR

重大なエラーのみのログ

WARN

操作を反映できる警告をログに記録します。

INFO

状態および操作の追跡に役立つさまざまな情報メッセージをログに記録します。

DEBUG

デバッグの目的で詳細なログを有効にします。

TRACE

DEBUG レベルよりも多くの詳細ロギングを有効にします。

後続のレベルでは、以前のレベルのすべてのメッセージをログに記録することに注意してください。たとえば、ログレベルを INFO に設定すると、ERR および WARN ログレベルに含まれるメッセージをログに記録します。

Red Hat logoGithubredditYoutubeTwitter

詳細情報

試用、購入および販売

コミュニティー

会社概要

Red Hat は、企業がコアとなるデータセンターからネットワークエッジに至るまで、各種プラットフォームや環境全体で作業を簡素化できるように、強化されたソリューションを提供しています。

多様性を受け入れるオープンソースの強化

Red Hat では、コード、ドキュメント、Web プロパティーにおける配慮に欠ける用語の置き換えに取り組んでいます。このような変更は、段階的に実施される予定です。詳細情報: Red Hat ブログ.

Red Hat ドキュメントについて

Legal Notice

Theme

© 2026 Red Hat
トップに戻る