A Discrete-Event Network Simulator
API
main.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016 University of Campinas (Unicamp)
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Author: Luciano Jerez Chaves <ljerezchaves@gmail.com>
18  */
19 
20 /*
21  * - This is the internal network of an organization.
22  * - 2 servers and N client nodes are located far from each other.
23  * - Between border and aggregation switches there are two narrowband links of
24  * 10 Mbps each. Other local connections have links of 100 Mbps.
25  * - The default learning application manages the client switch.
26  * - An specialized OpenFlow QoS controller is used to manage the border and
27  * aggregation switches, balancing traffic among internal servers and
28  * aggregating narrowband links to increase throughput.
29  *
30  * QoS controller Learning controller
31  * | |
32  * +--------------+ |
33  * +----------+ | | | +----------+
34  * | Server 0 | ==== +--------+ +--------+ +--------+ ==== | Client 0 |
35  * +----------+ | Border | ~~~~ | Aggreg | | Client | +----------+
36  * +----------+ | Switch | ~~~~ | Switch | ==== | Switch | +----------+
37  * | Server 1 | ==== +--------+ +--------+ +--------+ ==== | Client N |
38  * +----------+ 2x10 100 +----------+
39  * Mbps Mbps
40  **/
41 
42 #include "qos-controller.h"
43 
44 #include <ns3/applications-module.h>
45 #include <ns3/core-module.h>
46 #include <ns3/csma-module.h>
47 #include <ns3/internet-module.h>
48 #include <ns3/mobility-module.h>
49 #include <ns3/netanim-module.h>
50 #include <ns3/network-module.h>
51 #include <ns3/ofswitch13-module.h>
52 
53 using namespace ns3;
54 
55 int
56 main(int argc, char* argv[])
57 {
58  uint16_t clients = 2;
59  uint16_t simTime = 10;
60  bool verbose = false;
61  bool trace = false;
62 
63  // Configure command line parameters
65  cmd.AddValue("clients", "Number of client nodes", clients);
66  cmd.AddValue("simTime", "Simulation time (seconds)", simTime);
67  cmd.AddValue("verbose", "Enable verbose output", verbose);
68  cmd.AddValue("trace", "Enable datapath stats and pcap traces", trace);
69  cmd.Parse(argc, argv);
70 
71  if (verbose)
72  {
74  LogComponentEnable("OFSwitch13Device", LOG_LEVEL_ALL);
75  LogComponentEnable("OFSwitch13Port", LOG_LEVEL_ALL);
76  LogComponentEnable("OFSwitch13Queue", LOG_LEVEL_ALL);
77  LogComponentEnable("OFSwitch13SocketHandler", LOG_LEVEL_ALL);
78  LogComponentEnable("OFSwitch13Controller", LOG_LEVEL_ALL);
79  LogComponentEnable("OFSwitch13LearningController", LOG_LEVEL_ALL);
80  LogComponentEnable("OFSwitch13Helper", LOG_LEVEL_ALL);
81  LogComponentEnable("OFSwitch13InternalHelper", LOG_LEVEL_ALL);
82  LogComponentEnable("QosController", LOG_LEVEL_ALL);
83  }
84 
85  // Configure dedicated connections between controller and switches
86  Config::SetDefault("ns3::OFSwitch13Helper::ChannelType",
88 
89  // Increase TCP MSS for larger packets
90  Config::SetDefault("ns3::TcpSocket::SegmentSize", UintegerValue(1400));
91 
92  // Enable checksum computations (required by OFSwitch13 module)
93  GlobalValue::Bind("ChecksumEnabled", BooleanValue(true));
94 
95  // Discard the first MAC address ("00:00:00:00:00:01") which will be used by
96  // the border switch in association with the first IP address ("10.1.1.1")
97  // for the Internet service.
99 
100  // Create nodes for servers, switches, controllers and clients
101  NodeContainer serverNodes;
102  NodeContainer switchNodes;
103  NodeContainer controllerNodes;
104  NodeContainer clientNodes;
105  serverNodes.Create(2);
106  switchNodes.Create(3);
107  controllerNodes.Create(2);
108  clientNodes.Create(clients);
109 
110  // Setting node positions for NetAnim support
111  Ptr<ListPositionAllocator> listPosAllocator;
112  listPosAllocator = CreateObject<ListPositionAllocator>();
113  listPosAllocator->Add(Vector(0, 0, 0)); // Server 0
114  listPosAllocator->Add(Vector(0, 75, 0)); // Server 1
115  listPosAllocator->Add(Vector(50, 50, 0)); // Border switch
116  listPosAllocator->Add(Vector(100, 50, 0)); // Aggregation switch
117  listPosAllocator->Add(Vector(150, 50, 0)); // Client switch
118  listPosAllocator->Add(Vector(75, 25, 0)); // QoS controller
119  listPosAllocator->Add(Vector(150, 25, 0)); // Learning controller
120  for (size_t i = 0; i < clients; i++)
121  {
122  listPosAllocator->Add(Vector(200, 25 * i, 0)); // Clients
123  }
124 
125  MobilityHelper mobilityHelper;
126  mobilityHelper.SetMobilityModel("ns3::ConstantPositionMobilityModel");
127  mobilityHelper.SetPositionAllocator(listPosAllocator);
128  mobilityHelper.Install(NodeContainer(serverNodes, switchNodes, controllerNodes, clientNodes));
129 
130  // Create device containers
131  NetDeviceContainer serverDevices;
132  NetDeviceContainer clientDevices;
133  NetDeviceContainer switch0Ports;
134  NetDeviceContainer switch1Ports;
135  NetDeviceContainer switch2Ports;
136  NetDeviceContainer link;
137 
138  // Create two 10Mbps connections between border and aggregation switches
139  CsmaHelper csmaHelper;
140  csmaHelper.SetChannelAttribute("DataRate", DataRateValue(DataRate("10Mbps")));
141 
142  link = csmaHelper.Install(NodeContainer(switchNodes.Get(0), switchNodes.Get(1)));
143  switch0Ports.Add(link.Get(0));
144  switch1Ports.Add(link.Get(1));
145 
146  link = csmaHelper.Install(NodeContainer(switchNodes.Get(0), switchNodes.Get(1)));
147  switch0Ports.Add(link.Get(0));
148  switch1Ports.Add(link.Get(1));
149 
150  // Configure the CsmaHelper for 100Mbps connections
151  csmaHelper.SetChannelAttribute("DataRate", DataRateValue(DataRate("100Mbps")));
152 
153  // Connect aggregation switch to client switch
154  link = csmaHelper.Install(NodeContainer(switchNodes.Get(1), switchNodes.Get(2)));
155  switch1Ports.Add(link.Get(0));
156  switch2Ports.Add(link.Get(1));
157 
158  // Connect servers to border switch
159  link = csmaHelper.Install(NodeContainer(serverNodes.Get(0), switchNodes.Get(0)));
160  serverDevices.Add(link.Get(0));
161  switch0Ports.Add(link.Get(1));
162 
163  link = csmaHelper.Install(NodeContainer(serverNodes.Get(1), switchNodes.Get(0)));
164  serverDevices.Add(link.Get(0));
165  switch0Ports.Add(link.Get(1));
166 
167  // Connect client nodes to client switch
168  for (size_t i = 0; i < clients; i++)
169  {
170  link = csmaHelper.Install(NodeContainer(clientNodes.Get(i), switchNodes.Get(2)));
171  clientDevices.Add(link.Get(0));
172  switch2Ports.Add(link.Get(1));
173  }
174 
175  // Configure OpenFlow QoS controller for border and aggregation switches
176  // (#0 and #1) into controller node 0.
177  Ptr<OFSwitch13InternalHelper> ofQosHelper = CreateObject<OFSwitch13InternalHelper>();
178  Ptr<QosController> qosCtrl = CreateObject<QosController>();
179  ofQosHelper->InstallController(controllerNodes.Get(0), qosCtrl);
180 
181  // Configure OpenFlow learning controller for client switch (#2) into controller node 1
182  Ptr<OFSwitch13InternalHelper> ofLearningHelper = CreateObject<OFSwitch13InternalHelper>();
183  Ptr<OFSwitch13LearningController> learnCtrl = CreateObject<OFSwitch13LearningController>();
184  ofLearningHelper->InstallController(controllerNodes.Get(1), learnCtrl);
185 
186  // Install OpenFlow switches 0 and 1 with border controller
187  OFSwitch13DeviceContainer ofSwitchDevices;
188  ofSwitchDevices.Add(ofQosHelper->InstallSwitch(switchNodes.Get(0), switch0Ports));
189  ofSwitchDevices.Add(ofQosHelper->InstallSwitch(switchNodes.Get(1), switch1Ports));
190  ofQosHelper->CreateOpenFlowChannels();
191 
192  // Install OpenFlow switches 2 with learning controller
193  ofSwitchDevices.Add(ofLearningHelper->InstallSwitch(switchNodes.Get(2), switch2Ports));
194  ofLearningHelper->CreateOpenFlowChannels();
195 
196  // Install the TCP/IP stack into hosts nodes
197  InternetStackHelper internet;
198  internet.Install(serverNodes);
199  internet.Install(clientNodes);
200 
201  // Set IPv4 server and client addresses (discarding the first server address)
202  Ipv4AddressHelper ipv4switches;
203  Ipv4InterfaceContainer internetIpIfaces;
204  ipv4switches.SetBase("10.1.0.0", "255.255.0.0", "0.0.1.2");
205  internetIpIfaces = ipv4switches.Assign(serverDevices);
206  ipv4switches.SetBase("10.1.0.0", "255.255.0.0", "0.0.2.1");
207  internetIpIfaces = ipv4switches.Assign(clientDevices);
208 
209  // Configure applications for traffic generation. Client hosts send traffic
210  // to server. The server IP address 10.1.1.1 is attended by the border
211  // switch, which redirects the traffic to internal servers, equalizing the
212  // number of connections to each server.
213  Ipv4Address serverAddr("10.1.1.1");
214 
215  // Installing a sink application at server nodes
216  PacketSinkHelper sinkHelper("ns3::TcpSocketFactory",
218  ApplicationContainer sinkApps = sinkHelper.Install(serverNodes);
219  sinkApps.Start(Seconds(0));
220 
221  // Installing a sender application at client nodes
222  BulkSendHelper senderHelper("ns3::TcpSocketFactory", InetSocketAddress(serverAddr, 9));
223  ApplicationContainer senderApps = senderHelper.Install(clientNodes);
224 
225  // Get random start times
226  Ptr<UniformRandomVariable> rngStart = CreateObject<UniformRandomVariable>();
227  rngStart->SetAttribute("Min", DoubleValue(0));
228  rngStart->SetAttribute("Max", DoubleValue(1));
230  for (appIt = senderApps.Begin(); appIt != senderApps.End(); ++appIt)
231  {
232  (*appIt)->SetStartTime(Seconds(rngStart->GetValue()));
233  }
234 
235  // Enable pcap traces and datapath stats
236  if (trace)
237  {
238  ofLearningHelper->EnableOpenFlowPcap("openflow");
239  ofLearningHelper->EnableDatapathStats("switch-stats");
240  ofQosHelper->EnableOpenFlowPcap("openflow");
241  ofQosHelper->EnableDatapathStats("switch-stats");
242  csmaHelper.EnablePcap("switch", switchNodes, true);
243  csmaHelper.EnablePcap("server", serverDevices);
244  csmaHelper.EnablePcap("client", clientDevices);
245  }
246 
247  // Creating NetAnim output file
248  AnimationInterface anim("qosctrl-netanim.xml");
251 
252  // Set NetAnim node descriptions
253  anim.UpdateNodeDescription(0, "Server 0");
254  anim.UpdateNodeDescription(1, "Server 1");
255  anim.UpdateNodeDescription(2, "Border switch");
256  anim.UpdateNodeDescription(3, "Aggregation switch");
257  anim.UpdateNodeDescription(4, "Client switch");
258  anim.UpdateNodeDescription(5, "QoS controller");
259  anim.UpdateNodeDescription(6, "Learning controller");
260  for (size_t i = 0; i < clients; i++)
261  {
262  std::ostringstream desc;
263  desc << "Client " << i;
264  anim.UpdateNodeDescription(7 + i, desc.str());
265  }
266 
267  // Set NetAnim icon images and size
268  char cwd[1024];
269  if (getcwd(cwd, sizeof(cwd)) != nullptr)
270  {
271  std::string path =
272  std::string(cwd) + "/contrib/ofswitch13/examples/ofswitch13-qos-controller/images/";
273  uint32_t serverImg = anim.AddResource(path + "server.png");
274  uint32_t switchImg = anim.AddResource(path + "switch.png");
275  uint32_t controllerImg = anim.AddResource(path + "controller.png");
276  uint32_t clientImg = anim.AddResource(path + "client.png");
277 
278  anim.UpdateNodeImage(0, serverImg);
279  anim.UpdateNodeImage(1, serverImg);
280  anim.UpdateNodeImage(2, switchImg);
281  anim.UpdateNodeImage(3, switchImg);
282  anim.UpdateNodeImage(4, switchImg);
283  anim.UpdateNodeImage(5, controllerImg);
284  anim.UpdateNodeImage(6, controllerImg);
285  for (size_t i = 0; i < clients; i++)
286  {
287  anim.UpdateNodeImage(i + 7, clientImg);
288  }
289  for (size_t i = 0; i < clients + 7U; i++)
290  {
291  anim.UpdateNodeSize(i, 10, 10);
292  }
293  }
294 
295  // Run the simulation
296  Simulator::Stop(Seconds(simTime));
297  Simulator::Run();
299 
300  // Dump total of received bytes by sink applications
301  Ptr<PacketSink> sink1 = DynamicCast<PacketSink>(sinkApps.Get(0));
302  Ptr<PacketSink> sink2 = DynamicCast<PacketSink>(sinkApps.Get(1));
303  std::cout << "Bytes received by server 1: " << sink1->GetTotalRx() << " ("
304  << (8. * sink1->GetTotalRx()) / 1000000 / simTime << " Mbps)" << std::endl;
305  std::cout << "Bytes received by server 2: " << sink2->GetTotalRx() << " ("
306  << (8. * sink2->GetTotalRx()) / 1000000 / simTime << " Mbps)" << std::endl;
307 }
Interface to network animator.
void UpdateNodeImage(uint32_t nodeId, uint32_t resourceId)
Helper function to update the image of a node.
void SetStartTime(Time t)
Specify the time at which capture should start.
uint32_t AddResource(std::string resourcePath)
Add a resource such as the path to an image file.
void UpdateNodeSize(Ptr< Node > n, double width, double height)
Helper function to update the size of a node.
void SetStopTime(Time t)
Specify the time at which capture should stop.
void UpdateNodeDescription(Ptr< Node > n, std::string descr)
Helper function to update the description for a given node.
holds a vector of ns3::Application pointers.
Iterator Begin() const
Get an iterator which refers to the first Application in the container.
Iterator End() const
Get an iterator which indicates past-the-last Application in the container.
void Start(Time start) const
Start all of the Applications in this container at the start time given as a parameter.
std::vector< Ptr< Application > >::const_iterator Iterator
Application container iterator.
Ptr< Application > Get(uint32_t i) const
Get the Ptr<Application> stored in this container at a given index.
AttributeValue implementation for Boolean.
Definition: boolean.h:37
A helper to make it easier to instantiate an ns3::BulkSendApplication on a set of nodes.
Parse command-line arguments.
Definition: command-line.h:232
build a set of CsmaNetDevice objects
Definition: csma-helper.h:48
void SetChannelAttribute(std::string n1, const AttributeValue &v1)
Definition: csma-helper.cc:56
NetDeviceContainer Install(Ptr< Node > node) const
This method creates an ns3::CsmaChannel with the attributes configured by CsmaHelper::SetChannelAttri...
Definition: csma-helper.cc:226
AttributeValue implementation for DataRate.
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition: double.h:42
Hold variables of type enum.
Definition: enum.h:56
static void Bind(std::string name, const AttributeValue &value)
Iterate over the set of GlobalValues until a matching name is found and then set its value with Globa...
an Inet address class
aggregate IP/TCP/UDP functionality to existing Nodes.
void Install(std::string nodeName) const
Aggregate implementations of the ns3::Ipv4, ns3::Ipv6, ns3::Udp, and ns3::Tcp classes onto the provid...
A helper class to make life easier while doing simple IPv4 address assignment in scripts.
void SetBase(Ipv4Address network, Ipv4Mask mask, Ipv4Address base="0.0.0.1")
Set the base network number, network mask and base address.
Ipv4InterfaceContainer Assign(const NetDeviceContainer &c)
Assign IP addresses to the net devices specified in the container based on the current network prefix...
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:43
static Ipv4Address GetAny()
holds a vector of std::pair of Ptr<Ipv4> and interface index.
static Mac48Address Allocate()
Allocate a new Mac48Address.
Helper class used to assign positions and mobility models to nodes.
void Install(Ptr< Node > node) const
"Layout" a single node according to the current position allocator type.
void SetMobilityModel(std::string type, Ts &&... args)
void SetPositionAllocator(Ptr< PositionAllocator > allocator)
Set the position allocator which will be used to allocate the initial position of every node initiali...
holds a vector of ns3::NetDevice pointers
void Add(NetDeviceContainer other)
Append the contents of another NetDeviceContainer to the end of this container.
Ptr< NetDevice > Get(uint32_t i) const
Get the Ptr<NetDevice> stored in this container at a given index.
keep track of a set of node pointers.
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
Ptr< Node > Get(uint32_t i) const
Get the Ptr<Node> stored in this container at a given index.
Holds a vector of ns3::OFSwitch13Device pointers.
void Add(OFSwitch13DeviceContainer other)
Append the contents of another OFSwitch13DeviceContainer to the end of this container.
static void EnableDatapathLogs(std::string prefix="", bool explicitFilename=false)
Enable OpenFlow datapath logs at all OpenFlow switch devices on the simulation.
@ DEDICATEDCSMA
Uses individual CSMA channels.
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:200
A helper to make it easier to instantiate an ns3::PacketSinkApplication on a set of nodes.
uint64_t GetTotalRx() const
Definition: packet-sink.cc:96
void EnablePcap(std::string prefix, Ptr< NetDevice > nd, bool promiscuous=false, bool explicitFilename=false)
Enable pcap output the indicated net device.
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition: simulator.cc:140
static void Run()
Run the simulation.
Definition: simulator.cc:176
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Definition: simulator.cc:184
Hold an unsigned integer type.
Definition: uinteger.h:45
double GetValue(double min, double max)
Get the next random value drawn from the distribution.
void SetDefault(std::string name, const AttributeValue &value)
Definition: config.cc:891
void(* DataRate)(DataRate oldValue, DataRate newValue)
TracedValue callback signature for DataRate.
Definition: data-rate.h:328
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1336
AnimationInterface * anim
Every class exported by the ns3 library is enclosed in the ns3 namespace.
void LogComponentEnable(const std::string &name, LogLevel level)
Enable the logging output associated with that log component.
Definition: log.cc:305
@ LOG_LEVEL_ALL
Print everything.
Definition: log.h:116
cmd
Definition: second.py:33
bool verbose