24 #include "ns3/nstime.h" 
   26 #include "ns3/fatal-error.h" 
   27 #include "ns3/assert.h" 
   28 #include "ns3/names.h" 
   29 #include "ns3/net-device-container.h" 
   30 #include "ns3/point-to-point-helper.h" 
   31 #include "ns3/point-to-point-net-device.h" 
   32 #include "ns3/internet-stack-helper.h" 
   33 #include "ns3/ipv4-address-helper.h" 
   34 #include "ns3/ipv4-global-routing-helper.h" 
   35 #include "ns3/drop-tail-queue.h" 
   36 #include "ns3/ipv4-interface.h" 
   38 #include "ns3/string.h" 
   39 #include "ns3/pointer.h" 
   40 #include "ns3/uinteger.h" 
   41 #include "ns3/ipv4-address.h" 
   42 #include "ns3/node-list.h" 
   43 #include "ns3/random-variable.h" 
   45 #include "ns3/mobility-model.h" 
   49 #include <boost/foreach.hpp> 
   50 #include <boost/lexical_cast.hpp> 
   52 #include <boost/graph/graphviz.hpp> 
   53 #include <boost/graph/connected_components.hpp> 
   58 using namespace boost;
 
   60 NS_LOG_COMPONENT_DEFINE(
"RocketfuelMapReader");
 
   65                                          const std::string& referenceOspfRate)
 
   67   , m_referenceOspfRate(boost::lexical_cast<DataRate>(referenceOspfRate))
 
   78   NS_FATAL_ERROR(
"Deprecated call. Use the other overloaded method instead");
 
   79   return NodeContainer();
 
   84 #define REGMATCH_MAX 16 
   88 #define SPACE "[ \t]+" 
   89 #define MAYSPACE "[ \t]*" 
   91 #define ROCKETFUEL_MAPS_LINE                                                                       \ 
   92   START "(-*[0-9]+)" SPACE "(@[?A-Za-z0-9,+]+)" SPACE "(\\+)*" MAYSPACE "(bb)*" MAYSPACE           \ 
   93         "\\(([0-9]+)\\)" SPACE "(&[0-9]+)*" MAYSPACE "->" MAYSPACE "(<[0-9 \t<>]+>)*" MAYSPACE     \ 
   94         "(\\{-[0-9\\{\\} \t-]+\\})*" SPACE "=([A-Za-z0-9.!-]+)" SPACE "r([0-9])" MAYSPACE END 
   97 RocketfuelMapReader::CreateLink(
string nodeName1, 
string nodeName2, 
double averageRtt,
 
   98                                 const string& minBw, 
const string& maxBw, 
const string& minDelay,
 
   99                                 const string& maxDelay)
 
  101   Ptr<Node> node1 = Names::Find<Node>(
m_path, nodeName1);
 
  102   Ptr<Node> node2 = Names::Find<Node>(
m_path, nodeName2);
 
  103   Link link(node1, nodeName1, node2, nodeName2);
 
  105   DataRate randBandwidth(
 
  106     m_randVar.GetInteger(static_cast<uint32_t>(lexical_cast<DataRate>(minBw).GetBitRate()),
 
  107                          static_cast<uint32_t>(lexical_cast<DataRate>(maxBw).GetBitRate())));
 
  109   int32_t metric = std::max(1, static_cast<int32_t>(1.0 * m_referenceOspfRate.GetBitRate()
 
  110                                                     / randBandwidth.GetBitRate()));
 
  113     Time::FromDouble((m_randVar.GetValue(lexical_cast<Time>(minDelay).ToDouble(Time::US),
 
  114                                          lexical_cast<Time>(maxDelay).ToDouble(Time::US))),
 
  117   uint32_t queue = ceil(averageRtt * (randBandwidth.GetBitRate() / 8.0 / 1100.0));
 
  119   link.SetAttribute(
"DataRate", boost::lexical_cast<string>(randBandwidth));
 
  120   link.SetAttribute(
"OSPF", boost::lexical_cast<string>(metric));
 
  121   link.SetAttribute(
"Delay",
 
  122                     boost::lexical_cast<string>(ceil(randDelay.ToDouble(Time::US))) + 
"us");
 
  123   link.SetAttribute(
"MaxPackets", boost::lexical_cast<string>(queue));
 
  130 RocketfuelMapReader::GenerateFromMapsFile(
int argc, 
char* argv[])
 
  140   unsigned int num_neigh = 0;
 
  142   vector<string> neigh_list;
 
  157   num_neigh_s = ::atoi(argv[4]);
 
  158   if (num_neigh_s < 0) {
 
  160     NS_LOG_WARN(
"Negative number of neighbors given");
 
  163     num_neigh = num_neigh_s;
 
  169     char* stringp = argv[6];
 
  170     while ((nbr = strsep(&stringp, 
" \t")) != NULL) {
 
  171       nbr[strlen(nbr) - 1] = 
'\0';
 
  172       neigh_list.push_back(nbr + 1);
 
  176   if (num_neigh != neigh_list.size()) {
 
  177     NS_LOG_WARN(
"Given number of neighbors = " << num_neigh << 
" != size of neighbors list = " 
  178                                                << neigh_list.size());
 
  191   radius = ::atoi(&argv[9][1]);
 
  200   node_map_t::iterator node = m_graphNodes.find(uid);
 
  201   if (node == m_graphNodes.end()) {
 
  203     tie(node, ok) = m_graphNodes.insert(make_pair(uid, add_vertex(nodeProperty(uid), m_graph)));
 
  204     NS_ASSERT(ok == 
true);
 
  206     put(vertex_index, m_graph, node->second, m_maxNodeId);
 
  210   for (uint32_t i = 0; i < neigh_list.size(); ++i) {
 
  211     nuid = neigh_list[i];
 
  217     node_map_t::iterator otherNode = m_graphNodes.find(nuid);
 
  218     if (otherNode == m_graphNodes.end()) {
 
  221         m_graphNodes.insert(make_pair(nuid, add_vertex(nodeProperty(nuid), m_graph)));
 
  222       NS_ASSERT(ok == 
true);
 
  224       put(vertex_index, m_graph, otherNode->second, m_maxNodeId);
 
  230     add_edge(node->second, otherNode->second, m_graph);
 
  235 RocketfuelMapReader::assignGw(Traits::vertex_descriptor vertex, uint32_t degree,
 
  236                               node_type_t nodeType)
 
  238   graph_traits<Graph>::adjacency_iterator u, endu;
 
  239   for (tie(u, endu) = adjacent_vertices(vertex, m_graph); u != endu; u++) {
 
  240     if (
get(vertex_rank, m_graph, *u) != UNKNOWN)
 
  243     put(vertex_rank, m_graph, *u, nodeType);
 
  244     put(vertex_color, m_graph, *u, 
"green");
 
  246     uint32_t u_degree = out_degree(*u, m_graph);
 
  247     if (u_degree < degree)
 
  248       assignGw(*u, degree, BACKBONE);
 
  253 RocketfuelMapReader::AssignClients(uint32_t clientDegree, uint32_t gwDegree)
 
  255   graph_traits<Graph>::vertex_iterator v, endv;
 
  256   for (tie(v, endv) = vertices(m_graph); v != endv; v++) {
 
  257     uint32_t degree = out_degree(*v, m_graph);
 
  258     if (degree == clientDegree) {
 
  259       put(vertex_rank, m_graph, *v, CLIENT);
 
  260       put(vertex_color, m_graph, *v, 
"red");
 
  262       assignGw(*v, gwDegree + 1, GATEWAY);
 
  269                           bool connectBackbones )
 
  274   topgen.open(GetFileName().c_str());
 
  278   istringstream lineBuffer;
 
  283   if (!topgen.is_open()) {
 
  284     NS_LOG_WARN(
"Couldn't open the file " << GetFileName());
 
  288   while (!topgen.eof()) {
 
  298     getline(topgen, line);
 
  299     buf = (
char*)line.c_str();
 
  306       regerror(ret, ®ex, errbuf, 
sizeof(errbuf));
 
  312     if (ret == REG_NOMATCH) {
 
  313       NS_LOG_WARN(
"match failed (maps file): %s" << buf);
 
  323       if (regmatch[i].rm_so == -1) {
 
  327         line[regmatch[i].rm_eo] = 
'\0';
 
  328         argv[i - 1] = &line[regmatch[i].rm_so];
 
  333     GenerateFromMapsFile(argc, argv);
 
  337   if (keepOneComponent) {
 
  338     NS_LOG_DEBUG(
"Before eliminating disconnected nodes: " << num_vertices(m_graph));
 
  339     KeepOnlyBiggestConnectedComponent();
 
  340     NS_LOG_DEBUG(
"After eliminating disconnected nodes:  " << num_vertices(m_graph));
 
  343   for (
int clientDegree = 1; clientDegree <= params.
clientNodeDegrees; clientDegree++) {
 
  344     AssignClients(clientDegree, std::min(clientDegree, 3));
 
  347   graph_traits<Graph>::vertex_iterator v, endv;
 
  348   for (tie(v, endv) = vertices(m_graph); v != endv; v++) {
 
  349     node_type_t type = 
get(vertex_rank, m_graph, *v);
 
  350     if (type == UNKNOWN) {
 
  351       put(vertex_rank, m_graph, *v, BACKBONE);
 
  352       put(vertex_color, m_graph, *v, 
"blue");
 
  356   if (connectBackbones) {
 
  357     ConnectBackboneRouters();
 
  360   graph_traits<Graph>::edge_iterator e, ende;
 
  361   for (tie(e, ende) = edges(m_graph); e != ende;) {
 
  362     Traits::vertex_descriptor u = source(*e, m_graph), v = target(*e, m_graph);
 
  364     node_type_t u_type = 
get(vertex_rank, m_graph, u), v_type = 
get(vertex_rank, m_graph, v);
 
  366     if (u_type == BACKBONE && v_type == BACKBONE) {
 
  369     else if ((u_type == GATEWAY && v_type == BACKBONE)
 
  370              || (u_type == BACKBONE && v_type == GATEWAY)) {
 
  373     else if (u_type == GATEWAY && v_type == GATEWAY) {
 
  376     else if ((u_type == GATEWAY && v_type == CLIENT) || (u_type == CLIENT && v_type == GATEWAY)) {
 
  381       NS_LOG_DEBUG(
"Wrong link type between nodes: " << u_type << 
" <-> " << v_type
 
  382                                                      << 
" (deleting the link)");
 
  384       graph_traits<Graph>::edge_iterator tmp = e;
 
  387       remove_edge(*e, m_graph);
 
  394   if (keepOneComponent) {
 
  395     NS_LOG_DEBUG(
"Before 2 eliminating disconnected nodes: " << num_vertices(m_graph));
 
  396     KeepOnlyBiggestConnectedComponent();
 
  397     NS_LOG_DEBUG(
"After 2 eliminating disconnected nodes:  " << num_vertices(m_graph));
 
  400   for (tie(v, endv) = vertices(m_graph); v != endv; v++) {
 
  401     string nodeName = 
get(vertex_name, m_graph, *v);
 
  404     node_type_t type = 
get(vertex_rank, m_graph, *v);
 
  407       Names::Rename(nodeName, 
"bb-" + nodeName);
 
  408       put(vertex_name, m_graph, *v, 
"bb-" + nodeName);
 
  409       m_backboneRouters.Add(node);
 
  412       Names::Rename(nodeName, 
"leaf-" + nodeName);
 
  413       put(vertex_name, m_graph, *v, 
"leaf-" + nodeName);
 
  414       m_customerRouters.Add(node);
 
  417       Names::Rename(nodeName, 
"gw-" + nodeName);
 
  418       put(vertex_name, m_graph, *v, 
"gw-" + nodeName);
 
  419       m_gatewayRouters.Add(node);
 
  422       NS_FATAL_ERROR(
"Should not happen");
 
  427   for (tie(e, ende) = edges(m_graph); e != ende; e++) {
 
  428     Traits::vertex_descriptor u = source(*e, m_graph), v = target(*e, m_graph);
 
  430     node_type_t u_type = 
get(vertex_rank, m_graph, u), v_type = 
get(vertex_rank, m_graph, v);
 
  432     string u_name = 
get(vertex_name, m_graph, u), v_name = 
get(vertex_name, m_graph, v);
 
  434     if (u_type == BACKBONE && v_type == BACKBONE) {
 
  438     else if ((u_type == GATEWAY && v_type == BACKBONE)
 
  439              || (u_type == BACKBONE && v_type == GATEWAY)) {
 
  443     else if (u_type == GATEWAY && v_type == GATEWAY) {
 
  447     else if ((u_type == GATEWAY && v_type == CLIENT) || (u_type == CLIENT && v_type == GATEWAY)) {
 
  452       NS_FATAL_ERROR(
"Wrong link type between nodes: " << u_type << 
" <-> " << v_type);
 
  458   NS_LOG_INFO(
"Clients:   " << m_customerRouters.GetN());
 
  459   NS_LOG_INFO(
"Gateways:  " << m_gatewayRouters.GetN());
 
  460   NS_LOG_INFO(
"Backbones: " << m_backboneRouters.GetN());
 
  461   NS_LOG_INFO(
"Links:     " << 
GetLinks().size());
 
  469   return m_backboneRouters;
 
  475   return m_gatewayRouters;
 
  481   return m_customerRouters;
 
  487   for (NodeContainer::Iterator node = m.Begin(); node != m.End(); node++) {
 
  488     std::string name = Names::FindName(*node);
 
  492        << 
"\t" << 0 << 
"\t" << 0 << 
"\n";
 
  499   ofstream os(file.c_str(), ios::trunc);
 
  500   os << 
"# any empty lines and lines starting with '#' symbol is ignored\n" 
  502      << 
"# The file should contain exactly two sections: router and link, each starting with the " 
  503         "corresponding keyword\n" 
  505      << 
"# router section defines topology nodes and their relative positions (e.g., to use in " 
  509      << 
"# each line in this section represents one router and should have the following data\n" 
  510      << 
"# node  comment     yPos    xPos\n";
 
  516   os << 
"# link section defines point-to-point links between nodes and characteristics of these " 
  521      << 
"# Each line should be in the following format (only first two are required, the rest can " 
  523      << 
"# srcNode   dstNode     bandwidth   metric  delay   queue\n" 
  524      << 
"# bandwidth: link bandwidth\n" 
  525      << 
"# metric: routing metric\n" 
  526      << 
"# delay:  link delay\n" 
  527      << 
"# queue:  MaxPackets for transmission queue on the link (both directions)\n";
 
  529   for (std::list<Link>::iterator link = m_linksList.begin(); link != m_linksList.end(); link++) {
 
  530     string src = Names::FindName(link->GetFromNode());
 
  531     string dst = Names::FindName(link->GetToNode());
 
  536     if (link->GetAttributeFailSafe(
"DataRate", tmp))
 
  537       os << link->GetAttribute(
"DataRate") << 
"\t";
 
  539       NS_FATAL_ERROR(
"DataRate must be specified for the link");
 
  541     if (link->GetAttributeFailSafe(
"OSPF", tmp))
 
  542       os << link->GetAttribute(
"OSPF") << 
"\t";
 
  544       DataRate rate = boost::lexical_cast<DataRate>(link->GetAttribute(
"DataRate"));
 
  546       int32_t cost = std::max(1, static_cast<int32_t>(1.0 * m_referenceOspfRate.GetBitRate()
 
  547                                                       / rate.GetBitRate()));
 
  552     if (link->GetAttributeFailSafe(
"Delay", tmp)) {
 
  553       os << link->GetAttribute(
"Delay") << 
"\t";
 
  555       if (link->GetAttributeFailSafe(
"MaxPackets", tmp)) {
 
  556         os << link->GetAttribute(
"MaxPackets") << 
"\t";
 
  565 template<
class Names, 
class Colors>
 
  566 class name_color_writer {
 
  568   name_color_writer(Names _names, Colors _colors)
 
  574   template<
class VertexOrEdge>
 
  576   operator()(std::ostream& out, 
const VertexOrEdge& v)
 const 
  579     out << 
"[shape=\"circle\",width=0.1,label=\"\",style=filled,fillcolor=\"" << colors[v] << 
"\"]";
 
  587 template<
class Names, 
class Colors>
 
  588 inline name_color_writer<Names, Colors>
 
  589 make_name_color_writer(Names n, Colors c)
 
  591   return name_color_writer<Names, Colors>(n, c);
 
  599   ofstream of(file.c_str());
 
  600   property_map<Graph, vertex_name_t>::type names = 
get(vertex_name, m_graph);
 
  601   property_map<Graph, vertex_color_t>::type colors = 
get(vertex_color, m_graph);
 
  602   write_graphviz(of, m_graph, make_name_color_writer(names, colors));
 
  606 RocketfuelMapReader::KeepOnlyBiggestConnectedComponent()
 
  608   std::map<graph_traits<Graph>::vertex_descriptor, 
int> temp;
 
  609   associative_property_map<std::map<graph_traits<Graph>::vertex_descriptor, 
int>> components(temp);
 
  614   int num = connected_components(m_graph, components);
 
  615   NS_LOG_DEBUG(
"Topology has " << num << 
" components");
 
  617   vector<int> sizes(num, 0);
 
  619   graph_traits<Graph>::vertex_iterator v, endv;
 
  620   for (tie(v, endv) = vertices(m_graph); v != endv; v++) {
 
  621     sizes[
get(components, *v)]++;
 
  623   int largestComponent = max_element(sizes.begin(), sizes.end()) - sizes.begin();
 
  632   for (tie(v, endv) = vertices(m_graph); v != endv; v++) {
 
  633     if (
get(components, *v) == largestComponent)
 
  636     clear_vertex(*v, m_graph);
 
  641   for (tie(v, endv) = vertices(m_graph); v != endv;) {
 
  642     if (
get(components, *v) == largestComponent) {
 
  647     graph_traits<Graph>::vertex_iterator tmp = v;
 
  650     remove_vertex(*v, m_graph);
 
  656   for (tie(v, endv) = vertices(m_graph); v != endv; v++) {
 
  657     put(vertex_index, m_graph, *v, index++);
 
  662 RocketfuelMapReader::ConnectBackboneRouters()
 
  667   typedef adjacency_list<setS, setS, boost::undirectedS,
 
  668                          property<vertex_name_t, Traits::vertex_descriptor,
 
  669                                   property<vertex_index_t, int, property<vertex_index1_t, int>>>>
 
  672   map<Traits::vertex_descriptor, graph_traits<BbGraph>::vertex_descriptor> nodeMap;
 
  676   graph_traits<Graph>::vertex_iterator v, endv;
 
  677   for (tie(v, endv) = vertices(m_graph); v != endv; v++) {
 
  678     node_type_t type = 
get(vertex_rank, m_graph, *v);
 
  679     if (type == BACKBONE) {
 
  680       graph_traits<BbGraph>::vertex_descriptor newv = add_vertex(*v, bbGraph);
 
  681       put(vertex_index, bbGraph, newv, index++);
 
  686   graph_traits<BbGraph>::vertex_iterator bb, endBb;
 
  687   for (tie(bb, endBb) = vertices(bbGraph); bb != endBb; bb++) {
 
  688     Traits::vertex_descriptor actualVertex = 
get(vertex_name, bbGraph, *bb);
 
  690     graph_traits<Graph>::adjacency_iterator u, endu;
 
  691     for (tie(u, endu) = adjacent_vertices(actualVertex, m_graph); u != endu; u++) {
 
  692       if (nodeMap.find(*u) != nodeMap.end()) {
 
  693         add_edge(nodeMap[actualVertex], nodeMap[*u], bbGraph);
 
  698   property_map<BbGraph, vertex_index1_t>::type components = 
get(vertex_index1, bbGraph);
 
  700   int num = connected_components(bbGraph, components);
 
  701   NS_LOG_DEBUG(
"Backbone has " << num << 
" components");
 
  705   vector<vector<graph_traits<BbGraph>::vertex_descriptor>> subgraphs(num);
 
  706   for (tie(bb, endBb) = vertices(bbGraph); bb != endBb; bb++) {
 
  707     int component = 
get(vertex_index1, bbGraph, *bb);
 
  708     subgraphs[component].push_back(*bb);
 
  711   UniformVariable randVar;
 
  713   for (
int i = 1; i < num; i++) {
 
  714     int node1 = randVar.GetInteger(0, subgraphs[i - 1].size() - 1);
 
  715     int node2 = randVar.GetInteger(0, subgraphs[i].size() - 1);
 
  717     Traits::vertex_descriptor v1 = 
get(vertex_name, bbGraph, subgraphs[i - 1][node1]),
 
  718                               v2 = 
get(vertex_name, bbGraph, subgraphs[i][node2]);
 
  720     NS_LOG_DEBUG(
"Connecting " << 
get(vertex_name, m_graph, v1) << 
"[" << node1 << 
"] with " 
  721                                << 
get(vertex_name, m_graph, v2) << 
"[" << node2 << 
"]");
 
  723     add_edge(v1, v2, m_graph);
 
This class reads annotated topology and apply settings to the corresponding nodes and links...
 
const NodeContainer & GetGatewayRouters() const 
 
virtual void SaveGraphviz(const std::string &file)
Save topology in graphviz format (.dot file) 
 
virtual void SaveTopology(const std::string &file)
Save positions (e.g., after manual modification using visualizer) 
 
virtual const std::list< Link > & GetLinks() const 
Get links read by the reader. 
 
const NodeContainer & GetCustomerRouters() const 
 
void ApplySettings()
This method applies setting to corresponding nodes and links NetDeviceContainer must be allocated Nod...
 
const NodeContainer & GetBackboneRouters() const 
 
virtual ~RocketfuelMapReader()
 
virtual NodeContainer Read()
Deprecated call. 
 
#define ROCKETFUEL_MAPS_LINE
 
static void nodeWriter(std::ostream &os, NodeContainer &m)
 
Ptr< Node > CreateNode(const std::string name, uint32_t systemId)