基于NS3仿真的三种网络互联接口的TCP吞吐性能分析
1. 三种类型网络互联接口
1)P2P的有线网络连接是两个终端直接建立有线连接,不经过中继设备直接交换数据或服务,连接方式如图1(a)。
2)总线型的网络连接是采用单根传输线作为总线,所有工作站都共用一条总线,总线中任一节点发生故障不会造成整个网络的瘫痪,连接方式如图1(b)。
3)无线型网络是两个终端不通过电缆等有线方式,将无线电波作为载波和物理层的网络建立节点之间的连接,连接方式如图1©。
2. 网络仿真设计
本次仿真首先建立的是两个终端间的线路连接,所以用NS3中的NodeContainer类创建两个节点并为其配置IP地址,数据源的IP地址为10.1.1.2,另一终端的IP地址为10.1.1.1。
2.1 创建链路
基于三种网络互联接口,本次实验定义了以下三种链路类型:
- P2P有线网络链路
首先定义链路类型为PointToPoint,且将设备的传输速率定义为5Mbps和信道的延时定义为2ms。最后将定义好的链路安装到先前创建的节点上。 - 总线型链路
总线型链路的设置与P2P有线网络有所不同,其数据传输都是在一根总线上,所以配置传输速率大小的时候,需配置的是信道最大传输速率,将其定义为5Mbps,此外信道时延定义为2ms。最后将链路安装到节点上。 - WIFI无线链路
WIFI无线模块设置的参数包括无线链路标准、发送数据速率和模式、信道频率、信道速率等,与之前两种方式相比较为复杂。首先初始化信道,参数设置为默认值,无线链路标准被设置为802.11b,采用的是2.4GHz的频段,传输速率在不同噪声条件下可以变为1Mbp、2Mbps、5.5Mbps、11Mbps等。紧接着就是初始化wifi物理层和设置Mac层,本次报告采用的是adhoc模式的Mac层,这种Mac层是没有QoS保障,容易受到物理安全的攻击,最后将协议安装到wifi的物理层、Mac层和节点上。此外设置了两个节点的位置,在三维空间中,一个节点安于(0,0,0),另一个节点安于(5,5,5)的位置中。
2.2 应用服务安装
本次仿真首先建立的是两个终端间的线路连接,接收端使用NS3中的PacketSink类为节点安装应用服务,负责接受和消耗生成到该IP地址和端口的流量,发送端用OnOffApplication类创建协议仿真的CBR源,这种信源可为单个目的地生成流量,但是其发送状态和停止状态默认情况下是会交替,所以将其OnTime和OffTime属性分别设置为1和0,能保持信源一直处于发送状态。并且将发送端和接受端都设置为TCP协议传输,配置完应用服务后就将两者安装到DeviceContainer节点上。
2.3 其他配置
在本次仿真中,引入了拥塞控制,设置控制TCP拥塞算法为WestWood,并设置信源的丢包率为0.01,在发生拥塞时,输出提示信息。设置发包起点时间为1s,结束时间为9s,记录仿真过程中数据传输的数据,并生成trace文件。然后用gawk处理NS3的trace文件,一个数据包的传输记录下三种事件,对应为“入发送对列”、“出发送队列”以及“到达接受节点”,本文以一段时间内的数据包长度加起来,除以这一段时间长度作为当前时间的平均吞吐量。
3. 仿真结果与分析
在Ubuntu系统中利用NS3仿真软件,对以上三种网络结构进行仿真(程序见附录,程序1),生成trace文件,每一行代表一种事件,本文只取事件“r”,即指数据包到达接受节点,具体数据如图3.1
假设收到N个包,则共计算N次,最后一次作为这段时间的平均吞吐量。由于设置了丢包率,因此收到的包的id会存在不连续的情况,所以引入一个变量cnt,记录当前收到包的数据(程序见附录,程序2),然后用gnuplot,根据提取出的数据绘制出吞吐量变化的图形,如图3.3:
上图中,横坐标代表的是时间t,纵坐标表示的是吞吐量的大小,单位为kbit/s。从上面三张图中,可以观察出,当设置信道速率为5Mbps,信源速率为54Mbps时,从吞吐量大小上来看,只有P2P网络结构的吞吐量能达到5000k bit/s,而WIFI网络结构的吞吐量次之,只有3000k bit/s,总线型网络的吞吐量最差,只达到了1000k bit/s。而从时间上来看,P2P和CSMA网络结构大约在三秒的时候,吞吐量到达了顶峰值,而WIFI型网络结构大约在五秒的时候才到达顶峰,可见有线型网络的吞吐量增加速度大于无线型网络的速度。
修改信源发送数据速率为1Mbps,比较在其他情况下,三种网络结构的吞吐量性能差异,绘制图如图3.3。从图中可以看出,在低速率下三者差别都不大,都在1000kbit/s左右,但是总线型的值还是相对而言低一些。

4. 附录–程序
NS3的仿真程序,生成P2P、CSMA、WIFI的追踪文件
#include <iostream>
#include <fstream>
#include <ns3/flow-monitor-helper.h>
#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"
#include "ns3/csma-module.h"
#include "ns3/yans-wifi-helper.h"
#include "ns3/mobility-helper.h"
#include "ns3/ipv4-address-helper.h"
#include "ns3/yans-wifi-channel.h"
#include "ns3/mobility-model.h"
#include "ns3/error-model.h"
using namespace ns3;
NS_LOG_COMPONENT_DEFINE ("TcpTestOverNets");
static void RxDrop(Ptr<const Packet> p)
{
NS_LOG_UNCOND("Drop at " << Simulator::Now().GetSeconds());
}
int main (int argc, char *argv[])
{
bool p2p = true;
bool cs = true;
double error_p = 0.01;
CommandLine cmd;
cmd.AddValue ("p2p", "enable P2P link", p2p);
cmd.AddValue ("cs", "enable CSMA link", cs);
cmd.Parse (argc, argv);
Time::SetResolution (Time::NS);
//LogComponentEnable ("UdpEchoClientApplication", LOG_LEVEL_INFO);
//LogComponentEnable ("UdpEchoServerApplication", LOG_LEVEL_INFO);
Config::SetDefault("ns3::TcpL4Protocol::SocketType", StringValue("ns3::TcpWestwood"));
NodeContainer nodes;
nodes.Create (2);
NetDeviceContainer devices;
PointToPointHelper pointToPoint;
CsmaHelper csma;
WifiHelper wifi;
YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default ();
if (p2p)
{
pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
devices = pointToPoint.Install (nodes);
}
else if (cs) {
csma.SetChannelAttribute ("DataRate", StringValue ("5Mbps"));
csma.SetChannelAttribute ("Delay", StringValue ("2ms"));
devices = csma.Install (nodes);
}
else
{
wifi.SetStandard (WIFI_PHY_STANDARD_80211b);
// This is one parameter that matters when using FixedRssLossModel
// set it to zero; otherwise, gain will be added
//wifiPhy.Set ("RxGain", DoubleValue (0) );
// ns-3 supports RadioTap and Prism tracing extensions for 802.11b
//wifiPhy.SetPcapDataLinkType (WifiPhyHelper::DLT_IEEE802_11_RADIO);
YansWifiChannelHelper wifiChannel;
wifiChannel.SetPropagationDelay ("ns3::ConstantSpeedPropagationDelayModel");
// The below FixedRssLossModel will cause the rss to be fixed regardless
// of the distance between the two stations, and the transmit power
wifiChannel.AddPropagationLoss ("ns3::FixedRssLossModel","Rss",DoubleValue (-80));
wifiPhy.SetChannel (wifiChannel.Create ());
// Add a mac and disable rate control
WifiMacHelper wifiMac;
//wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager",
// "DataMode",StringValue (phyMode),
// "ControlMode",StringValue (phyMode));
// Set it to adhoc mode
wifiMac.SetType ("ns3::AdhocWifiMac");
devices = wifi.Install (wifiPhy, wifiMac, nodes);
// Note that with FixedRssLossModel, the positions below are not
// used for received signal strength.
MobilityHelper mobility;
Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
positionAlloc->Add (Vector (0.0, 0.0, 0.0));
positionAlloc->Add (Vector (5.0, 5.0, 5.0));
mobility.SetPositionAllocator (positionAlloc);
mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
mobility.Install (nodes);
}
InternetStackHelper stack;
stack.Install (nodes);
//设置丢包率
Ptr<UniformRandomVariable> uv = CreateObject<UniformRandomVariable> ();
uv->SetStream (50);
RateErrorModel error_model;
error_model.SetRandomVariable (uv);
error_model.SetUnit (RateErrorModel::ERROR_UNIT_PACKET);
error_model.SetRate (error_p);
devices.Get(1)->SetAttribute("ReceiveErrorModel", PointerValue (&error_model));
devices.Get(1)->TraceConnectWithoutContext ("PhyRxDrop", MakeCallback (&RxDrop)); //关联回调函数
Ipv4AddressHelper address;
address.SetBase ("10.1.1.0", "255.255.255.0");
Ipv4InterfaceContainer interfaces = address.Assign (devices);
NS_LOG_INFO ("Create applications.");
//
uint16_t port = 50000;
Address localAddress (InetSocketAddress (Ipv4Address::GetAny (), port));
PacketSinkHelper packetSinkHelper ("ns3::TcpSocketFactory", localAddress);
//packetSinkHelper.SetConstantRate(DataRate("500kb/s"))
ApplicationContainer app = packetSinkHelper.Install (nodes.Get (0));
app.Start (Seconds (1.0));
app.Stop (Seconds (10.0));
//
// Create OnOff applications to send TCP to the hub, one on each spoke node.
//
OnOffHelper onOffHelper ("ns3::TcpSocketFactory", Address ());
onOffHelper.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]"));
onOffHelper.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
onOffHelper.SetAttribute ("PacketSize", UintegerValue(1024));
onOffHelper.SetAttribute ("DataRate", StringValue("54Mbps"));
ApplicationContainer cApps;
AddressValue remote (InetSocketAddress (interfaces.GetAddress (0), port));
onOffHelper.SetAttribute ("Remote", remote);
cApps.Add (onOffHelper.Install (nodes.Get(1)));
cApps.Start (Seconds (1.0));
cApps.Stop (Seconds (10.0));
NS_LOG_INFO ("Enable pcap tracing.");
NS_LOG_INFO ("Configure Tracing.");
AsciiTraceHelper ascii;
//
// Do pcap tracing on all point-to-point devices on all nodes.
//
if (p2p){
pointToPoint.EnableAsciiAll (ascii.CreateFileStream ("hc-p2p.tr"));
pointToPoint.EnablePcapAll ("hc-p2p");
}
else if(cs){
csma.EnableAsciiAll (ascii.CreateFileStream ("hc-csma.tr"));
csma.EnablePcap ("hc-csma", devices, true);
}
else{
wifiPhy.EnableAsciiAll (ascii.CreateFileStream ("hc-wifi.tr"));
wifiPhy.EnablePcap ("hc-wifi", devices);
}
NS_LOG_INFO ("Run Simulation.");
Simulator::Run ();
Simulator::Destroy ();
NS_LOG_INFO ("Done.");
return 0;
}
在运行本程序的时候,若要仿真P2P则加入参数 --p2p=1,仿真CSMA则加入参数–p2p=0 --cs=1,仿真WIFi加入参数–p2p=0 --cs=0。完成上面三个仿真后,能生成hc-p2p.tr,hc-csma.tr,hc-wifi.tr三份追踪文件。
用gawk处理ns3的tr格式trace文件计算吞吐量,未安装gawk的先去安装gawk
然后用throughput.awk脚本对tr文件进行处理,参考代码如下:
BEGIN {
init=0;
cnt = 0;
FS="[() \t]";#field seperator is ')' or'('or ' '
myScrIP = "10.1.1.2";
myDstIP = "10.1.1.1"
}
{
action = $1;
time = $2;
namespace=$3;
for (i=1;i<=NF;i++){
if ($i ~ /id/)
myPacketID = $(i+1);
else if ($i ~ /length:/)
myLength = $(i+1);
else if ($i ~ />/){
srcIP = $(i-1);
dstIP = $(i+1);
if(match(srcIP, myScrIP) && match(dstIP, myDstIP) )#link matches
{
packet_id = myPacketID;
pktsize = myLength;
#record send time of the packet
if (start_time[packet_id]==0)
{
start_time[packet_id]=time;
}
if (action=="r")
{
if(end_time_packet[packet_id] ==0 )#the first time we receive this packet
{
end_time_packet[packet_id] = time;#record time according to id
packetCNT[packet_id]=cnt;
pkt_byte_sum[cnt+1]=pkt_byte_sum[cnt]+ pktsize;
end_time[cnt]=time;
cnt++;
}
else
{
end_time[packetCNT[packet_id]]=time;
}
}
}
}
}
}
END {
printf("%s\t%s\n", end_time[0], 0);
for(j=1 ; j<cnt;j++){
throughput = (pkt_byte_sum[j] / (end_time[j] - start_time[0]))*8/1000;
printf("%s\t%s\n", end_time[j], throughput );
}
}
处理tr文件方法
gawk -f throughput.awk hc-wifi.tr > hc-WIFI
生成的hc-WIFI用gnuplot来绘出结果即可