5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ns-3.30でネットワーク構築(後編)

Last updated at Posted at 2019-09-24

【 ns-3.30の使い方123 → [4] → 567 】

ネットワークシミュレータであるns3の説明をいくつかにわけて投稿しています.この投稿は「ネットワーク構築(後編)」です.

4. ネットワーク構築(後編)

ネットワーク構築(前編)の後編です. 少し踏み込んで,WiFiとEthernetが複合したトポロジーでシミュレーションをしてみましょう.公式チュートリアルにのっとり,1段階目としてEthernetのシミュレーションを,2段階目としてそこへWiFi環境を盛り込み発展させます.また,出力されるpcapファイルを通して通信内容を見ます.

  • second.ccの実行
  • second.ccの解説
  • third.ccの実行
  • third.ccの解説
  • まとめ

文献

second.ccの実行

まず,Ethernetのバストポロジのシミュレーションをします.サンプルコードはexamples/tutorial/second.ccです.トポロジはP2Pとバストポロジが組み合わさっており,ノードn1は2つのネットワークに接続されています.そして,n0からn4に向けてpingを打ちます.

second_topology.png

前半のときと同じように,second.ccをscratch/mysecond.ccにコピーしてから実行します.

$ cp examples/tutorial/second.cc scratch/mysecond.cc
$ ./waf --run mysecond
At time 2s client sent 1024 bytes to 10.1.2.4 port 9
At time 2.0078s server received 1024 bytes from 10.1.1.1 port 49153
At time 2.0078s server sent 1024 bytes to 10.1.1.1 port 49153
At time 2.01761s client received 1024 bytes from 10.1.2.4 port 9

myfirst.ccのときと似た結果ですが,IPアドレスが異なります.2秒にn0(10.1.1.1)からn4(10.1.2.4)へ向けpingが送られ,2.0078秒にn4がn0へpongを送り返しています.

mysecond.ccではn0,n1,n2でパケットキャプチャをしています.ns3のルートに3つのpcapファイル1が生成されているので,tcpdumpコマンド1で中身を見てみます.

$ ls *.pcap 
second-0-0.pcap  second-1-0.pcap  second-2-0.pcap

# n0
$ tcpdump -nn -tt -r second-0-0.pcap
reading from file second-0-0.pcap, link-type PPP (PPP)
2.000000 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024
2.017607 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024

# n1のP2P側
$ tcpdump -nn -tt -r second-1-0.pcap
reading from file second-1-0.pcap, link-type PPP (PPP)
2.003686 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024
2.013921 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024

# n2
$ tcpdump -nn -tt -r second-2-0.pcap
reading from file second-2-0.pcap, link-type EN10MB (Ethernet)
2.007698 ARP, Request who-has 10.1.2.4 (ff:ff:ff:ff:ff:ff) tell 10.1.2.1, length 50
2.007710 ARP, Reply 10.1.2.4 is-at 00:00:00:00:00:06, length 50
2.007803 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024
2.013815 ARP, Request who-has 10.1.2.1 (ff:ff:ff:ff:ff:ff) tell 10.1.2.4, length 50
2.013828 ARP, Reply 10.1.2.1 is-at 00:00:00:00:00:03, length 50
2.013921 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024

pcapファイルの命名規則は[プレフィックス]-[ノード番号]-[ネットデバイス番号].pcapです.second-0-0.pcapはn0でのパケットキャプチャデータで,ping(1つ目)とpong(2つ目)のパケットが確かに記録されています.pcapファイルの読み方は割愛します.

プロミスキャスモード2でキャプチャしているため,ブロードキャストのARPリクエストしか受信していないはずのn2でもping/pongやARPリプライの記録が含まれています.

規模が大きなシミュレーションのpcapファイルは,Wiresharkで見ると統計などが取れて便利です.

wireshark.png

second.ccの解説

復習も兼ねてコメント行以外の全行を説明します.

second.cc
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/csma-module.h"
#include "ns3/internet-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/applications-module.h"
#include "ns3/ipv4-global-routing-helper.h"

何をインクルードすればよいかは前の記事で説明しています.

second.cc
using namespace ns3;

ns3::PointToPointHelper()などと書かなくてはいけない部分で,ns3::を省略できるようになります.

second.cc
NS_LOG_COMPONENT_DEFINE ("SecondScriptExample");

今後,LogComponentEnable ("SecondScriptExample", LOG_LEVEL_INFO);で,このファイルのログを出力することができるようになります.ただし,ログとして何かを出力する記述がこのファイルにはないため,有効化しても何も出力されません.

pro1.png

コマンドライン・ロギングなどの設定

second.cc
  bool verbose = true;
  uint32_t nCsma = 3;

結果出力するかを決める変数verboseと,バストポロジに接続する__n1を除いた__ホスト数nCsmaを初期化します.nCsmaが3のとき,バストポロジには4ホスト接続されます.

second.cc
  CommandLine cmd;
  cmd.AddValue ("nCsma", "Number of \"extra\" CSMA nodes/devices", nCsma);
  cmd.AddValue ("verbose", "Tell echo applications to log if true", verbose);

  cmd.Parse (argc,argv);

CommandLineのAddValue()を使えば,コマンドラインオプションを簡単に自作できます.第一引数はオプション名,第二引数はオプションの説明文,第三引数はそのオプションで指定した値を入れる変数名です.nCsmaのAddValue()によって,./waf --run "mysecond --nCsma=10"という実行が可能になり,その場合,変数nCsmaには10が代入されます.オプションを指定する際はシナリオ名とオプションを"ダブルクオーテーション"でくくってください.AddValue()したあとはParseメソッドを呼びます.

second.cc
  if (verbose)
    {
      LogComponentEnable ("UdpEchoClientApplication", LOG_LEVEL_INFO);
      LogComponentEnable ("UdpEchoServerApplication", LOG_LEVEL_INFO);
    }

verboseがtrueのときに,ログを出力するよう設定します.verboseがfalseにとき,シミュレーションは何も標準出力しません.

second_--verbose=false.png

second.cc
  nCsma = nCsma == 0 ? 1 : nCsma;

バストポロジにはn1以外にサーバが接続されるため,nCsmaを1以上にします.

ノードの設定

second.cc
  NodeContainer p2pNodes;
  p2pNodes.Create (2);

  NodeContainer csmaNodes;
  csmaNodes.Add (p2pNodes.Get (1));
  csmaNodes.Create (nCsma);

管理しやすいようにネットワークごとにノードコンテナを作ります.n1はどちらのコンテナにも所属させます.

second_nodecontainer.png

チャネルとネットデバイスの設定

second.cc
  PointToPointHelper pointToPoint;
  pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
  pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));

  NetDeviceContainer p2pDevices;
  p2pDevices = pointToPoint.Install (p2pNodes);

P2Pトポロジの構築です.リンク速度は5Mbps,遅延は2ms.

second.cc
  CsmaHelper csma;
  csma.SetChannelAttribute ("DataRate", StringValue ("100Mbps"));
  csma.SetChannelAttribute ("Delay", TimeValue (NanoSeconds (6560)));

  NetDeviceContainer csmaDevices;
  csmaDevices = csma.Install (csmaNodes);

バストポロジの構築です.リンク速度は100Mbps,遅延は6560ns.

second.cc
  InternetStackHelper stack;
  stack.Install (p2pNodes.Get (0));
  stack.Install (csmaNodes);

プロトコルスタックをノードに設定します.

second.cc
  Ipv4AddressHelper address;
  address.SetBase ("10.1.1.0", "255.255.255.0");
  Ipv4InterfaceContainer p2pInterfaces;
  p2pInterfaces = address.Assign (p2pDevices);

  address.SetBase ("10.1.2.0", "255.255.255.0");
  Ipv4InterfaceContainer csmaInterfaces;
  csmaInterfaces = address.Assign (csmaDevices);

IPアドレスの設定です.2つのネットワークごとに設定するため,2回Assign()しています.

second_ip.png

アプリケーションの設定

second.cc
  UdpEchoServerHelper echoServer (9);

  ApplicationContainer serverApps = echoServer.Install (csmaNodes.Get (nCsma));
  serverApps.Start (Seconds (1.0));
  serverApps.Stop (Seconds (10.0));

  UdpEchoClientHelper echoClient (csmaInterfaces.GetAddress (nCsma), 9);
  echoClient.SetAttribute ("MaxPackets", UintegerValue (1));
  echoClient.SetAttribute ("Interval", TimeValue (Seconds (1.0)));
  echoClient.SetAttribute ("PacketSize", UintegerValue (1024));

  ApplicationContainer clientApps = echoClient.Install (p2pNodes.Get (0));
  clientApps.Start (Seconds (2.0));
  clientApps.Stop (Seconds (10.0));

first.ccとほぼ同じです.ノードn0にクライアントアプリケーションを,ノードnCsmaにサーバアプリケーションをインストールし,n0からnCsmaへ向けて1つのパケット(ping)を送信します.

グローバルルーティング

second.cc
  Ipv4GlobalRoutingHelper::PopulateRoutingTables ();

グローバルルーティングと呼び,ルーティング情報を与えずとも,各ホストが適切なルーティングをするようになる,シミュレーションならではの便利な仕組みです.現実世界では,ネットワーク管理者が入力するかなんらかのプロトコルでルーティング情報を得なくては,各ホストが適切にルーティングできませんが,シミュレーションなので自動で設定してくれます.それとは別に,静的に設定する方法もあります.

EnablePcap

second.cc
  pointToPoint.EnablePcapAll ("second");
  csma.EnablePcap ("second", csmaDevices.Get (1), true);

pcapファイルを出力するようにする設定です.P2Pトポロジの全てのネットデバイス(second-0-0.pcapとsecond-1-0.pcap)と,バストポロジの1番目のネットデバイス(second-2-0.pcap)でパケットキャプチャします.EnablePcap()の第一引数は出力ファイルのプレフィックスで,第二引数はネットデバイスのポインタ,第三引数はプロミスキャスモードを有効にするか.

second_enablepcap.png

シミュレーションの設定

second.cc
  Simulator::Run ();
  Simulator::Destroy ();
  return 0;

シミュレーションの開始と終了後のメモリ解放

後始末

second.ccの解説はここまでです.出力されたpcapファイルはもういらないので削除しておきましょう.

$ rm second-0-0.pcap second-1-0.pcap second-2-0.pcap

third.ccの実行

second.ccにWiFi環境を組み合わせたシミュレーションをします.サンプルファイルはexamples/tutorial/third.ccです.n0がアクセスポイント(AP)となり,そこに3つの動くモバイルノードが接続します.そして,モバイルノードの1つがバストポロジの1つに向けてpingを打ちます.

third_topology.png
$ cp examples/tutorial/third.cc scratch/mythird.cc
$ ./waf --run mythird
At time 2s client sent 1024 bytes to 10.1.2.4 port 9
At time 2.01796s server received 1024 bytes from 10.1.3.3 port 49153
At time 2.01796s server sent 1024 bytes to 10.1.3.3 port 49153
At time 2.03364s client received 1024 bytes from 10.1.2.4 port 9

モバイルノードn7(10.1.3.3)とサーバn4(10.1.2.4)がping/pongしている様子がわかります.

third.ccの解説

second.ccにWiFiトポロジの設定とモビリティモデルの設定が追加されています.新しい部分のみ解説します.

third.cc
// 47, 48行目
  uint32_t nWifi = 3;
  bool tracing = false;

// 52, 54行目
  cmd.AddValue ("nWifi", "Number of wifi STA devices", nWifi);
  cmd.AddValue ("tracing", "Enable pcap tracing", tracing);

// 58〜65行目
  // The underlying restriction of 18 is due to the grid position
  // allocator's configuration; the grid layout will exceed the
  // bounding box if more than 18 nodes are provided.
  if (nWifi > 18)
    {
      std::cout << "nWifi should be 18 or less; otherwise grid layout exceeds the bounding box" << std::endl;
      return 1;
    }

// 176〜181行
  if (tracing == true)
    {
      pointToPoint.EnablePcapAll ("third");
      phy.EnablePcap ("third", apDevices.Get (0));
      csma.EnablePcap ("third", csmaDevices.Get (0), true);
    }

コマンドラインでモバイルノード数を変更できるように変数nWiFiを宣言しています(モバイルノードの配置の関係で18ノード以下になるようにしています).変数tracingがtrueのときはpcapファイルを出力させます.

WiFiの設定

あらかじめ言うと,使用するヘルパーは4つです.

ns3のWiFiは,物理層の役割のWifiPhyとデータリンク層の役割のWifiMacで構成されています.前者はYansWifiPhyHelperで,後者はWifiMacHelperで設定します.YANSとは,シミュレーションに最適化されたWifiPhyモデルのことで,ns3でWiFiを使うときは基本これです.チャンネルの設定はYansWifiChannelHelperで行い,YansWifiPhyHelperのSetChannelメソッドでWifiPhyにチャンネルを関連付けます.WifiHelperで,設定したWifiPhyとWifiMacを結びつけ,ノードにインストールします.また,WifiPhyとWifiMacで共通の設定(使用する無線LAN規格の指定やリモートステーションマネージャの指定など)もWifiHelperで設定します.

wifi_architecture.png

WifiPhyの設定

コードの説明に戻ります.

third.cc
  YansWifiChannelHelper channel = YansWifiChannelHelper::Default ();
  YansWifiPhyHelper phy = YansWifiPhyHelper::Default ();
  phy.SetChannel (channel.Create ());

YansWifiChannelHelperとYansWifiPhyHelperのどちらもDefault()で初期化しています.これによって,属性変数PropagationLossModel(無線による伝搬ロスを再現するモデル)にConstantSpeedPropagationDelayModelが,属性変数PropagationDelayModel(無線による伝搬遅延を再現するモデル)にLogDistancePropagationLossModelが,属性変数PostreceptionErrorModel(フレーム受信後のエラーレートモデル)にNistErrorRateModelが指定されます.

WifiPhyとWifiMacで共通の設定

third.cc
  WifiHelper wifi;
  wifi.SetRemoteStationManager ("ns3::AarfWifiManager");

WifiHelperでWifiPhyとWifiMacの両方で設定する必要があるリモートステーションマネージャをAARF(Adaptive Automatic Rate Fallback)に指定しています.他にSetStandard()を使えば特定の無線規格を再現できます.ここでは指定していないため,デフォルトの802.11aになります.

wifi.SetStandard (WIFI_PHY_STANDARD_80211ac);

WifiMacの設定(STA)

WifiMacはSTA(モバイルノード)側とAP側で別々の設定をします.

third.cc
  WifiMacHelper mac;
  Ssid ssid = Ssid ("ns-3-ssid");
  mac.SetType ("ns3::StaWifiMac",
               "Ssid", SsidValue (ssid),
               "ActiveProbing", BooleanValue (false));

SetType()の第一引数には,インフラストラクチャモードのときはns3::StaWifiMacまたはns3::ApWifiMacを指定します.第二引数以降の偶数番目には属性変数名を,奇数番目にはその値を指定します.このような書き方はns3では頻繁に出てきます.SSIDはデフォルトで「default」ですが,指定したければSsidインスタンスを生成して,それを値として渡します.ただし,SSIDはpcapファイルの内容が変わるだけで,シミュレーション結果には影響しません.属性変数ActiveProbing3がtrue のときは,APからのビーコンでAPの所在を確認するのではなく,STAからの能動的なプルーブリクエストによってAPからの返信を待つ方式になります.なお,falseと指定していますが,デフォルトでもfalseです.

インストール(STA)

Installの引数は,WifiPhyとWifiMacとインストール先ノード/コンテナの3つです.

third.cc
  NetDeviceContainer staDevices;
  staDevices = wifi.Install (phy, mac, wifiStaNodes);

このインストールにより,WifiNetDeviceの構成は以下のようになりました.

third_sta.png

WifiMacの設定とインストール(AP)

third.cc
  mac.SetType ("ns3::ApWifiMac",
               "Ssid", SsidValue (ssid));

  NetDeviceContainer apDevices;
  apDevices = wifi.Install (phy, mac, wifiApNode);

ほぼSTAのときと同じです.

モビリティモデルの設定

MobilityHelperを用いて,モバイルノードを配置しランダムに動くよう設定します.

third.cc
  MobilityHelper mobility;

  mobility.SetPositionAllocator ("ns3::GridPositionAllocator",
                                 "MinX", DoubleValue (0.0),
                                 "MinY", DoubleValue (0.0),
                                 "DeltaX", DoubleValue (5.0),
                                 "DeltaY", DoubleValue (10.0),
                                 "GridWidth", UintegerValue (3),
                                 "LayoutType", StringValue ("RowFirst"));

SetPositionAllocatorでノードをどのように配置するかを決定します.ここではGridPositionAllocatorを第一引数で指定しているため,グリッド状に配置されます.第二引数以降は第一引数モデルの属性変数の設定です.

grid.png
third.cc
  mobility.SetMobilityModel ("ns3::RandomWalk2dMobilityModel",
                             "Bounds", RectangleValue (Rectangle (-50, 50, -50, 50)));
  mobility.Install (wifiStaNodes);

  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
  mobility.Install (wifiApNode);

SetMobilityModel()でノードの動き方を指定します.APは動かないためConstantPositionMobilityModelを,モバイルノードはランダムウォークするようRandomWalk2dMobilityModelを指定します.ランダムウォークでは,動ける範囲を座標で指定します.Rectangle (-50, 50, -50, 50) は原点から上下50m以内を意味します.

./waf --run "third --nWifi=18" --visと実行すると,モバイルノードがどのように動いているか確認できます.

シミュレーション終了時刻の設定

third.cc
  Simulator::Stop (Seconds (10.0));

シミュレーションはイベントキューが空になれば自動で終了しますが,WiFi環境があるとビーコンの発信が常に発生し,イベントキューが空になりません.明示的にシミュレーションを終了するにはSimulator::Stop()を使います.

まとめ

お疲れ様です.トポロジーの作成は有線・無線共にできるようになりました.次の記事では,ロギングについて説明します.

  1. pcapファイルはパケットの流れを記したファイル形式で,tcpdumpやWireSharkといったアプリケーションで見ることができます. 2

  2. 同一セグメント内の自分宛でないパケットも記録するモード.

  3. What are passive and active scanning? | WiFi Alliance

5
2
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
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?