アットウィキロゴ

2012年12月20日研究室ミーティング時点で発表した作業ログ

NS3-UANの解読作業を行っています。具体的には、uan-cw-example.ccという、NS3-UANのサンプルプログラムを走らせて、その出力を見た後、
プログラムを頭から読んでいき、関数の意味をNS3のウェブドキュメントを見て調べたり、プログラム中の定義を見たり、includeされているプログラムを
見たりしながら理解していきました。また、NS3ではログを出力する機能があるので、
呼び出されている関数が、順番にそこそこの細かさで出力されるように設定して、ログを出力し、それを見ながら、どこで何が起きているかを見ていきました。

その後、ノイズモデルがどうパケットのロスの計算に用いられているのかが結局分からなかったので、ノイズモデルプログラム中のノイズを計算する関数が
誰に呼び出されているかを推測し、呼び出し先の関数がまた誰に呼び出されているかをドキュメントで確認していくことで、パケット受け取り
の大雑把な流れを知りました。


以下詳細作業ログです。

===================================================================================================================================================================================================

☆11/24

NS3 Tutorialを読み進めようかとも思ったのですが、絶対に読んでおかねばならない所は読み終わった気がするので、効率を考えて、uanの実際のプログラムの解読にうつることにしました。まず、思い切りいじれ
るようにするために、ns3-allinoneのコピーを取っておきました。その後、uanのcwMacのexample fileを
./waf --run src/uan/examples/uan-cw-example
で実行しました。
すると、何やらよくわからない出力が出てきたので、std::coutを使いつつ理解を試みました。
とりあえず、gpl fileを出していることが分かったので、gnuplotをinstallして見てみることに。
gnuplot uan-cw-example.gpl -
gnuplotはデフォルトでは図が表示されてからすぐに消えてしまうので、commandで-をつけて対話型モードに移行するか、ファイル自体をpauseをするように書き換える必要があるようです。
参考:http://takeno.iee.niit.ac.jp/~shige/unix/gnuplot/faq/faq-j.html

プログラム冒頭の説明を以下に引用。
Q)The MAC protocol is implemented in the class UanMacCw. CW-MAC is similar in nature
* to the IEEE 802.11 DCF with a constant backoff window.  It requires two parameters to be set,
* the slot time and the contention window size.  The contention window size is the backoff window
* size in slots, and the slot time is the duration of each slot.  These parameters should be set
* according to the overall network size, internode spacing and the number of nodes in the network.
*
* This example deploys nodes randomly (according to RNG seed of course) in a finite square region
with
* the X and Y coordinates of the nodes distributed uniformly.  The CW parameter is varied
throughout
* the simulation in order to show the variation in throughput with respect to changes in CW.
(UQ

これをみつつ考えると、gpl fileはCWのサイズの変化に対するthroughputの変化を描いたものでした。
Contention windowの復習:http://times.ansl.ntt.co.jp/gijyutu/2007_07/Topic_01/13.html

contention windowが短すぎると衝突が起きてしまい、長すぎると無駄に待機してしまうから、throughputが悪くなってしまうと予想され、実際グラフはそうなっていました。

次回はどうやってthroughputの計算をしているのかの詳細を追うつもりです。
( simulationのメインは
ds = exp.Run (uan);
でやっているので、expクラスがどんなものか見ていく必要がありますね。

☆11/26

★前回の調査でexp.Run()がsimulationのメインの処理をしていることが分かったので、今度はRun()が具体的に何をしているかを調査することにしました。
まず、"uan-cw-example.cc"をみると、

Experiment::Experiment()
Experiment exp;

という記述があったので、Experimentクラスの中身を見てみることにしました。
includeをみると、experimentクラスは"uan-cw-example.h"にありそうだと推察されたので、そこをみてみました。
すると、下記のようなクラスの記述が見つかりました。

/**
* \class Experiment
* \brief Helper class for UAN CW MAC example
*
*/
class Experiment
{
public:
 Gnuplot2dDataset Run (UanHelper &uan);
 void ReceivePacket (Ptr<Socket> socket);
 void UpdatePositions (NodeContainer &nodes);
 void ResetData ();
 void IncrementCw (uint32_t cw);
 uint32_t m_numNodes;
 uint32_t m_dataRate;
 double m_depth;
 double m_boundary;
 uint32_t m_packetSize;
 uint32_t m_bytesTotal;
 uint32_t m_cwMin;
 uint32_t m_cwMax;
 uint32_t m_cwStep;
 uint32_t m_avgs;

 Time m_slotTime;
 Time m_simTime;

 std::string m_gnudatfile;
 std::string m_asciitracefile;
 std::string m_bhCfgFile;

 Gnuplot2dDataset m_data;
 std::vector<double> m_throughputs;

 Experiment ();
};

#endif
/* UAN_CW_EXAMPLE_H */

みると、Experimentクラスは中身がスカスカなことが分かりました。

それで、具体的な処理は、uan-cw-example.ccで、オーバーライドによって記述していると分かりました。以下がその中身です。

Gnuplot2dDataset
Experiment::Run (UanHelper &uan)
{
 uan.SetMac ("ns3::UanMacCw", "CW", UintegerValue (m_cwMin), "SlotTime", TimeValue (m_slotTime));
 NodeContainer nc = NodeContainer ();
 NodeContainer sink = NodeContainer ();
 nc.Create (m_numNodes);
 sink.Create (1);

 PacketSocketHelper socketHelper;
 socketHelper.Install (nc);
 socketHelper.Install (sink);

#ifdef
UAN_PROP_BH_INSTALLED
 Ptr<UanPropModelBh> prop = CreateObjectWithAttributes<UanPropModelBh> ("ConfigFile", StringValue
("exbhconfig.cfg"));
#else
 Ptr<UanPropModelIdeal> prop = CreateObjectWithAttributes<UanPropModelIdeal> ();
#endif
 Ptr<UanChannel> channel = CreateObjectWithAttributes<UanChannel> ("PropagationModel", PointerValue
(prop));

 //Create net device and nodes with UanHelper
 NetDeviceContainer devices = uan.Install (nc, channel);
 NetDeviceContainer sinkdev = uan.Install (sink, channel);
MobilityHelper mobility;
 Ptr<ListPositionAllocator> pos = CreateObject<ListPositionAllocator> ();

 {
   Ptr<UniformRandomVariable> urv = CreateObject<UniformRandomVariable> ();
   pos->Add (Vector (m_boundary / 2.0, m_boundary / 2.0, m_depth));
   double rsum = 0;

   double minr = 2 * m_boundary;
   for (uint32_t i = 0; i < m_numNodes; i++)
     {
       double x = urv->GetValue (0, m_boundary);
       double y = urv->GetValue (0, m_boundary);
       double newr = sqrt ((x - m_boundary / 2.0) * (x - m_boundary / 2.0)
                           + (y - m_boundary / 2.0) * (y - m_boundary / 2.0));
       rsum += newr;
       minr = std::min (minr, newr);
       pos->Add (Vector (x, y, m_depth));

     }
   NS_LOG_DEBUG ("Mean range from gateway: " << rsum / m_numNodes
                                             << "    min. range " << minr);

   mobility.SetPositionAllocator (pos);
   mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
   mobility.Install (sink);

   NS_LOG_DEBUG ("Position of sink: "
                 << sink.Get (0)->GetObject<MobilityModel> ()->GetPosition ());
   mobility.Install (nc);

   PacketSocketAddress socket;
   socket.SetSingleDevice (sinkdev.Get (0)->GetIfIndex ());
   socket.SetPhysicalAddress (sinkdev.Get (0)->GetAddress ());
   socket.SetProtocol (0);
OnOffHelper app ("ns3::PacketSocketFactory", Address (socket));
   app.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]"));
   app.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
   app.SetAttribute ("DataRate", DataRateValue (m_dataRate));
   app.SetAttribute ("PacketSize", UintegerValue (m_packetSize));

   ApplicationContainer apps = app.Install (nc);
   apps.Start (Seconds (0.5));
   Time nextEvent = Seconds (0.5);


   for (uint32_t cw = m_cwMin; cw <= m_cwMax; cw += m_cwStep)
     {

       for (uint32_t an = 0; an < m_avgs; an++)
         {
           nextEvent += m_simTime;
           Simulator::Schedule (nextEvent, &Experiment::ResetData, this);
           Simulator::Schedule (nextEvent, &Experiment::UpdatePositions, this, nc);
         }
       Simulator::Schedule (nextEvent, &Experiment::IncrementCw, this, cw);
     }
   apps.Stop (nextEvent + m_simTime);

   Ptr<Node> sinkNode = sink.Get (0);
   TypeId psfid = TypeId::LookupByName ("ns3::PacketSocketFactory");
   if (sinkNode->GetObject<SocketFactory> (psfid) == 0)
     {
       Ptr<PacketSocketFactory> psf = CreateObject<PacketSocketFactory> ();
       sinkNode->AggregateObject (psf);
     }
   Ptr<Socket> sinkSocket = Socket::CreateSocket (sinkNode, psfid);
   sinkSocket->Bind (socket);
   sinkSocket->SetRecvCallback (MakeCallback (&Experiment::ReceivePacket, this));
m_bytesTotal = 0;

   std::ofstream ascii (m_asciitracefile.c_str ());
   if (!ascii.is_open ())
     {
       NS_FATAL_ERROR ("Could not open ascii trace file: "
                       << m_asciitracefile);
     }
   uan.EnableAsciiAll (ascii);

   Simulator::Run ();
   sinkNode = 0;
   sinkSocket = 0;
   pos = 0;
   channel = 0;
   prop = 0;
   for (uint32_t i=0; i < nc.GetN (); i++)
     {
       nc.Get (i) = 0;
     }
   for (uint32_t i=0; i < sink.GetN (); i++)
     {
       sink.Get (i) = 0;
     }

   for (uint32_t i=0; i < devices.GetN (); i++)
     {
       devices.Get (i) = 0;
     }
   for (uint32_t i=0; i < sinkdev.GetN (); i++)
     {
       sinkdev.Get (i) = 0;
     }
Simulator::Destroy ();
   return m_data;
 }
}

★11/28
  • コードを読んでいた所、ptr<>なる文にでくわしたのですが、何をしているかよく分からなかりませんでした。ですので、調べて見たところ、ptr<>
はスマートポインタの宣言を表していて、スマートポインタは通常のポインタと異なり、オブジェクトが不要になったときに自動的にヒープのメモリ解放を行ってくれるポインタということのようです。ヒープメモリが何か
も忘れてしまっていたので調べて見たところ、スタックは関数の実行が終わったら消される、ヒープメモリは関数の外側にあり、関数の実行が終わっても消されないもののようです。
参考:
ttp://99blues.dyndns.org/blog/2010/02/auto_ptr/
ttp://www.curiocube.com/mikata/hello/ch11_heap.php

  • Ptr<T> CreateObjectWithAttributesの意味

「template<typename T >
Ptr<T> CreateObjectWithAttributes ( const AttributeList & attributes ) [friend]
Parameters:
    attributes  a list of attributes to set on the object during construction.
Returns:
   a pointer to a newly allocated object.

This allocates an object on the heap and initializes it with a set of attributes. 」

  • uan.SetMacの解読
uanはUanHelperクラスのobjectなので、UanHelperクラスを見てみることにしました。
ns-3.15/src/uan/helper/uan-helper.cc

「void
UanHelper::SetMac (std::string macType,
                  std::string n0, const AttributeValue &v0,
                  std::string n1, const AttributeValue &v1,
                  std::string n2, const AttributeValue &v2,
                  std::string n3, const AttributeValue &v3,
                  std::string n4, const AttributeValue &v4,
                  std::string n5, const AttributeValue &v5,
                  std::string n6, const AttributeValue &v6,
                  std::string n7, const AttributeValue &v7)
{
 m_mac = ObjectFactory ();
 m_mac.SetTypeId (macType);
 m_mac.Set (n0, v0);
 m_mac.Set (n1, v1);
 m_mac.Set (n2, v2);
 m_mac.Set (n3, v3);
 m_mac.Set (n4, v4);
 m_mac.Set (n5, v5);
 m_mac.Set (n6, v6);
 m_mac.Set (n7, v7);
}」

  • ObjectFactory()とは
ObjectFactoryクラスのメソッドで、ns3::Objectのサブクラスのインスタンスを作るものです。

☆11/29

  • class objectを理解したいとおもい、object.hをみてみたが、いまいち何をしているのか分からなかった。

Run (UanHelper &uan)では、uanが参照で渡されているから、以降の操作で中身が変化するということなのか。

★Mobilityの部分の解読

  • 文:Ptr<ListPositionAllocator> pos = CreateObject<ListPositionAllocator> (); ~~
pos->Add (Vector (m_boundary / 2.0, m_boundary / 2.0, m_depth));

上文において、CreateObject()はCompleteConstruct()を使ってListPositionAllocatorクラスのオブジェクトを作成。
その後メソッドADDを使って位置ベクトルを追加。

390 template <typename T>
391 Ptr<T> CreateObject (void)
392 {
393 return CompleteConstruct (new T ());
394 }

383 Ptr<T> CompleteConstruct (T *p)
384 {
385 p->SetTypeId (T::GetTypeId ());
386 p->Object::Construct (AttributeConstructionList ());
387 return Ptr<T> (p, false);
388 }

void ns3::ListPositionAllocator::Add ( Vector v)

  • 読んでみると、ノードを作成する時に、x-y positionは乱数で散らしているが、深さは統一しているよう。また、ノードは静的であると仮定している。
  • その後、スケジュールメソッドが出てきた。
文:Simulator::Schedule (nextEvent, &Experiment::ResetData, this);

Q)
EventId ns3::Simulator::Schedule ( Time const & time,
        MEM   mem_ptr,
        OBJ   obj
)
static

Schedule an event to expire at the relative time "time" is reached. This can be thought of as
scheduling an event for the current simulation time plus the Time passed as a parameter

When the event expires (when it becomes due to be run), the input method will be invoked on the
input object.
(UQ

より、nextEvent時間たった時に、&Experiment::ResetDataをthisに実行ということのようだ。

ResetDataはしたのようなメソッド。

Q)void
Experiment::ResetData ()
{
 NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << "  Resetting data");
 m_throughputs.push_back (m_bytesTotal * 8.0 / m_simTime.GetSeconds ());
 m_bytesTotal = 0;
}
(UQ

  • 標準出力例
Mean range from gateway: 166.966 min. range 72.406
Position of sink: 250:250:70
1000.5 Resetting data
1000.5 Updating positions
2000.5 Resetting data
2000.5 Updating positions
3000.5 Resetting data
3000.5 Updating positions
Average for cw=10 over 3 runs: 10.8373
4000.5 Resetting data
4000.5 Updating positions
5000.5 Resetting data
5000.5 Updating positions
6000.5 Resetting data
6000.5 Updating positions
Average for cw=20 over 3 runs: 20.736
7000.5 Resetting data
7000.5 Updating position
8000.5 Resetting data
8000.5 Updating positions
      • まだ続く

  • 結局、初期化しながら何度かthroughputを出して平均をだし、contensiton windowのサイズをあげて。結果がどうかわるかを見ているとわかりました。ちゃんと各回にためたデータの消去もしているようです。(m_throughputs.clear ();)

  • 今後は、fadingの取り込み方、地形効果を取り入れられるかなどに注目しつつ、既存モデルがどうやってthroughputを計算しているかをみていくつもりです。
研究としては、海中光通信モジュール開発、marine creatureの影響の考慮、も視野に入れてします。

☆12/4
地形データを取り込んで、それが、各チャネルに及ぼす影響を計算して、各チャネルの性質を変更するようなモジュールが作りたいです。地形データの取り込み自体は、ゲームなどにも使われてるし、調べればできそうですが、それが、各チャネルにどう効いてくるかを計算するのが難しそうです。(まじめにやると地形だけでなく、物性や渦などの海洋現象も絡んできます。)

☆12/5
前回シミュレータの挙動が分かった気がしていたのですが、改めてみてみると、よく分かっていないことに気づきました。
今日重要だと思ったのは、シミュレータには、scheduling phaseとrun
phaseがあって、simulationの計算自体は、Simlator::Run()の後に行われているということです。
uan-cw-exampleでのscheduleは4つあって、1つ目が、0.5sから終わりまで続く、送信ノード(nc)から受信ノード(sink)
へのパケット送信で、(アプリを載せています。)2つ目はresetdataがm_simTime毎に、3つ目は、updatepositionがm_simTime毎に、4つ目はincrement_cwが期待値を出す塊毎に予約されています。
これらのイベントがSimulator::Run()が実行されると時間順に順々に実行されます。

ということで、UWのモデルは、アプリが何バイトのデータをsinkに送れるかの計算に使われているはずです。
(はずなのですが、プログラムでいうとどこの記述なのかがいまいち見えません。)
ということで、次回はモデルがどう計算に使われているかを引き続き解読する必要があります。

☆12/7
以下のような作業をしました。
1:root@joe-laptop:~/repos/ns-3-allinone/ns-3.15/src/uan/model# vim uan-channel.cc
のtipeidメソッドに目印の標準出力を挿入しました。
2:./waf実行したところ、結果は下の用になりました。
「root@joe-laptop:~/repos/ns-3-allinone/ns-3.15# ./waf
Waf: Entering directory `/home/joe/repos/ns-3-allinone/ns-3.15/build'
[1529/1924] cxx: src/uan/model/uan-channel.cc -> build/src/uan/model/uan-channel.cc.1.o
[1754/1924] cxxshlib: build/src/uan/model/uan-channel.cc.1.o build/src/uan/model/uan-phy-gen.cc.1.o
build/src/uan/model/uan-mac.cc.1.o build/src/uan/model/uan-transducer.cc.1.o
build/src/uan/model/uan-transducer-hd.cc.1.o build/src/uan/model/uan-address.cc.1.o
build/src/uan/model/uan-net-device.cc.1.o build/src/uan/model/uan-tx-mode.cc.1.o
build/src/uan/model/uan-prop-model.cc.1.o build/src/uan/model/uan-prop-model-ideal.cc.1.o
build/src/uan/model/uan-mac-aloha.cc.1.o build/src/uan/model/uan-header-common.cc.1.o
build/src/uan/model/uan-noise-model-default.cc.1.o build/src/uan/model/uan-mac-cw.cc.1.o
build/src/uan/model/uan-prop-model-thorp.cc.1.o build/src/uan/model/uan-phy-dual.cc.1.o
build/src/uan/model/uan-header-rc.cc.1.o build/src/uan/model/uan-mac-rc.cc.1.o
build/src/uan/model/uan-mac-rc-gw.cc.1.o build/src/uan/model/uan-phy.cc.1.o
build/src/uan/model/uan-noise-model.cc.1.o build/src/uan/model/acoustic-modem-energy-model.cc.1.o
build/src/uan/helper/uan-helper.cc.1.o
build/src/uan/helper/acoustic-modem-energy-model-helper.cc.1.o -> build/libns3.15-uan-debug.so
[1766/1924] cxxprogram: build/src/uan/examples/uan-rc-example.cc.2.o ->
build/src/uan/examples/ns3.15-uan-rc-example-debug
[1786/1924] cxxshlib: build/src/uan/test/uan-test.cc.3.o
build/src/uan/test/uan-energy-model-test.cc.3.o -> build/libns3.15-uan-test-debug.so
[1807/1924] cxxprogram: build/src/uan/examples/uan-cw-example.cc.1.o ->
build/src/uan/examples/ns3.15-uan-cw-example-debug
[1861/1924] cxxshlib: build/src/netanim/model/animation-interface.cc.1.o
build/src/netanim/helper/animation-interface-helper.cc.1.o -> build/libns3.15-netanim-debug.so
[1863/1924] cxxshlib: build/src/point-to-point-layout/model/point-to-point-dumbbell.cc.1.o
build/src/point-to-point-layout/model/point-to-point-grid.cc.1.o
build/src/point-to-point-layout/model/point-to-point-star.cc.1.o ->
build/libns3.15-point-to-point-layout-debug.so
[1863/1924] cxxshlib: build/src/csma-layout/model/csma-star-helper.cc.1.o ->
build/libns3.15-csma-layout-debug.so
[1864/1924] cxxprogram: build/src/netanim/examples/uan-animation.cc.5.o ->
build/src/netanim/examples/ns3.15-uan-animation-debug
[1865/1924] cxxprogram: build/src/netanim/examples/wireless-animation.cc.4.o ->
build/src/netanim/examples/ns3.15-wireless-animation-debug
[1866/1924] cxxprogram: build/examples/matrix-topology/matrix-topology.cc.1.o ->
build/examples/matrix-topology/ns3.15-matrix-topology-debug
[1867/1924] cxxshlib: build/src/netanim/test/netanim-test.cc.3.o ->
build/libns3.15-netanim-test-debug.so
[1868/1924] cxxprogram: build/src/csma-layout/examples/csma-star.cc.1.o ->
build/src/csma-layout/examples/ns3.15-csma-star-debug
[1869/1924] cxxshlib: -> build/libns3.15-test-debug.so
[1870/1924] cxxprogram: build/src/netanim/examples/star-animation.cc.3.o ->
build/src/netanim/examples/ns3.15-star-animation-debug
[1871/1924] cxxprogram: build/src/network/examples/droptail_vs_red.cc.4.o ->
build/src/network/examples/ns3.15-droptail_vs_red-debug
[1872/1924] cxxprogram: build/src/netanim/examples/grid-animation.cc.2.o ->
build/src/netanim/examples/ns3.15-grid-animation-debug
[1873/1924] cxxprogram: build/examples/tcp/star.cc.5.o -> build/examples/tcp/ns3.15-star-debug
[1874/1924] cxxprogram: build/src/netanim/examples/dynamic_linknode.cc.6.o ->
build/src/netanim/examples/ns3.15-dynamic_linknode-debug
[1875/1924] cxxprogram: build/src/netanim/examples/dumbbell-animation.cc.1.o ->
build/src/netanim/examples/ns3.15-dumbbell-animation-debug
[1876/1924] cxxshlib: build/src/stats/bindings/ns3module.cc.7.o -> build/bindings/python/ns/stats.so
[1877/1924] cxxshlib: build/src/uan/bindings/ns3module.cc.7.o -> build/bindings/python/ns/uan.so
[1878/1924] cxxshlib: build/src/csma/bindings/ns3module.cc.5.o -> build/bindings/python/ns/csma.so
[1879/1924] cxxshlib: build/src/dsr/bindings/ns3module.cc.7.o -> build/bindings/python/ns/dsr.so
[1880/1924] cxxprogram: build/scratch/myfirst.cc.4.o -> build/scratch/myfirst
[1881/1924] cxxshlib: build/src/virtual-net-device/bindings/ns3module.cc.5.o ->
build/bindings/python/ns/virtual_net_device.so
[1882/1924] cxxshlib: build/src/wimax/bindings/ns3module.cc.7.o -> build/bindings/python/ns/wimax.so
[1883/1924] cxxprogram: build/scratch/second.cc.2.o -> build/scratch/second
[1884/1924] cxxshlib: build/src/core/bindings/ns3module.cc.8.o
build/src/core/bindings/module_helpers.cc.8.o -> build/bindings/python/ns/_core.so
[1885/1924] cxxprogram: build/scratch/subdir/scratch-simulator-subdir.cc.6.o ->
build/scratch/subdir/subdir
[1886/1924] cxxshlib: build/src/test/csma-system-test-suite.cc.4.o
build/src/test/global-routing-test-suite.cc.4.o build/src/test/static-routing-test-suite.cc.4.o
build/src/test/error-model-test-suite.cc.4.o build/src/test/mobility-test-suite.cc.4.o
build/src/test/ns3wifi/wifi-interference-test-suite.cc.4.o
build/src/test/ns3wifi/wifi-msdu-aggregator-test-suite.cc.4.o
build/src/test/ns3tcp/ns3tcp-cwnd-test-suite.cc.4.o
build/src/test/ns3tcp/ns3tcp-interop-test-suite.cc.4.o
build/src/test/ns3tcp/ns3tcp-loss-test-suite.cc.4.o
build/src/test/ns3tcp/ns3tcp-no-delay-test-suite.cc.4.o
build/src/test/ns3tcp/ns3tcp-socket-test-suite.cc.4.o
build/src/test/ns3tcp/ns3tcp-state-test-suite.cc.4.o
build/src/test/ns3tcp/nsctcp-loss-test-suite.cc.4.o
build/src/test/ns3tcp/ns3tcp-socket-writer.cc.4.o -> build/libns3.15-test-test-debug.so
[1887/1924] cxxshlib: build/src/network/bindings/ns3module.cc.7.o ->
build/bindings/python/ns/network.so
[1888/1924] cxxshlib: build/src/lte/bindings/ns3module.cc.7.o -> build/bindings/python/ns/lte.so
[1889/1924] cxxprogram: build/scratch/scratch-simulator.cc.1.o -> build/scratch/scratch-simulator
[1890/1924] cxxshlib: build/src/internet/bindings/ns3module.cc.7.o ->
build/bindings/python/ns/internet.so
[1891/1924] cxxshlib: build/src/antenna/bindings/ns3module.cc.7.o ->
build/bindings/python/ns/antenna.so
[1892/1924] cxxshlib: build/src/energy/bindings/ns3module.cc.7.o ->
build/bindings/python/ns/energy.so
[1893/1924] cxxshlib: build/src/mobility/bindings/ns3module.cc.7.o ->
build/bindings/python/ns/mobility.so
[1894/1924] cxxshlib: build/src/tools/bindings/ns3module.cc.7.o -> build/bindings/python/ns/tools.so
[1895/1924] cxxshlib: build/src/config-store/bindings/ns3module.cc.5.o ->
build/bindings/python/ns/config_store.so
[1896/1924] cxxshlib: build/src/dsdv/bindings/ns3module.cc.7.o -> build/bindings/python/ns/dsdv.so
[1897/1924] cxxshlib: build/src/bridge/bindings/ns3module.cc.5.o ->
build/bindings/python/ns/bridge.so
[1898/1924] cxxshlib: build/src/buildings/bindings/ns3module.cc.7.o ->
build/bindings/python/ns/buildings.so
[1899/1924] cxxshlib: build/src/flow-monitor/bindings/ns3module.cc.7.o ->
build/bindings/python/ns/flow_monitor.so
[1900/1924] cxxshlib: build/src/topology-read/bindings/ns3module.cc.7.o ->
build/bindings/python/ns/topology_read.so
[1901/1924] cxxprogram: build/scratch/test1.cc.5.o -> build/scratch/test1
[1902/1924] cxxprogram: build/utils/print-introspected-doxygen.cc.4.o ->
build/utils/ns3.15-print-introspected-doxygen-debug
[1903/1924] cxxshlib: build/src/mpi/bindings/ns3module.cc.5.o -> build/bindings/python/ns/mpi.so
[1904/1924] cxxprogram: build/scratch/mythird.cc.3.o -> build/scratch/mythird
[1905/1924] cxxshlib: build/src/olsr/bindings/ns3module.cc.7.o -> build/bindings/python/ns/olsr.so
[1906/1924] cxxshlib: build/src/tap-bridge/bindings/ns3module.cc.6.o ->
build/bindings/python/ns/tap_bridge.so
[1907/1924] cxxshlib: build/src/mesh/bindings/ns3module.cc.7.o -> build/bindings/python/ns/mesh.so
[1908/1924] cxxshlib: build/src/spectrum/bindings/ns3module.cc.7.o ->
build/bindings/python/ns/spectrum.so
[1909/1924] cxxshlib: build/src/aodv/bindings/ns3module.cc.7.o -> build/bindings/python/ns/aodv.so
[1910/1924] cxxshlib: build/src/emu/bindings/ns3module.cc.6.o -> build/bindings/python/ns/emu.so
[1911/1924] cxxshlib: build/src/applications/bindings/ns3module.cc.7.o ->
build/bindings/python/ns/applications.so
[1912/1924] cxxshlib: build/src/point-to-point-layout/bindings/ns3module.cc.5.o ->
build/bindings/python/ns/point_to_point_layout.so
[1913/1924] cxxshlib: build/src/nix-vector-routing/bindings/ns3module.cc.5.o ->
build/bindings/python/ns/nix_vector_routing.so
[1914/1924] cxxshlib: build/src/wifi/bindings/ns3module.cc.7.o -> build/bindings/python/ns/wifi.so
[1915/1924] cxxshlib: build/src/point-to-point/bindings/ns3module.cc.7.o ->
build/bindings/python/ns/point_to_point.so
[1916/1924] cxxshlib: build/src/csma-layout/bindings/ns3module.cc.5.o ->
build/bindings/python/ns/csma_layout.so
[1917/1924] cxxshlib: build/src/propagation/bindings/ns3module.cc.7.o ->
build/bindings/python/ns/propagation.so
[1918/1924] cxxprogram: build/utils/test-runner.cc.1.o -> build/utils/ns3.15-test-runner-debug
Waf: Leaving directory `/home/joe/repos/ns-3-allinone/ns-3.15/build'
'build' finished successfully (37.991s)

3:./waf --run src/uan/examples/uan-cw-example
を実行するとちゃんと、シミュレーション結果の出力の前に挿入標準出力が出てました。ですので、uan-channel.ccはこのプログラムのチャネル計算に使われていることがわかりました。

4:次にuan-noise-model-default.cc
にも標準出力を入れてみた

simulation結果は下の用になりました。
「(省略) noise desuyonoise desuyonoise desuyonoise desuyonoise desuyonoise desuyonoise desuyonoise
desuyonoise desuyonoise desuyonoise desuyonoise desuyonoise desuyonoise desuyonoise desuyonoise
desuyonoise desuyonoise desuyonoise desuyonoise desuyonoise desuyonoise desuyonoise desuyonoise
desuyonoise desuyonoise desuyonoise desuyonoise desuyonoise desuyonoise desuyonoise desuyonoise
desuyonoise desuyonoise desuyonoise desuyonoise desuyonoise desuyonoise desuyonoise desuyonoise
desuyonoise desuyonoise desuyonoise desuyonoise desuyonoise desuyonoise desuyonoise desuyonoise
desuyonoise desuyonoise desuyonoise desuyonoise desuyonoise desuyonoise desuyonoise desuyonoise
desuyonoise desuyonoise desuyonoise desuyonoise desuyonoise desuyonoise desuyonoise desuyonoise
desuyonoise desuyonoise desuyonoise desuyonoise desuyonoise desuyonoise desuyonoise desuyonoise
desuyonoise desuyonoise desuyonoise desuyonoise desuyonoise desuyonoise desuyonoise desuyonoise
desuyonoise desuyonoise desuyonoise desuyonoise desuyonoise desuyo120000 Resetting data
120000 Updating positions
Average for cw=400 over 3 runs: 38.912

やはり、uan-noise-model-default.ccは各simulationのアプリケーションでの計算に使われていてアプリケーションが送ったパケットがどの程度到達するかを決めているようです。

5:uan-noise-model-default.ccのノイズモデルを適当に変えてみました。具体的には、ノイズの値を100倍にしてみた。すると、スループットが0になりました。

疑問:ノイズがどうパケット到達の計算に使われているのかはどこに書いてあるかわかりません。100倍にしたら0になったというだけじゃ計算の仕方は全く分かりません。

☆12/10
スループットの計算をどうやっているのかを探ろうと考え、デバッグしようとしたのだがうまくいきませんでした。ですので、tutorialでログの出力について記述が合ったのを思い出したので、読み返してみました。

結局
export 'NS_LOG=*=level_all|prefix_func|prefix_time'
で詳細な出力が出るようになるので、
./waf --run src/uan/examples/uan-cw-example > log.out 2>&1
でログを出せば詳細な挙動が分かるようです。
(設定を元に戻すには、export NS_LOG= で大丈夫です。)

実際、送信ノード1個、平均取らず、contention window変えないという条件でログを出力しました。

3.7s UanMacCw:Enqueue(): Time 3.7: Addr 02-01-00: Enqueuing new packet while idle (sending)
3.7s UanPhyGen:SendPacket(): PHY 02-01-00: Transmitting packet
3.7s UanTransducerHd:Transmit(): Transducer transmitting: TX delay = +3500000000.0ns seconds for
packet size 35 bytes and rate = 80 bps
3.7s UanChannel:TxPacket(): Channel scheduling
3.7s UanChannel:TxPacket(): Scheduling 02-01-01
3.7s UanChannel:TxPacket(): txPowerDb=190dB, rxPowerDb=190dB, distance=165.012m,
delay=+110008279.0ns

ここら辺がUANモデルを使ってパケット到達性を計算しているところだと推測されます。

「512 UanPhyGen::SendPacket (Ptr<Packet> pkt, uint32_t modeNum)
513 {
514 NS_LOG_DEBUG ("PHY " << m_mac->GetAddress () << ": Transmitting packet");
515 if (m_disabled)
516 {
517 NS_LOG_DEBUG ("Energy depleted, node cannot transmit any packet. Dropping.");
518 return;
519 }
520
521 if (m_state == TX)
522 {
523 NS_LOG_DEBUG ("PHY requested to TX while already Transmitting. Dropping packet.");
524 return;
525 }
526 else if (m_state == SLEEP)
527 {
528 NS_LOG_DEBUG ("PHY requested to TX while sleeping. Dropping packet.");
529 return;
530 }
531
532 UanTxMode txMode = GetMode (modeNum);
533
534 if (m_pktRx != 0)
535 {
536 m_minRxSinrDb = -1e30;
537 m_pktRx = 0;
538 }
539
540 m_transducer->Transmit (Ptr<UanPhy> (this), pkt, m_txPwrDb, txMode);
541 m_state = TX;
542 UpdatePowerConsumption (TX);
543 double txdelay = pkt->GetSize () * 8.0 / txMode.GetDataRateBps ();
544 Simulator::Schedule (Seconds (txdelay), &UanPhyGen::TxEndEvent, this);
545 NS_LOG_DEBUG ("PHY " << m_mac->GetAddress () << " notifying listeners");
546 NotifyListenersTxStart (Seconds (txdelay));
547 m_txLogger (pkt, m_txPwrDb, txMode);
548 }」

UanMacCw:SendPacket() :これも気になります。

  • 12/11

3.81001s UanPhyGen:CalcSinrDb(): Calculating SINR: RxPower = 190 dB. Number of interferers = 1
Interference + noise power = 54.3837 dB. SINR = 135.616 dB.
3.81001s UanPhyGen:StartRxPacket(): PHY 02-01-01: Starting RX in IDLE mode. SINR = 135.616

ここでSINRの計算してるみたいです。

CalcSinrDb()の説明のなかで、modeという変数が出てきて、これが何を意図しているのかよくわからなかったのですが、uan-cwプログラムを見ると、
「 mode = UanTxModeFactory::CreateMode (UanTxMode::FSK, exp.m_dataRate,
                                      exp.m_dataRate, 12000,
                                      exp.m_dataRate, 2,
                                      "Default mode");

などという形で出てきていて、調べて見ると、modulationの仕方や、使用音波の中心周波数、バンド幅などを決めていると分かりました。

標準のPER,SINRのモデルはどうなっているのか気になったので調べてみました。(いろいろ海中音波のモデルがあっても結局PERとSINRの値に落とし込んでいるのではないかと推測したので。)


ns3::UanPhyPerGenDefault Class Reference

Default Packet Error Rate calculator for UanPhyGen Considers no error if SINR is > user defined
threshold (configured by an attribute).

ns3::UanPhyCalcSinrDefault Class Reference

Default SINR calculator for UanPhyGen The default ignores mode data and assumes that all rxpower
transmitted is captured by the receiver, and that all signal power associated with interfering
packets affects SINR identically to additional ambient noise.

transducerが何をしているのかよくわかりません。

「3.81001s UanTransducerHd:Receive(): 3.81001 Transducer in receive
3.81001s UanTransducerHd:Receive(): Transducer state = RX
3.81001s UanTransducerHd:Receive(): Calling StartRx」



7.31001s Node:NonPromiscReceiveFromDevice(0x8e90520)
7.31001s Node:ReceiveFromDevice(): Node 1 ReceiveFromDevice: dev 0 (type=ns3::UanNetDevice) Packet
UID 0
7.31001s PacketSocket:ForwardUp(0x8e918a0, 0x8e90b10, 0x8e914d0, 0, 02-01-00, 02-01-01, 0)

14.0972s Node:NonPromiscReceiveFromDevice(0x8e90520)
14.0972s Node:ReceiveFromDevice(): Node 1 ReceiveFromDevice: dev 0 (type=ns3::UanNetDevice) Packet
UID 1
14.0972s PacketSocket:ForwardUp(0x8e918a0, 0x8e90b10, 0x8e94380, 0, 02-01-00, 02-01-01, 0)」

パケット受け取りを表しているのは、このふたつのようです。(標準出力してみたところ受け取ったパケットは2個でしたし。)

☆12/12

より詳細なデバッグができると期待してD-trace installをinstallして使ってみようと試みましたが、うまく使えませんでした。

以下取った行動のログです。
1:d-traceの最新版をダウンロードしました。(ftp://crisp.dyndns-server.com/pub/release/website/dtrace/にて)
2:
bunzip2 < dtrace-20121210.tar.bz2 | tar xvf -
sudo apt-get install bison
sudo apt-get install flex
sudo apt-get install zlib1g-dev
sudo apt-get install libelf-dev
cd dtrace-20110120
make all
sudo make install
sudo make load
3:エラーが出たので
tools/get-deps.plを実行 to ensure everything is needed or a build.
参考:http://askubuntu.com/questions/60940/how-do-i-install-dtrace

この後、
http://gihyo.jp/dev/serial/01/dtrace4cpg/0001?page=2
を参考にしながら、お試し的なd-scriptとやらを実行してみましたが、
「dtrace: failed to compile script ./test.d: line 1: probe description pid6494:ls::entry does not
match any probes

などとエラーが出て駄目でした。時間のむだな気がしてきたので、とりあえずd-traceは保留することにしました。

☆12/12 NS3_UAN関連
OnOffaApplicationの詳細な説明を読みました

次にログを見ていく作業を行いました。今回は、0.5sに何が起こっているかを解読しました。送信ノード数が1つの場合と4つの場合のログを見比べることで、

「0.5s OnOffApplication:StartApplication()

0.5s DefaultSimulatorImpl:ProcessOneEvent(): handle 1500000000」
が一塊で、一つの送信ノードについて、パケット送信アプリの設定をしていることが分かりました。(詳しくは、ネットワークデバイスとプロトコルの結び付け、パケットの目的地の設定等)

ただ、いろいろ細かいところはまだわかりません。目的地の値が毎回変わってるのはなぜなのでしょうか。
仮説:単に受信ノードに複数のネットワークデバイスがのっていて、各送信ノードとの間でのパケットのやり取りには別個のネットワークデバイスを使っている

PacketSocket::ShutdownRecv (void):Do not allow any further Recv calls. This method is typically
implemented for Tcp sockets by a half close.
は、今設定している相手以外のパケットは受け取らないということですかね。

☆12/13
今回は、uan-noise-model-default.ccのetNoiseDbHz (fKhz)がどう計算に結びついているのかさっぱりなので、それをたどってみることにしました。


double
UanChannel::GetNoiseDbHz (double fKhz)
{
 NS_ASSERT (m_noise);
 double noise = m_noise->GetNoiseDbHz (fKhz);
 return noise;
}

まずはここで使われているようです。この関数自体は、UanPhyGen::CalculateSinrDbに参照されていて、また、UanPhyGen::CalculateSinrDbは、UanPhyGen:
:StartRxPacketに参照されているようです。

どうも、UanPhyGen::CalculateSinrDbがsinrを計算する、割と肝な関数のようです。こいつが呼び出しているのは、
UanPhyCalcSinr::CalcSinrDb
UanTransducer::GetArrivalList  ←干渉の計算に使う。到達音波の数を求める。
UanTxMode::GetCenterFreqHz
UanTxMode::GetBandwidthHz
UanChannel::GetNoiseDbH
の5つの関数です。

ノイズをUanChannel::GetNoiseDbH及びバンド幅から計算してメインのsinrの計算はUanPhyCalcSinr::CalcSinrDbに任せているようです。

「UanPhyCalcSinrDefault::CalcSinrDb (Ptr<Packet> pkt,
72 Time arrTime,
73 double rxPowerDb,
74 double ambNoiseDb,
75 UanTxMode mode,
76 UanPdp pdp,
77 const UanTransducer::ArrivalList &arrivalList) const
78 {
79 if (mode.GetModType () == UanTxMode::OTHER)
80 {
81 NS_LOG_WARN ("Calculating SINR for unsupported modulation type");
82 }
83
84 double intKp = -DbToKp (rxPowerDb); // This packet is in the arrivalList
85 UanTransducer::ArrivalList::const_iterator it = arrivalList.begin ();
86 for (; it != arrivalList.end (); it++)
87 {
88 intKp += DbToKp (it->GetRxPowerDb ());
89 }
90
91 double totalIntDb = KpToDb (intKp + DbToKp (ambNoiseDb));
92
93 NS_LOG_DEBUG ("Calculating SINR: RxPower = " << rxPowerDb << " dB. Number of interferers = " <<
arrivalList.size () << " Interference + noise power = " << totalIntDb << " dB. SINR = " << rxPowerDb
  • totalIntDb << " dB.");
94 return rxPowerDb - totalIntDb;
95 }」

DbToKpなどは単に単位変換しているだけの関数です。arribal listが現在そのノードを通過しているパケットを表しているので、自分自身を除いた通過パケットの受信電力の和を干渉値にしているということのようです。(干渉の計算はこれでいいのですかね。multipath fadingはここで考えてることになってるのでしょうか。)

参考:

「GetArrivalList ( void ) const
pure virtual
Returns
   List of all packets currently crossing this node in the water. 」

「UanPacketArrival::GetRxPowerDb ( void ) const
inline
Returns
   Received signal strength in dB re 1uPa 」


memo: ambient noise=環境ノイズ

☆次回やること
UanPhyGen::StartRxPacketのやってること把握したいです。

☆12/14

今回は UanPhyGen::StartRxPacketが何をしているのか探ります。

 579 void
 580 UanPhyGen::StartRxPacket (Ptr<Packet> pkt, double rxPowerDb, UanTxMode txMode, UanPdp pdp)
 581 {
 582   if (m_disabled)
 583     {
 584       NS_LOG_DEBUG ("Energy depleted, node cannot receive any packet. Dropping.");
 585       NotifyRxDrop(pkt);    // traced source netanim
 586       return;
 587     }
 588
 589   switch (m_state)
 590     {
 591     case TX:
 592       NotifyRxDrop(pkt);    // traced source netanim
 593       NS_ASSERT (false);
 594       break;
 595     case RX:
 596       {
 597         NS_ASSERT (m_pktRx);
 598         double newSinrDb = CalculateSinrDb (m_pktRx, m_pktRxArrTime, m_rxRecvPwrDb,
m_pktRxMode, m_pktRxPdp);
 599         m_minRxSinrDb  =  (newSinrDb < m_minRxSinrDb) ? newSinrDb : m_minRxSinrDb;
 600         NS_LOG_DEBUG ("PHY " << m_mac->GetAddress () << ": Starting RX in RX mode.  SINR of
pktRx = " << m_minRxSinrDb);
 601         NotifyRxBegin(pkt);    // traced source netanim
 602       }
 603       break;
 604
 605     case CCABUSY:
 606     case IDLE:
 607       {
 608         NS_ASSERT (!m_pktRx);
 609         bool hasmode = false;
 610         for (uint32_t i = 0; i < GetNModes (); i++)
 611           {
 612             if (txMode.GetUid () == GetMode (i).GetUid ())
 613               {
 614                 hasmode = true;
 615                 break;
 616               }
 617           }
 618         if (!hasmode)
 619           {
 620             break;
 621           }
 622
 623
 624         double newsinr = CalculateSinrDb (pkt, Simulator::Now (), rxPowerDb, txMode, pdp);
 625         NS_LOG_DEBUG ("PHY " << m_mac->GetAddress () << ": Starting RX in IDLE mode.  SINR = "
<< newsinr);
 626         if (newsinr > m_rxThreshDb)
 627           {
 628             m_state = RX;
 629             UpdatePowerConsumption (RX);
 630             NotifyRxBegin(pkt);    // traced source netanim
 631             m_rxRecvPwrDb = rxPowerDb;
 632             m_minRxSinrDb = newsinr;
 633             m_pktRx = pkt;
 634             m_pktRxArrTime = Simulator::Now ();
 635             m_pktRxMode = txMode;
 636             m_pktRxPdp = pdp;
 637             double txdelay = pkt->GetSize () * 8.0 / txMode.GetDataRateBps ();
 638             Simulator::Schedule (Seconds (txdelay), &UanPhyGen::RxEndEvent, this, pkt,
rxPowerDb, txMode);
 639             NotifyListenersRxStart ();
 640           }
 641
 642       }
 643       break;
 644     case SLEEP:
 645       NS_LOG_DEBUG ("Sleep mode. Dropping packet.");
 646       NotifyRxDrop(pkt);    // traced source netanim
 647       break;
 648     }
 649
 650   if (m_state == IDLE && GetInterferenceDb ( (Ptr<Packet>) 0) > m_ccaThreshDb)
 651     {
 652       m_state = CCABUSY;
 653       NotifyListenersCcaStart ();
 654     }
 655
 656 }

結局ノードの状態により場合分けして、IDLE状態だったら、SINRの値が閾値を超えていればreceive modeに入るようです。

UanPhyGen::RxEndEventは受信終了を行う関数で、 m_pktRx(受信パケットへのポインタ)の初期化や、m_state(ノードの状態)の変更を行っているようです。


疑問: m_rxThreshDbの初期値がどこで決められている?


結局total receive
bytesはどう計算されているのかと思い、改めてサンプルプログラムを見てみると、どうもプログラム中では、Socket::Recvによってのみその値が変化しているらしいことが分かった。

「Ptr< Packet > ns3::Socket::Recv ( void )
Read a single packet from the socket.」

ソケットは、UanPhyGen::StartRxPacketとどう絡んでいるのでしょうか?

☆12/15

目標:サンプルプログラムでの受信パケットの量の計算が結局どういう仕組みでもたらされているかを知る


「void ns3::Socket::SetRecvCallback (Callback< void, Ptr< Socket > > receivedData)
Notify application when new data is available to be read.
This callback is intended to notify a socket that would have been blocked in a blocking socket model
that data is available to be read.」

「 112 void
 113 Socket::SetRecvCallback (Callback<void, Ptr<Socket> > receivedData)
 114 {
 115   NS_LOG_FUNCTION_NOARGS ();
 116   m_receivedData = receivedData;
 117 }」

NS_LOG_FUNCTION_NOARGSはOutput the name of the functionということのようです。

m_receivedDataは、Callback<void, Ptr<Socket> > ns3::Socket::m_receivedData。コールバック変数ということのようです。

「 501 template <typename T, typename OBJ, typename R>
 502 Callback<R> MakeCallback (R (T::*memPtr)(void), OBJ objPtr) {
 503   return Callback<R> (objPtr, memPtr);
 504 }」

  • Callbackが何かを忘れていたので復習しました。発想としては、関数の引数に関数を使うということのようです。

今までスルーしてきた、thisの意味を大雑把に理解しました。どうやらメンバ関数を呼び出したオブジェクト自体を指すようです。

ですので、
「sinkSocket->SetRecvCallback (MakeCallback (&Experiment::ReceivePacket, this));」
は、sinkSocketオブジェクトがserRecvCallbackを実行し、その中身は、makecallbackというコールバック用の関数をコールバック変数m_receiveddataに登録するこ
とで、makecallbackという関数は、sinksocketオブジェクトを引数にしたexperiment::receivepacketを実行する関数であるということのようです。

Experiment::ReceivePacketにログを仕込んで詳細ログ(名前:log3.out)をとってみると、
11.2693s UanCwExample:ReceivePacket(): joe's debug m_bytestotal: 32
24.9719s UanCwExample:ReceivePacket(): joe's debug m_bytestotal: 32
29.2473s UanCwExample:ReceivePacket(): joe's debug m_bytestotal: 64
36.8215s UanCwExample:ReceivePacket(): joe's debug m_bytestotal: 96

みたいな感じになりました。

☆次やること
  • m_receivedDataがどこで使われているのかがよくわからないので調べたいです。それがわからないと受信の処理が結局どうなっているかわからないので。
  • UanPhyGen::StartRxPacketを誰が呼び出しているか、パケット送信の詳細、伝搬の詳細を明らかにします。

===================================================================================================================================================================================================

(3)今後の予定

(2)ではパケットロスの大雑把な仕組みを知ったと書いたのですが、そもそもノードの受信行動が何にトリガーされるのかや、パケット送信のプロセスはどうなっているのか、また伝搬の計算はどうなっているかについてまだ分かっていません。ですので、引き続き、関数ドキュメント、ソースコード、ログを見ながらNS3-UANの構造の理解をしていきたいと考えています。

しっかりと理解ができたら、その後地形効果を取り入れるプログラムを書いていくつもりです。
最終更新:2012年12月24日 10:47