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/error-model.h"
42 #include "ns3/constant-position-mobility-model.h"
43 #include "ns3/double.h"
47 #include <boost/foreach.hpp>
48 #include <boost/lexical_cast.hpp>
49 #include <boost/tokenizer.hpp>
51 #include <boost/graph/adjacency_list.hpp>
52 #include <boost/graph/graphviz.hpp>
57 #include <ns3/mpi-interface.h>
64 NS_LOG_COMPONENT_DEFINE(
"AnnotatedTopologyReader");
68 , m_randX(CreateObject<UniformRandomVariable>())
69 , m_randY(CreateObject<UniformRandomVariable>())
71 , m_requiredPartitions(1)
73 NS_LOG_FUNCTION(
this);
75 m_randX->SetAttribute(
"Min", DoubleValue(0));
76 m_randX->SetAttribute(
"Max", DoubleValue(100.0));
78 m_randY->SetAttribute(
"Min", DoubleValue(0));
79 m_randY->SetAttribute(
"Max", DoubleValue(100.0));
87 NS_LOG_FUNCTION(
this << ulx << uly << lrx << lry);
89 m_randX->SetAttribute(
"Min", DoubleValue(ulx));
90 m_randX->SetAttribute(
"Max", DoubleValue(lrx));
92 m_randY->SetAttribute(
"Min", DoubleValue(uly));
93 m_randY->SetAttribute(
"Max", DoubleValue(lry));
99 NS_LOG_FUNCTION(
this << model);
100 m_mobilityFactory.SetTypeId(model);
105 NS_LOG_FUNCTION(
this);
111 NS_LOG_FUNCTION(
this <<
name);
112 m_requiredPartitions = std::max(m_requiredPartitions, systemId + 1);
114 Ptr<Node> node = CreateObject<Node>(systemId);
126 NS_LOG_FUNCTION(
this <<
name << posX << posY);
127 m_requiredPartitions = std::max(m_requiredPartitions, systemId + 1);
129 Ptr<Node> node = CreateObject<Node>(systemId);
130 Ptr<MobilityModel> loc = DynamicCast<MobilityModel>(m_mobilityFactory.Create());
131 node->AggregateObject(loc);
133 loc->SetPosition(Vector(posX, posY, 0));
147 const std::list<TopologyReader::Link>&
157 topgen.open(GetFileName().c_str());
159 if (!topgen.is_open() || !topgen.good()) {
160 NS_FATAL_ERROR(
"Cannot open file " << GetFileName() <<
" for reading");
164 while (!topgen.eof()) {
166 getline(topgen, line);
168 if (line ==
"router")
173 NS_FATAL_ERROR(
"Topology file " << GetFileName() <<
" does not have \"router\" section");
177 while (!topgen.eof()) {
179 getline(topgen, line);
185 istringstream lineBuffer(line);
187 double latitude = 0, longitude = 0;
188 uint32_t systemId = 0;
190 lineBuffer >>
name >> city >> latitude >> longitude >> systemId;
196 if (
abs(latitude) > 0.001 &&
abs(latitude) > 0.001)
197 node =
CreateNode(
name, m_scale * longitude, -m_scale * latitude, systemId);
199 Ptr<UniformRandomVariable> var = CreateObject<UniformRandomVariable>();
200 node =
CreateNode(
name, var->GetValue(0, 200), var->GetValue(0, 200), systemId);
205 map<string, set<string>> processedLinks;
208 NS_LOG_ERROR(
"Topology file " << GetFileName() <<
" does not have \"link\" section");
213 while (!topgen.eof()) {
215 getline(topgen, line);
223 istringstream lineBuffer(line);
224 string from, to, capacity, metric, delay, maxPackets, lossRate;
226 lineBuffer >> from >> to >> capacity >> metric >> delay >> maxPackets >> lossRate;
228 if (processedLinks[to].size() != 0
229 && processedLinks[to].find(from) != processedLinks[to].end()) {
232 processedLinks[from].insert(to);
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");
239 Link link(fromNode, from, toNode, to);
241 link.SetAttribute(
"DataRate", capacity);
242 link.SetAttribute(
"OSPF", metric);
245 link.SetAttribute(
"Delay", delay);
246 if (!maxPackets.empty())
247 link.SetAttribute(
"MaxPackets", maxPackets);
250 if (!lossRate.empty())
251 link.SetAttribute(
"LossRate", lossRate);
254 NS_LOG_DEBUG(
"New link " << from <<
" <==> " << to <<
" / " << capacity <<
" with " << metric
255 <<
" metric (" << delay <<
", " << maxPackets <<
", " << lossRate
259 NS_LOG_INFO(
"Annotated topology created with " <<
m_nodes.GetN() <<
" nodes and " << LinksSize()
271 Ipv4AddressHelper address(base, Ipv4Mask(
"/24"));
273 BOOST_FOREACH (
const Link& link, m_linksList) {
274 address.Assign(NetDeviceContainer(link.GetFromNetDevice(), link.GetToNetDevice()));
276 base = Ipv4Address(base.Get() + 256);
277 address.SetBase(base, Ipv4Mask(
"/24"));
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"));
289 Ptr<Ipv4> ipv4 = link.GetFromNode()->GetObject<Ipv4>();
291 int32_t interfaceId = ipv4->GetInterfaceForDevice(link.GetFromNetDevice());
292 NS_ASSERT(interfaceId >= 0);
294 ipv4->SetMetric(interfaceId, metric);
299 shared_ptr<ndn::Face> face =
ndn->getFaceByNetDevice(link.GetFromNetDevice());
300 NS_ASSERT(face != 0);
302 face->setMetric(metric);
307 Ptr<Ipv4> ipv4 = link.GetToNode()->GetObject<Ipv4>();
309 int32_t interfaceId = ipv4->GetInterfaceForDevice(link.GetToNetDevice());
310 NS_ASSERT(interfaceId >= 0);
312 ipv4->SetMetric(interfaceId, metric);
317 shared_ptr<ndn::Face> face =
ndn->getFaceByNetDevice(link.GetToNetDevice());
318 NS_ASSERT(face != 0);
320 face->setMetric(metric);
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
338 PointToPointHelper p2p;
340 BOOST_FOREACH (Link& link, m_linksList) {
345 if (link.GetAttributeFailSafe(
"MaxPackets", tmp)) {
346 NS_LOG_INFO(
"MaxPackets = " + link.GetAttribute(
"MaxPackets"));
349 std::string maxPackets = link.GetAttribute(
"MaxPackets");
352 p2p.SetQueue(
"ns3::DropTailQueue<Packet>",
"MaxSize", StringValue(maxPackets +
"p"));
355 typedef boost::tokenizer<boost::escaped_list_separator<char>> tokenizer;
356 std::string value = link.GetAttribute(
"MaxPackets");
357 tokenizer tok(value);
359 tokenizer::iterator token = tok.begin();
360 p2p.SetQueue(*token);
362 for (token++; token != tok.end(); token++) {
363 boost::escaped_list_separator<char> separator(
'\\',
'=',
'\"');
364 tokenizer attributeTok(*token, separator);
366 tokenizer::iterator attributeToken = attributeTok.begin();
368 string attribute = *attributeToken;
371 if (attributeToken == attributeTok.end()) {
372 NS_LOG_ERROR(
"Queue attribute [" << *token
373 <<
"] should be in form <Attribute>=<Value>");
377 string value = *attributeToken;
379 p2p.SetQueueAttribute(attribute, StringValue(value));
384 if (link.GetAttributeFailSafe(
"DataRate", tmp)) {
385 NS_LOG_INFO(
"DataRate = " + link.GetAttribute(
"DataRate"));
386 p2p.SetDeviceAttribute(
"DataRate", StringValue(link.GetAttribute(
"DataRate")));
389 if (link.GetAttributeFailSafe(
"Delay", tmp)) {
390 NS_LOG_INFO(
"Delay = " + link.GetAttribute(
"Delay"));
391 p2p.SetChannelAttribute(
"Delay", StringValue(link.GetAttribute(
"Delay")));
394 NetDeviceContainer nd = p2p.Install(link.GetFromNode(), link.GetToNode());
395 link.SetNetDevices(nd.Get(0), nd.Get(1));
398 if (link.GetAttributeFailSafe(
"LossRate", tmp)) {
399 NS_LOG_INFO(
"LinkError = " + link.GetAttribute(
"LossRate"));
401 typedef boost::tokenizer<boost::escaped_list_separator<char>> tokenizer;
402 std::string value = link.GetAttribute(
"LossRate");
403 tokenizer tok(value);
405 tokenizer::iterator token = tok.begin();
406 ObjectFactory factory(*token);
408 for (token++; token != tok.end(); token++) {
409 boost::escaped_list_separator<char> separator(
'\\',
'=',
'\"');
410 tokenizer attributeTok(*token, separator);
412 tokenizer::iterator attributeToken = attributeTok.begin();
414 string attribute = *attributeToken;
417 if (attributeToken == attributeTok.end()) {
418 NS_LOG_ERROR(
"ErrorModel attribute [" << *token
419 <<
"] should be in form <Attribute>=<Value>");
423 string value = *attributeToken;
425 factory.Set(attribute, StringValue(value));
428 nd.Get(0)->SetAttribute(
"ReceiveErrorModel", PointerValue(factory.Create<ErrorModel>()));
429 nd.Get(1)->SetAttribute(
"ReceiveErrorModel", PointerValue(factory.Create<ErrorModel>()));
437 ofstream os(file.c_str(), ios::trunc);
438 os <<
"# any empty lines and lines starting with '#' symbol is ignored\n"
440 <<
"# The file should contain exactly two sections: router and link, each starting with the "
441 "corresponding keyword\n"
443 <<
"# router section defines topology nodes and their relative positions (e.g., to use in "
447 <<
"# each line in this section represents one router and should have the following data\n"
448 <<
"# node comment yPos xPos\n";
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();
457 <<
"\t" << -position.y <<
"\t" << position.x <<
"\n";
461 <<
"# link section defines point-to-point links between nodes and characteristics of these "
466 <<
"# Each line should be in the following format (only first two are required, the rest can "
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";
475 for (std::list<Link>::const_iterator link = m_linksList.begin(); link != m_linksList.end();
477 os << Names::FindName(link->GetFromNode()) <<
"\t";
478 os << Names::FindName(link->GetToNode()) <<
"\t";
481 if (link->GetAttributeFailSafe(
"DataRate", tmp))
482 os << link->GetAttribute(
"DataRate") <<
"\t";
484 NS_FATAL_ERROR(
"DataRate must be specified for the link");
486 if (link->GetAttributeFailSafe(
"OSPF", tmp))
487 os << link->GetAttribute(
"OSPF") <<
"\t";
491 if (link->GetAttributeFailSafe(
"Delay", tmp)) {
492 os << link->GetAttribute(
"Delay") <<
"\t";
494 if (link->GetAttributeFailSafe(
"MaxPackets", tmp)) {
495 os << link->GetAttribute(
"MaxPackets") <<
"\t";
497 if (link->GetAttributeFailSafe(
"LossRate", tmp)) {
498 os << link->GetAttribute(
"LossRate") <<
"\t";
508 template<
class Names>
511 name_writer(Names _names)
516 template<
class VertexOrEdge>
518 operator()(std::ostream& out,
const VertexOrEdge& v)
const
521 out <<
"[shape=\"circle\",width=0.1,label=\"\",style=filled,fillcolor=\"green\"]";
528 template<
class Names>
529 inline name_writer<Names>
530 make_name_writer(Names n)
532 return name_writer<Names>(n);
540 typedef boost::adjacency_list_traits<boost::setS, boost::setS, boost::undirectedS> Traits;
542 typedef boost::property<boost::vertex_name_t, std::string,
543 boost::property<boost::vertex_index_t, uint32_t>> nodeProperty;
545 typedef boost::no_property edgeProperty;
547 typedef boost::adjacency_list<boost::setS, boost::setS, boost::undirectedS, nodeProperty,
550 typedef map<string, Traits::vertex_descriptor> node_map_t;
551 node_map_t graphNodes;
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)));
559 put(boost::vertex_index, graph, retval.first->second, (*node)->GetId());
562 for (std::list<Link>::const_iterator link = m_linksList.begin(); link != m_linksList.end();
564 node_map_t::iterator from = graphNodes.find(Names::FindName(link->GetFromNode()));
565 node_map_t::iterator to = graphNodes.find(Names::FindName(link->GetToNode()));
568 boost::add_edge(from->second, to->second, graph);
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));