A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
nms-p2p-nix.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License version 2 as
5  * published by the Free Software Foundation;
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15  *
16  * (c) 2009, GTech Systems, Inc. - Alfred Park <park@gtech-systems.com>
17  *
18  * DARPA NMS Campus Network Model
19  *
20  * This topology replicates the original NMS Campus Network model
21  * with the exception of chord links (which were never utilized in the
22  * original model)
23  * Link Bandwidths and Delays may not be the same as the original
24  * specifications
25  *
26  * The fundamental unit of the NMS model consists of a campus network. The
27  * campus network topology can been seen here:
28  * http://www.nsnam.org/~jpelkey3/nms.png
29  * The number of hosts (default 42) is variable. Finally, an arbitrary
30  * number of these campus networks can be connected together (default 2)
31  * to make very large simulations.
32  */
33 
34 // for timing functions
35 #include <cstdlib>
36 #include <sys/time.h>
37 #include <fstream>
38 
39 #include "ns3/core-module.h"
40 #include "ns3/internet-module.h"
41 #include "ns3/network-module.h"
42 #include "ns3/point-to-point-module.h"
43 #include "ns3/applications-module.h"
44 #include "ns3/onoff-application.h"
45 #include "ns3/packet-sink.h"
46 #include "ns3/simulator.h"
47 #include "ns3/ipv4-static-routing-helper.h"
48 #include "ns3/ipv4-list-routing-helper.h"
49 #include "ns3/ipv4-nix-vector-helper.h"
50 
51 using namespace std;
52 using namespace ns3;
53 
54 typedef struct timeval TIMER_TYPE;
55 #define TIMER_NOW(_t) gettimeofday (&_t,NULL);
56 #define TIMER_SECONDS(_t) ((double)(_t).tv_sec + (_t).tv_usec*1e-6)
57 #define TIMER_DIFF(_t1, _t2) (TIMER_SECONDS (_t1)-TIMER_SECONDS (_t2))
58 
59 NS_LOG_COMPONENT_DEFINE ("CampusNetworkModel");
60 
61 void Progress ()
62 {
63  Simulator::Schedule (Seconds (0.1), Progress);
64 }
65 
66 template <typename T>
67 class Array2D
68 {
69  public:
70  Array2D (const size_t x, const size_t y) : p (new T*[x]), m_xMax (x)
71  {
72  for (size_t i = 0; i < m_xMax; i++)
73  p[i] = new T[y];
74  }
75 
76  ~Array2D (void)
77  {
78  for (size_t i = 0; i < m_xMax; i++)
79  delete[] p[i];
80  delete p;
81  p = 0;
82  }
83 
84  T* operator[] (const size_t i)
85  {
86  return p[i];
87  }
88  private:
89  T** p;
90  const size_t m_xMax;
91 };
92 
93 template <typename T>
94 class Array3D
95 {
96  public:
97  Array3D (const size_t x, const size_t y, const size_t z)
98  : p (new Array2D<T>*[x]), m_xMax (x)
99  {
100  for (size_t i = 0; i < m_xMax; i++)
101  p[i] = new Array2D<T> (y, z);
102  }
103 
104  ~Array3D (void)
105  {
106  for (size_t i = 0; i < m_xMax; i++)
107  {
108  delete p[i];
109  p[i] = 0;
110  }
111  delete[] p;
112  p = 0;
113  }
114 
115  Array2D<T>& operator[] (const size_t i)
116  {
117  return *(p[i]);
118  }
119  private:
121  const size_t m_xMax;
122 };
123 
124 int
125 main (int argc, char *argv[])
126 {
127  TIMER_TYPE t0, t1, t2;
128  TIMER_NOW (t0);
129  cout << " ==== DARPA NMS CAMPUS NETWORK SIMULATION ====" << endl;
130  LogComponentEnable ("OnOffApplication", LOG_LEVEL_INFO);
131 
132  int nCN = 2, nLANClients = 42;
133  bool nix = true;
134 
135  CommandLine cmd;
136  cmd.AddValue ("CN", "Number of total CNs [2]", nCN);
137  cmd.AddValue ("LAN", "Number of nodes per LAN [42]", nLANClients);
138  cmd.AddValue ("NIX", "Toggle nix-vector routing", nix);
139  cmd.Parse (argc,argv);
140 
141  if (nCN < 2)
142  {
143  cout << "Number of total CNs (" << nCN << ") lower than minimum of 2"
144  << endl;
145  return 1;
146  }
147 
148  cout << "Number of CNs: " << nCN << ", LAN nodes: " << nLANClients << endl;
149 
150  Array2D<NodeContainer> nodes_net0(nCN, 3);
151  Array2D<NodeContainer> nodes_net1(nCN, 6);
152  NodeContainer* nodes_netLR = new NodeContainer[nCN];
153  Array2D<NodeContainer> nodes_net2(nCN, 14);
154  Array3D<NodeContainer> nodes_net2LAN(nCN, 7, nLANClients);
155  Array2D<NodeContainer> nodes_net3(nCN, 9);
156  Array3D<NodeContainer> nodes_net3LAN(nCN, 5, nLANClients);
157 
158  PointToPointHelper p2p_2gb200ms, p2p_1gb5ms, p2p_100mb1ms;
159  InternetStackHelper stack;
161  Array2D<Ipv4InterfaceContainer> ifs0(nCN, 3);
162  Array2D<Ipv4InterfaceContainer> ifs1(nCN, 6);
163  Array2D<Ipv4InterfaceContainer> ifs2(nCN, 14);
164  Array2D<Ipv4InterfaceContainer> ifs3(nCN, 9);
165  Array3D<Ipv4InterfaceContainer> ifs2LAN(nCN, 7, nLANClients);
166  Array3D<Ipv4InterfaceContainer> ifs3LAN(nCN, 5, nLANClients);
167 
168  Ipv4AddressHelper address;
169  std::ostringstream oss;
170  p2p_1gb5ms.SetDeviceAttribute ("DataRate", StringValue ("1Gbps"));
171  p2p_1gb5ms.SetChannelAttribute ("Delay", StringValue ("5ms"));
172  p2p_2gb200ms.SetDeviceAttribute ("DataRate", StringValue ("2Gbps"));
173  p2p_2gb200ms.SetChannelAttribute ("Delay", StringValue ("200ms"));
174  p2p_100mb1ms.SetDeviceAttribute ("DataRate", StringValue ("100Mbps"));
175  p2p_100mb1ms.SetChannelAttribute ("Delay", StringValue ("1ms"));
176 
177  // Setup NixVector Routing
178  Ipv4NixVectorHelper nixRouting;
179  Ipv4StaticRoutingHelper staticRouting;
180 
182  list.Add (staticRouting, 0);
183  list.Add (nixRouting, 10);
184 
185  if (nix)
186  {
187  stack.SetRoutingHelper (list); // has effect on the next Install ()
188  }
189 
190  // Create Campus Networks
191  for (int z = 0; z < nCN; ++z)
192  {
193  cout << "Creating Campus Network " << z << ":" << endl;
194  // Create Net0
195  cout << " SubNet [ 0";
196  for (int i = 0; i < 3; ++i)
197  {
198  nodes_net0[z][i].Create (1);
199  stack.Install (nodes_net0[z][i]);
200  }
201  nodes_net0[z][0].Add (nodes_net0[z][1].Get (0));
202  nodes_net0[z][1].Add (nodes_net0[z][2].Get (0));
203  nodes_net0[z][2].Add (nodes_net0[z][0].Get (0));
204  NetDeviceContainer ndc0[3];
205  for (int i = 0; i < 3; ++i)
206  {
207  ndc0[i] = p2p_1gb5ms.Install (nodes_net0[z][i]);
208  }
209  // Create Net1
210  cout << " 1";
211  for (int i = 0; i < 6; ++i)
212  {
213  nodes_net1[z][i].Create (1);
214  stack.Install (nodes_net1[z][i]);
215  }
216  nodes_net1[z][0].Add (nodes_net1[z][1].Get (0));
217  nodes_net1[z][2].Add (nodes_net1[z][0].Get (0));
218  nodes_net1[z][3].Add (nodes_net1[z][0].Get (0));
219  nodes_net1[z][4].Add (nodes_net1[z][1].Get (0));
220  nodes_net1[z][5].Add (nodes_net1[z][1].Get (0));
221  NetDeviceContainer ndc1[6];
222  for (int i = 0; i < 6; ++i)
223  {
224  if (i == 1)
225  {
226  continue;
227  }
228  ndc1[i] = p2p_1gb5ms.Install (nodes_net1[z][i]);
229  }
230  // Connect Net0 <-> Net1
231  NodeContainer net0_1;
232  net0_1.Add (nodes_net0[z][2].Get (0));
233  net0_1.Add (nodes_net1[z][0].Get (0));
234  NetDeviceContainer ndc0_1;
235  ndc0_1 = p2p_1gb5ms.Install (net0_1);
236  oss.str ("");
237  oss << 10 + z << ".1.252.0";
238  address.SetBase (oss.str ().c_str (), "255.255.255.0");
239  ifs = address.Assign (ndc0_1);
240  // Create Net2
241  cout << " 2";
242  for (int i = 0; i < 14; ++i)
243  {
244  nodes_net2[z][i].Create (1);
245  stack.Install (nodes_net2[z][i]);
246  }
247  nodes_net2[z][0].Add (nodes_net2[z][1].Get (0));
248  nodes_net2[z][2].Add (nodes_net2[z][0].Get (0));
249  nodes_net2[z][1].Add (nodes_net2[z][3].Get (0));
250  nodes_net2[z][3].Add (nodes_net2[z][2].Get (0));
251  nodes_net2[z][4].Add (nodes_net2[z][2].Get (0));
252  nodes_net2[z][5].Add (nodes_net2[z][3].Get (0));
253  nodes_net2[z][6].Add (nodes_net2[z][5].Get (0));
254  nodes_net2[z][7].Add (nodes_net2[z][2].Get (0));
255  nodes_net2[z][8].Add (nodes_net2[z][3].Get (0));
256  nodes_net2[z][9].Add (nodes_net2[z][4].Get (0));
257  nodes_net2[z][10].Add (nodes_net2[z][5].Get (0));
258  nodes_net2[z][11].Add (nodes_net2[z][6].Get (0));
259  nodes_net2[z][12].Add (nodes_net2[z][6].Get (0));
260  nodes_net2[z][13].Add (nodes_net2[z][6].Get (0));
261  NetDeviceContainer ndc2[14];
262  for (int i = 0; i < 14; ++i)
263  {
264  ndc2[i] = p2p_1gb5ms.Install (nodes_net2[z][i]);
265  }
267  Array2D<NetDeviceContainer> ndc2LAN(7, nLANClients);
268  for (int i = 0; i < 7; ++i)
269  {
270  oss.str ("");
271  oss << 10 + z << ".4." << 15 + i << ".0";
272  address.SetBase (oss.str ().c_str (), "255.255.255.0");
273  for (int j = 0; j < nLANClients; ++j)
274  {
275  nodes_net2LAN[z][i][j].Create (1);
276  stack.Install (nodes_net2LAN[z][i][j]);
277  nodes_net2LAN[z][i][j].Add (nodes_net2[z][i+7].Get (0));
278  ndc2LAN[i][j] = p2p_100mb1ms.Install (nodes_net2LAN[z][i][j]);
279  ifs2LAN[z][i][j] = address.Assign (ndc2LAN[i][j]);
280  }
281  }
282  // Create Net3
283  cout << " 3 ]" << endl;
284  for (int i = 0; i < 9; ++i)
285  {
286  nodes_net3[z][i].Create (1);
287  stack.Install (nodes_net3[z][i]);
288  }
289  nodes_net3[z][0].Add (nodes_net3[z][1].Get (0));
290  nodes_net3[z][1].Add (nodes_net3[z][2].Get (0));
291  nodes_net3[z][2].Add (nodes_net3[z][3].Get (0));
292  nodes_net3[z][3].Add (nodes_net3[z][1].Get (0));
293  nodes_net3[z][4].Add (nodes_net3[z][0].Get (0));
294  nodes_net3[z][5].Add (nodes_net3[z][0].Get (0));
295  nodes_net3[z][6].Add (nodes_net3[z][2].Get (0));
296  nodes_net3[z][7].Add (nodes_net3[z][3].Get (0));
297  nodes_net3[z][8].Add (nodes_net3[z][3].Get (0));
298  NetDeviceContainer ndc3[9];
299  for (int i = 0; i < 9; ++i)
300  {
301  ndc3[i] = p2p_1gb5ms.Install (nodes_net3[z][i]);
302  }
304  Array2D<NetDeviceContainer> ndc3LAN(5, nLANClients);
305  for (int i = 0; i < 5; ++i)
306  {
307  oss.str ("");
308  oss << 10 + z << ".5." << 10 + i << ".0";
309  address.SetBase (oss.str ().c_str (), "255.255.255.255");
310  for (int j = 0; j < nLANClients; ++j)
311  {
312  nodes_net3LAN[z][i][j].Create (1);
313  stack.Install (nodes_net3LAN[z][i][j]);
314  nodes_net3LAN[z][i][j].Add (nodes_net3[z][i+4].Get (0));
315  ndc3LAN[i][j] = p2p_100mb1ms.Install (nodes_net3LAN[z][i][j]);
316  ifs3LAN[z][i][j] = address.Assign (ndc3LAN[i][j]);
317  }
318  }
319  cout << " Connecting Subnets..." << endl;
320  // Create Lone Routers (Node 4 & 5)
321  nodes_netLR[z].Create (2);
322  stack.Install (nodes_netLR[z]);
323  NetDeviceContainer ndcLR;
324  ndcLR = p2p_1gb5ms.Install (nodes_netLR[z]);
325  // Connect Net2/Net3 through Lone Routers to Net0
326  NodeContainer net0_4, net0_5, net2_4a, net2_4b, net3_5a, net3_5b;
327  net0_4.Add (nodes_netLR[z].Get (0));
328  net0_4.Add (nodes_net0[z][0].Get (0));
329  net0_5.Add (nodes_netLR[z].Get (1));
330  net0_5.Add (nodes_net0[z][1].Get (0));
331  net2_4a.Add (nodes_netLR[z].Get (0));
332  net2_4a.Add (nodes_net2[z][0].Get (0));
333  net2_4b.Add (nodes_netLR[z].Get (1));
334  net2_4b.Add (nodes_net2[z][1].Get (0));
335  net3_5a.Add (nodes_netLR[z].Get (1));
336  net3_5a.Add (nodes_net3[z][0].Get (0));
337  net3_5b.Add (nodes_netLR[z].Get (1));
338  net3_5b.Add (nodes_net3[z][1].Get (0));
339  NetDeviceContainer ndc0_4, ndc0_5, ndc2_4a, ndc2_4b, ndc3_5a, ndc3_5b;
340  ndc0_4 = p2p_1gb5ms.Install (net0_4);
341  oss.str ("");
342  oss << 10 + z << ".1.253.0";
343  address.SetBase (oss.str ().c_str (), "255.255.255.0");
344  ifs = address.Assign (ndc0_4);
345  ndc0_5 = p2p_1gb5ms.Install (net0_5);
346  oss.str ("");
347  oss << 10 + z << ".1.254.0";
348  address.SetBase (oss.str ().c_str (), "255.255.255.0");
349  ifs = address.Assign (ndc0_5);
350  ndc2_4a = p2p_1gb5ms.Install (net2_4a);
351  oss.str ("");
352  oss << 10 + z << ".4.253.0";
353  address.SetBase (oss.str ().c_str (), "255.255.255.0");
354  ifs = address.Assign (ndc2_4a);
355  ndc2_4b = p2p_1gb5ms.Install (net2_4b);
356  oss.str ("");
357  oss << 10 + z << ".4.254.0";
358  address.SetBase (oss.str ().c_str (), "255.255.255.0");
359  ifs = address.Assign (ndc2_4b);
360  ndc3_5a = p2p_1gb5ms.Install (net3_5a);
361  oss.str ("");
362  oss << 10 + z << ".5.253.0";
363  address.SetBase (oss.str ().c_str (), "255.255.255.0");
364  ifs = address.Assign (ndc3_5a);
365  ndc3_5b = p2p_1gb5ms.Install (net3_5b);
366  oss.str ("");
367  oss << 10 + z << ".5.254.0";
368  address.SetBase (oss.str ().c_str (), "255.255.255.0");
369  ifs = address.Assign (ndc3_5b);
370  // Assign IP addresses
371  cout << " Assigning IP addresses..." << endl;
372  for (int i = 0; i < 3; ++i)
373  {
374  oss.str ("");
375  oss << 10 + z << ".1." << 1 + i << ".0";
376  address.SetBase (oss.str ().c_str (), "255.255.255.0");
377  ifs0[z][i] = address.Assign (ndc0[i]);
378  }
379  for (int i = 0; i < 6; ++i)
380  {
381  if (i == 1)
382  {
383  continue;
384  }
385  oss.str ("");
386  oss << 10 + z << ".2." << 1 + i << ".0";
387  address.SetBase (oss.str ().c_str (), "255.255.255.0");
388  ifs1[z][i] = address.Assign (ndc1[i]);
389  }
390  oss.str ("");
391  oss << 10 + z << ".3.1.0";
392  address.SetBase (oss.str ().c_str (), "255.255.255.0");
393  ifs = address.Assign (ndcLR);
394  for (int i = 0; i < 14; ++i)
395  {
396  oss.str ("");
397  oss << 10 + z << ".4." << 1 + i << ".0";
398  address.SetBase (oss.str ().c_str (), "255.255.255.0");
399  ifs2[z][i] = address.Assign (ndc2[i]);
400  }
401  for (int i = 0; i < 9; ++i)
402  {
403  oss.str ("");
404  oss << 10 + z << ".5." << 1 + i << ".0";
405  address.SetBase (oss.str ().c_str (), "255.255.255.0");
406  ifs3[z][i] = address.Assign (ndc3[i]);
407  }
408  }
409  // Create Ring Links
410  if (nCN > 1)
411  {
412  cout << "Forming Ring Topology..." << endl;
413  NodeContainer* nodes_ring = new NodeContainer[nCN];
414  for (int z = 0; z < nCN-1; ++z)
415  {
416  nodes_ring[z].Add (nodes_net0[z][0].Get (0));
417  nodes_ring[z].Add (nodes_net0[z+1][0].Get (0));
418  }
419  nodes_ring[nCN-1].Add (nodes_net0[nCN-1][0].Get (0));
420  nodes_ring[nCN-1].Add (nodes_net0[0][0].Get (0));
421  NetDeviceContainer* ndc_ring = new NetDeviceContainer[nCN];
422  for (int z = 0; z < nCN; ++z)
423  {
424  ndc_ring[z] = p2p_2gb200ms.Install (nodes_ring[z]);
425  oss.str ("");
426  oss << "254.1." << z + 1 << ".0";
427  address.SetBase (oss.str ().c_str (), "255.255.255.0");
428  ifs = address.Assign (ndc_ring[z]);
429  }
430  delete[] ndc_ring;
431  delete[] nodes_ring;
432  }
433 
434  // Create Traffic Flows
435  cout << "Creating TCP Traffic Flows:" << endl;
436  Config::SetDefault ("ns3::OnOffApplication::MaxBytes", UintegerValue (500000));
437  Config::SetDefault ("ns3::OnOffApplication::OnTime",
438  StringValue ("ns3::ConstantRandomVariable[Constant=1.0]"));
439  Config::SetDefault ("ns3::OnOffApplication::OffTime",
440  StringValue ("ns3::ConstantRandomVariable[Constant=0.0]"));
441  Config::SetDefault ("ns3::TcpSocket::SegmentSize", UintegerValue (512));
442 
443  Ptr<UniformRandomVariable> urng = CreateObject<UniformRandomVariable> ();
444  int r1;
445  double r2;
446  for (int z = 0; z < nCN; ++z)
447  {
448  int x = z + 1;
449  if (z == nCN - 1)
450  {
451  x = 0;
452  }
453  // Subnet 2 LANs
454  cout << " Campus Network " << z << " Flows [ Net2 ";
455  for (int i = 0; i < 7; ++i)
456  {
457  for (int j = 0; j < nLANClients; ++j)
458  {
459  // Sinks
460  PacketSinkHelper sinkHelper ("ns3::TcpSocketFactory",
461  InetSocketAddress (Ipv4Address::GetAny (), 9999));
462  ApplicationContainer sinkApp = sinkHelper.Install (
463  nodes_net2LAN[z][i][j].Get (0));
464  sinkApp.Start (Seconds (0.0));
465  // Sources
466  r1 = 2 + (int)(4 * urng->GetValue ());
467  r2 = 10 * urng->GetValue ();
468  OnOffHelper client ("ns3::TcpSocketFactory", Address ());
469  AddressValue remoteAddress (InetSocketAddress (
470  ifs2LAN[z][i][j].GetAddress (0), 9999));
471  client.SetAttribute ("Remote", remoteAddress);
472  ApplicationContainer clientApp;
473  clientApp.Add (client.Install (nodes_net1[x][r1].Get (0)));
474  clientApp.Start (Seconds (r2));
475  }
476  }
477  // Subnet 3 LANs
478  cout << "Net3 ]" << endl;
479  for (int i = 0; i < 5; ++i)
480  {
481  for (int j = 0; j < nLANClients; ++j)
482  {
483  // Sinks
484  PacketSinkHelper sinkHelper ("ns3::TcpSocketFactory",
485  InetSocketAddress (Ipv4Address::GetAny (), 9999));
486  ApplicationContainer sinkApp = sinkHelper.Install (
487  nodes_net3LAN[z][i][j].Get (0));
488  sinkApp.Start (Seconds (0.0));
489  // Sources
490  r1 = 2 + (int)(4 * urng->GetValue ());
491  r2 = 10 * urng->GetValue ();
492  OnOffHelper client ("ns3::TcpSocketFactory", Address ());
493  AddressValue remoteAddress (InetSocketAddress (
494  ifs3LAN[z][i][j].GetAddress (0), 9999));
495  client.SetAttribute ("Remote", remoteAddress);
496  ApplicationContainer clientApp;
497  clientApp.Add (client.Install (nodes_net1[x][r1].Get (0)));
498  clientApp.Start (Seconds (r2));
499  }
500  }
501  }
502 
503  cout << "Created " << NodeList::GetNNodes () << " nodes." << endl;
504  TIMER_TYPE routingStart;
505  TIMER_NOW (routingStart);
506 
507  if (nix)
508  {
509  // Calculate routing tables
510  cout << "Using Nix-vectors..." << endl;
511  }
512  else
513  {
514  // Calculate routing tables
515  cout << "Populating Global Static Routing Tables..." << endl;
516  Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
517  }
518 
519  TIMER_TYPE routingEnd;
520  TIMER_NOW (routingEnd);
521  cout << "Routing tables population took "
522  << TIMER_DIFF (routingEnd, routingStart) << endl;
523 
524  Simulator::ScheduleNow (Progress);
525  cout << "Running simulator..." << endl;
526  TIMER_NOW (t1);
527  Simulator::Stop (Seconds (100.0));
528  Simulator::Run ();
529  TIMER_NOW (t2);
530  cout << "Simulator finished." << endl;
531  Simulator::Destroy ();
532 
533  double d1 = TIMER_DIFF (t1, t0), d2 = TIMER_DIFF (t2, t1);
534  cout << "-----" << endl << "Runtime Stats:" << endl;
535  cout << "Simulator init time: " << d1 << endl;
536  cout << "Simulator run time: " << d2 << endl;
537  cout << "Total elapsed time: " << d1+d2 << endl;
538 
539  delete[] nodes_netLR;
540  return 0;
541 }