一,流量模型原理
负指数分布有着无记忆性、极端值概率小的特点,常用于假定排队系统中服务器的服务时间;由于计算和通信在数据并行中交替进行,因此这种流量对于应用来说是现实的,如:网站访问的时间间隔。
1,负指数分布的on+off时间
onoffapp启动时间点为NextStartTime,每条流的on+off总时间为totaltime,流启动时间NextStartTime=NextStartTime+totaltime,从而实现单个节点的多次发流。
totaltime服从以on/offload为平均值的负指数分布,具有随机性;
2,负载计算
在大量实验中,原本随机的onoff模型会满足:totaltime=on/offload,即负载offload=on/totaltime;这是一种从时间角度刻画的负载程度,onoffapp以接入链路带宽的全速去发送流量,全速发流的时间on,占此APP的on+off总时间totaltime的比例,即负载的值。
3,总体效果
网络注入速率服从负指数分布,且大量实验后的平均值趋近于链路带宽乘以负载(0.1-1.0)。
二,ns-3实现
1,变量组及注释
ns-3中生成指数分布的随机数,需要使用ExponentialRandomVariable
类,头文件需要#include “ns3/random-variable-stream.h”
#include "ns3/random-variable-stream.h"
//exponentapp
double offerload=0.1;//负载0.1-1.0
double run_time=0.1;//单个节点onoffapp总运行时间
void ExponentApp();
int packetSize = 1024;//数据包字节大小
uint32_t RandDestNum=1;//随机目的节点个数
uint32_t bigFlowRate=10;//大流所占百分比
uint64_t RandFlowSize();//生成随机大小的大小流
double appSendRate = 1024*1024*1024*10.0;//APP发送速率,10Gbps
uint32_t port[10000];
uint32_t src;//源节点号
uint32_t dest;//目的节点号
2,目的节点sinkapp安装
使用UDP协议可以仅在每个节点安装一次sinkapp;TCP协议由于每个连接需要端口号不同,需要在clientapp安装时更新端口号,安装多个sinkapp。
for(uint32_t i = 0; i < numofHost; i++)
{
Address sinkLocalAddress (InetSocketAddress (Ipv4Address::GetAny (), port[i]));
PacketSinkHelper sinkHelper ("ns3::UdpSocketFactory", sinkLocalAddress);
ApplicationContainer sinkApp = sinkHelper.Install (hostNodes.Get(i));
sinkApp.Start (Seconds (0.0));
sinkApp.Stop (Seconds (100.0));
}
3,源和目的节点循环
源节点遍历全部host节点,目的节点随机生成,范围0~(numofhost-1)。确认源和目的节点后,将NextStartTime置0,保证所有节点均从0时刻开始流量传输。
for(uint32_t src=0;src<numofHost;src++){
for(uint32_t i=0;i<RandDestNum;i++){
do{
dest = rand()%numofHost;
}while(src == dest);
double NextStartTime = 0;
}
}
4,负指数分布totaltime
首先计算发送一个数据包所需时间sendf;
double sendf = packetSize*8/appSendRate;//发送一个数据包所需时间
生成以sendf/offload为平均值的负指数分布的随机时间,该随机时间乘以流的数据包个数即为负指数分布的totaltime。
while(run_time >= NextStartTime){
uint64_t flowsize = RandFlowSize();
uint64_t packetnum = flowsize/packetSize;
// 负指数分布的on+off时间
double mean = sendf/offerload;
ns3::Ptr<ns3::ExponentialRandomVariable> expVar = ns3::CreateObject<ns3::ExponentialRandomVariable> ();
expVar->SetAttribute ("Mean", ns3::DoubleValue (mean));
double totalTime = packetnum * expVar->GetValue();
OnOffHelper clientHelper1 ("ns3::UdpSocketFactory", Address ());
clientHelper1.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]"));
clientHelper1.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
clientHelper1.SetAttribute ("DataRate", DataRateValue (DataRate ("10Gbps")));
clientHelper1.SetAttribute ("PacketSize", UintegerValue (packetSize));
clientHelper1.SetAttribute ("MaxBytes", UintegerValue (flowsize));
std::cout << "At " << NextStartTime << " time " << src << "->" << dest << " : " << flowsize << std::endl;
ApplicationContainer clientApps1;
AddressValue remoteAddress (InetSocketAddress (ipEH[dest].GetAddress(1), port[dest]));
clientHelper1.SetAttribute ("Remote", remoteAddress);
clientApps1.Add (clientHelper1.Install (hostNodes.Get (src)));
clientApps1.Start (Seconds (NextStartTime));
clientApps1.Stop (Seconds (10.0));
NextStartTime = NextStartTime + totalTime;
}
发送数据流的app启动时刻以totaltime为间隔,保证了随机性。
5,随机大小流生成
生成1~100范围的随机数,如果该随机数小于大流比例的数值,则生成10~20MB大流,否则生成100KB~1MB小流;大小流数值范围可调,且服从均匀分布。
uint64_t RandFlowSize(){
uint32_t RandomNumber = 0;
uint64_t FlowRandBytes = 0;
RandomNumber= ((rand() % 100) + 1);
if(RandomNumber <= bigFlowRate){
FlowRandBytes = ((rand() % (20*1024 - 10*1024)) + 10*1024 + 1)*packetSize;//10-20MB大流
}
else{
FlowRandBytes = ((rand() % (1024 - 100)) + 100 + 1)*packetSize;//100KB-1MB小流
}
return FlowRandBytes;
}
三,流量模型实现代码
#include "ns3/random-variable-stream.h"
//exponentapp
double offerload=0.25;
double run_time=0.01;
void ExponentApp();
int packetSize = 1024;
uint32_t RandDestNum=1;//随机目的节点个数
uint32_t bigFlowRate=10;// %
uint64_t RandFlowSize();
double appSendRate = 1024*1024*1024*10.0;//10Gbps
uint32_t port[10000];
uint32_t src;
uint32_t dest;
...
void ExponentApp(){
double sendf = packetSize*8/appSendRate;//发送一个数据包所需时间
for(uint32_t i = 0; i < numofHost; i++)
{
Address sinkLocalAddress (InetSocketAddress (Ipv4Address::GetAny (), port[i]));
PacketSinkHelper sinkHelper ("ns3::UdpSocketFactory", sinkLocalAddress);//TCP协议下考虑安装多个端口号不同的sinkapp
ApplicationContainer sinkApp = sinkHelper.Install (hostNodes.Get(i));
sinkApp.Start (Seconds (0.0));
sinkApp.Stop (Seconds (100.0));
}
for(uint32_t src=0;src<numofHost;src++){
for(uint32_t i=0;i<RandDestNum;i++){
do{
dest = rand()%numofHost;
}while(src == dest);
double NextStartTime = 0;
while(run_time >= NextStartTime){
uint64_t flowsize = RandFlowSize();
uint64_t packetnum = flowsize/packetSize;
// 负指数分布的on+off时间
double mean = sendf/offerload;
ns3::Ptr<ns3::ExponentialRandomVariable> expVar = ns3::CreateObject<ns3::ExponentialRandomVariable> ();
expVar->SetAttribute ("Mean", ns3::DoubleValue (mean));
double totalTime = packetnum * expVar->GetValue();
OnOffHelper clientHelper1 ("ns3::UdpSocketFactory", Address ());
clientHelper1.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]"));
clientHelper1.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
clientHelper1.SetAttribute ("DataRate", DataRateValue (DataRate ("10Gbps")));
clientHelper1.SetAttribute ("PacketSize", UintegerValue (packetSize));
clientHelper1.SetAttribute ("MaxBytes", UintegerValue (flowsize));
std::cout << "At " << NextStartTime << " time " << src << "->" << dest << " : " << flowsize << std::endl;
ApplicationContainer clientApps1;
AddressValue remoteAddress (InetSocketAddress (ipEH[dest].GetAddress(1), port[dest]));
clientHelper1.SetAttribute ("Remote", remoteAddress);
clientApps1.Add (clientHelper1.Install (hostNodes.Get (src)));
clientApps1.Start (Seconds (NextStartTime));
clientApps1.Stop (Seconds (10.0));
NextStartTime = NextStartTime + totalTime;
}
}
}
}
uint64_t RandFlowSize(){
uint32_t RandomNumber = 0;
uint64_t FlowRandBytes = 0;
RandomNumber= ((rand() % 100) + 1);
if(RandomNumber <= bigFlowRate){
FlowRandBytes = ((rand() % (20*1024 - 10*1024)) + 10*1024 + 1)*packetSize;//10-20MB大流
}
else{
FlowRandBytes = ((rand() % (1024 - 100)) + 100 + 1)*packetSize;//100KB-1MB小流
}
return FlowRandBytes;
}