22 #include "annotated-topology-reader.h"
24 #include "ns3/nstime.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"
37 #include "ns3/string.h"
38 #include "ns3/pointer.h"
39 #include "ns3/uinteger.h"
40 #include "ns3/ipv4-address.h"
41 #include "ns3/ndn-l3-protocol.h"
42 #include "ns3/ndn-face.h"
43 #include "ns3/random-variable.h"
44 #include "ns3/error-model.h"
46 #include "ns3/constant-position-mobility-model.h"
48 #include <boost/foreach.hpp>
49 #include <boost/lexical_cast.hpp>
50 #include <boost/tokenizer.hpp>
52 #include <boost/graph/adjacency_list.hpp>
53 #include <boost/graph/graphviz.hpp>
58 #include <ns3/mpi-interface.h>
65 NS_LOG_COMPONENT_DEFINE (
"AnnotatedTopologyReader");
67 AnnotatedTopologyReader::AnnotatedTopologyReader (
const std::string &path,
double scale)
72 , m_requiredPartitions (1)
74 NS_LOG_FUNCTION (
this);
82 NS_LOG_FUNCTION (
this << ulx << uly << lrx << lry);
84 m_randX = UniformVariable (ulx, lrx);
85 m_randY = UniformVariable (uly, lry);
91 NS_LOG_FUNCTION (
this << model);
92 m_mobilityFactory.SetTypeId (model);
95 AnnotatedTopologyReader::~AnnotatedTopologyReader ()
97 NS_LOG_FUNCTION (
this);
101 AnnotatedTopologyReader::CreateNode (
const std::string name, uint32_t systemId)
103 NS_LOG_FUNCTION (
this << name);
104 m_requiredPartitions = std::max (m_requiredPartitions, systemId + 1);
106 Ptr<Node> node = CreateObject<Node> (systemId);
108 Names::Add (m_path, name, node);
115 AnnotatedTopologyReader::CreateNode (
const std::string name,
double posX,
double posY, uint32_t systemId)
117 NS_LOG_FUNCTION (
this << name << posX << posY);
118 m_requiredPartitions = std::max (m_requiredPartitions, systemId + 1);
120 Ptr<Node> node = CreateObject<Node> (systemId);
121 Ptr<MobilityModel> loc = DynamicCast<MobilityModel> (m_mobilityFactory.Create ());
122 node->AggregateObject (loc);
124 loc->SetPosition (Vector (posX, posY, 0));
126 Names::Add (m_path, name, node);
138 const std::list<TopologyReader::Link>&
148 topgen.open (GetFileName ().c_str ());
150 if ( !topgen.is_open () || !topgen.good () )
152 NS_FATAL_ERROR (
"Cannot open file " << GetFileName () <<
" for reading");
156 while (!topgen.eof ())
159 getline (topgen, line);
161 if (line ==
"router")
break;
166 NS_FATAL_ERROR (
"Topology file " << GetFileName () <<
" does not have \"router\" section");
170 while (!topgen.eof ())
173 getline (topgen,line);
174 if (line[0] ==
'#')
continue;
175 if (line==
"link")
break;
177 istringstream lineBuffer (line);
179 double latitude = 0, longitude = 0;
180 uint32_t systemId = 0;
182 lineBuffer >> name >> city >> latitude >> longitude >> systemId;
183 if (name.empty ())
continue;
187 if (abs(latitude) > 0.001 && abs(latitude) > 0.001)
188 node = CreateNode (name, m_scale*longitude, -m_scale*latitude, systemId);
191 UniformVariable var (0,200);
192 node = CreateNode (name, var.GetValue (), var.GetValue (), systemId);
197 map<string, set<string> > processedLinks;
201 NS_LOG_ERROR (
"Topology file " << GetFileName () <<
" does not have \"link\" section");
206 while (!topgen.eof ())
209 getline (topgen,line);
210 if (line ==
"")
continue;
211 if (line[0] ==
'#')
continue;
215 istringstream lineBuffer (line);
216 string from, to, capacity, metric, delay, maxPackets, lossRate;
218 lineBuffer >> from >> to >> capacity >> metric >> delay >> maxPackets >> lossRate;
220 if (processedLinks[to].size () != 0 &&
221 processedLinks[to].find (from) != processedLinks[to].end ())
225 processedLinks[from].insert (to);
227 Ptr<Node> fromNode = Names::Find<Node> (m_path, from);
228 NS_ASSERT_MSG (fromNode != 0, from <<
" node not found");
229 Ptr<Node> toNode = Names::Find<Node> (m_path, to);
230 NS_ASSERT_MSG (toNode != 0, to <<
" node not found");
232 Link link (fromNode, from, toNode, to);
234 link.SetAttribute (
"DataRate", capacity);
235 link.SetAttribute (
"OSPF", metric);
238 link.SetAttribute (
"Delay", delay);
239 if (!maxPackets.empty ())
240 link.SetAttribute (
"MaxPackets", maxPackets);
243 if (!lossRate.empty ())
244 link.SetAttribute (
"LossRate", lossRate);
247 NS_LOG_DEBUG (
"New link " << from <<
" <==> " << to <<
" / " << capacity <<
" with " << metric <<
" metric (" << delay <<
", " << maxPackets <<
", " << lossRate <<
")");
250 NS_LOG_INFO (
"Annotated topology created with " << m_nodes.GetN () <<
" nodes and " << LinksSize () <<
" links");
261 Ipv4AddressHelper address (base, Ipv4Mask (
"/24"));
263 BOOST_FOREACH (
const Link &link, m_linksList)
265 address.Assign (NetDeviceContainer (link.GetFromNetDevice (),
266 link.GetToNetDevice ()));
268 base = Ipv4Address (base.Get () + 256);
269 address.SetBase (base, Ipv4Mask (
"/24"));
276 BOOST_FOREACH (
const Link &link, m_linksList)
278 NS_LOG_DEBUG (
"OSPF: " << link.GetAttribute (
"OSPF"));
279 uint16_t metric = boost::lexical_cast<uint16_t> (link.GetAttribute (
"OSPF"));
282 Ptr<Ipv4> ipv4 = link.GetFromNode ()->GetObject<Ipv4> ();
285 int32_t interfaceId = ipv4->GetInterfaceForDevice (link.GetFromNetDevice ());
286 NS_ASSERT (interfaceId >= 0);
288 ipv4->SetMetric (interfaceId,metric);
291 Ptr<ndn::L3Protocol> ndn = link.GetFromNode ()->GetObject<
ndn::L3Protocol> ();
295 NS_ASSERT (face != 0);
297 face->SetMetric (metric);
302 Ptr<Ipv4> ipv4 = link.GetToNode ()->GetObject<Ipv4> ();
305 int32_t interfaceId = ipv4->GetInterfaceForDevice (link.GetToNetDevice ());
306 NS_ASSERT (interfaceId >= 0);
308 ipv4->SetMetric (interfaceId,metric);
311 Ptr<ndn::L3Protocol> ndn = link.GetToNode ()->GetObject<
ndn::L3Protocol> ();
315 NS_ASSERT (face != 0);
317 face->SetMetric (metric);
327 if (MpiInterface::IsEnabled () &&
328 MpiInterface::GetSize () != m_requiredPartitions)
330 std::cerr <<
"MPI interface is enabled, but number of partitions (" << MpiInterface::GetSize ()
331 <<
") is not equal to number of partitions in the topology (" << m_requiredPartitions <<
")";
336 PointToPointHelper p2p;
338 BOOST_FOREACH (Link &link, m_linksList)
344 if (link.GetAttributeFailSafe (
"MaxPackets", tmp))
346 NS_LOG_INFO (
"MaxPackets = " + link.GetAttribute (
"MaxPackets"));
350 uint32_t maxPackets = boost::lexical_cast<uint32_t> (link.GetAttribute (
"MaxPackets"));
353 p2p.SetQueue (
"ns3::DropTailQueue",
354 "MaxPackets", UintegerValue (maxPackets));
358 typedef boost::tokenizer<boost::escaped_list_separator<char> > tokenizer;
359 tokenizer tok (link.GetAttribute (
"MaxPackets"));
361 tokenizer::iterator token = tok.begin ();
362 p2p.SetQueue (*token);
364 for (token ++; token != tok.end (); token ++)
366 boost::escaped_list_separator<char> separator (
'\\',
'=',
'\"');
367 tokenizer attributeTok (*token, separator);
369 tokenizer::iterator attributeToken = attributeTok.begin ();
371 string attribute = *attributeToken;
374 if (attributeToken == attributeTok.end ())
376 NS_LOG_ERROR (
"Queue attribute [" << *token <<
"] should be in form <Attribute>=<Value>");
380 string value = *attributeToken;
382 p2p.SetQueueAttribute (attribute, StringValue (value));
387 if (link.GetAttributeFailSafe (
"DataRate", tmp))
389 NS_LOG_INFO (
"DataRate = " + link.GetAttribute(
"DataRate"));
390 p2p.SetDeviceAttribute (
"DataRate", StringValue (link.GetAttribute (
"DataRate")));
393 if (link.GetAttributeFailSafe (
"Delay", tmp))
395 NS_LOG_INFO (
"Delay = " + link.GetAttribute(
"Delay"));
396 p2p.SetChannelAttribute (
"Delay", StringValue (link.GetAttribute (
"Delay")));
399 NetDeviceContainer nd = p2p.Install(link.GetFromNode (), link.GetToNode ());
400 link.SetNetDevices (nd.Get (0), nd.Get (1));
403 if (link.GetAttributeFailSafe (
"LossRate", tmp))
405 NS_LOG_INFO (
"LinkError = " + link.GetAttribute(
"LossRate"));
407 typedef boost::tokenizer<boost::escaped_list_separator<char> > tokenizer;
408 tokenizer tok (link.GetAttribute(
"LossRate"));
410 tokenizer::iterator token = tok.begin ();
411 ObjectFactory factory (*token);
413 for (token ++; token != tok.end (); token ++)
415 boost::escaped_list_separator<char> separator (
'\\',
'=',
'\"');
416 tokenizer attributeTok (*token, separator);
418 tokenizer::iterator attributeToken = attributeTok.begin ();
420 string attribute = *attributeToken;
423 if (attributeToken == attributeTok.end ())
425 NS_LOG_ERROR (
"ErrorModel attribute [" << *token <<
"] should be in form <Attribute>=<Value>");
429 string value = *attributeToken;
431 factory.Set (attribute, StringValue (value));
434 nd.Get (0)->SetAttribute (
"ReceiveErrorModel", PointerValue (factory.Create<ErrorModel> ()));
435 nd.Get (1)->SetAttribute (
"ReceiveErrorModel", PointerValue (factory.Create<ErrorModel> ()));
443 ofstream os (file.c_str (), ios::trunc);
444 os <<
"# any empty lines and lines starting with '#' symbol is ignored\n"
446 <<
"# The file should contain exactly two sections: router and link, each starting with the corresponding keyword\n"
448 <<
"# router section defines topology nodes and their relative positions (e.g., to use in visualizer)\n"
451 <<
"# each line in this section represents one router and should have the following data\n"
452 <<
"# node comment yPos xPos\n";
454 for (NodeContainer::Iterator node = m_nodes.Begin ();
455 node != m_nodes.End ();
458 std::string name = Names::FindName (*node);
459 Ptr<MobilityModel> mobility = (*node)->GetObject<MobilityModel> ();
460 Vector position = mobility->GetPosition ();
462 os << name <<
"\t" <<
"NA" <<
"\t" << -position.y <<
"\t" << position.x <<
"\n";
465 os <<
"# link section defines point-to-point links between nodes and characteristics of these links\n"
469 <<
"# Each line should be in the following format (only first two are required, the rest can be omitted)\n"
470 <<
"# srcNode dstNode bandwidth metric delay queue\n"
471 <<
"# bandwidth: link bandwidth\n"
472 <<
"# metric: routing metric\n"
473 <<
"# delay: link delay\n"
474 <<
"# queue: MaxPackets for transmission queue on the link (both directions)\n"
475 <<
"# error: comma-separated list, specifying class for ErrorModel and necessary attributes\n";
477 for (std::list<Link>::const_iterator link = m_linksList.begin ();
478 link != m_linksList.end ();
481 os << Names::FindName (link->GetFromNode ()) <<
"\t";
482 os << Names::FindName (link->GetToNode ()) <<
"\t";
485 if (link->GetAttributeFailSafe (
"DataRate", tmp))
486 os << link->GetAttribute(
"DataRate") <<
"\t";
488 NS_FATAL_ERROR (
"DataRate must be specified for the link");
490 if (link->GetAttributeFailSafe (
"OSPF", tmp))
491 os << link->GetAttribute(
"OSPF") <<
"\t";
495 if (link->GetAttributeFailSafe (
"Delay", tmp))
497 os << link->GetAttribute(
"Delay") <<
"\t";
499 if (link->GetAttributeFailSafe (
"MaxPackets", tmp))
501 os << link->GetAttribute(
"MaxPackets") <<
"\t";
503 if (link->GetAttributeFailSafe (
"LossRate", tmp))
505 os << link->GetAttribute (
"LossRate") <<
"\t";
514 template <
class Names>
519 template <
class VertexOrEdge>
520 void operator()(std::ostream& out,
const VertexOrEdge& v)
const {
522 out <<
"[shape=\"circle\",width=0.1,label=\"\",style=filled,fillcolor=\"green\"]";
528 template <
class Names>
530 make_name_writer(Names n) {
538 typedef boost::adjacency_list_traits<boost::setS, boost::setS, boost::undirectedS> Traits;
540 typedef boost::property< boost::vertex_name_t, std::string, boost::property
541 < boost::vertex_index_t, uint32_t > > nodeProperty;
543 typedef boost::no_property edgeProperty;
545 typedef boost::adjacency_list< boost::setS, boost::setS, boost::undirectedS,
546 nodeProperty, edgeProperty > Graph;
548 typedef map<string, Traits::vertex_descriptor> node_map_t;
549 node_map_t graphNodes;
552 for (NodeContainer::Iterator node = m_nodes.Begin ();
553 node != m_nodes.End ();
556 std::pair<node_map_t::iterator, bool>
557 retval = graphNodes.insert (make_pair (Names::FindName (*node),
558 add_vertex (nodeProperty (Names::FindName (*node)), graph)));
561 put (boost::vertex_index, graph, retval.first->second, (*node)->GetId ());
564 for (std::list<Link>::const_iterator link = m_linksList.begin ();
565 link != m_linksList.end ();
568 node_map_t::iterator from = graphNodes.find (Names::FindName (link->GetFromNode ()));
569 node_map_t::iterator to = graphNodes.find (Names::FindName (link->GetToNode ()));
572 boost::add_edge (from->second, to->second, graph);
575 ofstream of (file.c_str ());
576 boost::property_map<Graph, boost::vertex_name_t>::type names =
get (boost::vertex_name, graph);
577 write_graphviz (of, graph, make_name_writer (names));
virtual void SaveGraphviz(const std::string &file)
Save topology in graphviz format (.dot file)
virtual NodeContainer GetNodes() const
Get nodes read by the reader.
virtual void SaveTopology(const std::string &file)
Save positions (e.g., after manual modification using visualizer)
Implementation network-layer of NDN stack.
virtual const std::list< Link > & GetLinks() const
Get links read by the reader.
virtual void ApplyOspfMetric()
Apply OSPF metric on Ipv4 (if exists) and Ccnx (if exists) stacks.
void ApplySettings()
This method applies setting to corresponding nodes and links NetDeviceContainer must be allocated Nod...
virtual void SetBoundingBox(double ulx, double uly, double lrx, double lry)
Set bounding box where nodes will be randomly places (if positions are unspecified) ...
virtual NodeContainer Read()
Main annotated topology reading function.
virtual Ptr< Face > GetFaceByNetDevice(Ptr< NetDevice > netDevice) const
Get face for NetDevice.
virtual void AssignIpv4Addresses(Ipv4Address base)
Assign IPv4 addresses to all links.
virtual void SetMobilityModel(const std::string &model)
Set mobility model to be used on nodes.