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)