個人的なまとめ。

てきとーに何か書きます。

NS-3でサンプルを動かしてから描画する所まで

NS-3のサンプルを動かしてみて、更に描画する所までをやってみようと思う。

環境 :Ubuntu 14.04 LTS 64bit
ns3 : ns-3.28
Animation : NetAnim

インストール

ns3のインストールは別の記事に任せる。
qiita.com
確か、これを参考にインストールを行った。
最初にaptで様々なパッケージをインストールしないといけないが、これも検索すれば記事が出てくる。

サンプルを動かす

とりあえずexampleの中のどれでも良いので、何かサンプルを動かしてみる。

waf --run example/wireless/wifi-ap

エラーが出なければインストールは問題無い。

別のサンプルを作って動かす

ns3のインストール等を検索していると、良い感じのPDFがあったので、これを基にサンプルプログラムを作って行く。
*自分でプログラムを作った場合は、ns-3.28の中のscratchの中に作成していく。
http://www.yamanaka.ics.keio.ac.jp/wp-content/uploads/2017/04/17Traffic_12-14.pdf

第5章のプログラムを動かしてみる。

Waf: Entering directory `/home/kosuke/workspace/ns-allinone-3.28/ns-3.28/build'
Waf: Leaving directory `/home/kosuke/workspace/ns-allinone-3.28/ns-3.28/build'
Build commands will be stored in build/compile_commands.json
'build' finished successfully (0.378s)
At time 2s client sent 1024 bytes to 10.1.1.2 port 5000
At time 2.01343s server received 1024 bytes from 10.1.1.1 port 49153
At time 2.01343s server sent 1024 bytes to 10.1.1.1 port 49153
At time 2.02686s client received 1024 bytes from 10.1.1.2 port 5000

問題なく動く事が分かる。

ClientがServerに1024バイトのパケットを送信する。
Serverはデータを受信し、Clientに送り返す。
ClientはServerからのデータを受信する。

といった流れである。

ノード数を増やす

今は一対一で通信を行ったが、そこに1台ノードを追加し新しいネットワークを追加する。

作成したプログラムが以下である。

#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/internet-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/applications-module.h"

using namespace ns3;

NS_LOG_COMPONENT_DEFINE ("Sample");

int main(int argc, char **argv)
{
    //時間をnano秒に設定する
    Time::SetResolution(Time::NS);
    // UDPを使う場合の設定
    LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_INFO);
    LogComponentEnable("UdpEchoServerApplication", LOG_LEVEL_INFO);

    //ノードを作成する
    NodeContainer network1_nodes, network2_nodes;
    //括弧の数字は作成するノード数
    network1_nodes.Create(2);

    //network1にnetwork2を追加する
    //その際に、network1のnode1がnetwork2のnode0になるように設定する
    network2_nodes.Add(network1_nodes.Get(1));
    network2_nodes.Create(1);

    //Helperを使用してPoint-to-Pointのリンクを作成
    PointToPointHelper pointToPoint1, pointToPoint2;
    pointToPoint1.SetDeviceAttribute("DataRate", StringValue("1Mbps"));
    pointToPoint1.SetChannelAttribute("Delay", StringValue("2ms"));
    pointToPoint2.SetDeviceAttribute("DataRate", StringValue("2Mbps"));
    pointToPoint2.SetChannelAttribute("Delay", StringValue("10ms"));

    //全ノード間にリンクを作成する
    //特定のノード間に設定を行う場合は、
    //device = pointToPoint.Install(nodes.Get(0), nodes.Get(1));
    //のような感じにする
    NetDeviceContainer dev1 = pointToPoint1.Install(network1_nodes);
    NetDeviceContainer dev2 = pointToPoint2.Install(network2_nodes);

    //プロトコルを全ノードにインストール
    InternetStackHelper stack;
    stack.InstallAll();

    //Ipv4を使用する
    Ipv4AddressHelper address1, address2;
    address1.SetBase("10.1.1.0", "255.255.255.0", "0.0.0.1");
    address2.SetBase("10.2.2.0", "255.255.255.0", "0.0.0.1");
    Ipv4InterfaceContainer interfaces1 = address1.Assign(dev1);
    Ipv4InterfaceContainer interfaces2 = address2.Assign(dev2);

    //サーバー側の設定
    UdpEchoServerHelper echoServer(5000);

    //UDP Echo Serverをnode1にインストール
    ApplicationContainer serverApps;
    serverApps = echoServer.Install(network2_nodes.Get(1));
    serverApps.Start(Seconds(1.0));
    serverApps.Stop(Seconds(10.0));

    //クライアント側の設定
    //宛先のアドレスとポート番号の設定が必要
    UdpEchoClientHelper echoClient(interfaces2.GetAddress(1), 5000);

    //毎秒1個、1024バイトのパケットを送信する
    echoClient.SetAttribute("MaxPackets", UintegerValue(1));
    echoClient.SetAttribute("Interval", TimeValue(Seconds(1.0)));
    echoClient.SetAttribute("PacketSize", UintegerValue(1024));

    //UDP Echo Clientをnode0にインストールする
    ApplicationContainer clientApps1, clientApps2;
    clientApps1 = echoClient.Install(network1_nodes.Get(0));
    clientApps2 = echoClient.Install(network1_nodes.Get(1));
    clientApps1.Start(Seconds(2.0));
    clientApps1.Stop(Seconds(10.0));
    clientApps2.Start(Seconds(3.0));
    clientApps2.Stop(Seconds(10.0));

    //自動でトポロジを形成してくれる。
    //これが無ければ正しくデータが送受信出来ない。
    Ipv4GlobalRoutingHelper::PopulateRoutingTables();

    //Pcapファイルを作成する
    pointToPoint1.EnablePcapAll ("SampleTrace");
    pointToPoint2.EnablePcapAll ("SampleTrace");

    //シミュレーション開始と終了
    NS_LOG_INFO ("Start Simulation");
    Simulator::Run();
    Simulator::Destroy();
    NS_LOG_INFO ("Finish Simulation");

    return 0;
}

多分、もう少し賢い書き方があると思うが、C++自体に慣れていないので、この辺は今後改善する。

実行結果を示す。

At time 2s client sent 1024 bytes to 10.2.2.2 port 5000
At time 2.02465s server received 1024 bytes from 10.1.1.1 port 49153
At time 2.02465s server sent 1024 bytes to 10.1.1.1 port 49153
At time 2.0493s client received 1024 bytes from 10.2.2.2 port 5000
At time 3s client sent 1024 bytes to 10.2.2.2 port 5000
At time 3.01422s server received 1024 bytes from 10.2.2.1 port 49153
At time 3.01422s server sent 1024 bytes to 10.2.2.1 port 49153
At time 3.02843s client received 1024 bytes from 10.2.2.2 port 5000

ノード間のやりとりをアニメーションにする

ns3をインストールするとNetAnimがインストールされていると思う。
されていなければ、別途自分でインストールをして欲しい。

今のプログラムにアニメーションを追加するコードは、

#include "ns3/netanim-module.h"

    //Make Animation
    std::string animFile = "Sample2-animation.xml";
    AnimationInterface anim (animFile);

    anim.SetConstantPosition(network1_nodes.Get(0), 1.0, 1.0);
    anim.UpdateNodeDescription(0, "node-1");
    anim.UpdateNodeSize(0, 0.5, 0.5);
    
    anim.SetConstantPosition(network1_nodes.Get(1), 5.0, 5.0);
    anim.UpdateNodeDescription(1, "node-2");
    anim.UpdateNodeSize(1, 0.5, 0.5);

    anim.SetConstantPosition(network2_nodes.Get(1), 10.0, 10.0);
    anim.UpdateNodeDescription(2, "node-3");
    anim.UpdateNodeSize(2, 0.5, 0.5);

を追加する。

追加する場所としては、自分は、”Pcapファイルを作成するコード”の次に記載している。


これで、.xmlファイルが作成されているので、NetAnimを開いて作成された.xmlファイルを開いてあげれば、
良い感じに描画されていると思う。
また、各ノード間のやりとりも再生を行う事で、流れを見ることが出来るようになる。