NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.5: NDN, CCN, CCNx, content centric networks
API Documentation
annotated-topology-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/assert.h"
27 #include "ns3/names.h"
28 #include "ns3/net-device-container.h"
29 #include "ns3/point-to-point-helper.h"
30 #include "ns3/point-to-point-net-device.h"
31 #include "ns3/internet-stack-helper.h"
32 #include "ns3/ipv4-address-helper.h"
33 #include "ns3/ipv4-global-routing-helper.h"
34 #include "ns3/drop-tail-queue.h"
35 #include "ns3/ipv4-interface.h"
36 #include "ns3/ipv4.h"
37 #include "ns3/string.h"
38 #include "ns3/pointer.h"
39 #include "ns3/uinteger.h"
40 #include "ns3/ipv4-address.h"
41 #include "ns3/error-model.h"
42 #include "ns3/constant-position-mobility-model.h"
43 #include "ns3/double.h"
44 
46 
47 #include <boost/foreach.hpp>
48 #include <boost/lexical_cast.hpp>
49 #include <boost/tokenizer.hpp>
50 
51 #include <boost/graph/adjacency_list.hpp>
52 #include <boost/graph/graphviz.hpp>
53 
54 #include <set>
55 
56 #ifdef NS3_MPI
57 #include <ns3/mpi-interface.h>
58 #endif
59 
60 using namespace std;
61 
62 namespace ns3 {
63 
64 NS_LOG_COMPONENT_DEFINE("AnnotatedTopologyReader");
65 
66 AnnotatedTopologyReader::AnnotatedTopologyReader(const std::string& path, double scale /*=1.0*/)
67  : m_path(path)
68  , m_randX(CreateObject<UniformRandomVariable>())
69  , m_randY(CreateObject<UniformRandomVariable>())
70  , m_scale(scale)
71  , m_requiredPartitions(1)
72 {
73  NS_LOG_FUNCTION(this);
74 
75  m_randX->SetAttribute("Min", DoubleValue(0));
76  m_randX->SetAttribute("Max", DoubleValue(100.0));
77 
78  m_randY->SetAttribute("Min", DoubleValue(0));
79  m_randY->SetAttribute("Max", DoubleValue(100.0));
80 
81  SetMobilityModel("ns3::ConstantPositionMobilityModel");
82 }
83 
84 void
85 AnnotatedTopologyReader::SetBoundingBox(double ulx, double uly, double lrx, double lry)
86 {
87  NS_LOG_FUNCTION(this << ulx << uly << lrx << lry);
88 
89  m_randX->SetAttribute("Min", DoubleValue(ulx));
90  m_randX->SetAttribute("Max", DoubleValue(lrx));
91 
92  m_randY->SetAttribute("Min", DoubleValue(uly));
93  m_randY->SetAttribute("Max", DoubleValue(lry));
94 }
95 
96 void
98 {
99  NS_LOG_FUNCTION(this << model);
100  m_mobilityFactory.SetTypeId(model);
101 }
102 
104 {
105  NS_LOG_FUNCTION(this);
106 }
107 
108 Ptr<Node>
109 AnnotatedTopologyReader::CreateNode(const std::string name, uint32_t systemId)
110 {
111  NS_LOG_FUNCTION(this << name);
112  m_requiredPartitions = std::max(m_requiredPartitions, systemId + 1);
113 
114  Ptr<Node> node = CreateObject<Node>(systemId);
115 
116  Names::Add(m_path, name, node);
117  m_nodes.Add(node);
118 
119  return node;
120 }
121 
122 Ptr<Node>
123 AnnotatedTopologyReader::CreateNode(const std::string name, double posX, double posY,
124  uint32_t systemId)
125 {
126  NS_LOG_FUNCTION(this << name << posX << posY);
127  m_requiredPartitions = std::max(m_requiredPartitions, systemId + 1);
128 
129  Ptr<Node> node = CreateObject<Node>(systemId);
130  Ptr<MobilityModel> loc = DynamicCast<MobilityModel>(m_mobilityFactory.Create());
131  node->AggregateObject(loc);
132 
133  loc->SetPosition(Vector(posX, posY, 0));
134 
135  Names::Add(m_path, name, node);
136  m_nodes.Add(node);
137 
138  return node;
139 }
140 
141 NodeContainer
143 {
144  return m_nodes;
145 }
146 
147 const std::list<TopologyReader::Link>&
149 {
150  return m_linksList;
151 }
152 
153 NodeContainer
155 {
156  ifstream topgen;
157  topgen.open(GetFileName().c_str());
158 
159  if (!topgen.is_open() || !topgen.good()) {
160  NS_FATAL_ERROR("Cannot open file " << GetFileName() << " for reading");
161  return m_nodes;
162  }
163 
164  while (!topgen.eof()) {
165  string line;
166  getline(topgen, line);
167 
168  if (line == "router")
169  break;
170  }
171 
172  if (topgen.eof()) {
173  NS_FATAL_ERROR("Topology file " << GetFileName() << " does not have \"router\" section");
174  return m_nodes;
175  }
176 
177  while (!topgen.eof()) {
178  string line;
179  getline(topgen, line);
180  if (line[0] == '#')
181  continue; // comments
182  if (line == "link")
183  break; // stop reading nodes
184 
185  istringstream lineBuffer(line);
186  string name, city;
187  double latitude = 0, longitude = 0;
188  uint32_t systemId = 0;
189 
190  lineBuffer >> name >> city >> latitude >> longitude >> systemId;
191  if (name.empty())
192  continue;
193 
194  Ptr<Node> node;
195 
196  if (abs(latitude) > 0.001 && abs(latitude) > 0.001)
197  node = CreateNode(name, m_scale * longitude, -m_scale * latitude, systemId);
198  else {
199  Ptr<UniformRandomVariable> var = CreateObject<UniformRandomVariable>();
200  node = CreateNode(name, var->GetValue(0, 200), var->GetValue(0, 200), systemId);
201  // node = CreateNode (name, systemId);
202  }
203  }
204 
205  map<string, set<string>> processedLinks; // to eliminate duplications
206 
207  if (topgen.eof()) {
208  NS_LOG_ERROR("Topology file " << GetFileName() << " does not have \"link\" section");
209  return m_nodes;
210  }
211 
212  // SeekToSection ("link");
213  while (!topgen.eof()) {
214  string line;
215  getline(topgen, line);
216  if (line == "")
217  continue;
218  if (line[0] == '#')
219  continue; // comments
220 
221  // NS_LOG_DEBUG ("Input: [" << line << "]");
222 
223  istringstream lineBuffer(line);
224  string from, to, capacity, metric, delay, maxPackets, lossRate;
225 
226  lineBuffer >> from >> to >> capacity >> metric >> delay >> maxPackets >> lossRate;
227 
228  if (processedLinks[to].size() != 0
229  && processedLinks[to].find(from) != processedLinks[to].end()) {
230  continue; // duplicated link
231  }
232  processedLinks[from].insert(to);
233 
234  Ptr<Node> fromNode = Names::Find<Node>(m_path, from);
235  NS_ASSERT_MSG(fromNode != 0, from << " node not found");
236  Ptr<Node> toNode = Names::Find<Node>(m_path, to);
237  NS_ASSERT_MSG(toNode != 0, to << " node not found");
238 
239  Link link(fromNode, from, toNode, to);
240 
241  link.SetAttribute("DataRate", capacity);
242  link.SetAttribute("OSPF", metric);
243 
244  if (!delay.empty())
245  link.SetAttribute("Delay", delay);
246  if (!maxPackets.empty())
247  link.SetAttribute("MaxPackets", maxPackets);
248 
249  // Saran Added lossRate
250  if (!lossRate.empty())
251  link.SetAttribute("LossRate", lossRate);
252 
253  AddLink(link);
254  NS_LOG_DEBUG("New link " << from << " <==> " << to << " / " << capacity << " with " << metric
255  << " metric (" << delay << ", " << maxPackets << ", " << lossRate
256  << ")");
257  }
258 
259  NS_LOG_INFO("Annotated topology created with " << m_nodes.GetN() << " nodes and " << LinksSize()
260  << " links");
261  topgen.close();
262 
263  ApplySettings();
264 
265  return m_nodes;
266 }
267 
268 void
270 {
271  Ipv4AddressHelper address(base, Ipv4Mask("/24"));
272 
273  BOOST_FOREACH (const Link& link, m_linksList) {
274  address.Assign(NetDeviceContainer(link.GetFromNetDevice(), link.GetToNetDevice()));
275 
276  base = Ipv4Address(base.Get() + 256);
277  address.SetBase(base, Ipv4Mask("/24"));
278  }
279 }
280 
281 void
283 {
284  BOOST_FOREACH (const Link& link, m_linksList) {
285  NS_LOG_DEBUG("OSPF: " << link.GetAttribute("OSPF"));
286  uint16_t metric = boost::lexical_cast<uint16_t>(link.GetAttribute("OSPF"));
287 
288  {
289  Ptr<Ipv4> ipv4 = link.GetFromNode()->GetObject<Ipv4>();
290  if (ipv4 != 0) {
291  int32_t interfaceId = ipv4->GetInterfaceForDevice(link.GetFromNetDevice());
292  NS_ASSERT(interfaceId >= 0);
293 
294  ipv4->SetMetric(interfaceId, metric);
295  }
296 
297  Ptr<ndn::L3Protocol> ndn = link.GetFromNode()->GetObject<ndn::L3Protocol>();
298  if (ndn != 0) {
299  shared_ptr<ndn::Face> face = ndn->getFaceByNetDevice(link.GetFromNetDevice());
300  NS_ASSERT(face != 0);
301 
302  face->setMetric(metric);
303  }
304  }
305 
306  {
307  Ptr<Ipv4> ipv4 = link.GetToNode()->GetObject<Ipv4>();
308  if (ipv4 != 0) {
309  int32_t interfaceId = ipv4->GetInterfaceForDevice(link.GetToNetDevice());
310  NS_ASSERT(interfaceId >= 0);
311 
312  ipv4->SetMetric(interfaceId, metric);
313  }
314 
315  Ptr<ndn::L3Protocol> ndn = link.GetToNode()->GetObject<ndn::L3Protocol>();
316  if (ndn != 0) {
317  shared_ptr<ndn::Face> face = ndn->getFaceByNetDevice(link.GetToNetDevice());
318  NS_ASSERT(face != 0);
319 
320  face->setMetric(metric);
321  }
322  }
323  }
324 }
325 
326 void
328 {
329 #ifdef NS3_MPI
330  if (MpiInterface::IsEnabled() && MpiInterface::GetSize() != m_requiredPartitions) {
331  std::cerr << "MPI interface is enabled, but number of partitions (" << MpiInterface::GetSize()
332  << ") is not equal to number of partitions in the topology (" << m_requiredPartitions
333  << ")";
334  exit(-1);
335  }
336 #endif
337 
338  PointToPointHelper p2p;
339 
340  BOOST_FOREACH (Link& link, m_linksList) {
341  // cout << "Link: " << Findlink.GetFromNode () << ", " << link.GetToNode () << endl;
342  string tmp;
343 
345  if (link.GetAttributeFailSafe("MaxPackets", tmp)) {
346  NS_LOG_INFO("MaxPackets = " + link.GetAttribute("MaxPackets"));
347 
348  try {
349  std::string maxPackets = link.GetAttribute("MaxPackets");
350 
351  // compatibility mode. Only DropTailQueue is supported
352  p2p.SetQueue("ns3::DropTailQueue<Packet>", "MaxSize", StringValue(maxPackets + "p"));
353  }
354  catch (...) {
355  typedef boost::tokenizer<boost::escaped_list_separator<char>> tokenizer;
356  std::string value = link.GetAttribute("MaxPackets");
357  tokenizer tok(value);
358 
359  tokenizer::iterator token = tok.begin();
360  p2p.SetQueue(*token);
361 
362  for (token++; token != tok.end(); token++) {
363  boost::escaped_list_separator<char> separator('\\', '=', '\"');
364  tokenizer attributeTok(*token, separator);
365 
366  tokenizer::iterator attributeToken = attributeTok.begin();
367 
368  string attribute = *attributeToken;
369  attributeToken++;
370 
371  if (attributeToken == attributeTok.end()) {
372  NS_LOG_ERROR("Queue attribute [" << *token
373  << "] should be in form <Attribute>=<Value>");
374  continue;
375  }
376 
377  string value = *attributeToken;
378 
379  p2p.SetQueueAttribute(attribute, StringValue(value));
380  }
381  }
382  }
383 
384  if (link.GetAttributeFailSafe("DataRate", tmp)) {
385  NS_LOG_INFO("DataRate = " + link.GetAttribute("DataRate"));
386  p2p.SetDeviceAttribute("DataRate", StringValue(link.GetAttribute("DataRate")));
387  }
388 
389  if (link.GetAttributeFailSafe("Delay", tmp)) {
390  NS_LOG_INFO("Delay = " + link.GetAttribute("Delay"));
391  p2p.SetChannelAttribute("Delay", StringValue(link.GetAttribute("Delay")));
392  }
393 
394  NetDeviceContainer nd = p2p.Install(link.GetFromNode(), link.GetToNode());
395  link.SetNetDevices(nd.Get(0), nd.Get(1));
396 
398  if (link.GetAttributeFailSafe("LossRate", tmp)) {
399  NS_LOG_INFO("LinkError = " + link.GetAttribute("LossRate"));
400 
401  typedef boost::tokenizer<boost::escaped_list_separator<char>> tokenizer;
402  std::string value = link.GetAttribute("LossRate");
403  tokenizer tok(value);
404 
405  tokenizer::iterator token = tok.begin();
406  ObjectFactory factory(*token);
407 
408  for (token++; token != tok.end(); token++) {
409  boost::escaped_list_separator<char> separator('\\', '=', '\"');
410  tokenizer attributeTok(*token, separator);
411 
412  tokenizer::iterator attributeToken = attributeTok.begin();
413 
414  string attribute = *attributeToken;
415  attributeToken++;
416 
417  if (attributeToken == attributeTok.end()) {
418  NS_LOG_ERROR("ErrorModel attribute [" << *token
419  << "] should be in form <Attribute>=<Value>");
420  continue;
421  }
422 
423  string value = *attributeToken;
424 
425  factory.Set(attribute, StringValue(value));
426  }
427 
428  nd.Get(0)->SetAttribute("ReceiveErrorModel", PointerValue(factory.Create<ErrorModel>()));
429  nd.Get(1)->SetAttribute("ReceiveErrorModel", PointerValue(factory.Create<ErrorModel>()));
430  }
431  }
432 }
433 
434 void
436 {
437  ofstream os(file.c_str(), ios::trunc);
438  os << "# any empty lines and lines starting with '#' symbol is ignored\n"
439  << "\n"
440  << "# The file should contain exactly two sections: router and link, each starting with the "
441  "corresponding keyword\n"
442  << "\n"
443  << "# router section defines topology nodes and their relative positions (e.g., to use in "
444  "visualizer)\n"
445  << "router\n"
446  << "\n"
447  << "# each line in this section represents one router and should have the following data\n"
448  << "# node comment yPos xPos\n";
449 
450  for (NodeContainer::Iterator node = m_nodes.Begin(); node != m_nodes.End(); node++) {
451  std::string name = Names::FindName(*node);
452  Ptr<MobilityModel> mobility = (*node)->GetObject<MobilityModel>();
453  Vector position = mobility->GetPosition();
454 
455  os << name << "\t"
456  << "NA"
457  << "\t" << -position.y << "\t" << position.x << "\n";
458  }
459 
460  os
461  << "# link section defines point-to-point links between nodes and characteristics of these "
462  "links\n"
463  << "\n"
464  << "link\n"
465  << "\n"
466  << "# Each line should be in the following format (only first two are required, the rest can "
467  "be omitted)\n"
468  << "# srcNode dstNode bandwidth metric delay queue\n"
469  << "# bandwidth: link bandwidth\n"
470  << "# metric: routing metric\n"
471  << "# delay: link delay\n"
472  << "# queue: MaxPackets for transmission queue on the link (both directions)\n"
473  << "# error: comma-separated list, specifying class for ErrorModel and necessary attributes\n";
474 
475  for (std::list<Link>::const_iterator link = m_linksList.begin(); link != m_linksList.end();
476  link++) {
477  os << Names::FindName(link->GetFromNode()) << "\t";
478  os << Names::FindName(link->GetToNode()) << "\t";
479 
480  string tmp;
481  if (link->GetAttributeFailSafe("DataRate", tmp))
482  os << link->GetAttribute("DataRate") << "\t";
483  else
484  NS_FATAL_ERROR("DataRate must be specified for the link");
485 
486  if (link->GetAttributeFailSafe("OSPF", tmp))
487  os << link->GetAttribute("OSPF") << "\t";
488  else
489  os << "1\t";
490 
491  if (link->GetAttributeFailSafe("Delay", tmp)) {
492  os << link->GetAttribute("Delay") << "\t";
493 
494  if (link->GetAttributeFailSafe("MaxPackets", tmp)) {
495  os << link->GetAttribute("MaxPackets") << "\t";
496 
497  if (link->GetAttributeFailSafe("LossRate", tmp)) {
498  os << link->GetAttribute("LossRate") << "\t";
499  }
500  }
501  }
502  os << "\n";
503  }
504 }
505 
507 
508 template<class Names>
509 class name_writer {
510 public:
511  name_writer(Names _names)
512  : names(_names)
513  {
514  }
515 
516  template<class VertexOrEdge>
517  void
518  operator()(std::ostream& out, const VertexOrEdge& v) const
519  {
520  // out << "[label=\"" << names[v] << "\",style=filled,fillcolor=\"" << colors[v] << "\"]";
521  out << "[shape=\"circle\",width=0.1,label=\"\",style=filled,fillcolor=\"green\"]";
522  }
523 
524 private:
525  Names names;
526 };
527 
528 template<class Names>
529 inline name_writer<Names>
530 make_name_writer(Names n)
531 {
532  return name_writer<Names>(n);
533 }
534 
536 
537 void
539 {
540  typedef boost::adjacency_list_traits<boost::setS, boost::setS, boost::undirectedS> Traits;
541 
542  typedef boost::property<boost::vertex_name_t, std::string,
543  boost::property<boost::vertex_index_t, uint32_t>> nodeProperty;
544 
545  typedef boost::no_property edgeProperty;
546 
547  typedef boost::adjacency_list<boost::setS, boost::setS, boost::undirectedS, nodeProperty,
548  edgeProperty> Graph;
549 
550  typedef map<string, Traits::vertex_descriptor> node_map_t;
551  node_map_t graphNodes;
552  Graph graph;
553 
554  for (NodeContainer::Iterator node = m_nodes.Begin(); node != m_nodes.End(); node++) {
555  std::pair<node_map_t::iterator, bool> retval = graphNodes.insert(
556  make_pair(Names::FindName(*node), add_vertex(nodeProperty(Names::FindName(*node)), graph)));
557  // NS_ASSERT (ok == true);
558 
559  put(boost::vertex_index, graph, retval.first->second, (*node)->GetId());
560  }
561 
562  for (std::list<Link>::const_iterator link = m_linksList.begin(); link != m_linksList.end();
563  link++) {
564  node_map_t::iterator from = graphNodes.find(Names::FindName(link->GetFromNode()));
565  node_map_t::iterator to = graphNodes.find(Names::FindName(link->GetToNode()));
566 
567  // add_edge (node->second, otherNode->second, m_graph);
568  boost::add_edge(from->second, to->second, graph);
569  }
570 
571  ofstream of(file.c_str());
572  boost::property_map<Graph, boost::vertex_name_t>::type names = get(boost::vertex_name, graph);
573  write_graphviz(of, graph, make_name_writer(names));
574 }
575 
576 }
ns3::AnnotatedTopologyReader::Read
virtual NodeContainer Read()
Main annotated topology reading function.
Definition: annotated-topology-reader.cpp:154
ns3
Copyright (c) 2011-2015 Regents of the University of California.
Definition: ndn-app-link-service.cpp:32
nonstd::variants::get
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:1753
ns3::AnnotatedTopologyReader::ApplyOspfMetric
virtual void ApplyOspfMetric()
Apply OSPF metric on Ipv4 (if exists) and Ccnx (if exists) stacks.
Definition: annotated-topology-reader.cpp:282
ns3::AnnotatedTopologyReader::GetNodes
virtual NodeContainer GetNodes() const
Get nodes read by the reader.
Definition: annotated-topology-reader.cpp:142
ns3::AnnotatedTopologyReader::ApplySettings
void ApplySettings()
This method applies setting to corresponding nodes and links NetDeviceContainer must be allocated Nod...
Definition: annotated-topology-reader.cpp:327
ns3::AnnotatedTopologyReader
AnnotatedTopologyReader
Definition: annotated-topology-reader.cpp:64
ns3::AnnotatedTopologyReader::GetLinks
virtual const std::list< Link > & GetLinks() const
Get links read by the reader.
Definition: annotated-topology-reader.cpp:148
ns3::AnnotatedTopologyReader::m_nodes
NodeContainer m_nodes
Definition: annotated-topology-reader.hpp:137
ns3::AnnotatedTopologyReader::CreateNode
Ptr< Node > CreateNode(const std::string name, uint32_t systemId)
Definition: annotated-topology-reader.cpp:109
ns3::AnnotatedTopologyReader::SetMobilityModel
virtual void SetMobilityModel(const std::string &model)
Set mobility model to be used on nodes.
Definition: annotated-topology-reader.cpp:97
ns3::AnnotatedTopologyReader::~AnnotatedTopologyReader
virtual ~AnnotatedTopologyReader()
Definition: annotated-topology-reader.cpp:103
ns3::AnnotatedTopologyReader::AssignIpv4Addresses
virtual void AssignIpv4Addresses(Ipv4Address base)
Assign IPv4 addresses to all links.
Definition: annotated-topology-reader.cpp:269
ns3::AnnotatedTopologyReader::SaveTopology
virtual void SaveTopology(const std::string &file)
Save positions (e.g., after manual modification using visualizer)
Definition: annotated-topology-reader.cpp:435
ns3::AnnotatedTopologyReader::SetBoundingBox
virtual void SetBoundingBox(double ulx, double uly, double lrx, double lry)
Set bounding box where nodes will be randomly places (if positions are unspecified)
Definition: annotated-topology-reader.cpp:85
ndn::time::abs
constexpr duration< Rep, Period > abs(duration< Rep, Period > d)
Definition: time.hpp:50
ns3::AnnotatedTopologyReader::m_path
std::string m_path
Definition: annotated-topology-reader.hpp:136
ndn::name
Definition: name-component-types.hpp:33
ns3::ndn::L3Protocol
Implementation network-layer of NDN stack.
Definition: ndn-l3-protocol.hpp:81
ns3::AnnotatedTopologyReader::SaveGraphviz
virtual void SaveGraphviz(const std::string &file)
Save topology in graphviz format (.dot file)
Definition: annotated-topology-reader.cpp:538
annotated-topology-reader.hpp
ndn-l3-protocol.hpp
ndn
Copyright (c) 2011-2015 Regents of the University of California.
Definition: ndn-strategy-choice-helper.hpp:34