1. 程式人生 > >NS-3學習筆記 2

NS-3學習筆記 2

今天從《ns-3 tutorial》第4章開始。

4. 基本概念

在看或寫ns-3程式前,需要理解掌握一些概念和抽象問題。
It’s be recommended taking the time to read through this section just to ensure you’re starting on a firm foundation.

4.1 關鍵概念(Key Abstractions)

先介紹幾個網路中常用的詞,它們在NS3中有特定含義。
1.node(節點)
NS3不侷限於Internet模擬,所以用node表示網路中的主機或終端,而不是直接用host。node與圖論中的“點”概念類似。NS-3中把基本計算裝置都稱為node,並將這個抽象概念用C++類Node描述。Node類中有一些管理計算裝置行為的方法和屬性。
你可能已經開始考慮怎麼給Node上應用、協議棧、外設了,以便這個裝置能有效工作,但這是稍後才能考慮的事,但都是基於node模型展開的。
2.Application(應用)


計算機軟體通常劃分為:系統軟體和應用軟體。兩者直接的切分線往往是基於系統特權級別的變化。在NS-3中沒有OS的概念,也沒有特權級別或系統呼叫的概念,但有Application應用程式的概念。就像真實世界裡運行於計算機中的應用程式執行某個任務一樣,在模擬世界中運行於NS3 Nodes上的Applications也執行某個模擬。
NS-3裡,一個能產生某項模擬活動的使用者程式就被抽象地稱為Application。這個抽象被C++類Application所描述。Application類中包含了一些使用者級操作以執行模擬活動。在本文中,我們使用特殊的Application類——UdpEchoClientApplication和UdpEchoServerApplication類,構成一個C/S模擬網路。
3.Channel(通道)

傳遞資料的網路媒介(線纜/無線頻道等)被稱為channels。在NS-3中,連線一個node到一個通訊通道,就像你在現實中把電腦後的網線連到牆上乙太網插槽中一樣。NS-3中把基本的通訊子網(就是物理層與鏈路層)抽象為Channel,並用C++類Channel描述。
Channel類裡提供了一系列方法,用於管理通訊子網物件和連線節點。使用者可以根據基本的Channel類編寫自己特定Channel類,例如某線纜。特定的Channel也可以是大的以太交換機或用於無線網路的充滿障礙的三維通道空間。
本文中使用特定的Channel類CsmaChannel、PointToPointChannel和WiFiChannel,也就是典型的使用以太技術的動態接入共享通道、點對點通道、wifi通道。
4.Net Device(網路裝置)

通常連線一臺主機到網路,我們需要買網線和網絡卡(NICs),網絡卡這類裝置稱為device,device需要在驅動driver支援下工作。在NS-3中,net device這個概念包含了軟體dirver和硬體device。一個net device安裝在Node上,使Node可以經由Channel與別的Node通訊。
NS3中Net Device被抽象描述為C++類NetDevice,它提供了一些方法來管理Node物件與Channel物件的連線。
本文中將使用特殊的網路裝置類CsmaNetDevice,PointToPointNetDevice和WifiNetDevice(即乙太網卡類/點到點網絡卡類/wifi網絡卡類)。
5.Topology Helpers(拓撲工具)
真實世界裡主機中安裝著網路裝置,NS-3中,node連線著net device。在較大的網路模擬中,可能需要安排Nodes、Netdevices和Channels的許多連線,這個時候需要拓撲工具來規劃網路形態。
在NS-3中,連線node與netdevice、netdevice與channel、指定IP地址等工作,需要呼叫拓撲工具topology helpers,這會使任務變得簡單。例如:生成網路裝置、增加MAC地址、安裝裝置到node,配置node協議棧,連線netdevice到通道等等。

補充一句,上述C++類在ns-allinone-3.26/ns-3.26/src/network/model中。

4.2 第一個NS-3指令碼

下載ns-allinone-3.26之後,你會在ns-3.26中看到如下內容:
這裡寫圖片描述

切換工作環境到examples/tutorial中,你會看到一個叫first.cc的檔案。這個檔案是一個簡單的p2p網路模擬程式,它連線兩個nodes,並在節點間傳送一個數據包(echo)。下面我們逐行學一下first.cc

/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation;
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#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 ("FirstScriptExample");

int
main (int argc, char *argv[])
{
  CommandLine cmd;
  cmd.Parse (argc, argv);

  Time::SetResolution (Time::NS);
  LogComponentEnable ("UdpEchoClientApplication", LOG_LEVEL_INFO);
  LogComponentEnable ("UdpEchoServerApplication", LOG_LEVEL_INFO);

  NodeContainer nodes;
  nodes.Create (2);

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

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

  InternetStackHelper stack;
  stack.Install (nodes);

  Ipv4AddressHelper address;
  address.SetBase ("10.1.1.0", "255.255.255.0");

  Ipv4InterfaceContainer interfaces = address.Assign (devices);

  UdpEchoServerHelper echoServer (9);

  ApplicationContainer serverApps = echoServer.Install (nodes.Get (1));
  serverApps.Start (Seconds (1.0));
  serverApps.Stop (Seconds (10.0));

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

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

  Simulator::Run ();
  Simulator::Destroy ();
  return 0;
}

1.程式模板(Boilerplate)
第1行是個emacs風格行,告訴emacs格式轉換等編碼風格方面的資訊,
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
如果你要參與開發NS-3,那就得遵循相關編碼風格規範(具體在doc/codingstd.txt中)。建議在所有NS-3程式中都這麼寫,特別是使用emacs編輯器的。
第2~15行是NS-3採用的GNU General Public License的相關說明。
2.模組引用
第17-21行,是C++引用其他模組的include語句,說明first.cc中會用到這些庫:core-module、network-module、Internet-module、point-to-point-module、Application-module。引用了這些已有的庫,有利於我們快速構建自己的程式,不必重新發明輪子。這些標頭檔案放在build/ns3/下,如果我們開啟上述之一network-module.h看一看,會看到這樣的內容:

#ifdef NS3_MODULE_COMPILATION
# error "Do not include ns3 module aggregator headers from other modules; these 
are meant only for end user scripts."
#endif
#ifndef NS3_MODULE_NETWORK  
// Module headers:
#include "address-utils.h"
#include "address.h"
#include "application-container.h"
#include "application.h"
#include "ascii-file.h"
#include "ascii-test.h"
#include "buffer.h"
#include "byte-tag-list.h"
#include "channel-list.h"
#include "channel.h"
#include "chunk.h"
#include "crc32.h"
#include "data-rate.h"
......

說明這個標頭檔案包含了許多具體的網路相關標頭檔案,這並不是說first.cc會使用所有的庫,只是為了寫程式方面,雖然不太經濟。

  • core-module.h包含了src/core中的所有標頭檔案;
  • network-module.h包含了src/network中的所有標頭檔案
  • Internet-module.h包含了src/Internet中的所有標頭檔案
  • point-to-point-module.h包含了src/point-to-point中的所有標頭檔案
  • application-module.h包含了src/Application中的所有標頭檔案
    編譯後,這些標頭檔案會被放到build/ns3或build/debug或build/optimized目錄中,具體在哪取決於版本和你的配置,我這裡都在build/ns3中。

3.NS3名稱空間
第23行宣告使用ns3為名稱空間。NS-3的程式都在這個空間內。這個ns3空間與全域性名稱空間彼此分開,有助於同其他程式碼進行整合。這裡使用using語句將ns3引入當前全域性宣告域內。
4.日誌
第25行設定了日誌檔案引數。NS_LOG_COMPONENT_DEFINE (“×××”)設定了相關引數,ns3將建立一個名為FirstScriptExample的日誌元件,來記錄控制檯訊息。
5.主函式
從27行到最後,都是主函式內容了。

int main (int argc, char *argv[])聲明瞭函式
Time::SetResolution (Time::NS);設定了SetResolution(計時精度)為納秒,納秒是NS3中最小的計時單位,可以改變該設定為大一些的計時單位。如果不設定,則預設為納秒。

接下來兩行指令碼開啟了兩個日誌元件,分別建在Echo client和Echo Server application中:

LogComponentEnable(“UdpEchoClientApplication”, LOG_LEVEL_INFO);
LogComponentEnable(“UdpEchoServerApplication”, LOG_LEVEL_INFO);

6.拓撲工具
下面的兩行用於生成ns-3 node物件,代表了本次模擬的計算機。

NodeContainer nodes;
nodes.Create (2);

(1)NodeContainer類是一個拓撲工具類,它提供了一種方便的生成、管理和訪問node物件的方法。上面第一句是宣告一個NodeContainer物件nodes,然後用其creat方法生成兩個node物件。現在這些node還不能工作,我們需要將它們連成一個網路,最簡單的網路就是兩臺機器組成的點對點網。

(2)PointToPointHelper類也是一個拓撲工具類,它用於構建一個點對點網路。回憶一下net device和Channel的概念,在這裡我們需要使用點對點的net device和Channel。定義如下:

PointToPointHelper pointToPoint;
pointToPoint.SetDeviceAttribute (“DataRate”, StringValue (“5Mbps”));
pointToPoint.SetChannelAttribute (“Delay”, StringValue (“2ms”));

屬性DataRate是 PointToPointNetDevice 物件中的屬性,可以在幫助中查到,除此以外,還有多個裝置屬性可以設定。例如:Mac48Address 、Ptr< PointToPointChannel >、Ptr< Packet >、Ptr< Node >等很多。

(3)NetDeviceContainer是其中第三個拓撲工具類。它的物件用於管理網路裝置,這些網路裝置由PointToPointHelper物件生成、配置和安裝(安裝到node上)。

NetDeviceContainer devices;
devices = pointToPoint.Install (nodes); //這個方法以NodeContainer物件為引數,對於NodContainer物件nodes包含的每個node,一個點對點網路裝置被生成且保存於NetDeviceContainer物件devices中。一個PointToPointChannel物件被生成,且兩個PointToPointDevices被連線起來。

在pointToPoint.Install()方法被執行後,我們將有兩個節點,每一個都安裝了點到點網絡卡和連線他們的一條點到點通道,裝置和通道將使用上文配置的引數配置。
(4)InternetStackHelper是用於方便安裝和配置管理Internet協議棧的工具類。

InternetStackHelper stack;
stack.Install (nodes);//執行後,含有TCP、IP、UDP等協議的Internet stack將安裝到nodes中的每個node上。

(5)Ipv4AddressHelper是一個幫助我們設定IP地址的工具類。

Ipv4AddressHelper address;
address.SetBase (“10.1.1.0”, “255.255.255.0”);//設定了一個ip網路號和子網掩碼,意味著這個網路的ip地址從10.1.1.0~10.1.1.255.

ns3的底層實現會記錄所有已經分配的ip地址,如果出現重複生成同樣的ip地址段(使用setbase方法),就會報告一個fatal error,這個錯將很難除錯發現。
(6)Ipv4InterfaceContainer是一個用於分配和管理ip地址的工具類。Ipv4AddressHelper的物件address將ip地址分配給Devices,這些已分配地址的介面們可交給Ipv4InterfaceContainer物件管理。這有利於在需要列出所有介面時,統一呼叫。

Ipv4InterfaceContainer interfaces = address.Assign (devices);//實現ip地址的分配,devices中的device們,將按遞增順序獲得ip地址和子網掩碼,從10.1.1.1到10.1.1.2

7.應用程式(Application)
在本程式中使用了兩個特殊的Application類:UdpEchoServerApplication和UdpEchoClientApplication。在管理和配置Application時,還是用工具類來實現,這裡有兩個工具類:UdpEchoServerHelper and UdpEchoClientHelper。應用程式的工具類不是應用本身,只是幫助我們生成具體應用的。

UdpEchoServerHelper echoServer (9);//設定了埠號為9的應用程式echoServer
ApplicationContainer serverApps = echoServer.Install (nodes.Get (1));//將echoServer這個程式安裝到一個node上。這個install方法也是以NodeContainer物件為引數的。
serverApps.Start (Seconds (1.0));//程式要設定一個啟動時間,生成網路流量。NS3中的時間物件使用Seconds物件。
serverApps.Stop (Seconds (10.0));//程式可以設定一個停止時間,結束生成網路流量

UdpEchoClientHelper echoClient (interfaces.GetAddress (1), 9);//生成echoClient應用,並設定了兩個屬性:RemoteAddress=interfaces.GetAddress (1),即10.1.1.1,RemotePort=9
echoClient.SetAttribute (“MaxPackets”, UintegerValue (1));//設定了client在模擬中,傳送資料包最多為1個
echoClient.SetAttribute (“Interval”, TimeValue (Seconds (1.0)));//設定Interval,資料包傳送的時間間隔為1秒
echoClient.SetAttribute (“PacketSize”, UintegerValue (1024));//設定包的大小為1024位元組。
ApplicationContainer clientApps = echoClient.Install (nodes.Get (0));//將應用echoClient安裝到節點上,同時建立clientApps管理所有客戶端應用程式。

上面對於echo client程式設定了5個屬性:“RemoteAddress” 、“RemotePort”、 “MaxPackets”、 “Interval”、”PacketSize”。
8.模擬器
設定完nodes、net devices、channels、applications、protocols等之後,下面啟動模擬。
之前已經設定了應用程式的啟動特性:

serverApps.Start (Seconds (1.0));//在第1秒啟動伺服器端所有程式
serverApps.Stop (Seconds (10.0));//在第10秒關閉伺服器所有程式
clientApps.Start (Seconds (2.0));//在第2秒啟動客戶端所有程式
clientApps.Stop (Seconds (10.0));//在第10秒關閉客戶端所有程式

之後執行run方法,執行模擬。根據程式中的排程,第1秒執行伺服器應用echoServer,第2秒客戶端程式echoClient啟動,發出一個數據包,到第10秒兩個程式結束執行。模擬執行完畢後執行destroy方法結束模擬。

Simulator::Run ();
Simulator::Destroy ();

ns-3是一個離散事件模擬器,每個事件與它執行的時間相聯絡,模擬過程以時間為序依次執行各個事件。當某個事件執行時,他可能生成0 、1或多個其他事件。當所有事件都按順序執行完畢時,模擬過程將自動停止,或者在事件執行中如有Stop事件(Simulator:Stop(stopTime))出現,模擬過程也會停下來。一些事件是無限迴圈的,例如FlowMonitor、RIPng、RealtimeSimulator等,這些事件需要使用Stop停止。

9.編譯你的指令碼
當寫完指令碼的原始碼後,可以把指令碼放到scratch目錄中,之後執行waf命令就可以自動編譯了。例如將 examples/tutorial/first.cc拷貝到scratch中,改名為myfirst.cc,然後回到ns-3.26工作目錄下,執行waf:
這裡寫圖片描述
可以看到,build finished successfully。之後,執行myfirst模擬程式:
命令為./waf –run scracth/myfirst
這裡寫圖片描述

4.3 NS-3原始碼

第4章看完了,明天看第5章。