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.