Project1-ns3 模拟数据中心
实验要求
根据上面的数据中心拓扑图,完成以下要求:
1. 根据给定的数据中心的拓扑结构,利用 ns3 进行仿真
2. 模拟两种通信模式(traffic pattern)
o all-to-all:每个服务器都发送消息给其他服务器消息,由拓扑结构可知,超过 50%的消息
传送将跨越两个簇(cluster)
o many-to-one:每个服务器都发送消息给其中一个服务器
3. 测量两种模式下网络的仿真可以达到的吞吐量,找出网络瓶颈,并且说明如何改进
注:拓扑中的网络都是 Ethernet 网
实验内容
数据中心模拟
①实现及主要代码解释
a. 设置自定义的 attribute
为了做实验方便,设置如下自定义 attribute:
pattern:通信模式,all-to-all 或 many-to-one,默认为 1
defaultDst:多对一模式下,接收消息的默认服务器序号,默认为 0
verbose:enable 或者 disable PacketSink 和 OnOffApplication 的日志,默认为 false
DataRate1:定义数据中心拓扑第一层的数据传输速率(Mbps),默认为 1.0
DataRate2:定义数据中心拓扑第二层的数据传输速率(Mbps),默认为 1.0
DataRate3:定义数据中心拓扑第三层的数据传输速率(Mbps),默认为 1.5
实现代码如下:
uint16_t pattern = 1;
uint16_t nodesNum = 8;
uint16_t defaultDst = 0;
float DataRate1 = 1.0;
float DataRate2 = 1.0;
float DataRate3 = 1.5;
uint16_t port = 50000;
bool verbose = false;
CommandLine cmd;
cmd.AddValue("pattern", "number of traffic pattern",
pattern);//pattern1:all-to-all pattern2:many-to-one
cmd.AddValue("defaultDst", "default destination server node in pattern
2", defaultDst);
cmd.AddValue("DataRate1", "data rate of csma network at level 1",
DataRate1);
cmd.AddValue("DataRate2", "data rate of csma network at level 2",
DataRate2);
cmd.AddValue("DataRate3", "data rate of csma network at level 3",
DataRate3);
cmd.AddValue ("verbose", "Tell sink and onoff applications to log if
true", verbose);
cmd.Parse(argc, argv);
LogComponentEnable ("DataCenterSimulation", LOG_LEVEL_INFO);
if (verbose)
{
}
LogComponentEnable ("PacketSink", LOG_LEVEL_INFO);
LogComponentEnable ("OnOffApplication", LOG_LEVEL_INFO);
b. 创建结点
根据实验要求,总共需要创建 15 个结点,包括:
8 servers
4 ToR switches
2 Aggregation switches
1 Core switch
实现代码如下:
//create nodes
NodeContainer n1_8;
n1_8.Create(8);
NodeContainer t1_4;
t1_4.Create(4);
NodeContainer a12;
a12.Create(2);
NodeContainer c1;
c1.Create(1);
c. 创建 CSMA 网络节点
整个数据中心网络拓扑从下往上可以分为三层,即
第一层:由服务器与 ToR 组成的 ethernet 网络,共有 4 个,编号为
CSMA11,CSMA12,CSMA13,CSMA14
第二层:由 ToR 与 Aggregation 组成的 ethernet 网络,共有 2 个,编号为 CSMA21,CSMA22
第三层:由 Aggregation 与 Core 组成的 ethernet 网络,共有 1 个,编号为 CSMA3
将创建好的 15 个网络结点分配到这 7 个 CSMA 网络中,实现代码如下:
//create csma nodes
NodeContainer csmaNodes11 =
NodeContainer(n1_8.Get(0),n1_8.Get(1),t1_4.Get(0));
NodeContainer csmaNodes12 =
NodeContainer(n1_8.Get(2),n1_8.Get(3),t1_4.Get(1));
NodeContainer csmaNodes13 =
NodeContainer(n1_8.Get(4),n1_8.Get(5),t1_4.Get(2));
NodeContainer csmaNodes14 =
NodeContainer(n1_8.Get(6),n1_8.Get(7),t1_4.Get(3));
NodeContainer csmaNodes21 =
NodeContainer(t1_4.Get(0),t1_4.Get(1),a12.Get(0));
NodeContainer csmaNodes22 =
NodeContainer(t1_4.Get(2),t1_4.Get(3),a12.Get(1));
NodeContainer csmaNodes3
=
NodeContainer(a12.Get(0),a12.Get(1),c1.Get(0));
d. 设置 CSMA 网络 attribute,并将其安装到相应结点上
根据实验要求中的网络拓扑,设置相应网络的属性
所有直接相连的两个结点之间的延迟都为 500ns
第一层和第二层 CSMA 网络的数据传输速率都为 1.0Mbps,第三层为 1.5Mbps
然后安装到相应的网络结点上,实现代码如下(DataRate 可以通过命令行参数设置,默认
值即为原实验要求):
//create the channels first without any IP addressing information
CsmaHelper csma1;
sprintf(buf,"%1.1fMbps",DataRate1);
csma1.SetChannelAttribute ("DataRate", StringValue (buf));
csma1.SetChannelAttribute ("Delay", StringValue ("500ns"));
NetDeviceContainer csmaDevices11 = csma1.Install (csmaNodes11);
NetDeviceContainer csmaDevices12 = csma1.Install (csmaNodes12);
NetDeviceContainer csmaDevices13 = csma1.Install (csmaNodes13);
NetDeviceContainer csmaDevices14 = csma1.Install (csmaNodes14);
CsmaHelper csma2;
sprintf(buf,"%1.1fMbps",DataRate2);
csma2.SetChannelAttribute ("DataRate", StringValue (buf));
csma2.SetChannelAttribute ("Delay", StringValue ("500ns"));
NetDeviceContainer csmaDevices21 = csma2.Install (csmaNodes21);
NetDeviceContainer csmaDevices22 = csma2.Install (csmaNodes22);
CsmaHelper csma3;
sprintf(buf,"%1.1fMbps",DataRate3);
csma3.SetChannelAttribute ("DataRate", StringValue (buf));
csma3.SetChannelAttribute ("Delay", StringValue ("500ns"));
NetDeviceContainer csmaDevices3
= csma3.Install (csmaNodes3);
e. 分配网络 IP
根据实验要求,为每个结点安装协议栈,并为 7 个 CSMA 网络分配 IP,实现代码如下
//assign IP address
NS_LOG_INFO ("Assign IP address.");
InternetStackHelper stack;
stack.Install (n1_8);
stack.Install (t1_4);
stack.Install (a12);
stack.Install (c1);
Ipv4AddressHelper address;
address.SetBase ("10.0.1.0", "255.255.255.0");
Ipv4InterfaceContainer csmaInterfaces11 = address.Assign
(csmaDevices11);
address.SetBase ("10.0.2.0", "255.255.255.0");
Ipv4InterfaceContainer csmaInterfaces12 = address.Assign
(csmaDevices12);
address.SetBase ("10.0.3.0", "255.255.255.0");
Ipv4InterfaceContainer csmaInterfaces13 = address.Assign
(csmaDevices13);
address.SetBase ("10.0.4.0", "255.255.255.0");
Ipv4InterfaceContainer csmaInterfaces14 = address.Assign
(csmaDevices14);
address.SetBase ("10.1.1.0", "255.255.255.0");
Ipv4InterfaceContainer csmaInterfaces21 = address.Assign
(csmaDevices21);
address.SetBase ("10.2.1.0", "255.255.255.0");
Ipv4InterfaceContainer csmaInterfaces22 = address.Assign
(csmaDevices22);
address.SetBase ("192.168.1.0", "255.255.255.0");
Ipv4InterfaceContainer csmaInterfaces3
= address.Assign
(csmaDevices3);
f. 初始化路由表
这里直接调用了 ns3 自带的路由实现,实现代码如下
// Create router nodes, initialize routing database and set up the
routing
// tables in the nodes.
Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
g. 创建和分配 PacketSink 和 OnOffClient
首先,创建 sink 和 OnOff,实现代码如下
//Create sinkApp and OnOffClient
ApplicationContainer clientApp[nodesNum][4];
ApplicationContainer sinkApp[nodesNum];
然后,分配 sink 到所有的 server 结点上,实现代码如下(其中 nodesNum 表示 server 个数):
for(unsigned int i = 0;i < nodesNum; i++)
{
PacketSinkHelper packetSinkHelper ("ns3::TcpSocketFactory",
getAddress(i,port,csmaInterfaces11,csmaInterfaces12,csmaInterfaces13,
csmaInterfaces14));
sinkApp[i] = packetSinkHelper.Install (n1_8.Get (i));
sinkApp[i].Start(Seconds (1.0));
sinkApp[i].Stop(Seconds (60.0));
}
再然后,分配 OnOffClient 到 server 结点上,并且根据 pattern 不同,进行不同的配置
pattern 1:每个服务器都发送消息给其他服务器消息,即发送消息给在另一个簇上面的 4
个服务器(每个服务器上建立 4 个 OnOffClient)
pattern 2:每个服务器都发送消息给同一个服务器,可以默认为 n1(每个服务器(n1 除
外)上建立 1 个 OnOffClient)
实现代码如下
for(int i = 0; i < nodesNum; i++)
{
uint16_t dst = 0;
if(pattern==1){//all-to-all pattern
for(int j = 0 ;j < 4; j++){
if(i<=3)
else
dst = j+4;
dst = j;
OnOffHelper
client("ns3::TcpSocketFactory",getAddress(dst,port,csmaInterfaces11,c
smaInterfaces12,csmaInterfaces13,csmaInterfaces14));
client.SetAttribute ("OnTime",
StringValue("ns3::ConstantRandomVariable[Constant=50]"));
client.SetAttribute ("OffTime",
StringValue("ns3::ConstantRandomVariable[Constant=0]"));
client.SetAttribute ("DataRate", DataRateValue (DataRate
("1.0Mbps")));
client.SetAttribute ("PacketSize", UintegerValue (2000));
clientApp[i][j] = client.Install (n1_8.Get (i));
clientApp[i][j].Start(Seconds (1.0));
clientApp[i][j].Stop (Seconds (51.0));
sprintf(buf,"OnOffClient @Node %d aims at Server
@Node %d",i+1,dst+1);
NS_LOG_INFO (buf);
}
}else if(pattern==2){//many-to-one pattern
if(i == defaultDst)continue;
dst = defaultDst;
OnOffHelper
client("ns3::TcpSocketFactory",getAddress(dst,port,csmaInterfaces11,c
smaInterfaces12,csmaInterfaces13,csmaInterfaces14));
client.SetAttribute ("OnTime",
StringValue("ns3::ConstantRandomVariable[Constant=50]"));
client.SetAttribute ("OffTime",
StringValue("ns3::ConstantRandomVariable[Constant=0]"));
client.SetAttribute ("DataRate", DataRateValue (DataRate
("1.0Mbps")));
client.SetAttribute ("PacketSize", UintegerValue (2000));
clientApp[i][0] = client.Install (n1_8.Get (i));
clientApp[i][0].Start(Seconds (1.0));
clientApp[i][0].Stop (Seconds (51.0));
sprintf(buf,"OnOffClient @Node %d aims at Server
@Node %d",i+1,dst+1);
NS_LOG_INFO (buf);
}
这里解释一下一个函数
getAddress:根据 server 的标号产生相应的 IP:port 地址
getAddress 实现代码如下
InetSocketAddress getAddress(int i,uint16_t
port,Ipv4InterfaceContainer i1,Ipv4InterfaceContainer
i2,Ipv4InterfaceContainer i3,Ipv4InterfaceContainer i4){
switch(i){
case 0:
return InetSocketAddress(i1.GetAddress(0),port);break;
case 1:
return InetSocketAddress(i1.GetAddress(1),port);break;
case 2: