Keysight(旧IXIA)IxNetworkを用いた
ネットワーク試験の自動化

【技業LOG】技術者が紹介するNTTPCのテクノロジー

2024.06.18
その他
菊池 陽平

ネットワークスペシャリスト
菊池 陽平

取得資格:ネットワークスペシャリスト、CCNP Enterprise、LPIC 304

はじめに

NTTPCが提供するSD-WANサービス「Master'sONE CloudWAN®」は、検証期間の短縮と品質維持のため、ネットワーク機能試験の自動化を行っています。

自動試験環境の一部の試験項目では、Keysight Technologies社(旧IXIA)のネットワーク測定器「IxNetwork」を使用しています。
本記事では、自動化を実現するIxNetworkクライアント"ixnetwork_restpy"を具体的なサンプルコードと合わせて紹介します。

本記事は下記のような方に向けた内容です。

  • IxNetworkを普段利用している方
  • ネットワーク機器のテスト自動化を実施中・これから実施したい方
  • Pythonの基礎的な文法を習得しており、簡単なプログラムを書ける方

IxNetworkによる試験自動化の活用例

Master'sONE CloudWAN®の自動試験は、Python上で動作するRobot Frameworkのテストケースとして実装しています。
現時点で自動試験には100項目以上のテストケースが存在しています。
もっとも単純なテストケースはエッジ装置間での疎通試験です。少し複雑なものでは、HybirdWAN機能による回線品質に応じた動的な使用回線の切り替え試験なども自動化しています。自動試験のほとんどの項目では、試験用通信を発生させるため、Linuxコンテナ上でpingやtraceroute、curl、iperfといった各種コマンド・ソフトウェアを使用しています。
これらのコマンドの実行や、試験に関連する各機器(スイッチなど)の操作やログ取得のため、各コマンド・各機器向けに操作用のライブラリをPythonで実装し、このライブラリをRobot Frameworkから呼び出すことにより自動試験を実現しています。

しかし、自動試験の一部の試験では、さらに高度なトラフィック生成やより精度の高い測定が要求されます。そのような試験にはネットワーク測定器 「IxNetwork」を使用しています。

IxNetworkは、L2/L3のあらゆるプロトコルに対応した高機能なネットワーク測定器です。トラフィック生成と測定のみならず、OSPFやBGPといったルーティングプロトコルなどにも対応しています。
また、REST APIによる操作をサポートしており、Python向けにはIxNetworkクライアントであるixnetwork_restpyが提供されています。
ixnetwork_restpyを活用することでPythonのプログラムから簡単にIxNetworkの操作を行うことができるようになり、簡単に自動試験にIxNetworkを組み込むことができます。

ixnetwork_restpyの概要

ixnetwork_restpyは、Python向けのIxNetworkクライアントです。
IxNetworkには自動化手段がいくつか用意されており、そのうちの1つがREST APIによる操作です。
ixnetwork_restpyは、このREST APIをPython上でより簡単に扱うことができるようになるライブラリです。

ixnetwork_restpyの使用準備

構成例

本記事では次のような試験環境を例として扱います。

試験環境 構成例

スクリプト実行サーバーは、ixnetwork_restpyを用いたスクリプトを実行するサーバーです。
今回はUbuntu22.04が稼働しているサーバーを使用していますが、Pythonの実行環境があればWindowsでもOKです。

APIサーバーは、IxNetworkのAPIサーバーを動作させるサーバーです。Windows版とLinux版があります。
ixnetwork_restpyはこのAPIサーバーを通じてIxNetworkのシャーシ(ハードウェア)を制御します。
今回はWindowsが稼働しているノートPCを使用し、IxNetworkクライアント付属のAPIサーバーを動かしています。
Linux版を使用する場合は、公式が提供しているOVFファイルからデプロイすることができます。

IxNetworkシャーシは、実際に通信を発生させるためのハードウェアです。
IxNetworkシャーシは物理版と仮想版が提供されており、今回は仮想版を使用しています。物理版と仮想版は試験性能に差があるものの、ixnetwork_restpyを使っての操作方法はどちらも同じです。)

これらのサーバーとIxNetworkシャーシは、管理用のネットワークでつながっており、相互に通信できる状態になっています。
IxNetworkシャーシのポートを2つ使用し、試験対象機器(今回は簡単のためL2スイッチ)と接続して、port3からport4にトラフィックを流します。

APIサーバーの準備

本記事の執筆にあたっては、次のバージョンのソフトウェアを使用しています。

  • IxNetwork(Windowsクライアント): 9.00.1915.16
  • IxNetwork(シャーシ 仮想版): 9.00.1900.10
  • Ixnetwork_restpy: 1.1.12
  • Python: 3.10.12

最新版では改善・変更されている個所があるかもしれません。
本記事のサンプルコードは自由に使用して頂いて構いませんが、ご利用のバージョンに対応した各種ドキュメントを合わせてご確認ください。

ixnetwork_restpyを使用するには、前述の通り、まずIxNetworkのAPIサーバーを用意する必要があります。

APIサーバーは次のサイトからダウンロードすることが可能です。
https://support.ixiacom.com/ixnetwork-software-downloads-documentation
APIサーバーにはWindows版とLinux版が存在します。

Windows版は通常のIxNetworkクライアントにAPIサーバー機能が実装されています。
WindowsのIxNetworkクライアントのインストール時に自動的にAPIサーバーもインストールされるため、とりあえず試すだけであれば、これが最も簡単に利用できます。
このWindows版のAPIサーバーは、APIからの操作がGUI上に反映されていくため、コードからの設定がどのように反映されていくかを確認することもできます。
(普段Windowsクライアントを使い慣れている方であれば、コード上での操作との対応関係がわかりやすいかと思います)
ixnetwork_restpyを利用する場合は、Windows版のAPIサーバーを利用するのがおすすめです。

Linux版(IxNetwork Web Edition)は1つのサーバーで複数のセッションを持つことができ、同時に複数人で利用したい場合はこちらを利用するのが便利です。
私自身はほとんど利用したことはないのですが、WebブラウザーからGUIにアクセスすることで、GUIからIxNetworkの制御を行うことができます。
(Windows版と同じく、APIからの操作もリアルタイムにGUIに反映されていくようです)

Windows版を使用するか、Linux版を使用するかは、状況に応じて使い分けると良いかと思います。
私の場合は、Windowsクライアントを使い慣れていることもあって、開発フェーズではWindows版を利用しています。
しかし、自動試験の運用フェーズでは、複数のテストが同時に動作することがあるため、セッションを複数利用可能なLinux版(IxNetwork Web Edition)を利用しています。
(以降の説明では、Windows版を利用します。)

IxNetworkのWindowsクライアントをインストールすると、APIサーバーも自動でインストールされ、スタートメニューのショートカットから起動できます。
(起動後は自動的にタスクトレイにしまわれていることがあるので、ウインドウが表示されない場合は、タスクトレイを確認してみましょう。)

起動すると、ウインドウのステータスバーにポート番号が表示されます。

以降のプログラムでAPIサーバーの指定の際には、このRESTポート番号(11009)を指定します。

ixnetwork_restpyのセットアップ

ixnetwork_restpyはPyPIで配信されており、pipでインストールすることができます。

pip install ixnetwork-restpy

ixnetwork_restpyの使い方とサンプルプログラム

ixnetwork_restpyの構造(クラスとリソースの階層構造)

ixnetwork_restpyでは、IxNetworkの設定を「リソース」と呼ばれるデータを階層構造で表現しています。
リソースは、いくつかの設定値が意味のある単位でまとめられています。
ixnetwork_restpyでは、リソース毎に対応するクラスが存在し、そのリソースに関連するパラメータ(設定値)はそのクラスのプロパティとして実装されています。
このプロパティにアクセスすることで設定値の参照・変更が可能です。
また、リソースは階層構造になっており、その階層構造はリファレンスで確認することができます。
ixnetwork_restpy リファレンス:
https://openixia.github.io/ixnetwork_restpy/#/reference

例えば「Topology」は抽象化されたネットワークや、実際にパケットを送受信するホストを内包しているリソースです。
このTopologyのもとに、設定上のポートである仮想ポートや、VLAN設定、通信時に使用するアドレス、ルーティングプロトコルで送受信するネットワークプレフィックスなどが設定されます。
実際にはこれらの設定もそれぞれリソースになっており、Topologyから参照されます。
例えば、TopologyにはPortsというプロパティが存在し、このプロパティには仮想ポートを示すvportと呼ばれるリソースがリストで格納されます。

APIリファレンス内のTopologyのPortsプロパティ

APIリファレンス内のTopologyのPortsプロパティ

プロパティを参照すると現在の設定を取得することができ、ここに書き込むことで設定を変更することができます。
さらに、リソースによって何かしらの操作(例えば、アドレスを追加する、トラフィックを生成する、など)を行うことができ、それらはメソッドとして実装されていて、呼び出すことで操作を行えます。

既存の設定ファイルを読み込んで使用する

簡単な使用例として、既存の設定ファイルを読み込んで使用するスクリプトを作ってみます。
過去の試験時の設定ファイルを試験結果やログファイルなどと一緒に保存している方も多いと思います。

次の例では、過去の試験時の設定ファイルを基にconfigを読み込み、トラフィックを流すサンプルプログラムです。

import time
import traceback

from ixnetwork_restpy import Files, SessionAssistant


def get_session(api_server_address, api_server_rest_port, username, password):
    # API Server(Windows)
    session_assistant = SessionAssistant(
        IpAddress=api_server_address,
        RestPort=api_server_rest_port,
        UserName=username,
        Password=password,
        LogLevel=SessionAssistant.LOGLEVEL_INFO,
        ClearConfig=True
    )

    sessions = session_assistant.TestPlatform.Sessions.find()
    if len(sessions) < 1:
        raise Exception("Failed to get new session")

    return sessions[0]

# 設定ファイルのパス
# (使用する設定ファイルはこのスクリプトを実行するサーバー上に置いておく)
config_file = "./simple_testcase.ixncfg"

# セッション取得
# APIサーバーのアドレス、ポート番号、認証情報(デフォルトはユーザー名・パスワード共にadmin)を指定する
session = get_session("10.0.1.251", 11009, "admin", "admin")
ixnetwork = session.Ixnetwork

try:
    # 設定ファイルのアップロードと読み込み
    session.UploadFile(config_file)
    ixnetwork.LoadConfig(Files(config_file))

    # 使用するIxNetworkシャーシの物理ポートをdictで指定する
    # Arg1: シャーシのアドレス
    # Arg2: シャーシのカード番号
    # Arg3: シャーシのポート番号
    test_port1 = dict(Arg1="10.0.1.72", Arg2=1, Arg3=3)
    test_port2 = dict(Arg1="10.0.1.72", Arg2=1, Arg3=4)

    # Topologyを名前で検索し、そのTopologyに含まれる仮想ポートを取得する
    topology1 = ixnetwork.Topology.find(Name="Topology 1")[0]
    vport1 = topology1.Ports[0]

    # 次のようにつなげて書くこともできる
    vport2 = ixnetwork.Topology.find(Name="Topology 2")[0].Ports[0]

    # 物理ポートと仮想ポートの割り当て
    # 仮想ポートは設定上のポートであり、実際にトラフィックを流す際にはAssignPortsで、シャーシの物理ポートを割り当てて使用する
    # 第1引数: 割り当てに含めるシャーシの物理ポートのリスト
    # 第2引数: 割り当てで除外するシャーシの物理ポートのリスト
    #          リファレンスにも詳しい説明がなく、動作や利用用途が不明
    #          実際に挙動を確認すると第1引数のリストから第2引数のポートを除いたものが、割り当て対象になっているように見える
    #          (今回は空を指定し、第1引数のポートすべてを割り当て対象にする)
    # 第3引数: 使用する設定上の仮想ポートのリスト
    # 第4引数: 使用する物理ポートが使用済みの場合、強制的に使用権を取得するかどうか
    ixnetwork.AssignPorts([test_port1, test_port2], [], [vport1, vport2], True)    # プロトコル起動
    ixnetwork.StartAllProtocols()
    time.sleep(10)

    # TrafficItemのApply操作前にGenerate操作が必要(GUIのTrafficItemのRegenerateボタン相当)
    for t in ixnetwork.Traffic.TrafficItem.find():
        t.Generate()

    # TrafficItemを適用し、トラフィックを流す準備
    ixnetwork.Traffic.Apply()

    # トラフィック生成開始
    ixnetwork.Traffic.Start()
    print("Start Traffic generation.")

    time.sleep(20)

    # トラフィック止める
    ixnetwork.Traffic.Stop()
    print("Finish Traffic generation.")

except:
    print(traceback.format_exc())

finally:
    # 終了時にはセッションを解放する
    session.remove()

設定ファイルを読み込んだ後に、実際に利用する物理ポートとの割り当てを行っています。
そのあと、プロトコルを起動しトラフィックを生成するという流れです。

手動でGUIを使用してIxNetworkを制御する際にも行う操作なので、IxNetworkを普段利用している方は、GUI上での操作との対応がイメージできると思います。

実行するとこのような感じです。
(ユーザー名やホスト名が入っている個所は書き換えています)

username@sv03:~/work$ python exist_config.py
2024-02-16 02:27:13 [ixnetwork_restpy.connection tid:139982382391744] [INFO] using python version 3.10.12 (main, Nov 20 2023, 15:14:05) [GCC 11.4.0]
2024-02-16 02:27:13 [ixnetwork_restpy.connection tid:139982382391744] [INFO] using ixnetwork-restpy version 1.1.12
2024-02-16 02:27:13 [ixnetwork_restpy.connection tid:139982382391744] [WARNING] Verification of certificates is disabled
2024-02-16 02:27:13 [ixnetwork_restpy.connection tid:139982382391744] [INFO] Determining the platform and rest_port using the 10.0.1.251 address...
2024-02-16 02:27:13 [ixnetwork_restpy.connection tid:139982382391744] [INFO] Connection established to `http://10.0.1.251:11009 on windows`
2024-02-16 02:27:13 [ixnetwork_restpy.connection tid:139982382391744] [INFO] Using IxNetwork api server version 9.00.1915.16
2024-02-16 02:27:13 [ixnetwork_restpy.connection tid:139982382391744] [INFO] User info IxNetwork/LAPTOP-HOGEHOGE/username
2024-02-16 02:27:23 [ixnetwork_restpy.connection tid:139982382391744] [INFO] Using IxNetwork api server version 9.00.1915.16
2024-02-16 02:27:23 [ixnetwork_restpy.connection tid:139982382391744] [INFO] User info IxNetwork/LAPTOP-HOGEHOGE/username
Start Traffic generation.
Finish Traffic generation.

トラフィックを流しているだけなので、サーバーへの接続情報が表示されているくらいで特に役に立つ情報は出てきません。

ちなみに、SessionAssistantの初期の際に、LogLevel="all"を指定するとより詳細なログを出してくれるようになります。

次のものは、LogLevel="all"を指定した場合のログからの抜粋ですが、コンフィグファイルをアップロードして読み込んでいる個所のリクエスト・レスポンスが表示されています。

2024-02-16 02:25:20 [ixnetwork_restpy.connection tid:140324461846976] [DEBUG] POST http://10.0.1.251:11009/api/v1/sessions/1/ixnetwork/files?filename=simple_testcase.ixncfg
2024-02-16 02:25:20 [ixnetwork_restpy.connection tid:140324461846976] [DEBUG] 201 Created b'{"absolute":null,"files":[{"name":"simple_testcase.ixncfg","length":101186,"modifiedUnixTime":1708082720,"createdUnixTime":1706198458}],"directories":[]}'
2024-02-16 02:25:20 [ixnetwork_restpy.connection tid:140324461846976] [DEBUG] POST http://10.0.1.251:11009/api/v1/sessions/1/ixnetwork/operations/loadconfig {"Arg1": "simple_testcase.ixncfg"}
2024-02-16 02:25:23 [ixnetwork_restpy.connection tid:140324461846976] [DEBUG] 202 Accepted b'{"executionTimeMs":3578.0,"id":"","state":"SUCCESS","progress":100,"message":null,"url":"","resultUrl":"","result":"kVoid"}'

Pythonスクリプトだけで設定を作る方法

既存の設定ファイルを活用するだけでなく、Pythonスクリプトのみで一から設定を作り上げることも可能です。
こちらは難易度が上がりますが、試験設定をコードとして記述できます。
gitなどのソースコード管理ツールを使えば、他の試験コードと同様にIxNetworkの試験設定もコードとして管理できるようになります。

サンプルプログラムがこちらです。

import time
import traceback

from ixnetwork_restpy import BatchAdd, SessionAssistant, StatViewAssistant


def get_session(api_server_address, api_server_rest_port, username, password):
    # API Server(Windows)
    session_assistant = SessionAssistant(
        IpAddress=api_server_address,
        RestPort=api_server_rest_port,
        UserName=username,
        Password=password,
        LogLevel=SessionAssistant.LOGLEVEL_INFO,
        ClearConfig=True
    )

    sessions = session_assistant.TestPlatform.Sessions.find()
    if len(sessions) < 1:
        raise Exception("Failed to get new session")

    return sessions[0]

# セッション取得
session = get_session("10.0.1.251", 11009, "admin", "admin")
ixnetwork = session.Ixnetwork

try:
    # 物理ポート
    test_port1 = dict(Arg1="10.0.1.72", Arg2=1, Arg3=3)
    test_port2 = dict(Arg1="10.0.1.72", Arg2=1, Arg3=4)

    # topologyの作成
    # 仮想ポートをtopologyに追加し、ホスト数やアドレスなどを設定する
    vport1 = ixnetwork.Vport.add()
    topology1 = ixnetwork.Topology.add(Name="topology1")
    topology1.Ports = [vport1]
    device_group1 = topology1.DeviceGroup.add(Multiplier=1)
    ethernet1 = device_group1.Ethernet.add()
    ipv4_1 = ethernet1.Ipv4.add()
    ipv4_1.Address.Single("192.168.1.1")
    ipv4_1.Prefix.Single("24")
    ipv4_1.GatewayIp.Single("192.168.1.2")

    vport2 = ixnetwork.Vport.add()
    topology2 = ixnetwork.Topology.add(Name="topology2")
    topology2.Ports = [vport2]
    device_group2 = topology2.DeviceGroup.add(Multiplier=1)
    ethernet2 = device_group2.Ethernet.add()
    ipv4_2 = ethernet2.Ipv4.add()
    ipv4_2.Address.Single("192.168.1.2")
    ipv4_2.Prefix.Single("24")
    ipv4_2.GatewayIp.Single("192.168.1.1")


    # traffic itemの作成
    # Trackingの設定はBatchAssistantの利用し、1度のREST呼び出しでまとめて操作する必要がある
    # BatchAssistantを使わないと次のようなエラーが出る
    # Exception: This feature is only available with Batch Assistance
    traffic_item_name = "traffic1"
    with BatchAdd(ixnetwork):
        traffic_item1 = ixnetwork.Traffic.TrafficItem.add(
            Name=traffic_item_name,
            TrafficType="ipv4",
            TrafficItemType="l2L3"
        )
        endpoint_set1 = traffic_item1.EndpointSet.add()
        endpoint_set1.Sources = topology1
        endpoint_set1.Destinations = topology2
        track1 = traffic_item1.Tracking.add()
        track1.TrackBy = ["trackingenabled0"]

    # フレームレートと送信時間の設定
    config = ixnetwork.Traffic.TrafficItem.find(Name=traffic_item_name)[0].ConfigElement.find()[0]
    config.FrameRate.Type = "bitsPerSecond"
    config.FrameRate.BitRateUnitsType = "mbitsPerSec"
    config.FrameRate.Rate = 50
    config.TransmissionControl.Type = "continuous"

    # 物理ポートの割り当て
    ixnetwork.AssignPorts([test_port1, test_port2], [], [vport1, vport2], True)

    # プロトコル起動
    ixnetwork.StartAllProtocols()
    time.sleep(10)


    # Traffic Itemを適用
    traffic_item1.Generate()
    ixnetwork.Traffic.Apply()

    # トラフィック生成開始
    ixnetwork.Traffic.Start()

    print("Start Traffic generation.")
    time.sleep(20)

    ixnetwork.Traffic.Stop()
    print("Finish Traffic generation.")


    # 以降は統計データの取得と合否判定
    # 統計のViewに反映されるまで数秒待つ
    time.sleep(10)

    # 統計データの取得にはStatViewAssistantを利用すると良い
    # ただしAPI Referenceにリファレンスがない
    # サンプルコードはあるので、そちらを参考にしつつ、必要に応じてライブラリのコードを確認する必要がある
    # https://github.com/OpenIxia/ixnetwork_restpy/tree/master/ixnetwork_restpy/assistants/statistics

    # 対象とするstatisticsをViewの名前で取得する
    stat = StatViewAssistant(ixnetwork, ViewName="Traffic Item Statistics")
    # ちなみに利用可能なViewの一覧は次の通り取得できる
    # print(StatViewAssistant.GetViewNames(ixnetwork))

    # 取得したstatisticsのRowsプロパティを参照すると、Viewの各行がiterableなオブジェクトとして得ることができる
    # また、配列のようにindexを指定することで特定の行を取り出すこともできる
    # print(stat.Rows[0])
    #
    # ただし、ループで取り出すのは少し面倒なので、RowFilterを利用すると便利
    # 今回はTraffic Itemは1つだけなので、1行しか存在しないが、複数行ある場合は、次のように行を絞り込める
    # 列名:TrafficItemの列がtraffic1という値になっている行に絞る
    stat.AddRowFilter("Traffic Item", StatViewAssistant.EQUAL, "traffic1")
    #
    # 第2引数は比較条件を指定する、使用できる条件は次の通り
    # > Comparator (enum(REGEX|EQUAL|NOT_EQUAL)): A StatViewAssistant comparator constant
    # https://github.com/OpenIxia/ixnetwork_restpy/blob/master/ixnetwork_restpy/assistants/statistics/statviewassistant.py
    #
    # AddRowFilterを複数回適用することでさらに絞り込むことができる
    # フィルタを解除したい場合は、次のようにすべてのフィルタをクリアできる
    # stat.ClearRowFilters()

    # 1行のみに絞られていること
    assert len(stat.Rows) == 1
    print("=== traffic statistics ===")
    print(stat.Rows[0])
    print("==========================")

    # 対象の行が特定出来たら、辞書のようにkeyでアクセスして任意の列の値を取り出すことができる
    loss_value = float(stat.Rows[0]["Loss %"])

    # CheckConditionで、値を直接比較することもできるので、単なる合否判定ならこちらが便利
    # 複数行ある場合は、すべての行に対して指定された列の値をチェックする
    # (リファレンスがないので、直接コードで確認。コード上のコメントにも記述があった)
    # > Check that all the ColumnName cells in the view meet the comparator and condition value.
    # https://github.com/OpenIxia/ixnetwork_restpy/blob/master/ixnetwork_restpy/assistants/statistics/statviewassistant.py
    stat.CheckCondition("Loss %", StatViewAssistant.EQUAL, 0.0)

    print("Loss: %f%%" % loss_value)
    print("Test Passed!")
except:
    print(traceback.format_exc())

finally:
    session.remove()

統計情報からロス率を取得して、合否判定まで実装してみました。

統計情報の取得は、直接Statisticsのリソースを扱うと大変なのですが、StatViewAssistantを利用することで簡単に扱うことができました。

実行結果はこのような感じです。

username@sv03:~/work$ poetry run python create_config.py
2024-03-21 06:40:51 [ixnetwork_restpy.connection tid:140467684934080] [INFO] using python version 3.10.12 (main, Nov 20 2023, 15:14:05) [GCC 11.4.0]
2024-03-21 06:40:51 [ixnetwork_restpy.connection tid:140467684934080] [INFO] using ixnetwork-restpy version 1.1.12
2024-03-21 06:40:51 [ixnetwork_restpy.connection tid:140467684934080] [WARNING] Verification of certificates is disabled
2024-03-21 06:40:51 [ixnetwork_restpy.connection tid:140467684934080] [INFO] Determining the platform and rest_port using the 10.0.1.251 address...
2024-03-21 06:40:51 [ixnetwork_restpy.connection tid:140467684934080] [INFO] Connection established to `http://10.0.1.251:11009 on windows`
2024-03-21 06:40:51 [ixnetwork_restpy.connection tid:140467684934080] [INFO] Using IxNetwork api server version 9.00.1915.16
2024-03-21 06:40:51 [ixnetwork_restpy.connection tid:140467684934080] [INFO] User info IxNetwork/LAPTOP-HOGEHOGE/username
2024-03-21 06:41:01 [ixnetwork_restpy.connection tid:140467684934080] [INFO] Using IxNetwork api server version 9.00.1915.16
2024-03-21 06:41:01 [ixnetwork_restpy.connection tid:140467684934080] [INFO] User info IxNetwork/LAPTOP-HOGEHOGE/username
2024-03-21 06:41:02 [ixnetwork_restpy.connection tid:140467684934080] [INFO] [0.303s] Timer @ batchadd.py:384 -> Batch Add Completed
Start Traffic generation.
Finish Traffic generation.
=== traffic statistics ===
Row:0  View:Traffic Item Statistics  Sampled:2024-03-21 06:42:16.775343 UTC
        Traffic Item: traffic1
        Tx Frames: 1297176
        Rx Frames: 1297176
        Frames Delta: 0
        Loss %: 0.000
        Tx Frame Rate: 0.000
        Rx Frame Rate: 0.000
        Tx L1 Rate (bps): 0.000
        Rx L1 Rate (bps): 0.000
        Rx Bytes: 85613616
        Tx Rate (Bps): 0.000
        Rx Rate (Bps): 0.000
        Tx Rate (bps): 0.000
        Rx Rate (bps): 0.000
        Tx Rate (Kbps): 0.000
        Rx Rate (Kbps): 0.000
        Tx Rate (Mbps): 0.000
        Rx Rate (Mbps): 0.000
        Store-Forward Avg Latency (ns): 165002
        Store-Forward Min Latency (ns): 0
        Store-Forward Max Latency (ns): 4863820
        First TimeStamp: 00:00:02.011
        Last TimeStamp: 00:00:15.708
        Dead Flow: 0

==========================
Loss: 0.000000%
Test Passed!

設定ファイルを使い回す例と比べて少し難しくなります。
特にトラフィックの設定は、設定すべきパラメータが多く、IxNetworkにどのような設定・パラメータが存在しているのかを知っておく必要があります。

WindowsクライアントなどのGUI上から設定すると暗黙的に設定される値でも、コードからは明示的に設定しなければならない場合があります。
また、設定したいパラメータがどの階層に入っているのか分かりにくい場合があります。

コードで設定を記述する場合、基本的には公式ドキュメント内のサンプルコードやリファレンスが参考になります。
しかし、それらを参照してもいきなり設定を作るのは難しいため、まず目的の設定をGUIから設定し、ixnetwork_restpyを使用してその設定内容を確認すると良いでしょう。
ixnetwork_restpyの各リソースのクラスには__str__()メソッドが実装されており、printなどで表示することで、プロパティの設定値を確認することができます。

例えば、上記のサンプルコードで設定したリソースをいくつか表示してみるとそれぞれ次のような出力が得られます。

# print(ixnetwork.Topology.find("topology1")[0])
Topology[0]: /api/v1/sessions/1/ixnetwork/topology/1
        DescriptiveName: topology1
        Errors: []
        Name: topology1
        Note:
        PortCount: 1
        Ports: ['/api/v1/sessions/1/ixnetwork/vport/1']
        PortsStateCount: {'arg1': 1, 'arg2': 1, 'arg3': 0, 'arg4': 0, 'arg5': 0, 'arg6': 0}
        Status: started
        Vports: ['/api/v1/sessions/1/ixnetwork/vport/1']

# print(ixnetwork.Vport.find()[0])
Vport[0]: /api/v1/sessions/1/ixnetwork/vport/1
        ActualSpeed: 1000
        AssignedTo: 10.0.1.72:1:3
        ConnectedTo: /api/v1/sessions/1/ixnetwork/availableHardware/chassis/1/card/1/port/3
        ConnectionInfo: chassis="10.0.1.72" card="1" port="3" portip="10.0.1.72"
        ConnectionState: connectedLinkUp
        ConnectionStatus: 10.0.1.72;01;03
        InternalId: 1
        IsAvailable: True
        IsConnected: True
        IsFramePreemptionSupported: False
        IsMapped: True
        IsPullOnly: False
        IsVMPort: True
        IxnChassisVersion: 9.00.1906.13
        IxnClientVersion: 9.00.1906.13
        IxosChassisVersion: IxOS 9.00.1900.10
        Licenses: obsolete, do not use
        Name: Ethernet - 001
        RxMode: captureAndMeasure
        State: up
        StateDetail: idle
        TraceEnabled: False
        TraceLevel: kTrace
        TraceTag: PROFILE_PCPUSYNC;TRACE_CPF_DOD;ixnetservice;StatViewer;AppErrorModule;IxNetwork
        TransmitIgnoreLinkStatus: False
        TxGapControlMode: averageMode
        TxMode: interleaved
        Type: ethernetvm
        UseGlobalSettings: False
        ValidTxModes: ['sequential', 'sequentialCoarse', 'interleaved', 'interleavedCoarse']

# print(ixnetwork.Traffic.TrafficItem.find()[0])
TrafficItem[0]: /api/v1/sessions/1/ixnetwork/traffic/trafficItem/1
        AllowSelfDestined: False
        BiDirectional: False
        EgressEnabled: False
        EnableDynamicMplsLabelValues: False
        Enabled: True
        Errors: []
        FlowGroupCount: 1
        FrerDuplicateElimination: False
        HasOpenFlow: False
        HostsPerNetwork: 1
        InterAsBgpPreference: one
        InterAsLdpPreference: two
        MaxNumberOfVpnLabelStack: 2
        MergeDestinations: True
        MulticastForwardingMode: replication
        Name: traffic1
        NumVlansForMulticastReplication: 1
        OrdinalNo: 0
        OriginatorType: endUser
        RoundRobinPacketOrdering: False
        RouteMesh: oneToOne
        SrcDestMesh: oneToOne
        State: stopped
        Suspend: False
        TrafficItemType: l2L3
        TrafficType: ipv4
        TransmitMode: interleaved
        TransportLdpPreference: two
        TransportRsvpTePreference: one
        UseControlPlaneFrameSize: True
        UseControlPlaneRate: True
        Warnings: ['Frames Size Adjusted: The frame size was increased to 66 bytes to accommodate encapsulation requirements. ']

# print(ixnetwork.Traffic.TrafficItem.find(Name="traffic1")[0].ConfigElement.find())
ConfigElement[0]: /api/v1/sessions/1/ixnetwork/traffic/trafficItem/1/configElement/1
        Crc: goodCrc
        DestinationMacMode: manual
        EnableDisparityError: False
        EncapsulationName: Ethernet.IPv4
        EndpointSetId: 1
        PreambleCustomSize: 8
        PreambleFrameSizeMode: auto

このようにプロパティを取得することができるので、GUIから設定したものを参考にしながらプログラムの実装を進めると良いです。

今回はWindows版のAPIサーバーをメインに説明してきましたが、Linux版(IxNetwork Web Edition)にも自動化コードの開発に便利な機能があります。

ブラウザーでAPIサーバーのGUIにアクセスし、API Browserと呼ばれる機能を使うと現在のリソース状態を取得することができます。
基本的に出てくる内容は、上記で各リソースをprintで表示した時と同じです。
GUIから全リソースを網羅的に確認できるので便利です。

また、新しいバージョンでは自動試験コードの開発支援機能がさらに強化されています。

Version 9.10以降では、Script Watchと呼ばれる機能で、APIのリクエスト・レスポンスが記録されおり、後から必要に応じて確認することができます。

9.20以降では、RestPy Snipetと呼ばれる機能により、ブラウザーのGUI上から設定した各リソースの設定を、ixnetwork_restpyを利用して設定した場合のコード例を出力できます。
特にトラフィック設定周りは、GUIから設定では暗黙的に設定される値が多いため、それらの設定値がコードとして出力されるのは非常に役立つと思います。

私は現在IxNetwork Version 9.00を使用しており、これらの新機能はまだ利用したことはありません。
新しいバージョンでは、Linux版(IxNetwork Web Edition)を使用した方がWindows版のAPIサーバーよりも自動化開発は効率的に進められそうだと感じました。

まとめ

今回紹介したようにixnetwork_restpyを使用することにより、IxNetworkの操作を自動化することができます。
これまで使用してきた設定ファイルを資産として活用することもでき、今あるテストシナリオをすぐに自動化することができます。
コードのみで設定を記述することも可能で、他の自動試験コードと合わせてgitなどによりソースコードとして管理することができます。

IxNetworkとixnetwork_restpyは、数ヶ月毎にアップデートされており、少しずつ自動化関連機能やサンプルコードも増えています。
今後さらなる自動化関連のサポートが充実していくことを期待しています。

NTTPCでは、IxNetworkをはじめとするKeysight Technologies社のネットワーク測定器を販売しています。導入をお考えの方は是非お問い合わせください。

技業LOG

この記事の関連するサービスは
こちら

ネットワークテスター / パケットブローカー

ワイヤレスエッジからインターネットコアまでのネットワークテストソリューション、およびネットワークタップ・可視化ソリューションを提供

Master'sONE CloudWAN®

NTTPCコミュニケーションズが提供するSD-WAN技術を用いたVPNサービス

おすすめ記事

    お気軽にご相談ください