NS3_Tutorial 中文版: 第五章 Tweaking NS3(2/2)

【致謝】: 感謝關注NS3 Tutorial中文版的廣大網友們,感謝NS3翻譯小組,感謝初稿的翻譯者們,感謝審稿和編輯們!!!   (詳細的名單請查看博文翻譯Tutorial
 
  聲明:引用和轉載相關內容,請尊重作者、翻譯者和審稿者的辛勤付出,我們堅信開源的思想,我們希望自己的工作可以爲更多的人提供幫助,我們不希望成爲隨意粘貼和任意複製的對象。
5 Tweaking NS3 NS3調整?)

翻譯: 楊飛

校稿: Xiaochuan Shen

編輯: ProbibidoAmor

5.2 使用命令行參數

 

5.2.1 重載默認屬性

 

另一個不用編譯就可改變ns-3腳本行爲的方法就是通過使用命令行參數。我們提供了一種分析命令行屬性和基於這些屬性自動設置的本地和全局變量的機制。
使用命令行屬性系統的第一步就是聲明命令行分析器。可以用下面的代碼來非常簡單的完成。
    int
  main (int argc, char *argv[])
  {
    ... 

 

    CommandLine cmd;
    cmd.Parse (argc, argv);

 

    ...
  }
這兩行簡單的代碼實際上是很有用的。它提供了向ns-3全局變量和屬性傳遞參數的途徑。在scratch/myfirst.ccmain函數開始加上這兩行代碼。編譯並運行腳本,同時可以根據下面這兩行向腳本尋求幫助。
  ./waf --run "scratch/myfirst --PrintHelp"
這個命令是讓Waf運行scratch/myfirst腳本並且通過命令行參數--PrintHelp。引號需要用來確定那個程序得到那個參數。命令行分析器將查看--PrintHelp參數並返回一下內容,
  Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
  Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
  'build' finished successfully (0.413s)
  TcpL4Protocol:TcpStateMachine()
  CommandLine:HandleArgument(): Handle arg name=PrintHelp value=
  --PrintHelp: Print this help message.
  --PrintGroups: Print the list of groups.
  --PrintTypeIds: Print all TypeIds.
  --PrintGroup=[group]: Print all TypeIds of group.
  --PrintAttributes=[typeid]: Print all attributes of typeid.
  --PrintGlobals: Print the list of globals.
下面來關注--PrintAttributes選項。在我們查看first.cc腳本時,已經提到過ns-3屬性系統。
    PointToPointHelper pointToPoint;
    pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
    pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
我們提到DataRate事實上是PointToPointNetDevice的一個屬性。現在使用命令行參數分析器來看一下PointToPointNetDevice的屬性。幫助列表需要我們提供一個TypeId。本例中,這個TypeIdns3::PointToPointNetDevice。然後我們可以鍵入,
  ./waf --run "scratch/myfirst --PrintAttributes=ns3::PointToPointNetDevice"
系統將顯示出網絡設備這種所有屬性。你將看到,
  --ns3::PointToPointNetDevice::DataRate=[32768bps]:
    The default data rate for point to point links
當系統中的PointToPointNetDevice被創立時,DataRate將是一個默認值。我們的腳本用PointToPointHelper重載了這個默認值。現在讓我們刪除Scratch目錄中myfirst.ccSetDeviceAttributethe SetChannelAttribute調用來使用端到端設備使用默認值。
你的腳本現在只需要聲明PointToPointHelper而並不做任何設置,

  NodeContainer nodes;
  nodes.Create (2);

 

  PointToPointHelper pointToPoint;

 

  NetDeviceContainer devices;
  devices = pointToPoint.Install (nodes);

 

使用Waf(./waf)運行你的腳本,啓用UDP回顯服務器應用的一些日誌並且打開時間前綴。
  export 'NS_LOG=UdpEchoServerApplication=level_all|prefix_time'

運行腳本,可以看到下面的結果,
  Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
  Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
  'build' finished successfully (0.405s)
  0s UdpEchoServerApplication:UdpEchoServer()
  1s UdpEchoServerApplication:StartApplication()
  Sent 1024 bytes to 10.1.1.2
  2.25732s Received 1024 bytes from 10.1.1.1
  2.25732s Echoing packet
  Received 1024 bytes from 10.1.1.2
  10s UdpEchoServerApplication:StopApplication()
  UdpEchoServerApplication:DoDispose()
  UdpEchoServerApplication:~UdpEchoServer()

回憶上次響應服務器收到數據包的仿真時間,是2.00369秒,
  2.00369s UdpEchoServerApplication:HandleRead(): Received 1024 bytes from 10.1.1.1
現在在2.25732秒收到數據包。這是因爲我們將PointToPointNetDevice的數據傳輸率從每秒5Mbits降到了每秒32768bits
如果我們採用命令行來改用一個新的DataRate,能夠加速我們的仿真速度。我們可以根據幫助文檔中指明的規則,按照下面的方式來做:
  ./waf --run "scratch/myfirst --ns3::PointToPointNetDevice::DataRate=5Mbps"

這個將DataRate屬性的默認值設置回每秒5Mbits。你對結果是不是感到很驚訝?爲了設置回腳本最初的行爲,我們必須將信道設成光速的延遲。我們可以讓命令行系統按照我們剛爲網絡設備做的那樣顯示出信道屬性:
  ./waf --run "scratch/myfirst --PrintAttributes=ns3::PointToPointChannel"

我們發現信道的Delay屬性是通過下面這種方法設置的,
  --ns3::PointToPointChannel::Delay=[0ns]:
    Transmission delay through the channel

我們可以通過命令行來設置這兩個默認值。
  ./waf --run "scratch/myfirst
    --ns3::PointToPointNetDevice::DataRate=5Mbps
    --ns3::PointToPointChannel::Delay=2ms"

這樣在腳本中精確地設置好了DataRateDelay,我們會重新得到以前的時間:
  Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
  Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
  'build' finished successfully (0.417s)
  0s UdpEchoServerApplication:UdpEchoServer()
  1s UdpEchoServerApplication:StartApplication()
  Sent 1024 bytes to 10.1.1.2
  2.00369s Received 1024 bytes from 10.1.1.1
  2.00369s Echoing packet
  Received 1024 bytes from 10.1.1.2
  10s UdpEchoServerApplication:StopApplication()
  UdpEchoServerApplication:DoDispose()
  UdpEchoServerApplication:~UdpEchoServer()

這樣,仿真恢復到了在2.00369秒服務器端收到數據包。我們可以用這樣的方法來設置腳本中的任何屬性。特別的我們可以將UdpEchoClient接收到的MaxPackets屬性設置爲1以外的其他值。
下面請讀者嘗試一下。記住必須要註釋掉我們重載默認屬性的地方,並且設置的MaxPackets屬性。還必須重新編譯腳本。你必須使用命令行的幫助功能來找到設置新的默認屬性值得語法格式。一旦設置好,就可以從命令行控制回顯數據包數目。作爲例子,我們這裏給出了命令行的設置。
  ./waf --run "scratch/myfirst
    --ns3::PointToPointNetDevice::DataRate=5Mbps
    --ns3::PointToPointChannel::Delay=2ms
    --ns3::UdpEchoClient::MaxPackets=2"

 

5.2.2 鉤掛自己的參數值

你可以在命令行系統中增加自己的鉤子。可以通過使用命令分析器中的AddValue方法非常簡單的實現。
我們用與以前一個完全不同的方法即鉤掛的方法來指定回顯數據包數。首先我們增加一個局部變量nPacket。我們將其默認值初始化爲1,以便和以前的情形保持一致。爲了允許命令行分析器來改變這個值,我們需要將這個值鉤掛到分析器上。我們需要增加一個AddValue調用。現在修改scratch/myfirst.cc腳本,將以下面的代碼放在開始處,
  int
  main (int argc, char *argv[])
  {
    uint32_t nPackets = 1;

 

    CommandLine cmd;
    cmd.AddValue("nPackets", "Number of packets to echo", nPackets);
    cmd.Parse (argc, argv);

 

    ...

 

向下拉到我們設置MaxPackets屬性的地方並把它來從1改到nPacket,如下所示,
  echoClient.SetAttribute ("MaxPackets", UintegerValue (nPackets));
現在可以運行腳本,並且採用了--PrintHelp參數,你需要在幫助列表中查看新User參數。
嘗試,
  ./waf --run "scratch/myfirst --PrintHelp"

 

  Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
  Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
  'build' finished successfully (0.403s)
  --PrintHelp: Print this help message.
  --PrintGroups: Print the list of groups.
  --PrintTypeIds: Print all TypeIds.
  --PrintGroup=[group]: Print all TypeIds of group.
  --PrintAttributes=[typeid]: Print all attributes of typeid.
  --PrintGlobals: Print the list of globals.
  User Arguments:
      --nPackets: Number of packets to echo

如果你想指明回顯數據包個數,可以在命令行設置nPackets屬性,
  ./waf --run "scratch/myfirst --nPackets=2"

 

你應該會看到
  Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
  Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
  'build' finished successfully (0.404s)
  0s UdpEchoServerApplication:UdpEchoServer()
  1s UdpEchoServerApplication:StartApplication()
  Sent 1024 bytes to 10.1.1.2
  2.25732s Received 1024 bytes from 10.1.1.1
  2.25732s Echoing packet
  Received 1024 bytes from 10.1.1.2
  Sent 1024 bytes to 10.1.1.2
  3.25732s Received 1024 bytes from 10.1.1.1
  3.25732s Echoing packet
  Received 1024 bytes from 10.1.1.2
  10s UdpEchoServerApplication:StopApplication()
  UdpEchoServerApplication:DoDispose()
  UdpEchoServerApplication:~UdpEchoServer()

從日誌輸出中我們可以看到已經回顯了兩個數據包。一切都非常簡單吧!
通過以上的介紹我們可以看出:如果你是ns-3用戶,你就可以使用命令行參數系統來控制全局變量和對象屬性。如果你是一個模型作者,你可以爲你的對象增加新屬性,而模型的用戶可以通過命令行系統來設置這些新屬性的值。如果你是腳本作者,你可以爲你的腳本增加新變量,同時輕易的將它們鉤掛在命令行系統下。

 

5.3 使用Tracing系統

整個仿真的目的是爲了進一步研究生成結果,ns-3 tracing系統就是爲了這個目的而制的。ns-3是一個c++程序,c++的標準輸入輸出設施在ns3種都可以使用:
  #include <iostream>
  ...
  int main ()
  {
    ...
    std::cout << "The value of x is " << x << std::endl;
    ...
  }

你甚至可以使用日誌模塊來爲你的解決方案增加小的結構。但這種方法會產生很多已知的問題,因此我們提供了一種生成事件tracing的子系統來解決我們認爲重要的問題。
The basic goals of the ns-3 tracing system are:
Ns-3 tracing系統的基本目標是:
·             對於基本的任務,tracing系統允許用戶爲常用的tracing發送端生成標準的tracing,可以定製哪些個對象生成tracing
·             中間用戶必須能夠能夠通過擴展tracing系統來修改生成的輸出格式,或是在不修改仿真器核心的情況下插入新的tracing發送端;
·             高級用戶可以修改仿真器的核心來增加新的tracing發送端和接收端。
Ns-3 tracing系統是建立在獨立的tracing發送端和tracing接收端的概念上的,並且有統一的機制來連接發送端和接收端。Trace發送端是可以在仿真過程中產生信號事件並且提供有關數據訪問通道。例如,一個trace發送端可以提供一個數據包被一個網絡設備接收的時間並且根據接收端的要求提供此數據包的內容。
Trace發送端自身是沒有用的,必須要跟接收端提供有用信息的代碼段相連Trace接收端是trace發送端提供數據和事件的使用者。例如,可以創建一個輸出接收數據包有用部分的trace接收端(當連接到之前例子的trace發送端)
這種發送端和接收端工作的基本原理是允許用戶給已有的tracing發送端關聯上新類型的接收端,而不需要編輯和重新編譯仿真器的核心。因此,以上面爲例,一個用戶可以在腳本中定義新的tracing接收端,並且可以將其關聯到仿真核心中定義的tracing接收端。
本教程中,我們將展示之前定義好的發送端和接收端,並且示範用戶怎樣輕易的定製它們。如需擴展tracing命名空間,和創建新tracing發送端的高級的tracing配置,請查看ns3手冊。

5.3.1 ASCII Tracing

 

ns-3提供了封裝底層tracing系統的幫助功能,用來提供配置簡單數據包trace得更多細節。如果你開啓了這個功能,將在ASCII文件中輸出結果,這就是爲什麼這種tracingASCII tracing。對於熟悉ns-2的用戶,這種trace類型是跟ns2生成的out.tr相類似的。
我們開始併爲我們的腳本增加一些ASCII tracing結果。
首先需要做的是在腳本的GNU GPL說明之後加上下面的包含語句:
  #include <fstream>

 

然後,在Simulator::Run()前增加下面的代碼:
  std::ofstream ascii;
  ascii.open ("myfirst.tr");
  PointToPointHelper::EnableAsciiAll (ascii);

前兩行只是很平常的C++代碼,用來打開一個將被寫入名爲myfirst.tr文件中的數據流。如果對這段代碼不熟悉,可以查看你所鍾愛的C++教程。代碼段中的最後一行代碼告訴ns-3在仿真中爲所有點到點設備啓用ASCII tracing功能;並且你想要用ASCII格式來寫出數據流中數據包的移動信息。類似於ns-2trace事件等同於流行的trace“+”“-”“d”“r”事件。
可以編譯腳本並用下面的命令行運行:
  ./waf --run scratch/myfirst

跟你之前看到很多次的一樣,你將看到來自Waf的信息和編譯成功信息。
腳本運行時,程序將創建一個名爲myfirst.tr的文件。由於Waf的工作方式,所以這個文件將不在本地目錄下創建,而是在ns3根目錄中創建。如果你想改變trace文件的保存目錄,你可以使用Waf--cwd選項來指定。而我們還沒有這麼做,因此我們需要轉到ns3的根目錄,並且用你喜歡的編輯器來查看ASCII trace文件myfirst.tr

5.3.1.1 分析Ascii Traces

 

在一個極其密集的文檔中有很多信息,但是需要注意的第一件事是在這個文件中有很多分立的行。除非你大大加寬你的窗口,否則是很難看清楚的。
每一行對應了一個trace事件。本例中我們在查看每個點到點設備的傳輸隊列的trace事件。傳輸隊列是任一個目的地爲點到點信道的數據包的必經隊列。注意trace文件的每行以一個單獨的字符開始(後面帶有空格)。這個字符具有如下含義:
·             +: An enqueue operation occurred on the device queue;
·             -: A dequeue operation occurred on the device queue;
·             d: A packet was dropped, typically because the queue was full;
·             r: A packet was received by the net device.

 

·             +:設備隊列中的入隊操作;
·             -:設備隊列中的出隊操作;
·             d:數據包被丟棄,通常因爲隊列已滿;
·             r:網絡設備接收到數據包。
我們來更詳細的看一下trace文件的第一行。爲了看得更清晰,我把這一行分成了不同的部分,並在左邊標出序號:
  00 +
  01 2
  02 /NodeList/0/DeviceList/0/$ns3::PointToPointNetDevice/TxQueue/Enqueue
  03 ns3::PppHeader (
  04   Point-to-Point Protocol: IP (0x0021))
  05   ns3::Ipv4Header (
  06     tos 0x0 ttl 64 id 0 protocol 17 offset 0 flags [none]
  07     length: 1052 10.1.1.1 > 10.1.1.2)
  08     ns3::UdpHeader (
  09       length: 1032 49153 > 9)
  10       Payload (size=1024)

 

展開後的trace事件的第一行(序號00)代表操作。+字符表示是一個傳輸隊列的入隊操作。第二行(序號01)是單位爲秒的仿真時間。你或許回憶起我們讓UdpEchoClientApplication在兩秒開始發送數據包。我們確定這個正在發生。
Trace的下一行(序號02)告訴我們trace發送端發起這個事件(tracing命名空間表示)。你可以認爲tracing命名空間有點像一個文件系統命名空間。命名空間的根爲NodeList。這個NodeListNS-3核心代碼管理的一個容器,此容器包含有一個腳本中創建的所有的節點。。正如一個文件系統在根下有目錄,在NodeList下有節點數。字符串/NodeList/0是指NodeList中第0個節點,我們通常認爲是"node 0".每個節點中有一個已經安裝好的設備列表。這個列表是在命名空間的下一個出現的。可以看到trace事件來自節點中安裝的第0個設備DeviceList/0
下一個字符串,$ns3::PointToPointNetDevice告訴我們第0個節點的設備列表的第0個位置的設備類型。回憶序號00處的+操作表示設備的傳輸隊列發生了入隊操作,這個在"trace path"TxQueue/Enqueue的最後部分反映出來了。
Trace中剩下的幾行是很直觀的。序號03-04處表明數據包封裝成點到點協議。序號05-07處顯示數據包IP版本,發送端IP地址10.1.1.1,接收端IP地址爲10.1.1.2。序號08-09出顯示數據包的UDP頭,最後序號10處表明數據包數據量爲1024bytes
trace文件中的下一行顯示了這個數據包在這個節點中從傳輸隊列中被移除。
Trace文件的第三行顯示了數據包正在被回顯服務器所在的節點的網絡設備接收。trace如下。
  00 r
  01 2.25732
  02 /NodeList/1/DeviceList/0/$ns3::PointToPointNetDevice/MacRx
  03   ns3::Ipv4Header (
  04     tos 0x0 ttl 64 id 0 protocol 17 offset 0 flags [none]
  05     length: 1052 10.1.1.1 > 10.1.1.2)
  06     ns3::UdpHeader (
  07       length: 1032 49153 > 9)
  08       Payload (size=1024)

 

注意,trace操作現在是r並且仿真時間已經增加到2.25732秒。如果你一直按照本教程來操作,你已經把網絡設備的DataRate,和信道Delay設置成默認值。那麼對於這個值,你應該覺得眼熟,因爲上一章中已經見過這個值。
在第2行中,Trace發送端命名空間條目已經改變,來顯示這個事件是來自節點1(/NodeList/1),即數據包的接收trace(/MacRx)。通過查看文件中其他的traces,你可以很容易的跟蹤數據包。

5.3.2 PCAP 格式Tracing

 

ns-3設備控制器也可以被用來創建.pcap格式的trace文件。縮寫pcap(通常爲小寫)表示packet capture,事實上是包含有定義一個.pcap文件格式的API。可以讀取並且顯示這種格式的最流行的程序是Wireshark(以前被稱爲Ethereal)。然而,有很多其他的分析器也使用這個包格式。我們鼓勵讀者瞭解其他的分析pcap追蹤文件的工具。在本教程中,我們用tcpdump來查看pcap trace
用來啓用pcap tracing的代碼只有一行,
  PointToPointHelper::EnablePcapAll ("myfirst");
scratch/myfirst.cc中我們剛增加的ASCII追蹤代碼後面插入這行代碼。注意我們剛使用的是字符串''myfirst"而不是"myfirst.pcap"。這是因爲這裏傳遞的參數是個前綴,而不是完整的文件名。在仿真過程中,helper將爲任何一個點到點設備創建一個追蹤文件。文件名將包含預設前綴,節點名,設備名,和".pcap"後綴。
在我們的例子腳本中,我們最終將看到名爲"myfirst-0-0.pcap""myfirst-1-0.pcap"。這分別是爲節點0設備0,和節點1設備0創建的pcap trace文件。
一旦你已經增加了啓用pcap tracing的代碼行,你可以以下面的方式來運行腳本:
  ./waf --run scratch/myfirst

 

如果你查看ns3根目錄,你將看到三個日誌文件:myfirst.tr是我們之前看到過的ASCII trace文件。Myfirst-0-0.pcapmyfirst-1-0.pcap是我們剛生成的新的pcap文件。

5.3.2.1 tcpdump讀取結果

 

此處最簡單的做法就是使用tcpdump來查看pcap文件,
  tcpdump -nn -tt -r myfirst-0-0.pcap
  reading from file myfirst-0-0.pcap, link-type PPP (PPP)
  2.000000 IP 10.1.1.1.49153 > 10.1.1.2.9: UDP, length 1024
  2.514648 IP 10.1.1.2.9 > 10.1.1.1.49153: UDP, length 1024

 

  tcpdump -nn -tt -r myfirst-1-0.pcap
  reading from file myfirst-1-0.pcap, link-type PPP (PPP)
  2.257324 IP 10.1.1.1.49153 > 10.1.1.2.9: UDP, length 1024
  2.257324 IP 10.1.1.2.9 > 10.1.1.1.49153: UDP, length 1024

myfirst-0-0.pcap(客戶端設備)文件中可以看到回顯數據包在第二秒被髮送。如果查看第二個文件(myfirst-1-0.pcap)可以看到此包在2.257324秒被收到。在第二個文件中可以看到在2.257324秒這個包被迴應,最終,在客戶端2.514648秒迴應的包被收到。

5.3.2.2 Wireshark讀取結果

如果你對Wireshark不熟悉,從http://www.wireshark.org/可以下載到程序和文檔。
Wireshark是一個可以用來顯示trace文件的用戶圖形接口。如果你安裝了Wireshark,可以打開和查看每一個trace文件,就像這些trace是使用包嗅探工具在真正的網絡上抓下來一樣。

    未完,待續! 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章