1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

TRexを用いたRouterのNAT機能の検証方法

Last updated at Posted at 2025-12-23

この記事はBBSakuraNetworksアドベントカレンダー2025の23日目の記事です。

はじめに

BBSakura Networksでアルバイトとして勤務をしている池田です。
日々の業務として、ネットワーク機器の評価・検証を行っています。

本記事では、検証業務で用いているTRexを使って、ルータのNAT機能をどのように検証しているかを紹介します。特に、ソフトウェアルータを対象としたNAT性能検証の一例として、具体的な構成や設定、注意点をまとめています。

TRexとは

Cisco TRexは、Ciscoが提供している高性能なトラフィックジェネレーターです。
ネットワーク機器やサーバーに対して大量の通信を生成し、性能検証や負荷テストを行うために使われます。

ソフトウェアベースで動作し、汎用的なハードウェアでも高速・大容量のトラフィック生成が可能なのが特徴です。
L2〜L7まで幅広い通信に対応しており、実運用に近いテストを行うことができます。

検証構成

スクリーンショット 2025-12-19 21.21.54.png

今回の構成では、ソフトウェアルータとしてOSSであるVyOSを試験対象としています。TRexから生成したトラフィックをVyOSに通過させ、NAT処理を行った上で、受信側のTRexへ転送する構成です。

本記事で紹介する手法は、VyOSに限らず、他のソフトウェアルータや物理ルータに対しても同様に適用することが可能です。図中のVyOSを、NAT処理を行う試験対象のルータに置き換えることで、さまざまな機器のNAT性能評価に応用できます。

使用機材・ソフトウェア

TRex側とDUT(VyOS)側で役割が異なるため、環境を分けて整理します。
TRex(トラフィック生成側)

項目 内容
ソフトウェア TRex v3.06
実行環境 仮想マシン(VM)
CPU 32vCPU
メモリ 16GiB
Host OS Ubuntu 22.04.5 LTS

秒間に多数の新規セッションを生成するため、CPUコア数を多めに割り当てています。
ASTFモードではメモリ使用量も増加するため、16GiBのメモリを確保しています。

VyOS(DUT)

項目 内容
ソフトウェア VyOS 1.4.1
実行環境 仮想マシン(VM)
CPU 2vCPU
メモリ 4GiB

VyOSはNAT処理性能の評価対象であるため、最小限のリソース構成としています。

TRexを利用する際は、OSとPythonのバージョン整合性に注意が必要です。TRexはHost OSのPython環境に依存するため、バージョン差異によるエラーが発生しやすいためです。

  • Ubuntu 22.04以前を使用する場合: 多くのリリースで動作が安定しており、最も無難な選択肢です。

  • Ubuntu 24.04を使用する場合: 標準のPython 3.12に対応した TRex v3.08以降 を使用することが必須となります。

2025年12月時点の最新バージョンは v3.08 ですが、検証環境のOSに合わせて適切なバージョンを選択してください。

TRexのバージョンと対応環境については、以下の公式リリースノートを参照してください。

Router側のNAT設定

VyOSの設定例を以下に示します。内部ネットワークから外部ネットワークへの通信に対して、Source NAT(masquerade)を行うシンプルな構成です。

interfaces {
    ethernet eth3 {
        address 192.168.1.82/24
        hw-id 52:54:00:b0:1e:15
    }
    ethernet eth4 {
        address 16.1.0.1/15
        hw-id 52:54:00:31:44:ce
    }
    ethernet eth5 {
        address 48.0.1.1/23
        hw-id 52:54:00:c4:a5:8b
    }
    loopback lo {
    }
}
nat {
    source {
        rule 100 {
            description "src-nat inside->outside"
            destination {
                address 48.0.0.0/24
            }
            outbound-interface {
                name eth5
            }
            source {
                address 16.0.0.0/16
            }
            translation {
                address masquerade
            }
        }
    }
}
protocols {
    static {
        route 0.0.0.0/0 {
            next-hop 192.168.1.1 {
            }
        }
        route 16.0.0.0/16 {
            next-hop 16.1.0.2 {
            }
        }
        route 48.0.0.0/24 {
            next-hop 48.0.1.2 {
            }
        }
    }
}

また、NATセッション数を十分に確保するため、VyOS側で以下のsysctl設定を行っています。

sudo sysctl -w net.netfilter.nf_conntrack_max=1048576
sudo sysctl -w net.netfilter.nf_conntrack_tcp_timeout_established=600

なお、これらのパラメータは、VyOSにおいてはset system sysctl 配下でコンフィグとして設定できるようです。

TRex設定

TRex インストール

sudo apt-get update
sudo apt-get install -y python3 python3-pip pciutils ethtool tmux screen \
                        make gcc unzip tar linux-headers-$(uname -r)
sudo modprobe vfio-pci
sudo mkdir -p /opt/trex
cd /opt/trex
sudo wget --no-cache https://trex-tgn.cisco.com/trex/release/latest --no-check-certificate
sudo tar -xzvf latest

HugePagesの設定

TRexは内部でDPDK (Data Plane Development Kit) を利用して高速なパケット処理を行います。DPDK では、ユーザ空間からNICを直接操作するため、

  • ページフォルトの発生を抑える
  • TLB ミスを減らす
  • メモリ連続性を確保する

といった目的で HugePages を利用します。

HugePagesを事前に確保しておかないと、TRex起動時にエラーとなったり、十分なスループットが出ない原因となるため、必ず設定しておきます。

echo 4096 | sudo tee /proc/sys/vm/nr_hugepages
echo 'vm.nr_hugepages=1024' | sudo tee /etc/sysctl.d/80-trex-hugepages.conf
sudo sysctl --system
sudo mkdir -p /mnt/huge
sudo mount -t hugetlbfs nodev /mnt/huge

DPDK ドライバへのバインド

TRexはDPDKを用いてNICを直接制御します。
そのため、通常Linuxが使用するカーネル標準ドライバ (virtio-net / ixgbe など) から、
DPDK 用の PMD (Poll Mode Driver) へNICをバインドし直す必要があります。

dpdk_setup_ports.py は以下を自動で行うユーティリティです。

  • 使用可能な NIC(PCI アドレス)の一覧表示
  • 対象 NIC を vfio-pci ドライバへバインド
  • TRex 用設定ファイル(trex_cfg.yaml)の雛形生成
cd /opt/trex/v3.06
sudo ./dpdk_setup_ports.py -s     # NIC と現在のドライバを確認
sudo ./dpdk_setup_ports.py -i     # vfio-pci へバインド & 設定ファイル生成

この操作により、NICはLinux ネットワークインタフェースとしては見えなくなり、
TRex(DPDK)が専有する形になります。

設定ファイルのチューニング

dpdk_setup_ports.py により生成される trex_cfg.yaml は最低限動作する設定ですが、NAT 性能検証では NAT セッション数を意図的に増やすための調整を行っています。

virtual_ip:
  start_ip: 48.0.0.0
  end_ip:   48.0.0.255

この設定により、TRex が使用する送信元/宛先 IP アドレスを動的に変化させ、多数の異なるフローを生成します。
これによって VyOS 側では新規 NAT セッションが継続的に作成され、conntrack テーブルを十分に消費する状態を作り出すことができます。

本検証では、スループットだけでなく NAT セッション処理能力 を評価することを目的としているため、この設定を有効にしています。

追加した設定を含めた/etc/trex_cfg.yamlは以下の通りです。

### Config file generated by dpdk_setup_ports.py ###

- version: 2
  interfaces: ['07:00.0', '08:00.0']
  port_info:
      - ip: 16.1.0.2
        default_gw: 16.1.0.1
        dest_mac: 52:54:00:51:bd:1e
      - ip: 48.0.1.2
        default_gw: 48.0.1.1
        dest_mac: 52:54:00:66:13:38
        virtual_ip  :
          start_ip  : 48.0.0.0
          end_ip    : 48.0.0.255

  platform:
      master_thread_id: 0
      latency_thread_id: 1
      dual_if:
        - socket: 0
          threads: [2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31]

TRex 実行

TRex 実行前の MACアドレス解決について

TRex でトラフィックを生成する前に、対向機器(DUT)との MACアドレス解決を完了させておく必要があります。
ASTF プロファイル内で ARP 処理を実装している場合は不要ですが、本検証では TRex の サービスモード を用いて事前に ARPによるMACアドレス解決を行います。

service mode では、TRex のポートが ARP や ICMP(PING)に応答する状態となり、 トラフィック送信前の疎通確認や MACアドレス解決に利用できます。

TRex 起動と MACアドレス解決手順

まず、ASTF モードで TRex サーバを起動します。

sudo ./t-rex-64 --astf -c 16 -i

また、CPUコア数(-c オプション)を2以上指定する場合、KVMにおいては以下の操作を行う必要があります。

KVMでのTRexマルチコア動作設定 TRexが入っているVMを一度shutdownする
sudo virsh dumpxml [VM名] > [VM名].xml

interfaceの部分に追加する

    <interface type='bridge'>
      <mac address='52:54:00:d2:7f:4e'/>
      <source bridge='virbr1'/>
      <model type='virtio'/>
      <driver name='vhost' queues='16'/>
      <address type='pci' domain='0x0000' bus='0x07' slot='0x00' function='0x0'/>
    </interface>
    <interface type='bridge'>
      <mac address='52:54:00:fb:a5:f3'/>
      <source bridge='virbr3'/>
      <model type='virtio'/>
      <driver name='vhost' queues='16'/>
      <address type='pci' domain='0x0000' bus='0x08' slot='0x00' function='0x0'/>
    </interface>
sudo virsh define [VM名].xml

これで再度起動する

別ターミナルから TRex コンソールへ接続します。

./trex-console

次に service mode を有効化し、MACアドレス解決を実行します。

trex> service
trex(service)> arp
trex(service)> service --off

MACアドレス解決が完了したら service mode を終了し、トラフィック生成を開始します。

trex> start -m 55000 -f imix_astf.py

実行中の確認と停止

実行中は TUI 画面で Global Statistics や Port Statistics を確認できます。

trex> tui

検証を終了する場合は、以下のコマンドでトラフィックを停止します。

trex> stop

実行ファイル

TRexの実行は3つのモードが存在します。
今回はそのうち、ASTFモードで実行可能なshortパケット検証用コードとimixパケット検証用コードを以下に提示します。
環境に合わせて適宜修正し、使用してください。

モード名 ファイル種別 内容
STLモード Python パケットを一方的に送信するパケットベースのトラフィック生成モードです。L2/L3スイッチやルータに対する帯域・パケット転送性能の評価に向いています。ストリーミングトラフィックなど、セッション管理を伴わない通信の検証に利用します。
STFモード YAML TCP/UDPのフローを再現するフローベースのトラフィック生成モードです。DUTにおいてL7までのパケット内容を確認できますが、TCPフラグやオプションなど、プロトコル動作そのものの制御は行えません。
ASTFモード Python STFモードを拡張し、TCPセッションの確立・終了やSSL通信を含むアプリケーションレベルのトラフィックを再現できます。

short_astf.py

# short_astf.py
from trex.astf.api import *
from scapy.all import *
import argparse
import os


class ProfShort():
    def __init__(self):
        pass

    def get_profile(self, tunables, **kwargs):
        parser = argparse.ArgumentParser(
            description='Argparser for {}'.format(os.path.basename(__file__)),
            formatter_class=argparse.ArgumentDefaultsHelpFormatter)
        args = parser.parse_args(tunables)

        # IPレンジ設定
        ip_gen_c = ASTFIPGenDist(ip_range=["16.0.0.1", "16.0.0.254"], distribution="seq")
        ip_gen_s = ASTFIPGenDist(ip_range=["48.0.0.1", "48.0.0.254"], distribution="seq")

        ip_gen = ASTFIPGen(
            glob=ASTFIPGenGlobal(ip_offset="1.0.0.0"),
            dist_client=ip_gen_c,
            dist_server=ip_gen_s
        )

        # UDPパケット作成
        base_pkt = Ether()/IP()/UDP(sport=1234, dport=4321)
        payload_len = max(0, 64 - len(base_pkt))
        payload = b'x' * payload_len

        # クライアント:UDP送信
        prog_c = ASTFProgram()
        prog_c.send(payload)

        # サーバ:UDP受信
        prog_s = ASTFProgram()
        prog_s.recv(len(payload))

        # clusterは引数なしで生成(TRex 3.06~3.08対応)
        cluster = ASTFCluster()

        # Client/Server Template(ip_genをキーワードで渡す)
        client = ASTFTCPClientTemplate(cluster=cluster, ip_gen=ip_gen, program=prog_c)
        server = ASTFTCPServerTemplate(program=prog_s)

        template = ASTFTemplate(client_template=client,
                                server_template=server)

        # ASTFProfile生成
        profile = ASTFProfile(default_ip_gen=ip_gen, templates=[template])

        return profile


def register():
    return ProfShort()

imix_astf.py

# imix_astf.py
from trex.astf.api import *
from scapy.all import *
import argparse
import os

class ProfImix():

    def __init__(self):
        # IMIXテーブル
        self.imix_table = [
            {'size': 60,   'pps': 28, 'isg': 0},
            {'size': 590,  'pps': 16, 'isg': 0.1},
            {'size': 1514, 'pps': 4, 'isg': 0.2}
        ]
        # IPレンジ
        self.ip_range = {
            'src': ["16.0.0.1", "16.0.0.254"],
            'dst': ["48.0.0.1", "48.0.0.254"]
        }

    def get_profile(self, tunables, **kwargs):
        parser = argparse.ArgumentParser(
            description='Argparser for {}'.format(os.path.basename(__file__)),
            formatter_class=argparse.ArgumentDefaultsHelpFormatter)
        args = parser.parse_args(tunables)

        # IPレンジ設定
        ip_gen_c = ASTFIPGenDist(ip_range=self.ip_range['src'], distribution="seq")
        ip_gen_s = ASTFIPGenDist(ip_range=self.ip_range['dst'], distribution="seq")

        ip_gen = ASTFIPGen(
            glob=ASTFIPGenGlobal(ip_offset="1.0.0.0"),
            dist_client=ip_gen_c,
            dist_server=ip_gen_s
        )

        # ASTFCluster生成
        cluster = ASTFCluster()

        # プログラム作成(クライアント送信 / サーバ受信)
        prog_c = ASTFProgram()
        prog_s = ASTFProgram()

        for entry in self.imix_table:
            size = entry['size']
            payload_len = max(0, size - len(Ether()/IP()/UDP()))
            payload = b'x' * payload_len

            # 送信
            prog_c.send(payload)
            # 受信
            prog_s.recv(len(payload))

        # Template生成
        client = ASTFTCPClientTemplate(cluster=cluster, ip_gen=ip_gen, program=prog_c)
        server = ASTFTCPServerTemplate(program=prog_s)
        template = ASTFTemplate(client_template=client, server_template=server)

        # ASTFProfile生成
        profile = ASTFProfile(default_ip_gen=ip_gen, templates=[template])

        return profile

def register():
    return ProfImix()

imix_astf.pyはTRexに付随している検証用ファイル(imix.py)を参考に作成しています

実行結果

この環境では、以下の結果になりました。

shortパケット IMIXパケット
bps 150 Mbps 300 Mbps
pps 250 kpps 300 kpps

補足

TRexでNAT検証を行う場合は、ASTF(Advanced Stateful Traffic)モード を使用します。

過去にはSTFモードにおける --learn-mode オプションを用いてNAT検証を行う方法も紹介されていましたが、今回検証した限りでは期待した動作を確認できませんでした。そのため、現在はASTFモードを用いた検証を推奨します。

詳細は以下の公式ドキュメントをご参照ください。

まとめ

本記事では、TRexを用いてVyOSのNAT機能を検証する方法について紹介しました。TRexを活用することで、高価な専用機材を用いずとも、NATセッション数やスループットといった重要な指標を実践的に検証することが可能です。

TRexやVyOSのバージョン、host OSの違いによって挙動が変わる点には注意が必要ですが、検証環境を正しく構築することで、再現性の高いNAT性能評価を行うことができます。今後、ソフトウェアルータや物理ルータのNAT性能検証を行う際の参考になれば幸いです。

参考記事

https://qiita.com/Shakapon/items/128f8d39cdacb8f1fc0a
https://metonymical.hatenablog.com/entry/2020/07/24/204413
https://www.youtube.com/watch?v=u7YV-53VxEU
https://trex-tgn.cisco.com/trex/doc/trex_astf.html

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?