NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.5: NDN, CCN, CCNx, content centric networks
API Documentation
rocketfuel-map-reader.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
20 // Based on the code by Hajime Tazaki <tazaki@sfc.wide.ad.jp>
21 
23 
24 #include "ns3/nstime.h"
25 #include "ns3/log.h"
26 #include "ns3/fatal-error.h"
27 #include "ns3/assert.h"
28 #include "ns3/names.h"
29 #include "ns3/net-device-container.h"
30 #include "ns3/point-to-point-helper.h"
31 #include "ns3/point-to-point-net-device.h"
32 #include "ns3/internet-stack-helper.h"
33 #include "ns3/ipv4-address-helper.h"
34 #include "ns3/ipv4-global-routing-helper.h"
35 #include "ns3/drop-tail-queue.h"
36 #include "ns3/ipv4-interface.h"
37 #include "ns3/ipv4.h"
38 #include "ns3/string.h"
39 #include "ns3/pointer.h"
40 #include "ns3/uinteger.h"
41 #include "ns3/ipv4-address.h"
42 #include "ns3/node-list.h"
43 
44 #include "ns3/mobility-model.h"
45 
46 #include <regex.h>
47 
48 #include <boost/foreach.hpp>
49 #include <boost/lexical_cast.hpp>
50 
51 #include <boost/graph/graphviz.hpp>
52 #include <boost/graph/connected_components.hpp>
53 
54 #include <iomanip>
55 
56 using namespace std;
57 using namespace boost;
58 
59 NS_LOG_COMPONENT_DEFINE("RocketfuelMapReader");
60 
61 namespace ns3 {
62 
63 RocketfuelMapReader::RocketfuelMapReader(const std::string& path /*=""*/, double scale /*=1.0*/,
64  const std::string& referenceOspfRate)
65  : AnnotatedTopologyReader(path, scale)
66  , m_randVar(CreateObject<UniformRandomVariable>())
67  , m_referenceOspfRate(boost::lexical_cast<DataRate>(referenceOspfRate))
68 {
69 }
70 
72 {
73 }
74 
75 NodeContainer
77 {
78  NS_FATAL_ERROR("Deprecated call. Use the other overloaded method instead");
79  return NodeContainer();
80 }
81 
82 /* uid @loc [+] [bb] (num_neigh) [&ext] -> <nuid-1> <nuid-2> ... {-euid} ... =name[!] rn */
83 
84 #define REGMATCH_MAX 16
85 
86 #define START "^"
87 #define END "$"
88 #define SPACE "[ \t]+"
89 #define MAYSPACE "[ \t]*"
90 
91 #define ROCKETFUEL_MAPS_LINE \
92  START "(-*[0-9]+)" SPACE "(@[?A-Za-z0-9,+]+)" SPACE "(\\+)*" MAYSPACE "(bb)*" MAYSPACE \
93  "\\(([0-9]+)\\)" SPACE "(&[0-9]+)*" MAYSPACE "->" MAYSPACE "(<[0-9 \t<>]+>)*" MAYSPACE \
94  "(\\{-[0-9\\{\\} \t-]+\\})*" SPACE "=([A-Za-z0-9.!-]+)" SPACE "r([0-9])" MAYSPACE END
95 
96 void
97 RocketfuelMapReader::CreateLink(string nodeName1, string nodeName2, double averageRtt,
98  const string& minBw, const string& maxBw, const string& minDelay,
99  const string& maxDelay)
100 {
101  Ptr<Node> node1 = Names::Find<Node>(m_path, nodeName1);
102  Ptr<Node> node2 = Names::Find<Node>(m_path, nodeName2);
103  Link link(node1, nodeName1, node2, nodeName2);
104 
105  DataRate randBandwidth(
106  m_randVar->GetInteger(static_cast<uint32_t>(lexical_cast<DataRate>(minBw).GetBitRate()),
107  static_cast<uint32_t>(lexical_cast<DataRate>(maxBw).GetBitRate())));
108 
109  int32_t metric = std::max(1, static_cast<int32_t>(1.0 * m_referenceOspfRate.GetBitRate()
110  / randBandwidth.GetBitRate()));
111 
112  Time randDelay =
113  Time::FromDouble((m_randVar->GetValue(lexical_cast<Time>(minDelay).ToDouble(Time::US),
114  lexical_cast<Time>(maxDelay).ToDouble(Time::US))),
115  Time::US);
116 
117  uint32_t queue = ceil(averageRtt * (randBandwidth.GetBitRate() / 8.0 / 1100.0));
118 
119  link.SetAttribute("DataRate", boost::lexical_cast<string>(randBandwidth));
120  link.SetAttribute("OSPF", boost::lexical_cast<string>(metric));
121  link.SetAttribute("Delay",
122  boost::lexical_cast<string>(ceil(randDelay.ToDouble(Time::US))) + "us");
123  link.SetAttribute("MaxPackets", boost::lexical_cast<string>(queue));
124 
125  AddLink(link);
126 }
127 
128 // NodeContainer
129 void
130 RocketfuelMapReader::GenerateFromMapsFile(int argc, char* argv[])
131 {
132  string uid;
133  string loc;
134  string ptr;
135  string name;
136  string nuid;
137  // bool dns = false;
138  // bool bb = false;
139  int num_neigh_s = 0;
140  unsigned int num_neigh = 0;
141  int radius = 0;
142  vector<string> neigh_list;
143 
144  uid = argv[0];
145  loc = argv[1];
146 
147  // if (argv[2])
148  // {
149  // dns = true;
150  // }
151 
152  // if (argv[3])
153  // {
154  // bb = true;
155  // }
156 
157  num_neigh_s = ::atoi(argv[4]);
158  if (num_neigh_s < 0) {
159  num_neigh = 0;
160  NS_LOG_WARN("Negative number of neighbors given");
161  }
162  else {
163  num_neigh = num_neigh_s;
164  }
165 
166  /* neighbors */
167  if (argv[6]) {
168  char* nbr;
169  char* stringp = argv[6];
170  while ((nbr = strsep(&stringp, " \t")) != NULL) {
171  nbr[strlen(nbr) - 1] = '\0';
172  neigh_list.push_back(nbr + 1);
173  }
174  }
175 
176  if (num_neigh != neigh_list.size()) {
177  NS_LOG_WARN("Given number of neighbors = " << num_neigh << " != size of neighbors list = "
178  << neigh_list.size());
179  }
180 
181  /* externs */
182  if (argv[7]) {
183  // euid = argv[7];
184  }
185 
186  /* name */
187  if (argv[8]) {
188  name = argv[8];
189  }
190 
191  radius = ::atoi(&argv[9][1]);
192  if (radius > 0) {
193  return;
194  }
195 
196  // Create node and link
197  if (uid.empty())
198  return;
199 
200  node_map_t::iterator node = m_graphNodes.find(uid);
201  if (node == m_graphNodes.end()) {
202  bool ok;
203  tie(node, ok) = m_graphNodes.insert(make_pair(uid, add_vertex(nodeProperty(uid), m_graph)));
204  NS_ASSERT(ok == true);
205 
206  put(vertex_index, m_graph, node->second, m_maxNodeId);
207  m_maxNodeId++;
208  }
209 
210  for (uint32_t i = 0; i < neigh_list.size(); ++i) {
211  nuid = neigh_list[i];
212 
213  if (nuid.empty()) {
214  continue;
215  }
216 
217  node_map_t::iterator otherNode = m_graphNodes.find(nuid);
218  if (otherNode == m_graphNodes.end()) {
219  bool ok;
220  tie(otherNode, ok) =
221  m_graphNodes.insert(make_pair(nuid, add_vertex(nodeProperty(nuid), m_graph)));
222  NS_ASSERT(ok == true);
223 
224  put(vertex_index, m_graph, otherNode->second, m_maxNodeId);
225  m_maxNodeId++;
226  }
227 
228  // cout << node->second << " <-> " << otherNode->second << endl;
229  // parallel edges are disabled in the graph, so no need to worry
230  add_edge(node->second, otherNode->second, m_graph);
231  }
232 }
233 
234 void
235 RocketfuelMapReader::assignGw(Traits::vertex_descriptor vertex, uint32_t degree,
236  node_type_t nodeType)
237 {
238  graph_traits<Graph>::adjacency_iterator u, endu;
239  for (tie(u, endu) = adjacent_vertices(vertex, m_graph); u != endu; u++) {
240  if (get(vertex_rank, m_graph, *u) != UNKNOWN)
241  continue;
242 
243  put(vertex_rank, m_graph, *u, nodeType);
244  put(vertex_color, m_graph, *u, "green");
245 
246  uint32_t u_degree = out_degree(*u, m_graph);
247  if (u_degree < degree)
248  assignGw(*u, degree, BACKBONE);
249  }
250 };
251 
252 void
253 RocketfuelMapReader::AssignClients(uint32_t clientDegree, uint32_t gwDegree)
254 {
255  graph_traits<Graph>::vertex_iterator v, endv;
256  for (tie(v, endv) = vertices(m_graph); v != endv; v++) {
257  uint32_t degree = out_degree(*v, m_graph);
258  if (degree == clientDegree) {
259  put(vertex_rank, m_graph, *v, CLIENT);
260  put(vertex_color, m_graph, *v, "red");
261 
262  assignGw(*v, gwDegree + 1, GATEWAY);
263  }
264  }
265 };
266 
267 NodeContainer
268 RocketfuelMapReader::Read(RocketfuelParams params, bool keepOneComponent /*=true*/,
269  bool connectBackbones /*=true*/)
270 {
271  m_maxNodeId = 0;
272 
273  ifstream topgen;
274  topgen.open(GetFileName().c_str());
275  // NodeContainer nodes;
276 
277  istringstream lineBuffer;
278  string line;
279  int lineNumber = 0;
280  char errbuf[512];
281 
282  if (!topgen.is_open()) {
283  NS_LOG_WARN("Couldn't open the file " << GetFileName());
284  return m_nodes;
285  }
286 
287  while (!topgen.eof()) {
288  int ret;
289  int argc;
290  char* argv[REGMATCH_MAX];
291  char* buf;
292 
293  lineNumber++;
294  line.clear();
295  lineBuffer.clear();
296 
297  getline(topgen, line);
298  buf = (char*)line.c_str();
299 
300  regmatch_t regmatch[REGMATCH_MAX];
301  regex_t regex;
302 
303  ret = regcomp(&regex, ROCKETFUEL_MAPS_LINE, REG_EXTENDED | REG_NEWLINE);
304  if (ret != 0) {
305  regerror(ret, &regex, errbuf, sizeof(errbuf));
306  regfree(&regex);
307  continue;
308  }
309 
310  ret = regexec(&regex, buf, REGMATCH_MAX, regmatch, 0);
311  if (ret == REG_NOMATCH) {
312  NS_LOG_WARN("match failed (maps file): %s" << buf);
313  regfree(&regex);
314  continue;
315  }
316 
317  line = buf;
318  argc = 0;
319 
320  /* regmatch[0] is the entire strings that matched */
321  for (int i = 1; i < REGMATCH_MAX; i++) {
322  if (regmatch[i].rm_so == -1) {
323  argv[i - 1] = NULL;
324  }
325  else {
326  line[regmatch[i].rm_eo] = '\0';
327  argv[i - 1] = &line[regmatch[i].rm_so];
328  argc = i;
329  }
330  }
331 
332  GenerateFromMapsFile(argc, argv);
333  regfree(&regex);
334  }
335 
336  if (keepOneComponent) {
337  NS_LOG_DEBUG("Before eliminating disconnected nodes: " << num_vertices(m_graph));
338  KeepOnlyBiggestConnectedComponent();
339  NS_LOG_DEBUG("After eliminating disconnected nodes: " << num_vertices(m_graph));
340  }
341 
342  for (int clientDegree = 1; clientDegree <= params.clientNodeDegrees; clientDegree++) {
343  AssignClients(clientDegree, std::min(clientDegree, 3));
344  }
345 
346  graph_traits<Graph>::vertex_iterator v, endv;
347  for (tie(v, endv) = vertices(m_graph); v != endv; v++) {
348  node_type_t type = get(vertex_rank, m_graph, *v);
349  if (type == UNKNOWN) {
350  put(vertex_rank, m_graph, *v, BACKBONE);
351  put(vertex_color, m_graph, *v, "blue");
352  }
353  }
354 
355  if (connectBackbones) {
356  ConnectBackboneRouters();
357  }
358 
359  graph_traits<Graph>::edge_iterator e, ende;
360  for (tie(e, ende) = edges(m_graph); e != ende;) {
361  Traits::vertex_descriptor u = source(*e, m_graph), v = target(*e, m_graph);
362 
363  node_type_t u_type = get(vertex_rank, m_graph, u), v_type = get(vertex_rank, m_graph, v);
364 
365  if (u_type == BACKBONE && v_type == BACKBONE) {
366  // ok
367  }
368  else if ((u_type == GATEWAY && v_type == BACKBONE)
369  || (u_type == BACKBONE && v_type == GATEWAY)) {
370  // ok
371  }
372  else if (u_type == GATEWAY && v_type == GATEWAY) {
373  // ok
374  }
375  else if ((u_type == GATEWAY && v_type == CLIENT) || (u_type == CLIENT && v_type == GATEWAY)) {
376  // ok
377  }
378  else {
379  // not ok
380  NS_LOG_DEBUG("Wrong link type between nodes: " << u_type << " <-> " << v_type
381  << " (deleting the link)");
382 
383  graph_traits<Graph>::edge_iterator tmp = e;
384  tmp++;
385 
386  remove_edge(*e, m_graph);
387  e = tmp;
388  continue;
389  }
390  e++;
391  }
392 
393  if (keepOneComponent) {
394  NS_LOG_DEBUG("Before 2 eliminating disconnected nodes: " << num_vertices(m_graph));
395  KeepOnlyBiggestConnectedComponent();
396  NS_LOG_DEBUG("After 2 eliminating disconnected nodes: " << num_vertices(m_graph));
397  }
398 
399  for (tie(v, endv) = vertices(m_graph); v != endv; v++) {
400  string nodeName = get(vertex_name, m_graph, *v);
401  Ptr<Node> node = CreateNode(nodeName, 0);
402 
403  node_type_t type = get(vertex_rank, m_graph, *v);
404  switch (type) {
405  case BACKBONE:
406  Names::Rename(nodeName, "bb-" + nodeName);
407  put(vertex_name, m_graph, *v, "bb-" + nodeName);
408  m_backboneRouters.Add(node);
409  break;
410  case CLIENT:
411  Names::Rename(nodeName, "leaf-" + nodeName);
412  put(vertex_name, m_graph, *v, "leaf-" + nodeName);
413  m_customerRouters.Add(node);
414  break;
415  case GATEWAY:
416  Names::Rename(nodeName, "gw-" + nodeName);
417  put(vertex_name, m_graph, *v, "gw-" + nodeName);
418  m_gatewayRouters.Add(node);
419  break;
420  case UNKNOWN:
421  NS_FATAL_ERROR("Should not happen");
422  break;
423  }
424  }
425 
426  for (tie(e, ende) = edges(m_graph); e != ende; e++) {
427  Traits::vertex_descriptor u = source(*e, m_graph), v = target(*e, m_graph);
428 
429  node_type_t u_type = get(vertex_rank, m_graph, u), v_type = get(vertex_rank, m_graph, v);
430 
431  string u_name = get(vertex_name, m_graph, u), v_name = get(vertex_name, m_graph, v);
432 
433  if (u_type == BACKBONE && v_type == BACKBONE) {
434  CreateLink(u_name, v_name, params.averageRtt, params.minb2bBandwidth, params.maxb2bBandwidth,
435  params.minb2bDelay, params.maxb2bDelay);
436  }
437  else if ((u_type == GATEWAY && v_type == BACKBONE)
438  || (u_type == BACKBONE && v_type == GATEWAY)) {
439  CreateLink(u_name, v_name, params.averageRtt, params.minb2gBandwidth, params.maxb2gBandwidth,
440  params.minb2gDelay, params.maxb2gDelay);
441  }
442  else if (u_type == GATEWAY && v_type == GATEWAY) {
443  CreateLink(u_name, v_name, params.averageRtt, params.minb2gBandwidth, params.maxb2gBandwidth,
444  params.minb2gDelay, params.maxb2gDelay);
445  }
446  else if ((u_type == GATEWAY && v_type == CLIENT) || (u_type == CLIENT && v_type == GATEWAY)) {
447  CreateLink(u_name, v_name, params.averageRtt, params.ming2cBandwidth, params.maxg2cBandwidth,
448  params.ming2cDelay, params.maxg2cDelay);
449  }
450  else {
451  NS_FATAL_ERROR("Wrong link type between nodes: " << u_type << " <-> " << v_type);
452  }
453  }
454 
455  ApplySettings();
456 
457  NS_LOG_INFO("Clients: " << m_customerRouters.GetN());
458  NS_LOG_INFO("Gateways: " << m_gatewayRouters.GetN());
459  NS_LOG_INFO("Backbones: " << m_backboneRouters.GetN());
460  NS_LOG_INFO("Links: " << GetLinks().size());
461 
462  return m_nodes;
463 }
464 
465 const NodeContainer&
467 {
468  return m_backboneRouters;
469 }
470 
471 const NodeContainer&
473 {
474  return m_gatewayRouters;
475 }
476 
477 const NodeContainer&
479 {
480  return m_customerRouters;
481 }
482 
483 static void
484 nodeWriter(std::ostream& os, NodeContainer& m)
485 {
486  for (NodeContainer::Iterator node = m.Begin(); node != m.End(); node++) {
487  std::string name = Names::FindName(*node);
488 
489  os << name << "\t"
490  << "NA"
491  << "\t" << 0 << "\t" << 0 << "\n";
492  }
493 };
494 
495 void
496 RocketfuelMapReader::SaveTopology(const std::string& file)
497 {
498  ofstream os(file.c_str(), ios::trunc);
499  os << "# any empty lines and lines starting with '#' symbol is ignored\n"
500  << "\n"
501  << "# The file should contain exactly two sections: router and link, each starting with the "
502  "corresponding keyword\n"
503  << "\n"
504  << "# router section defines topology nodes and their relative positions (e.g., to use in "
505  "visualizer)\n"
506  << "router\n"
507  << "\n"
508  << "# each line in this section represents one router and should have the following data\n"
509  << "# node comment yPos xPos\n";
510 
511  nodeWriter(os, m_backboneRouters);
512  nodeWriter(os, m_gatewayRouters);
513  nodeWriter(os, m_customerRouters);
514 
515  os << "# link section defines point-to-point links between nodes and characteristics of these "
516  "links\n"
517  << "\n"
518  << "link\n"
519  << "\n"
520  << "# Each line should be in the following format (only first two are required, the rest can "
521  "be omitted)\n"
522  << "# srcNode dstNode bandwidth metric delay queue\n"
523  << "# bandwidth: link bandwidth\n"
524  << "# metric: routing metric\n"
525  << "# delay: link delay\n"
526  << "# queue: MaxPackets for transmission queue on the link (both directions)\n";
527 
528  for (std::list<Link>::iterator link = m_linksList.begin(); link != m_linksList.end(); link++) {
529  string src = Names::FindName(link->GetFromNode());
530  string dst = Names::FindName(link->GetToNode());
531  os << src << "\t";
532  os << dst << "\t";
533 
534  string tmp;
535  if (link->GetAttributeFailSafe("DataRate", tmp))
536  os << link->GetAttribute("DataRate") << "\t";
537  else
538  NS_FATAL_ERROR("DataRate must be specified for the link");
539 
540  if (link->GetAttributeFailSafe("OSPF", tmp))
541  os << link->GetAttribute("OSPF") << "\t";
542  else {
543  DataRate rate = boost::lexical_cast<DataRate>(link->GetAttribute("DataRate"));
544 
545  int32_t cost = std::max(1, static_cast<int32_t>(1.0 * m_referenceOspfRate.GetBitRate()
546  / rate.GetBitRate()));
547 
548  os << cost << "\t";
549  }
550 
551  if (link->GetAttributeFailSafe("Delay", tmp)) {
552  os << link->GetAttribute("Delay") << "\t";
553 
554  if (link->GetAttributeFailSafe("MaxPackets", tmp)) {
555  os << link->GetAttribute("MaxPackets") << "\t";
556  }
557  }
558  os << "\n";
559  }
560 }
561 
563 
564 template<class Names, class Colors>
565 class name_color_writer {
566 public:
567  name_color_writer(Names _names, Colors _colors)
568  : names(_names)
569  , colors(_colors)
570  {
571  }
572 
573  template<class VertexOrEdge>
574  void
575  operator()(std::ostream& out, const VertexOrEdge& v) const
576  {
577  // out << "[label=\"" << names[v] << "\",style=filled,fillcolor=\"" << colors[v] << "\"]";
578  out << "[shape=\"circle\",width=0.1,label=\"\",style=filled,fillcolor=\"" << colors[v] << "\"]";
579  }
580 
581 private:
582  Names names;
583  Colors colors;
584 };
585 
586 template<class Names, class Colors>
587 inline name_color_writer<Names, Colors>
588 make_name_color_writer(Names n, Colors c)
589 {
590  return name_color_writer<Names, Colors>(n, c);
591 }
592 
594 
595 void
596 RocketfuelMapReader::SaveGraphviz(const std::string& file)
597 {
598  ofstream of(file.c_str());
599  property_map<Graph, vertex_name_t>::type names = get(vertex_name, m_graph);
600  property_map<Graph, vertex_color_t>::type colors = get(vertex_color, m_graph);
601  write_graphviz(of, m_graph, make_name_color_writer(names, colors));
602 }
603 
604 void
605 RocketfuelMapReader::KeepOnlyBiggestConnectedComponent()
606 {
607  std::map<graph_traits<Graph>::vertex_descriptor, int> temp;
608  associative_property_map<std::map<graph_traits<Graph>::vertex_descriptor, int>> components(temp);
609 
610  // //check if topology has breaks in its structure and trim it if yes
611  // property_map<Graph, vertex_index1_t>::type components = get (vertex_index1, m_graph);
612 
613  int num = connected_components(m_graph, components);
614  NS_LOG_DEBUG("Topology has " << num << " components");
615 
616  vector<int> sizes(num, 0);
617 
618  graph_traits<Graph>::vertex_iterator v, endv;
619  for (tie(v, endv) = vertices(m_graph); v != endv; v++) {
620  sizes[get(components, *v)]++;
621  }
622  int largestComponent = max_element(sizes.begin(), sizes.end()) - sizes.begin();
623  // cout << "Largest: " << largestComponent << endl;
624 
625  // for (int i =0 ; i < num; i++) cout << sizes[i] << " ";
626  // cout << endl;
627 
629  // remove nodes and edges from smaller components //
631  for (tie(v, endv) = vertices(m_graph); v != endv; v++) {
632  if (get(components, *v) == largestComponent)
633  continue;
634 
635  clear_vertex(*v, m_graph);
636  }
637 
638  // this works only if vertices are organized in listS or setS (iterator is not invalidated on
639  // remove)
640  for (tie(v, endv) = vertices(m_graph); v != endv;) {
641  if (get(components, *v) == largestComponent) {
642  v++;
643  continue;
644  }
645 
646  graph_traits<Graph>::vertex_iterator tmp = v;
647  tmp++;
648 
649  remove_vertex(*v, m_graph);
650  v = tmp;
651  }
652 
653  int index = 0;
654  // renumber nodes
655  for (tie(v, endv) = vertices(m_graph); v != endv; v++) {
656  put(vertex_index, m_graph, *v, index++);
657  }
658 }
659 
660 void
661 RocketfuelMapReader::ConnectBackboneRouters()
662 {
663  // not the tricky part. we want backbone to be a fully connected component,
664  // so traffic doesn't bounce from backbone to gateway and back
665 
666  typedef adjacency_list<setS, setS, boost::undirectedS,
667  property<vertex_name_t, Traits::vertex_descriptor,
668  property<vertex_index_t, int, property<vertex_index1_t, int>>>>
669  BbGraph;
670  BbGraph bbGraph;
671  map<Traits::vertex_descriptor, graph_traits<BbGraph>::vertex_descriptor> nodeMap;
672 
673  int index = 0;
674 
675  graph_traits<Graph>::vertex_iterator v, endv;
676  for (tie(v, endv) = vertices(m_graph); v != endv; v++) {
677  node_type_t type = get(vertex_rank, m_graph, *v);
678  if (type == BACKBONE) {
679  graph_traits<BbGraph>::vertex_descriptor newv = add_vertex(*v, bbGraph);
680  put(vertex_index, bbGraph, newv, index++);
681  nodeMap[*v] = newv;
682  }
683  }
684 
685  graph_traits<BbGraph>::vertex_iterator bb, endBb;
686  for (tie(bb, endBb) = vertices(bbGraph); bb != endBb; bb++) {
687  Traits::vertex_descriptor actualVertex = get(vertex_name, bbGraph, *bb);
688 
689  graph_traits<Graph>::adjacency_iterator u, endu;
690  for (tie(u, endu) = adjacent_vertices(actualVertex, m_graph); u != endu; u++) {
691  if (nodeMap.find(*u) != nodeMap.end()) {
692  add_edge(nodeMap[actualVertex], nodeMap[*u], bbGraph);
693  }
694  }
695  }
696 
697  property_map<BbGraph, vertex_index1_t>::type components = get(vertex_index1, bbGraph);
698 
699  int num = connected_components(bbGraph, components);
700  NS_LOG_DEBUG("Backbone has " << num << " components");
701  if (num == 1)
702  return; // nothing to do
703 
704  vector<vector<graph_traits<BbGraph>::vertex_descriptor>> subgraphs(num);
705  for (tie(bb, endBb) = vertices(bbGraph); bb != endBb; bb++) {
706  int component = get(vertex_index1, bbGraph, *bb);
707  subgraphs[component].push_back(*bb);
708  }
709 
710  Ptr<UniformRandomVariable> randVar = CreateObject<UniformRandomVariable>();
711 
712  for (int i = 1; i < num; i++) {
713  int node1 = randVar->GetInteger(0, subgraphs[i - 1].size() - 1);
714  int node2 = randVar->GetInteger(0, subgraphs[i].size() - 1);
715 
716  Traits::vertex_descriptor v1 = get(vertex_name, bbGraph, subgraphs[i - 1][node1]),
717  v2 = get(vertex_name, bbGraph, subgraphs[i][node2]);
718 
719  NS_LOG_DEBUG("Connecting " << get(vertex_name, m_graph, v1) << "[" << node1 << "] with "
720  << get(vertex_name, m_graph, v2) << "[" << node2 << "]");
721 
722  add_edge(v1, v2, m_graph);
723  }
724 }
725 
726 } /* namespace ns3 */
R & get(variant< T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15 > &v, nonstd_lite_in_place_type_t(R)=nonstd_lite_in_place_type(R))
Definition: variant.hpp:1552
This class reads annotated topology and apply settings to the corresponding nodes and links.
Table::const_iterator iterator
Definition: cs-internal.hpp:41
virtual void SaveGraphviz(const std::string &file)
Save topology in graphviz format (.dot file)
virtual void SaveTopology(const std::string &file)
Save positions (e.g., after manual modification using visualizer)
const NodeContainer & GetGatewayRouters() const
void ApplySettings()
This method applies setting to corresponding nodes and links NetDeviceContainer must be allocated Nod...
#define REGMATCH_MAX
Copyright (c) 2011-2015 Regents of the University of California.
virtual NodeContainer Read()
Deprecated call.
const NodeContainer & GetCustomerRouters() const
#define ROCKETFUEL_MAPS_LINE
static void nodeWriter(std::ostream &os, NodeContainer &m)
const NodeContainer & GetBackboneRouters() const
virtual const std::list< Link > & GetLinks() const
Get links read by the reader.
Ptr< Node > CreateNode(const std::string name, uint32_t systemId)