0
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?

Containerlab上のixia-c-oneでDUT(cEOS)を介したL3トラフィック試験をやってみる

0
Last updated at Posted at 2026-07-13

はじめに

今回はContainerlab上でixia-cとDUTを接続し、トラフィックを印加した試験を試してみる。
構成としては非常にシンプルでixia-cの間にDUTを挟み込む構成とした。
DUTはcEOS(4.34.6M)を使う。

labのデプロイ

トポロジー定義ファイル(YAML)は、eth1とeth2の間にDUTを挟み込んだ構成とした。
前回はixia-cのトポロジーのみ作成していたが、今回はDUTであるcEOSのトポロジーを追加している。
また、Linkの設定でixia-cとcEOSが接続するように設定を加えている。

トポロジー設定

name: ixia-c-one-dut-test

topology:
  nodes:
    ixia-c:
      kind: keysight_ixia-c-one
      image: ghcr.io/open-traffic-generator/ixia-c-one:1.55.0-1

    ceos:
      kind: arista_ceos
      image: ceos:4.34.6M
      startup-config: ceos.cfg

  links:
    - endpoints: ["ixia-c:eth1", "ceos:eth1"]
    - endpoints: ["ixia-c:eth2", "ceos:eth2"]

topologyの項目に記載するcEOSの今回のstartup-config(ceos.cfg)は以下になる。

hostname ceos

service routing protocols model multi-agent

interface Ethernet1
   no switchport
   ip address 10.1.0.254/24
   no shutdown

interface Ethernet2
   no switchport
   ip address 10.2.0.254/24
   no shutdown

ip routing

デプロイ実施

containerlab deploy --topo ixia-c-one-dut-test.yml
23:46:23 INFO Containerlab started version=0.76.1
23:46:23 INFO Parsing & checking topology file=ixia-c-one-dut-test.yml
23:46:23 INFO Creating docker network name=clab IPv4 subnet=172.20.20.0/24 IPv6 subnet=3fff:172:20:20::/64 MTU=0
23:46:23 INFO Creating lab directory path=/home/test/lab/containerlab/clab-ixia-c-one-dut-test
23:46:23 INFO Creating container name=ixia-c
23:46:24 INFO Creating container name=ceos
23:46:24 INFO Created link: ixia-c:eth1 ▪┄┄▪ ceos:eth1
23:46:24 INFO Running postdeploy actions for keysight_ixia-c-one 'ixia-c' node
23:46:24 INFO Created link: ixia-c:eth2 ▪┄┄▪ ceos:eth2
23:46:24 INFO Running postdeploy actions for Arista cEOS 'ceos' node
23:47:05 INFO Adding host entries path=/etc/hosts
23:47:05 INFO Adding SSH config for nodes path=/etc/ssh/ssh_config.d/clab-ixia-c-one-dut-test.conf
23:47:05 INFO containerlab version
  🎉=
  │ A newer containerlab version (0.77.0) is available!
  │ Release notes: https://containerlab.dev/rn/0.77/
  │ Run 'clab version upgrade' or see https://containerlab.dev/install/ for other installation options.
╭─────────────────────────────────┬────────────────────────────────────────────────────┬─────────┬────────── ─────────╮
│               Name              │                     Kind/Image                     │  State  │   IPv4/6 Address  │
├─────────────────────────────────┼────────────────────────────────────────────────────┼─────────┼────────── ─────────┤
│ clab-ixia-c-one-dut-test-ceos   │ arista_ceos                                        │ running │ 172.20.20.3       │
│                                 │ ceos:4.34.6M                                       │         │ 3fff:172:20:20::3 │
├─────────────────────────────────┼────────────────────────────────────────────────────┼─────────┼────────── ─────────┤
│ clab-ixia-c-one-dut-test-ixia-c │ keysight_ixia-c-one                                │ running │ 172.20.20.2       │
│                                 │ ghcr.io/open-traffic-generator/ixia-c-one:1.55.0-1 │         │ 3fff:172:20:20::2 │
╰─────────────────────────────────┴────────────────────────────────────────────────────┴─────────┴────────── ─────────╯

ixia-cの試験コード(Port EndpointとDevice Endpointどちらを選択するか)

トラフィック印加自体はPort Endpointでも実現できる。ただし、DUTを介して異なるサブネット間で通信させる場合は、送信パケットの宛先MACアドレスをDUTのインターフェースMACアドレスに設定する必要がある。また、Port EndpointはARPへ応答するDeviceを持たないため、DUT側にもIxia-c側IPアドレスに対応する静的ARPを設定する必要がある。
一方、Device Endpointでは、Ethernet Interface、IPv4 Interface、DefaultGatewayを設定することで、Ixia-cがARP解決を行う。そのため、FlowごとにDUTのMACアドレスを手動で指定したり、DUT側へ静的ARPを設定したりする必要がなく、L3のDUTを介した試験をより自然に実行できる。

Device Endpointは送受信EndpointやARP解決を担う設定であり、Flowで使用するEthernet、IPv4、UDPなどのPacket Header設定とは別である。この点は以前実施したDevice Endpointの検証結果と同様であり、今回の DUT(cEOS)を挟んだ構成でも、Packet Headerを明示することで期待どおりにL3転送できることを確認した。

動作確認用サンプルコード

# Python標準ライブラリ(試験時間の待機処理に使用)
import time

# OTG APIを操作するPython SDK
import snappi


def test_device_endpoint_minimum():
    # ------------------------------------------------------------------
    # Controllerへ接続
    # ------------------------------------------------------------------
    api = snappi.api(
        location="https://clab-ixia-c-one-dut-test-ixia-c:8443",
        verify=False,
    )

    # ------------------------------------------------------------------
    # Config作成
    # ------------------------------------------------------------------
    cfg = api.config()

    # ------------------------------------------------------------------
    # Port作成
    # ------------------------------------------------------------------
    p1 = cfg.ports.add(
        name="p1",
        location="eth1",
    )

    p2 = cfg.ports.add(
        name="p2",
        location="eth2",
    )

    # ------------------------------------------------------------------
    # Device作成
    # ------------------------------------------------------------------
    dev1 = cfg.devices.add(name="Device1")
    dev2 = cfg.devices.add(name="Device2")

    # ------------------------------------------------------------------
    # Device1: Ethernet / IPv4 Interface
    # ------------------------------------------------------------------
    eth1 = dev1.ethernets.add(name="Device1.Ethernet1")
    eth1.connection.port_name = p1.name
    eth1.mac = "00:00:00:00:00:01"

    ip1 = eth1.ipv4_addresses.add(name="Device1.IPv4")
    ip1.address = "10.1.0.1"
    ip1.gateway = "10.1.0.254"
    ip1.prefix = 24

    # ------------------------------------------------------------------
    # Device2: Ethernet / IPv4 Interface
    # ------------------------------------------------------------------
    eth2 = dev2.ethernets.add(name="Device2.Ethernet1")
    eth2.connection.port_name = p2.name
    eth2.mac = "00:00:00:00:00:02"

    ip2 = eth2.ipv4_addresses.add(name="Device2.IPv4")
    ip2.address = "10.2.0.1"
    ip2.gateway = "10.2.0.254"
    ip2.prefix = 24

    # ------------------------------------------------------------------
    # Flow1: Device1 → Device2
    # ------------------------------------------------------------------
    flow1 = cfg.flows.add(name="Device1_to_Device2")

    # Device Endpointを使用
    flow1.tx_rx.device.tx_names = [ip1.name]
    flow1.tx_rx.device.rx_names = [ip2.name]
    
    # Packet Headerを明示
    eth, ipv4, udp = flow1.packet.ethernet().ipv4().udp()

    # IP Address
    ipv4.src.value = "10.1.0.1"
    ipv4.dst.value = "10.2.0.1"
    
    # UDP Port
    udp.src_port.value = 50000
    udp.dst_port.value = 50001

    # Frame Size
    flow1.size.fixed = 512

    # Rate
    flow1.rate.percentage = 10

    # Duration
    flow1.duration.fixed_seconds.seconds = 10

    # Metrics
    flow1.metrics.enable = True
    
    # ------------------------------------------------------------------
    # Flow2: Device2 → Device1
    # ------------------------------------------------------------------
    flow2 = cfg.flows.add(name="Device2_to_Device1")

    # Device Endpointを使用
    flow2.tx_rx.device.tx_names = [ip2.name]
    flow2.tx_rx.device.rx_names = [ip1.name]
    
    # Packet Headerを明示
    eth, ipv4, udp = flow2.packet.ethernet().ipv4().udp()

    # IP Address
    ipv4.src.value = "10.2.0.1"
    ipv4.dst.value = "10.1.0.1"
    
    # UDP Port
    udp.src_port.value = 50001
    udp.dst_port.value = 50000

    # Frame Size
    flow2.size.fixed = 512

    # Rate
    flow2.rate.percentage = 10

    # Duration
    flow2.duration.fixed_seconds.seconds = 10

    # Metrics
    flow2.metrics.enable = True

    # ------------------------------------------------------------------
    # Config確認
    # ------------------------------------------------------------------
    print(
        "\nCONFIGURATION",
        cfg.serialize(encoding=cfg.JSON),
        sep="\n",
    )

    # ------------------------------------------------------------------
    # Config反映
    # ------------------------------------------------------------------
    api.set_config(cfg)

    # ------------------------------------------------------------------
    # Protocol起動
    # ------------------------------------------------------------------
    state = api.control_state()
    state.protocol.all.state = state.protocol.all.START
    api.set_control_state(state)

    print("Protocol Started")

    # ARP解決待ち
    time.sleep(10)

    # ------------------------------------------------------------------
    # Traffic印加開始
    # ------------------------------------------------------------------
    state = api.control_state()
    state.traffic.flow_transmit.state = (
        state.traffic.flow_transmit.START
    )
    state.traffic.flow_transmit.flow_names = [
        flow1.name,
        flow2.name,
    ]
    api.set_control_state(state)

    print("Traffic Started")

    # ------------------------------------------------------------------
    # Metrics取得
    # ------------------------------------------------------------------
    request = api.metrics_request()
    request.flow.flow_names = [
        flow1.name,
        flow2.name,
    ]

    for _ in range(20):
        metrics = api.get_metrics(request)
        print(metrics)

        if metrics.flow_metrics and all(
            metric.transmit == metric.STOPPED
            for metric in metrics.flow_metrics
        ):
            break

        time.sleep(1)

    # ------------------------------------------------------------------
    # Traffic印加停止
    # ------------------------------------------------------------------
    state = api.control_state()
    state.traffic.flow_transmit.state = (
        state.traffic.flow_transmit.STOP
    )
    state.traffic.flow_transmit.flow_names = [
        flow1.name,
        flow2.name,
    ]
    api.set_control_state(state)

    print("Traffic Stopped")

    # ------------------------------------------------------------------
    # Protocol停止
    # ------------------------------------------------------------------
    state = api.control_state()
    state.protocol.all.state = state.protocol.all.STOP
    api.set_control_state(state)

    print("Protocol Stopped")

動作確認結果

Device Endpointの動作確認としてトラフィックを印加した。Flow Metricsでは送受信レートやフレーム数を確認できる。また、cEOS側ではARPテーブルやInterface Counterを確認することで、DUTが期待どおりにパケット転送をしていることを確認した。

$ ./do.sh pytest examples/clab-device-endpoint2.py -s
============================= test session starts ==============================
platform linux -- Python 3.12.3, pytest-7.1.1, pluggy-1.6.0 -- /home/test/lab/ixia-c/conformance/.env/bin/python
cachedir: .pytest_cache
rootdir: /home/test/lab/ixia-c/conformance, configfile: pytest.ini
plugins: html-4.2.0
collecting ... collected 1 item

examples/clab-device-endpoint2.py::test_device_endpoint_minimum 2026-07-13 13:23:02.988 [snappi] [WARNING] Version check is disabled

-------------------------------- live log call ---------------------------------
WARNING  snappi:snappi.py:106 Version check is disabled
2026-07-13 13:23:02.988 [snappi] [WARNING] Certificate verification is d

flow_metrics:
  name: Device1_to_Device2
  frames_tx: '1809955'
  frames_rx: '37916'
  tx_rate_bps: 773928500
  rx_rate_bps: 16764332

  name: Device2_to_Device1
  frames_tx: '1793259'
  frames_rx: '37918'
  tx_rate_bps: 787894400
  rx_rate_bps: 16760348

Traffic Stopped
Protocol Stopped
PASSED

※frames_tx が180万前後に対し frames_rx が3.8万程度と大きな差があるが、Discardについては後述

cEOS側の確認。Startup-configにSSHの設定を書く等でも良いが、今回は別の方法でceosにログインする。

 docker exec -it clab-ixia-c-one-dut-test-ceos Cli
ceos#show arp
Address         Age (sec)  Hardware Addr   Interface
10.1.0.1          2:14:01  0000.0000.0001  Ethernet1
10.2.0.1          1:40:24  0000.0000.0002  Ethernet2
ceos#show interfaces counters
Port                           InOctets     InUcastPkts     InMcastPkts     InBcastPkts
Et1                            22240302           43438               0               1
Et2                            22239790           43437               0               1
Ma0                                   0               0               0               0

Port                          OutOctets    OutUcastPkts    OutMcastPkts    OutBcastPkts
Et1                            22239744           43437               0               0
Et2                            22240256           43438               0               0
Ma0                                1410               6               0               0
ceos#
ceos#show interfaces counters discards
Port               InDiscards    OutDiscards
--------------- ---------------- -----------
Et1                   1766517              0
Et2                   1749822              0
Ma0                         0              0
---------           ---------      ---------
Totals                3516339              0

Flow Metricsでは、片方向あたり約0.78Gbps、双方向合計約1.56Gbpsのトラフィックを送信できることを確認した。一方、cEOSではInput Discardsが多数発生していた。送信レートをrate.percentage = 0.01へ変更するとDiscardは発生しなくなったことから、今回のInput Discardsは、cEOSを含む仮想検証環境の処理能力に対して送信レートが高かったことが主な要因と考えられる。

送信レートを下げた試験での結果

flow_metrics:
  name: Device1_to_Device2
 frames_tx: '2351'
  frames_rx: '2351'
  tx_rate_bps: 962770.6
  rx_rate_bps: 962405.4
flow_metrics:
  Device2_to_Device1
  frames_tx: '2350
  frames_rx: '2350'
  tx_rate_bps: 962406.06
  rx_rate_bps: 962406


ceos#show interfaces counters
Port                           InOctets     InUcastPkts     InMcastPkts     InBcastPkts
Et1                             1203758            2351               0               1
Et2                             1203246            2350               0               1
Ma0                                   0               0               0               0

Port                          OutOctets    OutUcastPkts    OutMcastPkts    OutBcastPkts
Et1                             1203200            2350               0               0
Et2                             1203712            2351               0               0
Ma0                                 235               1               0               0
ceos#
ceos#show interfaces counters discards
Port               InDiscards    OutDiscards
--------------- ---------------- -----------
Et1                         0              0
Et2                         0              0
Ma0                         0              0
---------           ---------      ---------
Totals                      0              0

まとめ

今回はixia-cに加えDUTとしてcEOSを間に挟んだ構成でトラフィック印加を試みた。cEOSや他の仮想ルータを並べた試験やルーティングの試験等様々なケースに適用できると感じた。物理アプライアンスを繋げる試験も実施したいところではあるが現在環境が準備できないので、準備できる機会があれば試してみたいと考えている。

今回もDevice Endpointによる検証は以前と同様の結果となり、L3 DUTを挟んだ構成でも期待どおりの転送を確認できた。
今回作成した試験コードは、Containerlab上で仮想DUTを組み合わせたL3試験のひな形として利用できる。
また、ixia-c・ixia-c-oneであっても試験コードは流用して使えることが分かった。

0
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
0
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?