27.7. tc-ctinfo ユーティリティーを使用したパケットのレート制限の設定

接続追跡エントリーには、Netfilter マークと接続情報が格納されます。ルーターがファイアウォールからパケットを転送するとき、ルーターはパケットから接続追跡エントリーを削除または変更します。接続追跡情報 (ctinfo) モジュールは、接続追跡マークからさまざまなフィールドにデータを取得します。このカーネルモジュールは、Netfilter マークを、ソケットバッファーマークメタデータフィールド (skb) にコピーすることで保存します。以下は、ctinfo モジュールを使用してサーバーシステムでパケットのレートを制限する手順です。

前提条件

  • iperf3 ユーティリティーがサーバーとクライアントにインストールされている。

手順

  1. サーバーで次の手順を実行します。

    1. ネットワークインターフェイスに仮想リンクを追加します。

      # ip link add name ifb4eth0 numtxqueues 48 numrxqueues 48 type ifb

      このコマンドには次のパラメーターがあります。

      • name ifb4eth0 :新しい仮想デバイス名を設定します
      • numtxqueues 48 :送信キューの数を設定します
      • numrxqueues 48 :受信キューの数を設定します
      • type ifb :新しいデバイスのタイプを設定します
    2. インターフェイス ifb4eth0 の状態を変更します。

      # ip link set dev ifb4eth0 up
    3. ネットワークインターフェイスに qdisc を追加し、着信トラフィックに適用します。

      # tc qdisc add dev enp1s0 handle ffff: ingress

      オプション handle ffff: では、handle パラメーターはメジャー番号をデフォルト値 ffff: としてクラスフルな qdisc に割り当てます。qdisc は、トラフィック制御を分析する queueing discipline パラメーターです。

    4. IP プロトコルのインターフェイス enp1s0 にフィルターを追加して、パケットを分類します。

      # tc filter add dev enp1s0 parent ffff: protocol ip u32 match u32 0 0 action ctinfo cpmark 100 action mirred egress redirect dev ifb4eth0

      このコマンドには次の属性があります。

      • parent ffff: :親 qdisc のメジャー番号 ffff: を設定します。
      • u32 match u32 0 0 :パターン u32 の IP ヘッダーと 一致 するように u32 フィルターを設定します。最初の 0 は、IP ヘッダーの 2 番目のバイトを表し、もう 1 つの 0 は、一致させるビットがどれであるかをマスク照合フィルターに指示します。
      • action ctinfo :接続追跡マークからさまざまなフィールドにデータを取得するアクションを設定します。
      • cpmark 100 :接続追跡マーク (connmark) 100 をパケットの IP ヘッダーフィールドにコピーします。
      • action mirred egress redirect dev ifb4eth0 :actionmirred を設定して、受信パケットを宛先インターフェイス ifb4eth0 にリダイレクトします。
    5. インターフェイス ifb4eth0 にクラスフル qdisc を追加します。

      # tc qdisc add dev ifb4eth0 root handle 1: htb default 1000

      このコマンドは、メジャー番号 1 をルート qdisc に設定し、マイナー ID が1000 で階層トークンバケットが htb のクラスフルな qdisc を使用します。

    6. ifb4eth0 のトラフィックを 1 Mbit/s に制限し、上限を 2 Mbit/s に設定します。

      # tc class add dev ifb4eth0 parent 1:1 classid 1:100 htb ceil 2mbit rate 1mbit prio 100

      このコマンドには次のパラメーターがあります。

      • parent 1:1 :classid1root1 として parent を設定します。
      • classid 1:100 :1:100 という名前の classid を設定します。ここで、1 は親 qdisc の数、100 は親 qdisc のクラス数です。
      • htb ceil 2mbit :htb のクラスフルな qdisc では、ceil レート制限として 2 Mbit/s の上限帯域幅が許可されます。
    7. クラスレス qdisc の Stochastic Fairness Queuing (sfq) をインターフェイス ifb4eth060 秒の時間間隔で適用して、キューアルゴリズムの摂動を減らします。

      # tc qdisc add dev ifb4eth0 parent 1:100 sfq perturb 60
    8. ファイアウォールマーク (fw) フィルターをデバイス ifb4eth0 に追加します。

      # tc filter add dev ifb4eth0 parent 1:0 protocol ip prio 100 handle 100 fw classid 1:100
    9. 接続マーク (CONNMARK) からパケットのメタマークを復元します。

      # nft add rule ip mangle PREROUTING counter meta mark set ct mark

      このコマンドでは、nft ユーティリティーにはチェーンルール仕様 PREROUTING を含む mangle テーブルがあり、ルーティング前に受信パケットを変更してパケットマークを CONNMARK に置き換えます。

    10. nft テーブルとチェーンが存在しない場合に、テーブルを作成してチェーンルールを追加するには、次の手順を実行します。

      # nft add table ip mangle
      # nft add chain ip mangle PREROUTING {type filter hook prerouting priority mangle \;}
    11. 指定された宛先アドレス 192.0.2.3 で受信した tcp パケットにメタマークを設定します。

      # nft add rule ip mangle PREROUTING ip daddr 192.0.2.3 counter meta mark set 0x64
    12. パケットマークを接続マークに保存します。

      # nft add rule ip mangle PREROUTING counter ct mark set mark
    13. システムで iperf3 をサーバーとして実行し、クライアント接続の応答を待機するサーバー -s としてリッスンします。

      # iperf3 -s
  2. クライアントとして別のシステムで iperf3 を実行し、IP アドレス 192.0.2.3 でリッスンしているサーバーに接続して、定期的な HTTP 要求応答タイムスタンプを取得します。

    # iperf3 -c 192.0.2.3 -t TCP_STREAM | tee rate
  3. サーバーで、Ctrl+C を押します。
  4. サーバー上の iperf3 ユーティリティーが結果を表示します。

    Accepted connection from 192.0.2.4, port 52128
    [5]  local 192.0.2.3 port 5201 connected to 192.0.2.4 port 52130
    [ID] Interval       	Transfer 	Bitrate
    [5]   0.00-1.00   sec   119 KBytes   973 Kbits/sec
    [5]   1.00-2.00   sec   116 KBytes   950 Kbits/sec
    ....
    - - - - - - - - - - - - - - - - - - - - - - - - -
    [ID] Interval       	Transfer 	Bitrate
    [5]   0.00-14.81  sec  1.51 MBytes   853 Kbits/sec  receiver
    
    iperf3: interrupt - the server has terminated
  5. Ctrl+C を押して、サーバー上の iperf3 を終了します。

    Connecting to host 192.0.2.3, port 5201
    [5] local 192.0.2.4 port 52130 connected to 192.0.2.3 port 5201
    [ID] Interval       	Transfer 	Bitrate     	Retr  Cwnd
    [5]   0.00-1.00   sec   481 KBytes  3.94 Mbits/sec	0   76.4 KBytes
    [5]   1.00-2.00   sec   223 KBytes  1.83 Mbits/sec	0   82.0 KBytes
    ....
    - - - - - - - - - - - - - - - - - - - - - - - - -
    [ID] Interval       	Transfer 	Bitrate     	Retr
    [5]   0.00-14.00  sec  3.92 MBytes  2.35 Mbits/sec   32     sender
    [5]   0.00-14.00  sec  0.00 Bytes  0.00 bits/sec            receiver
    
    iperf3: error - the server has terminated

検証

  1. インターフェイス ifb4eth0 上のクラス htb および sfq のパケット数に関する統計を表示します。

    # tc -s qdisc show dev ifb4eth0
    
    qdisc htb 1: root
    ....
     Sent 26611455 bytes 3054 pkt (dropped 76, overlimits 4887 requeues 0)
    ....
    qdisc sfq 8001: parent
    ....
     Sent 26535030 bytes 2296 pkt (dropped 76, overlimits 0 requeues 0)
    ....
  2. アクション mirred および ctinfo のパケット数の統計を表示します。

    # tc -s filter show dev enp1s0 ingress
    
    filter parent ffff: protocol ip pref 49152 u32 chain 0
    filter parent ffff: protocol ip pref 49152 u32 chain 0 fh 800: ht divisor 1
    filter parent ffff: protocol ip pref 49152 u32 chain 0 fh 800::800 order 2048 key ht 800 bkt 0 terminal flowid not_in_hw (rule hit 8075 success 8075)
      match 00000000/00000000 at 0 (success 8075 )
        action order 1: ctinfo zone 0 pipe
          index 1 ref 1 bind 1 cpmark 0x00000064 installed 3105 sec firstused 3105 sec DSCP set 0 error 0
          CPMARK set 7712
        Action statistics:
        Sent 25891504 bytes 3137 pkt (dropped 0, overlimits 0 requeues 0)
        backlog 0b 0p requeues 0
    
        action order 2: mirred (Egress Redirect to device ifb4eth0) stolen
           index 1 ref 1 bind 1 installed 3105 sec firstused 3105 sec
        Action statistics:
        Sent 25891504 bytes 3137 pkt (dropped 0, overlimits 61 requeues 0)
        backlog 0b 0p requeues 0
  3. htb レートリミッターとその設定の統計を表示します。

    # tc -s class show dev ifb4eth0
    
    class htb 1:100 root leaf 8001: prio 7 rate 1Mbit ceil 2Mbit burst 1600b cburst 1600b
     Sent 26541716 bytes 2373 pkt (dropped 61, overlimits 4887 requeues 0)
     backlog 0b 0p requeues 0
     lended: 7248 borrowed: 0 giants: 0
     tokens: 187250 ctokens: 93625

関連情報

  • tc(8) の man ページ
  • tc-ctinfo (8) の man ページ
  • nft(8) の man ページ