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/random-variable.h"
42 #include "ns3/error-model.h"
43 #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");
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);
97 NS_LOG_FUNCTION(
this);
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);
118 NS_LOG_FUNCTION(
this << name << posX << posY);
119 m_requiredPartitions = std::max(m_requiredPartitions, systemId + 1);
121 Ptr<Node> node = CreateObject<Node>(systemId);
122 Ptr<MobilityModel> loc = DynamicCast<MobilityModel>(m_mobilityFactory.Create());
123 node->AggregateObject(loc);
125 loc->SetPosition(Vector(posX, posY, 0));
127 Names::Add(
m_path, name, node);
139 const std::list<TopologyReader::Link>&
149 topgen.open(GetFileName().c_str());
151 if (!topgen.is_open() || !topgen.good()) {
152 NS_FATAL_ERROR(
"Cannot open file " << GetFileName() <<
" for reading");
156 while (!topgen.eof()) {
158 getline(topgen, line);
160 if (line ==
"router")
165 NS_FATAL_ERROR(
"Topology file " << GetFileName() <<
" does not have \"router\" section");
169 while (!topgen.eof()) {
171 getline(topgen, line);
177 istringstream lineBuffer(line);
179 double latitude = 0, longitude = 0;
180 uint32_t systemId = 0;
182 lineBuffer >> name >> city >> latitude >> longitude >> systemId;
188 if (abs(latitude) > 0.001 && abs(latitude) > 0.001)
189 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;
200 NS_LOG_ERROR(
"Topology file " << GetFileName() <<
" does not have \"link\" section");
205 while (!topgen.eof()) {
207 getline(topgen, line);
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()) {
224 processedLinks[from].insert(to);
226 Ptr<Node> fromNode = Names::Find<Node>(
m_path, from);
227 NS_ASSERT_MSG(fromNode != 0, from <<
" node not found");
228 Ptr<Node> toNode = Names::Find<Node>(
m_path, to);
229 NS_ASSERT_MSG(toNode != 0, to <<
" node not found");
231 Link link(fromNode, from, toNode, to);
233 link.SetAttribute(
"DataRate", capacity);
234 link.SetAttribute(
"OSPF", metric);
237 link.SetAttribute(
"Delay", delay);
238 if (!maxPackets.empty())
239 link.SetAttribute(
"MaxPackets", maxPackets);
242 if (!lossRate.empty())
243 link.SetAttribute(
"LossRate", lossRate);
246 NS_LOG_DEBUG(
"New link " << from <<
" <==> " << to <<
" / " << capacity <<
" with " << metric
247 <<
" metric (" << delay <<
", " << maxPackets <<
", " << lossRate
251 NS_LOG_INFO(
"Annotated topology created with " <<
m_nodes.GetN() <<
" nodes and " << LinksSize()
263 Ipv4AddressHelper address(base, Ipv4Mask(
"/24"));
265 BOOST_FOREACH (
const Link& link, m_linksList) {
266 address.Assign(NetDeviceContainer(link.GetFromNetDevice(), link.GetToNetDevice()));
268 base = Ipv4Address(base.Get() + 256);
269 address.SetBase(base, Ipv4Mask(
"/24"));
276 BOOST_FOREACH (
const Link& link, m_linksList) {
277 NS_LOG_DEBUG(
"OSPF: " << link.GetAttribute(
"OSPF"));
278 uint16_t metric = boost::lexical_cast<uint16_t>(link.GetAttribute(
"OSPF"));
281 Ptr<Ipv4> ipv4 = link.GetFromNode()->GetObject<Ipv4>();
283 int32_t interfaceId = ipv4->GetInterfaceForDevice(link.GetFromNetDevice());
284 NS_ASSERT(interfaceId >= 0);
286 ipv4->SetMetric(interfaceId, metric);
289 Ptr<ndn::L3Protocol> ndn = link.GetFromNode()->GetObject<
ndn::L3Protocol>();
292 NS_ASSERT(face != 0);
294 face->setMetric(metric);
299 Ptr<Ipv4> ipv4 = link.GetToNode()->GetObject<Ipv4>();
301 int32_t interfaceId = ipv4->GetInterfaceForDevice(link.GetToNetDevice());
302 NS_ASSERT(interfaceId >= 0);
304 ipv4->SetMetric(interfaceId, metric);
307 Ptr<ndn::L3Protocol> ndn = link.GetToNode()->GetObject<
ndn::L3Protocol>();
310 NS_ASSERT(face != 0);
312 face->setMetric(metric);
322 if (MpiInterface::IsEnabled() && MpiInterface::GetSize() != m_requiredPartitions) {
323 std::cerr <<
"MPI interface is enabled, but number of partitions (" << MpiInterface::GetSize()
324 <<
") is not equal to number of partitions in the topology (" << m_requiredPartitions
330 PointToPointHelper p2p;
332 BOOST_FOREACH (Link& link, m_linksList) {
337 if (link.GetAttributeFailSafe(
"MaxPackets", tmp)) {
338 NS_LOG_INFO(
"MaxPackets = " + link.GetAttribute(
"MaxPackets"));
341 uint32_t maxPackets = boost::lexical_cast<uint32_t>(link.GetAttribute(
"MaxPackets"));
344 p2p.SetQueue(
"ns3::DropTailQueue",
"MaxPackets", UintegerValue(maxPackets));
347 typedef boost::tokenizer<boost::escaped_list_separator<char>> tokenizer;
348 std::string value = link.GetAttribute(
"MaxPackets");
349 tokenizer tok(value);
351 tokenizer::iterator token = tok.begin();
352 p2p.SetQueue(*token);
354 for (token++; token != tok.end(); token++) {
355 boost::escaped_list_separator<char> separator(
'\\',
'=',
'\"');
356 tokenizer attributeTok(*token, separator);
358 tokenizer::iterator attributeToken = attributeTok.begin();
360 string attribute = *attributeToken;
363 if (attributeToken == attributeTok.end()) {
364 NS_LOG_ERROR(
"Queue attribute [" << *token
365 <<
"] should be in form <Attribute>=<Value>");
369 string value = *attributeToken;
371 p2p.SetQueueAttribute(attribute, StringValue(value));
376 if (link.GetAttributeFailSafe(
"DataRate", tmp)) {
377 NS_LOG_INFO(
"DataRate = " + link.GetAttribute(
"DataRate"));
378 p2p.SetDeviceAttribute(
"DataRate", StringValue(link.GetAttribute(
"DataRate")));
381 if (link.GetAttributeFailSafe(
"Delay", tmp)) {
382 NS_LOG_INFO(
"Delay = " + link.GetAttribute(
"Delay"));
383 p2p.SetChannelAttribute(
"Delay", StringValue(link.GetAttribute(
"Delay")));
386 NetDeviceContainer nd = p2p.Install(link.GetFromNode(), link.GetToNode());
387 link.SetNetDevices(nd.Get(0), nd.Get(1));
390 if (link.GetAttributeFailSafe(
"LossRate", tmp)) {
391 NS_LOG_INFO(
"LinkError = " + link.GetAttribute(
"LossRate"));
393 typedef boost::tokenizer<boost::escaped_list_separator<char>> tokenizer;
394 std::string value = link.GetAttribute(
"LossRate");
395 tokenizer tok(value);
397 tokenizer::iterator token = tok.begin();
398 ObjectFactory factory(*token);
400 for (token++; token != tok.end(); token++) {
401 boost::escaped_list_separator<char> separator(
'\\',
'=',
'\"');
402 tokenizer attributeTok(*token, separator);
404 tokenizer::iterator attributeToken = attributeTok.begin();
406 string attribute = *attributeToken;
409 if (attributeToken == attributeTok.end()) {
410 NS_LOG_ERROR(
"ErrorModel attribute [" << *token
411 <<
"] should be in form <Attribute>=<Value>");
415 string value = *attributeToken;
417 factory.Set(attribute, StringValue(value));
420 nd.Get(0)->SetAttribute(
"ReceiveErrorModel", PointerValue(factory.Create<ErrorModel>()));
421 nd.Get(1)->SetAttribute(
"ReceiveErrorModel", PointerValue(factory.Create<ErrorModel>()));
429 ofstream os(file.c_str(), ios::trunc);
430 os <<
"# any empty lines and lines starting with '#' symbol is ignored\n"
432 <<
"# The file should contain exactly two sections: router and link, each starting with the "
433 "corresponding keyword\n"
435 <<
"# router section defines topology nodes and their relative positions (e.g., to use in "
439 <<
"# each line in this section represents one router and should have the following data\n"
440 <<
"# node comment yPos xPos\n";
442 for (NodeContainer::Iterator node =
m_nodes.Begin(); node !=
m_nodes.End(); node++) {
443 std::string name = Names::FindName(*node);
444 Ptr<MobilityModel> mobility = (*node)->GetObject<MobilityModel>();
445 Vector position = mobility->GetPosition();
449 <<
"\t" << -position.y <<
"\t" << position.x <<
"\n";
453 <<
"# link section defines point-to-point links between nodes and characteristics of these "
458 <<
"# Each line should be in the following format (only first two are required, the rest can "
460 <<
"# srcNode dstNode bandwidth metric delay queue\n"
461 <<
"# bandwidth: link bandwidth\n"
462 <<
"# metric: routing metric\n"
463 <<
"# delay: link delay\n"
464 <<
"# queue: MaxPackets for transmission queue on the link (both directions)\n"
465 <<
"# error: comma-separated list, specifying class for ErrorModel and necessary attributes\n";
467 for (std::list<Link>::const_iterator link = m_linksList.begin(); link != m_linksList.end();
469 os << Names::FindName(link->GetFromNode()) <<
"\t";
470 os << Names::FindName(link->GetToNode()) <<
"\t";
473 if (link->GetAttributeFailSafe(
"DataRate", tmp))
474 os << link->GetAttribute(
"DataRate") <<
"\t";
476 NS_FATAL_ERROR(
"DataRate must be specified for the link");
478 if (link->GetAttributeFailSafe(
"OSPF", tmp))
479 os << link->GetAttribute(
"OSPF") <<
"\t";
483 if (link->GetAttributeFailSafe(
"Delay", tmp)) {
484 os << link->GetAttribute(
"Delay") <<
"\t";
486 if (link->GetAttributeFailSafe(
"MaxPackets", tmp)) {
487 os << link->GetAttribute(
"MaxPackets") <<
"\t";
489 if (link->GetAttributeFailSafe(
"LossRate", tmp)) {
490 os << link->GetAttribute(
"LossRate") <<
"\t";
500 template<
class Names>
503 name_writer(Names _names)
508 template<
class VertexOrEdge>
510 operator()(std::ostream& out,
const VertexOrEdge& v)
const
513 out <<
"[shape=\"circle\",width=0.1,label=\"\",style=filled,fillcolor=\"green\"]";
520 template<
class Names>
521 inline name_writer<Names>
522 make_name_writer(Names n)
524 return name_writer<Names>(n);
532 typedef boost::adjacency_list_traits<boost::setS, boost::setS, boost::undirectedS> Traits;
534 typedef boost::property<boost::vertex_name_t, std::string,
535 boost::property<boost::vertex_index_t, uint32_t>> nodeProperty;
537 typedef boost::no_property edgeProperty;
539 typedef boost::adjacency_list<boost::setS, boost::setS, boost::undirectedS, nodeProperty,
542 typedef map<string, Traits::vertex_descriptor> node_map_t;
543 node_map_t graphNodes;
546 for (NodeContainer::Iterator node =
m_nodes.Begin(); node !=
m_nodes.End(); node++) {
547 std::pair<node_map_t::iterator, bool> retval = graphNodes.insert(
548 make_pair(Names::FindName(*node), add_vertex(nodeProperty(Names::FindName(*node)), graph)));
551 put(boost::vertex_index, graph, retval.first->second, (*node)->GetId());
554 for (std::list<Link>::const_iterator link = m_linksList.begin(); link != m_linksList.end();
556 node_map_t::iterator from = graphNodes.find(Names::FindName(link->GetFromNode()));
557 node_map_t::iterator to = graphNodes.find(Names::FindName(link->GetToNode()));
560 boost::add_edge(from->second, to->second, graph);
563 ofstream of(file.c_str());
564 boost::property_map<Graph, boost::vertex_name_t>::type names =
get(boost::vertex_name, graph);
565 write_graphviz(of, graph, make_name_writer(names));
shared_ptr< Face > getFaceByNetDevice(Ptr< NetDevice > netDevice) const
Remove face from ndn stack (remove callbacks)
virtual void ApplyOspfMetric()
Apply OSPF metric on Ipv4 (if exists) and Ccnx (if exists) stacks.
virtual void SetMobilityModel(const std::string &model)
Set mobility model to be used on nodes.
virtual const std::list< Link > & GetLinks() const
Get links read by the reader.
virtual void AssignIpv4Addresses(Ipv4Address base)
Assign IPv4 addresses to all links.
virtual void SaveTopology(const std::string &file)
Save positions (e.g., after manual modification using visualizer)
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.
Implementation network-layer of NDN stack.
virtual ~AnnotatedTopologyReader()
virtual NodeContainer GetNodes() const
Get nodes read by the reader.
virtual void SaveGraphviz(const std::string &file)
Save topology in graphviz format (.dot file)
Ptr< Node > CreateNode(const std::string name, uint32_t systemId)