茹新宇,劉 淵
(1.江南大學 數字媒體學院,江蘇 無錫 214122;2.江蘇聯合職業技術學院 無錫交通分院,江蘇 無錫 214151)
仿真所固有的低成本、虛擬化優勢,使其成為極具吸引力的重要科研手段[1]。網絡仿真目前已是互聯網算法性能、協議拓撲最經濟快捷的評價方法之一。網絡仿真器主要通過部署虛擬環境,允許對特定節點或路徑模擬其網絡行為,并提供仿真結果,以便研究、參考或改進。借助仿真的高靈活度和可擴展性,不同網絡實體的協議算法、概念模型及其拓撲架構可在虛擬環境中搭建、測試并實施。現有工具,如QualNet、OPNET[2]和REAL等,由于使用條款、實施成本及代碼開源等因素而遠未普及。鑒于現場布置及情景再現等客觀條件,新網絡仿真器NS3應運而生。作為NS2的繼任者,它運用全新理念來解決和減輕NS2存在的問題,現已大量部署于實驗場景。它支持當前主流協議,為實驗提供仿真結果。
文中對NS3進行了深入探究,重點闡述了其TCP實現過程,并提出了具有前瞻性的研究方向。
NS系列仿真器是由UC Berkeley開發的優秀網絡仿真軟件,使用經典的Unix語言作為環境工具,在GNU/Linux平臺下開發[3]。為便于安裝、維護及更新,如今已被移植進Windows/Cygwin,BSD及Mac OSX等系統。NS2作為一款開源軟件,支持多種協議且易于擴展,但同時也存在較多問題。如它采用分裂對象模型,在OTcl中編寫腳本,仿真結果由NAM實現可視化,卻無法單純從C++運行。另外,網絡層抽象仿真,結果跟蹤困難,需借助解析文件提取,模型之間互操作及耦合性不足,分析工具“各自為政”。
目前仍在大規模開發的NS3項目始于2006年,它廣泛汲取主流仿真器NS2、YANS和GTNets的技術經驗,用C++語言實現,兼容時下流行的Python,目前已發展至3.26穩定版本。NS2部分模型已移植進NS3,使之在功能實現、版本更新、用戶體驗等方面都具有良好表現[4]。其核心及各功能模塊由C++代碼完成[5],對外提供豐富的擴展接口[6],可按需更改或增減模塊。NS3包含網絡組件模擬接口,擁有事件調度器,可通過執行相關事件,模擬真實通信“行為”。同時它還具備完美的跟蹤機制,便于用戶解析數據、傳輸過程及分析結果,詳細介紹如表1所示。

表1 NS3仿真器的優點與特點
NS2及其后繼者NS3具有相同背景、概念和類似目標,是一離散事件模擬器。雖然目前NS2仍有很大用戶群,但由于NS3的特征及設計優勢,使之日趨成為NS2的可靠替代品。它可較好地規避前者存在的問題,其協議和場景均用C++編寫。第三方軟件依賴和源代碼構建過程截然不同并優于NS2,系統集成度較好。兩者的部分特征對比如表2所示。
表3總結了現NS2已有模型與NS3計劃或已開發模型間的對比[7]。

表2 NS2與NS3的部分特征對比

表3 NS2與NS3的項目模型對比
NS3由一系列層次分明的功能模塊拼接而成,其組織結構及模塊間的基本依賴關系如圖1所示。

圖1 NS3的基本模塊體系結構
2.1.1常用模塊
Core:內核模塊,是NS3基本機制的實現,如智能指針(Ptr)、屬性(attribute)、回調(callback)、隨機變量(random variable)、日志(logging)、追蹤(tracing)和事件調度(event scheduler)等內容。
Network:數據分組(packet)模塊。
Internet:關于TCP/IPv4/6的相關協議族的實現,包括TCP/IPv4/6、ARP、UDP及鄰居發現等相關協議。
Topolopy-read:讀取指定軌跡文件數據,按指定格式生成相應網絡拓撲。
Protocol Status:協議框架模塊,收集、統計和分析數據。
另有,Tools:統計工具(包括gnuplot作圖接口);ApplicatioNS:應用模塊;Mobility:移動模塊;Visualizer:可視化工具;Netanim:動畫演示器;Propagation:傳播模型模塊;Flow-monitor:流量監控模塊等。
2.1.2典型模塊
CSMA:基于IEEE802.3以太網,包括MAC層、物理層和媒體信道。
Point-to-point:實現網絡間的點對點通信。
Wifi:基于IEEE802.11a/b/g無線網,包括AdHoc。
其他還有,Mesh:基于IEEE802.11s的無線網絡;Wimax:基于IEEE802.16的無線城域網;LTE:3GPP通用移動通信系統(UMTS)技術長期演進;UAN:水聲通信網絡;MPI:并行分布式離散事件標準信息傳遞接口;Click:集成可編程模塊化路由;Openflow:仿真交換機;Emu:集成實驗床和虛擬機環境等。
2.1.3最新技術
Waf是基于Python框架開發的編譯工具,NS3自身及將要執行的仿真代碼都由Waf編譯運行。Scratch目錄存放用戶腳本,運行案例可拷至該目錄。Example舉例如何使用NS3,內含許多模塊的使用。Doc目錄是幫助文檔,可使用./waf--doxygen編譯本地Doxygen文檔。Build編譯目錄,內含編譯文件時使用的共享庫和頭文件(build/NS3)。Src是NS3的源碼目錄。
模塊中的wscript文件結構固定,用來注冊模塊中的源碼和使用其他模塊情況。Model目錄包含模塊代碼的.cc和.h文件。Helper目錄存放模塊對應的helper類代碼的源文件。Test目錄包含原模塊測試代碼,而examples目錄存放應用該模塊的實例代碼。Doc是幫助文檔,bindings目錄則被模塊用來綁定Python語言。
NS3以較低層次的抽象來構造組件,模擬真實環境[8],其基本對象是節點、應用、信道和網絡設備等,由類表示或實現。
(1)節點(Node):網絡上所連接的基本計算單元或終端都抽象為節點,在C++中由Node類描述(如Nodeontainer類),用于追蹤一組節點指針。用戶可通過對節點添加應用、協議和網卡等進行二次開發[9]。
(2)應用(Application):被仿真的用戶程序抽象為應用。NS3以“Time”為參數,記錄接收和發送時間。在C++中抽象成Application類表示,實現時需繼承該類,將其部署在節點,驅動仿真器運行。由應用程序生成和回顯仿真數據包的客戶/服務器端程序集,如Application類稱為“UdpEchoClient Application”和“UdpEchoServer Application”。
(3)信道(Channel):基本的通信子網被抽象為信道。在C++中由Channel類描述,提供管理通信子網對象和節點連接至它們的各種方法。它可模擬簡單線纜、無線網,甚至以太網交換機。NS3包括Csma Channel、Point To Point Channel以及Wifi Channel等信道。
(4)網絡設備(NetDevice):硬件設備和軟件驅動的抽象表示,由C++的NetDevice類實現。通過綁定與類型匹配的信道,提供管理節點和信道對象連接。與信道對應,NetDevice也分為Csma NetDevice、Point To Point NetDevice和Wifi NetDevice等[10]。若需要一個所有被創建的NetDevice對象列表,則需用一個NetDeviceContainer對象來存放。
(5)分組(Packet):每個分組包含字節緩沖器、標簽和元數據。緩沖器是頭部和尾部的逐位串行表示,標簽則是任意用戶提供的數據結構的集合,而元數據可用以描述已序列化的頭和尾的類型。
(6)套接字(Socket):作為應用程序與網絡堆棧間的接口。NS3提供了兩種類型的套接字API,一是NS3API,二是使用本機API服務來提供類似POSIX的API,作為整個應用程序進程的一部分。
(7)拓撲幫助器(Topology Helper):NS3用Topology Helper類來整合大量分立步驟,使其成為一簡單易用的操作。由拓撲生成器調用底層核心完成節點、網絡設備、MAC地址、信道及協議棧等創建與配置。它可實現多節點連接及多子網聯網、分配IP地址等功能。如Topology Reader Helper類可簡化配置并使用通用Topology Reader。Internet Stack Helper是個安裝Point To Point Helper對象和點到點網絡設備的網絡協議棧的拓撲生成器類。
(8)典型容器助手(typical containers and helpers)。NS3分容器類和助手類,NodeContainer、NetDevice Container和Ipv4AddressContainer是不同容器類,而InternetStackHelper、WifiHelper、MobilityHelper和OlsrHelper則屬不同助手類。
NS3體系結構類似OSI模型,便于對網絡層次及協議仿真研究。數據按TCP/IP形式發送,以類方式實現。事件由節點觸發,當數據包到達節點,仿真器按事件預定的執行時間排序隊列、按步處理。數據包傳遞時,通過指針交互完成轉發,傳輸過程如圖2所示[11]。

圖2 NS3數據包傳輸過程
首先應用層創建數據包并通過套接字傳送至傳輸層(用套接字指針取代應用層指向該數據包)。在該層完成TCP或UDP頭的封裝后轉交至網絡層[12]。由該層判斷數據包的目的地址,若非當前節點則查詢路由,將數據包交至網絡設備層。該層查詢ARP,將數據包轉至指定接口,由該口將包發送至信道。信道通過入隊、鏈路延遲處理、TTL檢驗及出隊等完成數據包的發送。若出現隊列已滿或TTL生命期結束,則丟棄該包。當數據包經過信道傳輸到達目的節點后,再由網絡設備層開始逐層上傳,最后通過端口找到API套接字,并通過該套接字將包交由應用模塊處理。綜上所述,NS3的數據包傳輸過程與物理網絡類似,其仿真可信度較高。
NS3從拓撲建立開始,定義所選模型,而后通過設置參數、賦予地址來配置模型并執行代碼。仿真生成的Pcap包文件可采用trace格式跟蹤輸出,最后用Wireshark等工具跟蹤結果并分析數據,或由Net Anim來實現可視化輸出。其代碼創建過程如圖3所示。

圖3 NS3代碼體系結構
使用NS3進行網絡仿真時,一般需要4步:
(1)選擇或開發相應模塊;
(2)編寫仿真腳本(C++或Python)。包括:生成節點(如網卡、應用程序和協議棧等);安裝網絡設備(如CSMA、WiFi);安裝協議(一般TCP/IP及應用層協議);其他配置(如節點移動或能量管理等);
(3)啟動仿真器;
(4)仿真結果分析(包括輸出網絡場景和數據圖像等)。
NS3有兩類跟蹤:一是用Logging系統直接將執行過程顯示在命令行,有助于調試仿真腳本;另外常用Tracing系統將采集的數據直接存于一文件中,以便后期分析處理。
Logging系統從低到高可分7個等級,高的包含低的消息。通過.cc文件對程序添加記錄,通過環境變量修改系統等級,隨后終端運行。而Tracing系統則存儲大量信息,它包含3個基本概念:跟蹤源(Tracing Sources)、跟蹤宿(Tracing Sink)以及兩者的連接機制。該系統基于回調函數收集統計信息,當某跟蹤源產生一新事件,可通過回調了解其內部正在發生的模擬情形及設備運行狀況。
4.2.1TCP類及其相互作用
TCP類在網絡模型中與IPv4/6協議一起駐留,實現彼此通信的多個類與網絡層交互,并向應用層提供可靠的數據傳送。下面列出NS3中關于TCP實現的主要類別以及它們之間的相互作用,如圖4所示[13]。
TcpSocket:這個抽象類包含TCP套接字的基本屬性。
TcpSocketBase:此類為應用程序層提供了關鍵的TCP特性和一個套接字接口。它從TcpSocket繼承,用作所有TCP變體的基類。
Tcp Header:此類定義了TCP段的頭。
TcpTxBuffer:此類提供一個緩沖區,發送方在發送和確認之前,緩沖從應用程序接收的所有數據。
TcpRxBuffer:該類實現一個緩沖區,用于接收從網絡層收到的數據,然后將其傳遞給應用程序。
TcpL4Protocol:是TCP套接字和網絡層接口類,負責向網絡層收發數據包,并且負責傳入數據校驗和驗證。
除了上述主類外,NS3還包含了基于繼承TCP套接字的子類,可以實現多種變體。如Tcp Tahoe、Tcp Reno和Tcp NewReno及Tcp Westwood等。
4.2.2全局變量
現有的變體都是基于繼承TCP套接字的同一類實現的,它包括以下各全局變量,用以實現擁塞控制算法及其帶寬估計等。
m_cWnd是一uint32_t型變量,用于表示擁塞窗口。發送方用來確定可進入網絡而不致鏈路過載的字節數。當發生丟包時,使用m_cWnd來估計帶寬。
m_ssThresh也是uint32_t型變量,用于標記慢啟動結束門限閾值,其值取決于丟包時的鏈路帶寬估計。
m_initialcWnd是指定m_cWnd初值的uint32_t變量。
m_inFastRec是指示快速恢復開始和結束的布爾型變量。
m_prevAckNo類型為SequenceNumber32,用以保存最后接收到的ACK號。
m_accountedFor為uint32_t型變量,其在丟包時可跟蹤DUP ACK段數量,并在估計帶寬時使用。
m_lastAck是前一ACK到達時間的雙精度浮點型變量。
m_currentBW表示當前帶寬估計的雙精度浮點型變量。
m_minRtt是指定的最小RTT的時間類型變量。
m_lastBW是雙精度浮點型變量,其在通過Tustin濾波器之后,保存最后所估計的帶寬值。
m_lastSampleBW是雙精度浮點型變量,其保存測量帶寬的最后一個樣本值。
m_ackedSegments是整型變量,它保存當前RTT期間已確認的段的總數。
m_IsCount是一個布爾型變量,用于指示m_acked段計數過程的開始。
m_bwEstimateEvent是指定帶寬采樣事件類型EventId的變量。

圖4 TCP類圖一覽
4.2.3算法實現
NS3支持多種類型的TCP算法的實現,這些實現繼承自src/network目錄下的一些通用類,這樣用戶就能以最少的代價實現自己的算法。這里首先描述聚合的概念,在NS2中已廣泛使用的繼承和多態被用來擴展協議模型,如RenoTcpAgent就是通過重寫方法繼承自TcpAgent的,這促成了NS3的對象聚合系統。然后再介紹兩個重要的抽象基類:class TcpSocket,這在src/internet/model/tcp-socket. {cc,h}中定義。這個類主要用來管理能被不同算法重用的一些屬性。例如,屬性InitialCwnd可用于從TcpSocket類派生的任何實現。而class TcpSocketFactory則由協議的第4層實例使用,以創建正確的TCP套接字類型。
目前對于NS3,有四種方式實現TCP:NS3自帶的TCP實現;支持直接代碼執行(DCE);支持網絡模擬通訊座(NSC);虛擬機與NS3的組合。鑒于復雜程度,文中只介紹第一種實現方式。NS3自帶的TCP模型具有建立連接和關閉邏輯的雙向TCP功能。支持多種擁塞控制算法,如NewReno、Westwood、Hybla和HighSpeed等,暫不支持多路TCP和TCP SACK算法。
以前的擁塞控制被認為是通過繼承父類的獨立的TCP,每個擁塞控制(如NewReno)是TcpSocketBase的子類,需修改一些繼承的方法。但從NS3.25開始,TCP模塊經過了重新設計,其中擁塞避免、快速重傳與恢復算法已修改,并完成了在TcpSocketBase內的合并。架構被重做,以避免之前的繼承,讓每個擁塞控制都具有一個單獨的類,并且建立一個接口,用以在TcpSocketBase和擁塞模塊之間交換數據,可以為創建和執行自動化測試創造更好的環境。一般在src/applications/helper和src/network/helper中定義幫助函數,通過NS3使用套接字,在應用層設置TCP的使用,具體步驟及方法如下:
(1)創建TCP接收器。
// Create a packet sink on the star "hub" to receive these packets
uint16_t port=50000;
AddresssinkLocalAddress(InetSocketAddress
(Ipv4Address::GetAny (), port));
PacketSinkHelper sinkHelper("ns3::TcpSocketFactory", sinkLocalAddress);
ApplicationContainer sinkApp=sinkHelper.Install
(serverNode);
sinkApp.Start (Seconds (1.0));
sinkApp.Stop (Seconds (10.0));
類似的,以下代碼片段將OnOffApplication流量源配置為使用TCP:
//Create the OnOff applications to send TCP to the server
OnOffHelper clientHelper ("ns3::TcpSocketFactory", Address ());
這里已指定了抽象基類TcpSocketFactory的TypeId。NS3如何判斷腳本需要的是它自帶的TCP模型還是其他來源,當網絡堆棧添加到節點時,聚合到該節點的默認TCP實現是NS3TCP。因此,默認情況下,在使用NS3helper API時,聚合到具有Internet堆棧的節點的TCP是NS3TCP。
(2)配置TCP行為。
通過NS3屬性,系統導出參數,記錄在TcpSocket類的Doxygen中,例如最大段大小是可設置的屬性。要在創建任何Internet堆棧相關對象之前設置默認套接字的類型,可在仿真程序的頂部放置以下語句:
Config::SetDefault ("ns3::TcpL4Protocol::SocketType",StringValue ("ns3::TcpNewReno"));
(3)綁定Socket套接字。
對于用戶,希望有一個指向實際套接字的指針,需要用函數Bind()來綁定套接字。設置選項等可在每個套接字的基礎上完成,TCP的套接字可通過使用Socket::CreateSocket()的方法進行創建。傳遞給CreateSocket()的TypeId必須是類型ns3::SocketFactory。因此需要通過與底層TcpL4Protocol對象相關聯的屬性來完成底層套接字類型的配置,也可通過屬性配置系統完成。在下面的示例中,訪問節點容器“n0n1”以獲取第零個元素,并在此節點上創建綁定套接字。
// Create and bind the socket...
TypeId tid =TypeId::LookupByName("ns3::TcpNewReno");
Config::Set ("/NodeList/*/$ns3::TcpL4Protocol/SocketType", TypeIdValue (tid));
Ptr
(n0n1.Get(0), TcpSocketFactory::GetTypeId ( ));
上面節點號的“*”通配符被傳遞給屬性配置系統,以后所有節點上的套接字都被設置為NewReno,而不僅僅是節點'n0n1.Get(0)'了。如果想要將其限制為僅指定的節點,則必須執行以下操作:
// Create and bind the socket...
TypeId tid=TypeId::LookupByName
("ns3::TcpNewReno");
std::stringstream nodeId;
nodeId<
std::string specificNode="/NodeList/"+nodeId.str()+"/$ns3::TcpL4Protocol/SocketType";
Config::Set (specificNode, TypeIdValue (tid));
Ptr
(n0n1.Get(0),TcpSocketFactory::GetTypeId ());
一旦創建了TCP套接字,就需要遵循傳統的套接字邏輯以及connect()和send()(對于客戶端)或bind()、listen()和accept()(對于服務器端)。有關在NS3中使用套接字的信息,可以參閱Sockets API相關文獻[14]。
若要對已存在算法進行驗證,通常TCP測試從一個名為TcpGeneralTest的類繼承,該類提供了涉及TCP對象測試場景的操作設置,其位于src/internet/test目錄下。有關編寫新測試的更多信息,請參閱有關TCP測試文獻。一些測試存于src/test/ns3tcp目錄,其具有Internet模塊之外的依賴關系。更多信息可在NS3官網的Wiki頁面上找到。
NS3具有更好的開發環境(包括COM類接口聚合與查詢、自動內存管理及對象回調等核心功能),便于仿真全新的復雜模型。它克服了NS2的諸多缺陷和明顯弱點,越來越多的網絡仿真功能現已逐漸推行并植入到NS3中,使之適用于更多場景。文中結合項目開發經驗,從不同角度和深度對新一代網絡仿真器NS3作了較為全面的闡述與介紹,對其體系結構和主要功能模塊進行了深入剖析,尤其對NS3的TCP實現機制作了重點探究。為NS3的使用及研發者提供了較好的理論指導意義和應用參考價值,為網絡相關課題的后續研究及深入學習提供了強有力的支持。目前,NS3的一些新功能正在積極開發之中,如節點多接口處理、IP尋址以及更多的因特網協議設計,包括更詳細的802.11模型等都非常值得期待,NS3最終必將會取代NS2。
[1] 梁軍學,林昭文,馬 嚴.未來互聯網試驗平臺[J].計算機學報,2013,36(7):1364-1374.
[2] 袁 曉,蔡志平,劉書昊,等.大規模網絡仿真軟件及其仿真技術[J].計算機技術與發展,2014,24(7):9-12.
[3] 馬浩然.基于NS3的分布式消息系統Kafka的仿真實現[J].軟件,2015,36(1):94-99.
[4] FONT J L,IIGO P,DOMNGUEZ M,et al.Analysis of source code metrics from ns-2and ns-3network simulators[J].Simulation Modelling Practice & Theory,2011,19(5):1330-1346.
[5] RILEY G F,HENDERSON T R.Modeling & tools for network simulation[M].Berlin:Springer,2010.
[6] DAS B,SUBUDHI B,PATI B B. Cooperative formation control of autonomous underwater vehicles:an overview[J].International Journal of Automation and Computing,2016,13(3):199-225.
[7] RACHNA C,SHWETA S,RITA K,et al.A study of comparison of network simulator-3and network simulator-2[J].International Journal of Computer Science and Information Technologies,2012,3(1):3085-3092.
[8] 閔圣天,曾文序,李滿榮,等.基于NS3的網絡協議分析與模擬[J].福建電腦,2014,30(2):99-100.
[9] 張登銀,張保峰.新型網絡模擬器NS-3研究[J].計算機技術與發展,2009,19(11):80-84.
[10] 欒 俊,李太浩.基于NS-3的WiFi場景仿真[J].農業網絡信息,2012(1):18-20.
[11] 李廣榮.基于NS-3的虛實網絡結合系統的設計與實現[D].哈爾濱:哈爾濱工業大學,2015.
[12] 楊鳴亮,張嘉毅,孫 振,等.關于NS3中GRE仿真的研究[J].電子測量技術,2011,34(1):22-26.
[13] GANGADHAR S,NGUYEN T A N,UMAPATHI G,et al.TCP Westwood(+) protocol implementation in ns-3[C]//Proceedings of the6th international ICST conference on simulation tools and techniques.Brussels, Belgium:ICST,2013:167-175.
[14] 袁鵬飛,鄭 濤,楊李冬,等.一種基于CAPPROBE帶寬估計的TCP Westwood算法[J].廈門大學學報:自然科學版,2014,53(4):469-476.