LoginSignup
8
1

More than 3 years have passed since last update.

ns-3.30でフローモニターを使ってスループットを計算

Last updated at Posted at 2019-09-27

【 ns-3.30の使い方123456 → [7] 】

ネットワークシミュレータであるns3の説明をいくつかにわけて投稿しています.この投稿は「7. フローモニター」です.

7. フローモニター

ネットワークシミュレーションをする上で,スループットやパケット損失率は間違いなく必要になるでしょう.ns3ではフローモニターという,フローごとのネットワーク統計を取ってくれる便利なモジュールがあります.ここでは,フローモニターの使い方をサンプルコードを使って説明します.

  • フローモニターを使ってスループットを測定
  • フローモニターの仕組み
  • まとめ

文献

フローモニターを使ってスループットを測定

サンプルコードはexamples/tcp/tcp-pacing.ccです.フローモニター以外の部分は本題ではないため,トポロジーと簡単なシナリオの説明だけにとどめます.

tcppacing_topology.png

2つのノードがP2Pで接続されたシンプルなトポロジー上で,片方からもう片方へ向けてTCPトラッフィックを4秒間流します.リンク帯域は40Gbpsで遅延は0.01ミリ秒です.ただし,TCPペーシング1が有効になっており,上限4Gbpsまでしか流さないため,計測されるスループットは4Gbps以下であることが期待されます.

実行してみましょう.私の環境でシミュレーションが終わるまでに22分かかりました.

$ cp examples/tcp/tcp-pacing.cc scratch/my-tcp-pacing.cc
$ ./waf my-tcp-pacing
Flow 1 (10.1.1.1 -> 10.1.1.2)
  Tx Packets: 3731227
  Tx Bytes:   2193960408
  TxOffered:  1950.19 Mbps
  Rx Packets: 3731217
  Rx Bytes:   2193954528
  Throughput: 1950.18 Mbps

一番下の方にスループットが表示されていますが,これこそフローモニターによって取得したデータをもとに計算した結果です.どうやら4秒間のスループットは2Gbpsのようです.

フローモニターの仕組み

tcp-pacing.ccを適当なエディタで開いてください(my-tcp-pacingでもOK).

code_flowmonitor.png

フローモニターのコードはSimulator::Run()の前後2箇所です.

Run()前

tcp-pacing.cc
  FlowMonitorHelper flowmon;
  Ptr<FlowMonitor> monitor = flowmon.InstallAll ();

フローモニターはFlowMonitorHelperを通して使います.InstallAll()によって全てのノードから送信されるフローのデータを集計できます.注意点として,InstallAll()をするのはSimulator::Run()の前です.シミュレーションを実行する前に,データを集計するノードをフローモニターに伝えなくてはいけません.また,FlowMonitorHelperを2つ宣言してもいけません.

Run()後

ここからはSimulator::Run()の後に書いてください.フローモニターからデータを取得できるのは,シミュレーションが終わった後です.

tcp-pacing.cc
  monitor->CheckForLostPackets ();
  Ptr<Ipv4FlowClassifier> classifier = DynamicCast<Ipv4FlowClassifier> (flowmon.GetClassifier ());
  FlowMonitor::FlowStatsContainer stats = monitor->GetFlowStats ();
  for (std::map<FlowId, FlowMonitor::FlowStats>::const_iterator i = stats.begin (); i != stats.end (); ++i)
    {
      Ipv4FlowClassifier::FiveTuple t = classifier->FindFlow (i->first);

134〜139行目はフローモニターのおまじないです.仕組みを知りたい方は各オブジェクトのドキュメントを参照してください.forはフローごとに回っており,iからそのフローのデータを取得できます.今回の例だと1TCPフローしかないため,10.1.1.2→10.1.1.1(SYN)と10.1.1.1→10.1.1.2(DATA)で2回for文が回ります.

tcp-pacing.cc
      if (t.sourceAddress == "10.1.1.2")
        {
          continue;
        }

tにはフローiの(sourceAddress, sourcePort, destinationAddress, destinationPort, protocol)情報が入っています.protocolはTCPなら6,UDPなら17です.ここでは,SYN方向のスループットは表示してもしょうがないため,DATA方向のみを表示しています.

tcp-pacing.cc
      std::cout << "Flow " << i->first  << " (" << t.sourceAddress << " -> " << t.destinationAddress << ")\n";
      std::cout << "  Tx Packets: " << i->second.txPackets << "\n";
      std::cout << "  Tx Bytes:   " << i->second.txBytes << "\n";
      std::cout << "  TxOffered:  " << i->second.txBytes * 8.0 / 9.0 / 1000 / 1000  << " Mbps\n";
      std::cout << "  Rx Packets: " << i->second.rxPackets << "\n";
      std::cout << "  Rx Bytes:   " << i->second.rxBytes << "\n";
      std::cout << "  Throughput: " << i->second.rxBytes * 8.0 / 9.0 / 1000 / 1000  << " Mbps\n";
    }

iからデータを取得し表示しています.iはstd::map型のタプルであり,後ろにデータ(FlowStats)が入っているため,i->secondでアクセスします.FlowStatsからは様々なデータを取得できます.

最後のスループットは以下のように計算されています.

Mbps = 受信バイト数 × 8bit / 9秒? / 10^6

ここは謎で,送信時間4秒で割るべきところを,なぜか9で割っています.おそらくサンプルコードが間違っているのだとは思いますが,4秒で割ると4.387Gbpsになり,TCPペーシングで指定した4Gbps以上に送信していたことになります.もしかすると,timeLastRxPacket - timeFirstRxPacketの値をいれると正しい値がでるのかもしれません.

とにかく,フローモニターを使えばスループットやパケット損失率,平均伝搬遅延などを計算できます.

まとめ

フローモニターは,既存のコードにフローモニターのコードを追加するだけで,簡単にスループットを計算できる便利なモジュールです.トレーシングシステムと組み合わせて,様々なデータを取得できます.

ここまでの記事でns3のいろは一通り説明できたかと思います.次からはいくつかのモジュールをピックアップして説明していきます.


  1. TCPのバーストトラフィックを回避するために,転送速度に上限を設ける仕組み.私も気になったので,調べてブログにまとめました.https://dorapon2000.hatenablog.com/entry/2019/09/27/162336 

8
1
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
8
1