A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
brite-topology-helper.cc
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  */
17 
18 #include "ns3/log.h"
19 #include "ns3/abort.h"
20 #include "ns3/net-device.h"
21 #include "ns3/net-device-container.h"
22 #include "ns3/point-to-point-helper.h"
23 #include "ns3/ipv4-address-helper.h"
24 #include "ns3/random-variable-stream.h"
25 #include "ns3/data-rate.h"
26 #include "ns3/rng-seed-manager.h"
27 
28 #include "brite-topology-helper.h"
29 
30 #include <iostream>
31 #include <fstream>
32 
33 NS_LOG_COMPONENT_DEFINE ("BriteTopologyHelper");
34 
35 namespace ns3 {
36 
37 BriteTopologyHelper::BriteTopologyHelper (std::string confFile,
38  std::string seedFile,
39  std::string newseedFile) : m_confFile (confFile),
40  m_seedFile (seedFile),
41  m_newSeedFile (newseedFile),
42  m_numAs (0),
43  m_topology (NULL),
44  m_numNodes (0),
45  m_numEdges (0)
46 {
47  NS_LOG_FUNCTION (this);
48 
49  m_uv = CreateObject<UniformRandomVariable> ();
50 
51 }
52 
53 BriteTopologyHelper::BriteTopologyHelper (std::string confFile) : m_confFile (confFile),
54  m_numAs (0),
55  m_topology (NULL),
56  m_numNodes (0),
57  m_numEdges (0)
58 {
59  NS_LOG_FUNCTION (this);
60 
61  m_uv = CreateObject<UniformRandomVariable> ();
62 
63 }
64 
65 BriteTopologyHelper::~BriteTopologyHelper ()
66 {
67  NS_LOG_FUNCTION (this);
68  delete m_topology;
69 
70  while (!m_netDevices.empty ())
71  {
72  delete m_netDevices.back ();
73  m_netDevices.pop_back ();
74  }
75 
76  while (!m_asLeafNodes.empty ())
77  {
78  delete m_asLeafNodes.back ();
79  m_asLeafNodes.pop_back ();
80  }
81 
82  while (!m_nodesByAs.empty ())
83  {
84  delete m_nodesByAs.back ();
85  m_nodesByAs.pop_back ();
86  }
87 }
88 
89 void
90 BriteTopologyHelper::AssignStreams (int64_t streamNumber)
91 {
92  m_uv->SetStream (streamNumber);
93 }
94 
95 void
97 {
98  NS_LOG_FUNCTION (this);
99  brite::Graph *g = m_topology->GetGraph ();
100  for (int i = 0; i < g->GetNumNodes (); ++i)
101  {
102  BriteNodeInfo nodeInfo;
103  nodeInfo.nodeId = g->GetNodePtr (i)->GetId ();
104  nodeInfo.xCoordinate = g->GetNodePtr (i)->GetNodeInfo ()->GetCoordX ();
105  nodeInfo.yCoordinate = g->GetNodePtr (i)->GetNodeInfo ()->GetCoordY ();
106  nodeInfo.inDegree = g->GetNodePtr (i)->GetInDegree ();
107  nodeInfo.outDegree = g->GetNodePtr (i)->GetOutDegree ();
108 
109  switch (g->GetNodePtr (i)->GetNodeInfo ()->GetNodeType ())
110  {
111  case brite::NodeConf::RT_NODE:
112 
113  if (((brite::RouterNodeConf*)(g->GetNodePtr (i)->GetNodeInfo ()))->GetASId () == -1)
114  {
115  m_numAs = nodeInfo.asId = 0;
116  }
117  else
118  {
119  m_numAs = nodeInfo.asId = ((brite::RouterNodeConf*)(g->GetNodePtr (i)->GetNodeInfo ()))->GetASId ();
120  }
121 
122  switch (((brite::RouterNodeConf*)(g->GetNodePtr (i)->GetNodeInfo ()))->GetRouterType ())
123  {
124  case brite::RouterNodeConf::RT_NONE:
125  nodeInfo.type = "RT_NONE ";
126  break;
127  case brite::RouterNodeConf::RT_LEAF:
128  nodeInfo.type = "RT_LEAF ";
129  break;
130  case brite::RouterNodeConf::RT_BORDER:
131  nodeInfo.type = "RT_BORDER";
132  break;
133  case brite::RouterNodeConf::RT_STUB:
134  nodeInfo.type = "RT_STUB ";
135  break;
136  case brite::RouterNodeConf::RT_BACKBONE:
137  nodeInfo.type = "RT_BACKBONE ";
138  break;
139  default:
140  NS_FATAL_ERROR ("Topology::Output(): Improperly classfied Router node encountered...");
141  }
142  break;
143 
144  case brite::NodeConf::AS_NODE:
145  m_numAs = nodeInfo.asId =
146  ((brite::ASNodeConf*)(g->GetNodePtr (i)->GetNodeInfo ()))->GetASId ();
147 
148  switch (((brite::ASNodeConf*)(g->GetNodePtr (i)->GetNodeInfo ()))->GetASType ())
149  {
150  case brite::ASNodeConf::AS_NONE:
151  nodeInfo.type = "AS_NONE ";
152  break;
153  case brite::ASNodeConf::AS_LEAF:
154  nodeInfo.type = "AS_LEAF ";
155  break;
156  case brite::ASNodeConf::AS_STUB:
157  nodeInfo.type = "AS_STUB ";
158  break;
159  case brite::ASNodeConf::AS_BORDER:
160  nodeInfo.type = "AS_BORDER ";
161  break;
162  case brite::ASNodeConf::AS_BACKBONE:
163  nodeInfo.type = "AS_BACKBONE ";
164  break;
165  default:
166  NS_FATAL_ERROR ("Topology::Output(): Improperly classfied AS node encountered...");
167  }
168  break;
169  }
170 
171  m_briteNodeInfoList.push_back (nodeInfo);
172  }
173 
174  //Currently m_numAs stores the highest AS number. We want m_numAs to store the number
175  //of AS created in the topology. Since AS numbering starts at 0 we add one to get
176  //the correct count
177  m_numAs++;
178 }
179 
180 void
182 {
183  NS_LOG_FUNCTION (this);
184  brite::Graph *g = m_topology->GetGraph ();
185  std::list<brite::Edge*>::iterator el;
186  std::list<brite::Edge*> edgeList = g->GetEdges ();
187 
188  for (el = edgeList.begin (); el != edgeList.end (); el++)
189  {
190  BriteEdgeInfo edgeInfo;
191  edgeInfo.edgeId = (*el)->GetId ();
192  edgeInfo.srcId = (*el)->GetSrc ()->GetId ();
193  edgeInfo.destId = (*el)->GetDst ()->GetId ();
194  edgeInfo.length = (*el)->Length ();
195 
196  switch ((*el)->GetConf ()->GetEdgeType ())
197  {
198  case brite::EdgeConf::RT_EDGE:
199  edgeInfo.delay = ((brite::RouterEdgeConf*)((*el)->GetConf ()))->GetDelay ();
200  edgeInfo.bandwidth = (*el)->GetConf ()->GetBW ();
201  //If there is only one AS, BRITE will use -1 as AS Number. We want it to be 0 instead.
202  edgeInfo.asFrom = (((brite::RouterNodeConf*)((*el)->GetSrc ()->GetNodeInfo ()))->GetASId () == -1) ? 0 : ((brite::RouterNodeConf*)((*el)->GetSrc ()->GetNodeInfo ()))->GetASId ();
203  edgeInfo.asTo = (((brite::RouterNodeConf*)((*el)->GetDst ()->GetNodeInfo ()))->GetASId () == -1) ? 0 : ((brite::RouterNodeConf*)((*el)->GetDst ()->GetNodeInfo ()))->GetASId ();
204  break;
205 
206  case brite::EdgeConf::AS_EDGE:
207  edgeInfo.delay = -1; /* No delay for AS Edges */
208  edgeInfo.bandwidth = (*el)->GetConf ()->GetBW ();
209  edgeInfo.asFrom = ((brite::ASNodeConf*)((*el)->GetSrc ()->GetNodeInfo ()))->GetASId ();
210  edgeInfo.asTo = ((brite::ASNodeConf*)((*el)->GetDst ()->GetNodeInfo ()))->GetASId ();
211  break;
212 
213  default:
214  NS_FATAL_ERROR ("Topology::Output(): Invalid Edge type encountered...");
215  }
216 
217  switch ((*el)->GetConf ()->GetEdgeType ())
218  {
219  case brite::EdgeConf::RT_EDGE:
220  switch (((brite::RouterEdgeConf*)(*el)->GetConf ())->GetRouterEdgeType ())
221  {
222  case brite::RouterEdgeConf::RT_NONE:
223  edgeInfo.type = "E_RT_NONE ";
224  break;
225  case brite::RouterEdgeConf::RT_STUB:
226  edgeInfo.type = "E_RT_STUB ";
227  break;
228  case brite::RouterEdgeConf::RT_BORDER:
229  edgeInfo.type = "E_RT_BORDER ";
230  break;
231  case brite::RouterEdgeConf::RT_BACKBONE:
232  edgeInfo.type = "E_RT_BACKBONE ";
233  break;
234  default:
235  NS_FATAL_ERROR ("Output(): Invalid router edge type...");
236  }
237  break;
238 
239  case brite::EdgeConf::AS_EDGE:
240  switch (((brite::ASEdgeConf*)((*el)->GetConf ()))->GetASEdgeType ())
241  {
242  case brite::ASEdgeConf::AS_NONE:
243  edgeInfo.type = "E_AS_NONE ";
244  break;
245  case brite::ASEdgeConf::AS_STUB:
246  edgeInfo.type = "E_AS_STUB ";
247  break;
248  case brite::ASEdgeConf::AS_BORDER:
249  edgeInfo.type = "E_AS_BORDER ";
250  break;
251  case brite::ASEdgeConf::AS_BACKBONE:
252  edgeInfo.type = "E_AS_BACKBONE ";
253  break;
254  default:
255  NS_FATAL_ERROR ("BriteOutput(): Invalid AS edge type...");
256  }
257  break;
258 
259  default:
260  NS_FATAL_ERROR ("BriteOutput(): Invalid edge type...");
261 
262  }
263 
264  m_briteEdgeInfoList.push_back (edgeInfo);
265  }
266 }
267 
268 Ptr<Node>
269 BriteTopologyHelper::GetLeafNodeForAs (uint32_t asNum, uint32_t leafNum)
270 {
271  return m_asLeafNodes[asNum]->Get (leafNum);
272 }
273 
274 Ptr<Node>
275 BriteTopologyHelper::GetNodeForAs (uint32_t asNum, uint32_t nodeNum)
276 {
277  return m_nodesByAs[asNum]->Get (nodeNum);
278 }
279 
280 uint32_t
281 BriteTopologyHelper::GetNNodesForAs (uint32_t asNum)
282 {
283  return m_nodesByAs[asNum]->GetN ();
284 }
285 
286 uint32_t
287 BriteTopologyHelper::GetNLeafNodesForAs (uint32_t asNum)
288 {
289  return m_asLeafNodes[asNum]->GetN ();
290 }
291 
292 uint32_t
294 {
295  return m_numNodes;
296 }
297 
298 uint32_t
300 {
301  return m_numEdges;
302 }
303 
304 uint32_t
306 {
307  return m_numAs;
308 }
309 
310 uint32_t
312 {
313  return m_systemForAs[asNum];
314 }
315 
317 {
318  NS_ASSERT_MSG (m_topology == NULL, "Brite Topology Already Created");
319 
320  //check to see if need to generate seed file
321  bool generateSeedFile = m_seedFile.empty ();
322 
323  if (generateSeedFile)
324  {
325  NS_LOG_LOGIC ("Generating BRITE Seed file");
326 
327  std::ofstream seedFile;
328 
329  //overwrite file if already there
330  seedFile.open ("briteSeedFile.txt", std::ios_base::out | std::ios_base::trunc);
331 
332  //verify open
333  NS_ASSERT (!seedFile.fail ());
334 
335  //Generate seed file expected by BRITE
336  //need unsigned shorts 0-65535
337  seedFile << "PLACES " << m_uv->GetInteger (0, 65535) << " " << m_uv->GetInteger (0, 65535) << " " << m_uv->GetInteger (0, 65535) << std::endl;
338  seedFile << "CONNECT " << m_uv->GetInteger (0, 65535) << " " << m_uv->GetInteger (0, 65535) << " " << m_uv->GetInteger (0, 65535) << std::endl;
339  seedFile << "EDGE_CONN " << m_uv->GetInteger (0, 65535) << " " << m_uv->GetInteger (0, 65535) << " " << m_uv->GetInteger (0, 65535) << std::endl;
340  seedFile << "GROUPING " << m_uv->GetInteger (0, 65535) << " " << m_uv->GetInteger (0, 65535) << " " << m_uv->GetInteger (0, 65535) << std::endl;
341  seedFile << "ASSIGNMENT " << m_uv->GetInteger (0, 65535) << " " << m_uv->GetInteger (0, 65535) << " " << m_uv->GetInteger (0, 65535) << std::endl;
342  seedFile << "BANDWIDTH " << m_uv->GetInteger (0, 65535) << " " << m_uv->GetInteger (0, 65535) << " " << m_uv->GetInteger (0, 65535) << std::endl;
343  seedFile.close ();
344 
345  //if we're using NS3 generated seed files don't want brite to create a new seed file.
346  m_seedFile = m_newSeedFile = "briteSeedFile.txt";
347  }
348 
349  brite::Brite br (m_confFile, m_seedFile, m_newSeedFile);
350  m_topology = br.GetTopology ();
351  BuildBriteNodeInfoList ();
352  BuildBriteEdgeInfoList ();
353 
354  //brite automatically spits out the seed values used to a seperate file so no need to keep this anymore
355  if (generateSeedFile)
356  {
357  remove ("briteSeedFile.txt");
358  }
359 
360 }
361 
362 void
363 BriteTopologyHelper::BuildBriteTopology (InternetStackHelper& stack)
364 {
365  NS_LOG_FUNCTION (this);
366 
367  GenerateBriteTopology ();
368 
369  //not using MPI so each AS is on system number 0
370  for (uint32_t i = 0; i < m_numAs; ++i)
371  {
372  m_systemForAs.push_back (0);
373  }
374 
375  //create all nodes with system number 0
376  m_nodes.Create (m_briteNodeInfoList.size ());
377 
378  m_numNodes = m_briteNodeInfoList.size ();
379 
380  NS_LOG_DEBUG (m_numNodes << " nodes created in BRITE topology");
381 
382  stack.Install (m_nodes);
383 
384  ConstructTopology ();
385 }
386 
387 void
388 BriteTopologyHelper::BuildBriteTopology (InternetStackHelper& stack, const uint32_t systemCount)
389 {
390  NS_LOG_FUNCTION (this);
391 
392  GenerateBriteTopology ();
393 
394  //determine as system number for each AS
395  NS_LOG_LOGIC ("Assigning << " << m_numAs << " AS to " << systemCount << " MPI instances");
396  for (uint32_t i = 0; i < m_numAs; ++i)
397  {
398  int val = i % systemCount;
399  m_systemForAs.push_back (val);
400  NS_LOG_INFO ("AS: " << i << " System: " << val);
401  }
402 
403  //create nodes
404  for (BriteTopologyHelper::BriteNodeInfoList::iterator it = m_briteNodeInfoList.begin (); it != m_briteNodeInfoList.end (); ++it)
405  {
406  m_nodes.Add (CreateObject<Node> (GetSystemNumberForAs ((*it).asId)));
407  m_numNodes++;
408  }
409 
410  NS_LOG_INFO (m_numNodes << " nodes created in BRITE topology");
411 
412  stack.Install (m_nodes);
413 
414  ConstructTopology ();
415 }
416 
417 void
419 {
420  NS_LOG_FUNCTION (this);
421  //assign IPs
422  for (unsigned int i = 0; i < m_netDevices.size (); ++i)
423  {
424  address.Assign (*m_netDevices[i]);
425  address.NewNetwork ();
426  }
427 }
428 
429 void
431 {
432  NS_LOG_FUNCTION (this);
433 
434  for (unsigned int i = 0; i < m_netDevices.size (); ++i)
435  {
436  address.Assign (*m_netDevices[i]);
437  address.NewNetwork ();
438  }
439 }
440 
441 void
443 {
444  NS_LOG_FUNCTION (this);
445  //create one node container to hold leaf nodes for attaching
446  for (uint32_t i = 0; i < m_numAs; ++i)
447  {
448  m_asLeafNodes.push_back (new NodeContainer ());
449  m_nodesByAs.push_back (new NodeContainer ());
450  }
451 
452  for (BriteTopologyHelper::BriteEdgeInfoList::iterator it = m_briteEdgeInfoList.begin (); it != m_briteEdgeInfoList.end (); ++it)
453  {
454  // Set the link delay
455  // The brite value for delay is given in milliseconds
456  m_britePointToPointHelper.SetChannelAttribute ("Delay",
457  TimeValue (MilliSeconds ((*it).delay)));
458 
459  // The brite value for data rate is given in Mbps
460  m_britePointToPointHelper.SetDeviceAttribute ("DataRate",
461  DataRateValue (DataRate ((*it).bandwidth * mbpsToBps)));
462 
463  m_netDevices.push_back ( new NetDeviceContainer ( m_britePointToPointHelper.Install (m_nodes.Get ((*it).srcId), m_nodes.Get ((*it).destId))));
464 
465  m_numEdges++;
466 
467  }
468 
469  NS_LOG_INFO ("Created " << m_numEdges << " edges in BRITE topology");
470 
471  //iterate through all nodes and add leaf nodes for each AS
472  for (BriteTopologyHelper::BriteNodeInfoList::iterator it = m_briteNodeInfoList.begin (); it != m_briteNodeInfoList.end (); ++it)
473  {
474  m_nodesByAs[(*it).asId]->Add (m_nodes.Get ((*it).nodeId));
475 
476  if ((*it).type == "RT_LEAF ")
477  {
478  m_asLeafNodes[(*it).asId]->Add (m_nodes.Get ((*it).nodeId));
479  }
480  }
481 }
482 
483 } // namespace ns3
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
#define NS_ASSERT(condition)
Definition: assert.h:64
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:122
uint32_t GetNAs(void) const
aggregate IP/TCP/UDP functionality to existing Nodes.
void AssignIpv6Addresses(Ipv6AddressHelper &address)
#define NS_LOG_INFO(msg)
Definition: log.h:264
#define NS_FATAL_ERROR(msg)
fatal error handling
Definition: fatal-error.h:72
Ipv6InterfaceContainer Assign(const NetDeviceContainer &c)
Allocate an Ipv6InterfaceContainer with auto-assigned addresses.
Class for representing data rates.
Definition: data-rate.h:71
hold objects of type ns3::Time
Definition: nstime.h:700
void AssignIpv4Addresses(Ipv4AddressHelper &address)
holds a vector of ns3::NetDevice pointers
#define NS_LOG_LOGIC(msg)
Definition: log.h:334
keep track of a set of node pointers.
void Install(std::string nodeName) const
Helper class to auto-assign global IPv6 unicast addresses.
#define NS_ASSERT_MSG(condition, message)
Definition: assert.h:86
Ipv4InterfaceContainer Assign(const NetDeviceContainer &c)
Assign IP addresses to the net devices specified in the container based on the current network prefix...
uint32_t GetSystemNumberForAs(uint32_t asNum) const
hold objects of type ns3::DataRate
#define NS_LOG_DEBUG(msg)
Definition: log.h:255
Ipv4Address NewNetwork(void)
Increment the network number and reset the IP address counter to the base value provided in the SetBa...
void NewNetwork(Ipv6Address network, Ipv6Prefix prefix) NS_DEPRECATED
Allocate a new network.
Time MilliSeconds(uint64_t ms)
create ns3::Time instances in units of milliseconds.
Definition: nstime.h:601
A helper class to make life easier while doing simple IPv4 address assignment in scripts.