blob: 774ce8fdada51dbee8e288704beb7dc41a54306d [file] [log] [blame]
Alexander Afanasyev957a84a2013-01-23 10:21:06 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2013 University of California, Los Angeles
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Author: Ilya Moiseenko <iliamo@cs.ucla.edu>
19 * Hajime Tazaki (tazaki@sfc.wide.ad.jp)
20 * Alexander Afanasyev <alexander.afanasyev@ucla.edu>
21 *
22 */
23
Alexander Afanasyev0c395372014-12-20 15:54:02 -080024#include "rocketfuel-map-reader.hpp"
Alexander Afanasyev957a84a2013-01-23 10:21:06 -080025
26#include "ns3/nstime.h"
27#include "ns3/log.h"
28#include "ns3/fatal-error.h"
29#include "ns3/assert.h"
30#include "ns3/names.h"
31#include "ns3/net-device-container.h"
32#include "ns3/point-to-point-helper.h"
33#include "ns3/point-to-point-net-device.h"
34#include "ns3/internet-stack-helper.h"
35#include "ns3/ipv4-address-helper.h"
36#include "ns3/ipv4-global-routing-helper.h"
37#include "ns3/drop-tail-queue.h"
38#include "ns3/ipv4-interface.h"
39#include "ns3/ipv4.h"
40#include "ns3/string.h"
41#include "ns3/pointer.h"
42#include "ns3/uinteger.h"
43#include "ns3/ipv4-address.h"
44#include "ns3/node-list.h"
45#include "ns3/random-variable.h"
46
47#include "ns3/mobility-model.h"
48
49#include <regex.h>
50
51#include <boost/foreach.hpp>
52#include <boost/lexical_cast.hpp>
53
54#include <boost/graph/graphviz.hpp>
55#include <boost/graph/connected_components.hpp>
56
57#include <iomanip>
58
59using namespace std;
60using namespace boost;
61
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080062NS_LOG_COMPONENT_DEFINE("RocketfuelMapReader");
Alexander Afanasyev957a84a2013-01-23 10:21:06 -080063
64namespace ns3 {
65
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080066RocketfuelMapReader::RocketfuelMapReader(const std::string& path /*=""*/, double scale /*=1.0*/,
67 const std::string& referenceOspfRate)
68 : AnnotatedTopologyReader(path, scale)
69 , m_referenceOspfRate(boost::lexical_cast<DataRate>(referenceOspfRate))
Alexander Afanasyev957a84a2013-01-23 10:21:06 -080070{
71}
72
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080073RocketfuelMapReader::~RocketfuelMapReader()
Alexander Afanasyev957a84a2013-01-23 10:21:06 -080074{
75}
76
77NodeContainer
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080078RocketfuelMapReader::Read()
Alexander Afanasyev957a84a2013-01-23 10:21:06 -080079{
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080080 NS_FATAL_ERROR("Deprecated call. Use the other overloaded method instead");
81 return NodeContainer();
Alexander Afanasyev957a84a2013-01-23 10:21:06 -080082}
83
Alexander Afanasyev957a84a2013-01-23 10:21:06 -080084/* uid @loc [+] [bb] (num_neigh) [&ext] -> <nuid-1> <nuid-2> ... {-euid} ... =name[!] rn */
85
86#define REGMATCH_MAX 16
87
88#define START "^"
89#define END "$"
90#define SPACE "[ \t]+"
91#define MAYSPACE "[ \t]*"
92
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080093#define ROCKETFUEL_MAPS_LINE \
94 START "(-*[0-9]+)" SPACE "(@[?A-Za-z0-9,+]+)" SPACE "(\\+)*" MAYSPACE "(bb)*" MAYSPACE \
95 "\\(([0-9]+)\\)" SPACE "(&[0-9]+)*" MAYSPACE "->" MAYSPACE "(<[0-9 \t<>]+>)*" MAYSPACE \
96 "(\\{-[0-9\\{\\} \t-]+\\})*" SPACE "=([A-Za-z0-9.!-]+)" SPACE "r([0-9])" MAYSPACE END
Alexander Afanasyev957a84a2013-01-23 10:21:06 -080097
98void
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080099RocketfuelMapReader::CreateLink(string nodeName1, string nodeName2, double averageRtt,
100 const string& minBw, const string& maxBw, const string& minDelay,
101 const string& maxDelay)
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800102{
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800103 Ptr<Node> node1 = Names::Find<Node>(m_path, nodeName1);
104 Ptr<Node> node2 = Names::Find<Node>(m_path, nodeName2);
105 Link link(node1, nodeName1, node2, nodeName2);
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800106
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800107 DataRate randBandwidth(
108 m_randVar.GetInteger(static_cast<uint32_t>(lexical_cast<DataRate>(minBw).GetBitRate()),
109 static_cast<uint32_t>(lexical_cast<DataRate>(maxBw).GetBitRate())));
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800110
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800111 int32_t metric = std::max(1, static_cast<int32_t>(1.0 * m_referenceOspfRate.GetBitRate()
112 / randBandwidth.GetBitRate()));
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800113
114 Time randDelay =
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800115 Time::FromDouble((m_randVar.GetValue(lexical_cast<Time>(minDelay).ToDouble(Time::US),
116 lexical_cast<Time>(maxDelay).ToDouble(Time::US))),
117 Time::US);
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800118
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800119 uint32_t queue = ceil(averageRtt * (randBandwidth.GetBitRate() / 8.0 / 1100.0));
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800120
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800121 link.SetAttribute("DataRate", boost::lexical_cast<string>(randBandwidth));
122 link.SetAttribute("OSPF", boost::lexical_cast<string>(metric));
123 link.SetAttribute("Delay",
124 boost::lexical_cast<string>(ceil(randDelay.ToDouble(Time::US))) + "us");
125 link.SetAttribute("MaxPackets", boost::lexical_cast<string>(queue));
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800126
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800127 AddLink(link);
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800128}
129
130// NodeContainer
131void
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800132RocketfuelMapReader::GenerateFromMapsFile(int argc, char* argv[])
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800133{
134 string uid;
135 string loc;
136 string ptr;
137 string name;
138 string nuid;
Alexander Afanasyev29c10ed2013-01-23 18:26:07 -0800139 // bool dns = false;
140 // bool bb = false;
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800141 int num_neigh_s = 0;
142 unsigned int num_neigh = 0;
143 int radius = 0;
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800144 vector<string> neigh_list;
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800145
146 uid = argv[0];
147 loc = argv[1];
148
Alexander Afanasyev29c10ed2013-01-23 18:26:07 -0800149 // if (argv[2])
150 // {
151 // dns = true;
152 // }
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800153
Alexander Afanasyev29c10ed2013-01-23 18:26:07 -0800154 // if (argv[3])
155 // {
156 // bb = true;
157 // }
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800158
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800159 num_neigh_s = ::atoi(argv[4]);
160 if (num_neigh_s < 0) {
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800161 num_neigh = 0;
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800162 NS_LOG_WARN("Negative number of neighbors given");
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800163 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800164 else {
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800165 num_neigh = num_neigh_s;
166 }
167
168 /* neighbors */
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800169 if (argv[6]) {
170 char* nbr;
171 char* stringp = argv[6];
172 while ((nbr = strsep(&stringp, " \t")) != NULL) {
173 nbr[strlen(nbr) - 1] = '\0';
174 neigh_list.push_back(nbr + 1);
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800175 }
176 }
177
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800178 if (num_neigh != neigh_list.size()) {
179 NS_LOG_WARN("Given number of neighbors = " << num_neigh << " != size of neighbors list = "
180 << neigh_list.size());
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800181 }
182
183 /* externs */
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800184 if (argv[7]) {
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800185 // euid = argv[7];
186 }
187
188 /* name */
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800189 if (argv[8]) {
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800190 name = argv[8];
191 }
192
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800193 radius = ::atoi(&argv[9][1]);
194 if (radius > 0) {
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800195 return;
196 }
197
198 // Create node and link
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800199 if (uid.empty())
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800200 return;
201
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800202 node_map_t::iterator node = m_graphNodes.find(uid);
203 if (node == m_graphNodes.end()) {
204 bool ok;
205 tie(node, ok) = m_graphNodes.insert(make_pair(uid, add_vertex(nodeProperty(uid), m_graph)));
206 NS_ASSERT(ok == true);
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800207
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800208 put(vertex_index, m_graph, node->second, m_maxNodeId);
209 m_maxNodeId++;
210 }
211
212 for (uint32_t i = 0; i < neigh_list.size(); ++i) {
213 nuid = neigh_list[i];
214
215 if (nuid.empty()) {
216 continue;
217 }
218
219 node_map_t::iterator otherNode = m_graphNodes.find(nuid);
220 if (otherNode == m_graphNodes.end()) {
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800221 bool ok;
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800222 tie(otherNode, ok) =
223 m_graphNodes.insert(make_pair(nuid, add_vertex(nodeProperty(nuid), m_graph)));
224 NS_ASSERT(ok == true);
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800225
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800226 put(vertex_index, m_graph, otherNode->second, m_maxNodeId);
227 m_maxNodeId++;
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800228 }
229
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800230 // cout << node->second << " <-> " << otherNode->second << endl;
231 // parallel edges are disabled in the graph, so no need to worry
232 add_edge(node->second, otherNode->second, m_graph);
233 }
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800234}
235
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800236void
237RocketfuelMapReader::assignGw(Traits::vertex_descriptor vertex, uint32_t degree,
238 node_type_t nodeType)
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800239{
240 graph_traits<Graph>::adjacency_iterator u, endu;
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800241 for (tie(u, endu) = adjacent_vertices(vertex, m_graph); u != endu; u++) {
242 if (get(vertex_rank, m_graph, *u) != UNKNOWN)
243 continue;
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800244
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800245 put(vertex_rank, m_graph, *u, nodeType);
246 put(vertex_color, m_graph, *u, "green");
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800247
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800248 uint32_t u_degree = out_degree(*u, m_graph);
249 if (u_degree < degree)
250 assignGw(*u, degree, BACKBONE);
251 }
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800252};
253
254void
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800255RocketfuelMapReader::AssignClients(uint32_t clientDegree, uint32_t gwDegree)
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800256{
257 graph_traits<Graph>::vertex_iterator v, endv;
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800258 for (tie(v, endv) = vertices(m_graph); v != endv; v++) {
259 uint32_t degree = out_degree(*v, m_graph);
260 if (degree == clientDegree) {
261 put(vertex_rank, m_graph, *v, CLIENT);
262 put(vertex_color, m_graph, *v, "red");
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800263
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800264 assignGw(*v, gwDegree + 1, GATEWAY);
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800265 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800266 }
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800267};
268
269NodeContainer
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800270RocketfuelMapReader::Read(RocketfuelParams params, bool keepOneComponent /*=true*/,
271 bool connectBackbones /*=true*/)
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800272{
273 m_maxNodeId = 0;
274
275 ifstream topgen;
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800276 topgen.open(GetFileName().c_str());
277 // NodeContainer nodes;
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800278 UniformVariable var;
279
280 istringstream lineBuffer;
281 string line;
282 int lineNumber = 0;
283 char errbuf[512];
284
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800285 if (!topgen.is_open()) {
286 NS_LOG_WARN("Couldn't open the file " << GetFileName());
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800287 return m_nodes;
288 }
289
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800290 while (!topgen.eof()) {
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800291 int ret;
292 int argc;
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800293 char* argv[REGMATCH_MAX];
294 char* buf;
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800295
296 lineNumber++;
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800297 line.clear();
298 lineBuffer.clear();
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800299
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800300 getline(topgen, line);
301 buf = (char*)line.c_str();
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800302
303 regmatch_t regmatch[REGMATCH_MAX];
304 regex_t regex;
305
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800306 ret = regcomp(&regex, ROCKETFUEL_MAPS_LINE, REG_EXTENDED | REG_NEWLINE);
307 if (ret != 0) {
308 regerror(ret, &regex, errbuf, sizeof(errbuf));
309 regfree(&regex);
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800310 continue;
311 }
312
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800313 ret = regexec(&regex, buf, REGMATCH_MAX, regmatch, 0);
314 if (ret == REG_NOMATCH) {
315 NS_LOG_WARN("match failed (maps file): %s" << buf);
316 regfree(&regex);
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800317 continue;
318 }
319
320 line = buf;
321 argc = 0;
322
323 /* regmatch[0] is the entire strings that matched */
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800324 for (int i = 1; i < REGMATCH_MAX; i++) {
325 if (regmatch[i].rm_so == -1) {
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800326 argv[i - 1] = NULL;
327 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800328 else {
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800329 line[regmatch[i].rm_eo] = '\0';
330 argv[i - 1] = &line[regmatch[i].rm_so];
331 argc = i;
332 }
333 }
334
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800335 GenerateFromMapsFile(argc, argv);
336 regfree(&regex);
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800337 }
338
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800339 if (keepOneComponent) {
340 NS_LOG_DEBUG("Before eliminating disconnected nodes: " << num_vertices(m_graph));
341 KeepOnlyBiggestConnectedComponent();
342 NS_LOG_DEBUG("After eliminating disconnected nodes: " << num_vertices(m_graph));
343 }
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800344
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800345 for (int clientDegree = 1; clientDegree <= params.clientNodeDegrees; clientDegree++) {
346 AssignClients(clientDegree, std::min(clientDegree, 3));
347 }
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800348
349 graph_traits<Graph>::vertex_iterator v, endv;
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800350 for (tie(v, endv) = vertices(m_graph); v != endv; v++) {
351 node_type_t type = get(vertex_rank, m_graph, *v);
352 if (type == UNKNOWN) {
353 put(vertex_rank, m_graph, *v, BACKBONE);
354 put(vertex_color, m_graph, *v, "blue");
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800355 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800356 }
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800357
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800358 if (connectBackbones) {
359 ConnectBackboneRouters();
360 }
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800361
362 graph_traits<Graph>::edge_iterator e, ende;
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800363 for (tie(e, ende) = edges(m_graph); e != ende;) {
364 Traits::vertex_descriptor u = source(*e, m_graph), v = target(*e, m_graph);
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800365
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800366 node_type_t u_type = get(vertex_rank, m_graph, u), v_type = get(vertex_rank, m_graph, v);
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800367
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800368 if (u_type == BACKBONE && v_type == BACKBONE) {
369 // ok
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800370 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800371 else if ((u_type == GATEWAY && v_type == BACKBONE)
372 || (u_type == BACKBONE && v_type == GATEWAY)) {
373 // ok
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800374 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800375 else if (u_type == GATEWAY && v_type == GATEWAY) {
376 // ok
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800377 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800378 else if ((u_type == GATEWAY && v_type == CLIENT) || (u_type == CLIENT && v_type == GATEWAY)) {
379 // ok
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800380 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800381 else {
382 // not ok
383 NS_LOG_DEBUG("Wrong link type between nodes: " << u_type << " <-> " << v_type
384 << " (deleting the link)");
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800385
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800386 graph_traits<Graph>::edge_iterator tmp = e;
387 tmp++;
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800388
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800389 remove_edge(*e, m_graph);
390 e = tmp;
391 continue;
392 }
393 e++;
394 }
395
396 if (keepOneComponent) {
397 NS_LOG_DEBUG("Before 2 eliminating disconnected nodes: " << num_vertices(m_graph));
398 KeepOnlyBiggestConnectedComponent();
399 NS_LOG_DEBUG("After 2 eliminating disconnected nodes: " << num_vertices(m_graph));
400 }
401
402 for (tie(v, endv) = vertices(m_graph); v != endv; v++) {
403 string nodeName = get(vertex_name, m_graph, *v);
404 Ptr<Node> node = CreateNode(nodeName, 0);
405
406 node_type_t type = get(vertex_rank, m_graph, *v);
407 switch (type) {
408 case BACKBONE:
409 Names::Rename(nodeName, "bb-" + nodeName);
410 put(vertex_name, m_graph, *v, "bb-" + nodeName);
411 m_backboneRouters.Add(node);
412 break;
413 case CLIENT:
414 Names::Rename(nodeName, "leaf-" + nodeName);
415 put(vertex_name, m_graph, *v, "leaf-" + nodeName);
416 m_customerRouters.Add(node);
417 break;
418 case GATEWAY:
419 Names::Rename(nodeName, "gw-" + nodeName);
420 put(vertex_name, m_graph, *v, "gw-" + nodeName);
421 m_gatewayRouters.Add(node);
422 break;
423 case UNKNOWN:
424 NS_FATAL_ERROR("Should not happen");
425 break;
426 }
427 }
428
429 for (tie(e, ende) = edges(m_graph); e != ende; e++) {
430 Traits::vertex_descriptor u = source(*e, m_graph), v = target(*e, m_graph);
431
432 node_type_t u_type = get(vertex_rank, m_graph, u), v_type = get(vertex_rank, m_graph, v);
433
434 string u_name = get(vertex_name, m_graph, u), v_name = get(vertex_name, m_graph, v);
435
436 if (u_type == BACKBONE && v_type == BACKBONE) {
437 CreateLink(u_name, v_name, params.averageRtt, params.minb2bBandwidth, params.maxb2bBandwidth,
438 params.minb2bDelay, params.maxb2bDelay);
439 }
440 else if ((u_type == GATEWAY && v_type == BACKBONE)
441 || (u_type == BACKBONE && v_type == GATEWAY)) {
442 CreateLink(u_name, v_name, params.averageRtt, params.minb2gBandwidth, params.maxb2gBandwidth,
443 params.minb2gDelay, params.maxb2gDelay);
444 }
445 else if (u_type == GATEWAY && v_type == GATEWAY) {
446 CreateLink(u_name, v_name, params.averageRtt, params.minb2gBandwidth, params.maxb2gBandwidth,
447 params.minb2gDelay, params.maxb2gDelay);
448 }
449 else if ((u_type == GATEWAY && v_type == CLIENT) || (u_type == CLIENT && v_type == GATEWAY)) {
450 CreateLink(u_name, v_name, params.averageRtt, params.ming2cBandwidth, params.maxg2cBandwidth,
451 params.ming2cDelay, params.maxg2cDelay);
452 }
453 else {
454 NS_FATAL_ERROR("Wrong link type between nodes: " << u_type << " <-> " << v_type);
455 }
456 }
457
458 ApplySettings();
459
460 NS_LOG_INFO("Clients: " << m_customerRouters.GetN());
461 NS_LOG_INFO("Gateways: " << m_gatewayRouters.GetN());
462 NS_LOG_INFO("Backbones: " << m_backboneRouters.GetN());
463 NS_LOG_INFO("Links: " << GetLinks().size());
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800464
465 return m_nodes;
466}
467
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800468const NodeContainer&
469RocketfuelMapReader::GetBackboneRouters() const
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800470{
471 return m_backboneRouters;
472}
473
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800474const NodeContainer&
475RocketfuelMapReader::GetGatewayRouters() const
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800476{
477 return m_gatewayRouters;
478}
479
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800480const NodeContainer&
481RocketfuelMapReader::GetCustomerRouters() const
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800482{
483 return m_customerRouters;
484}
485
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800486static void
487nodeWriter(std::ostream& os, NodeContainer& m)
Alexander Afanasyev29c10ed2013-01-23 18:26:07 -0800488{
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800489 for (NodeContainer::Iterator node = m.Begin(); node != m.End(); node++) {
490 std::string name = Names::FindName(*node);
Alexander Afanasyev29c10ed2013-01-23 18:26:07 -0800491
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800492 os << name << "\t"
493 << "NA"
494 << "\t" << 0 << "\t" << 0 << "\n";
495 }
Alexander Afanasyev29c10ed2013-01-23 18:26:07 -0800496};
497
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800498void
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800499RocketfuelMapReader::SaveTopology(const std::string& file)
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800500{
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800501 ofstream os(file.c_str(), ios::trunc);
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800502 os << "# any empty lines and lines starting with '#' symbol is ignored\n"
503 << "\n"
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800504 << "# The file should contain exactly two sections: router and link, each starting with the "
505 "corresponding keyword\n"
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800506 << "\n"
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800507 << "# router section defines topology nodes and their relative positions (e.g., to use in "
508 "visualizer)\n"
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800509 << "router\n"
510 << "\n"
511 << "# each line in this section represents one router and should have the following data\n"
512 << "# node comment yPos xPos\n";
513
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800514 nodeWriter(os, m_backboneRouters);
515 nodeWriter(os, m_gatewayRouters);
516 nodeWriter(os, m_customerRouters);
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800517
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800518 os << "# link section defines point-to-point links between nodes and characteristics of these "
519 "links\n"
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800520 << "\n"
521 << "link\n"
522 << "\n"
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800523 << "# Each line should be in the following format (only first two are required, the rest can "
524 "be omitted)\n"
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800525 << "# srcNode dstNode bandwidth metric delay queue\n"
526 << "# bandwidth: link bandwidth\n"
527 << "# metric: routing metric\n"
528 << "# delay: link delay\n"
529 << "# queue: MaxPackets for transmission queue on the link (both directions)\n";
530
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800531 for (std::list<Link>::iterator link = m_linksList.begin(); link != m_linksList.end(); link++) {
532 string src = Names::FindName(link->GetFromNode());
533 string dst = Names::FindName(link->GetToNode());
534 os << src << "\t";
535 os << dst << "\t";
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800536
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800537 string tmp;
538 if (link->GetAttributeFailSafe("DataRate", tmp))
539 os << link->GetAttribute("DataRate") << "\t";
540 else
541 NS_FATAL_ERROR("DataRate must be specified for the link");
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800542
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800543 if (link->GetAttributeFailSafe("OSPF", tmp))
544 os << link->GetAttribute("OSPF") << "\t";
545 else {
546 DataRate rate = boost::lexical_cast<DataRate>(link->GetAttribute("DataRate"));
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800547
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800548 int32_t cost = std::max(1, static_cast<int32_t>(1.0 * m_referenceOspfRate.GetBitRate()
549 / rate.GetBitRate()));
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800550
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800551 os << cost << "\t";
Alexander Afanasyev29c10ed2013-01-23 18:26:07 -0800552 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800553
554 if (link->GetAttributeFailSafe("Delay", tmp)) {
555 os << link->GetAttribute("Delay") << "\t";
556
557 if (link->GetAttributeFailSafe("MaxPackets", tmp)) {
558 os << link->GetAttribute("MaxPackets") << "\t";
559 }
560 }
561 os << "\n";
562 }
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800563}
564
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800565template<class Names, class Colors>
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800566class name_color_writer {
567public:
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800568 name_color_writer(Names _names, Colors _colors)
569 : names(_names)
570 , colors(_colors)
571 {
572 }
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800573
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800574 template<class VertexOrEdge>
575 void
576 operator()(std::ostream& out, const VertexOrEdge& v) const
577 {
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800578 // out << "[label=\"" << names[v] << "\",style=filled,fillcolor=\"" << colors[v] << "\"]";
579 out << "[shape=\"circle\",width=0.1,label=\"\",style=filled,fillcolor=\"" << colors[v] << "\"]";
580 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800581
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800582private:
583 Names names;
584 Colors colors;
585};
586
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800587template<class Names, class Colors>
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800588inline name_color_writer<Names, Colors>
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800589make_name_color_writer(Names n, Colors c)
590{
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800591 return name_color_writer<Names, Colors>(n, c);
592}
593
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800594void
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800595RocketfuelMapReader::SaveGraphviz(const std::string& file)
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800596{
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800597 ofstream of(file.c_str());
598 property_map<Graph, vertex_name_t>::type names = get(vertex_name, m_graph);
599 property_map<Graph, vertex_color_t>::type colors = get(vertex_color, m_graph);
600 write_graphviz(of, m_graph, make_name_color_writer(names, colors));
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800601}
602
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800603void
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800604RocketfuelMapReader::KeepOnlyBiggestConnectedComponent()
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800605{
606 std::map<graph_traits<Graph>::vertex_descriptor, int> temp;
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800607 associative_property_map<std::map<graph_traits<Graph>::vertex_descriptor, int>> components(temp);
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800608
609 // //check if topology has breaks in its structure and trim it if yes
610 // property_map<Graph, vertex_index1_t>::type components = get (vertex_index1, m_graph);
611
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800612 int num = connected_components(m_graph, components);
613 NS_LOG_DEBUG("Topology has " << num << " components");
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800614
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800615 vector<int> sizes(num, 0);
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800616
617 graph_traits<Graph>::vertex_iterator v, endv;
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800618 for (tie(v, endv) = vertices(m_graph); v != endv; v++) {
619 sizes[get(components, *v)]++;
620 }
621 int largestComponent = max_element(sizes.begin(), sizes.end()) - sizes.begin();
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800622 // cout << "Largest: " << largestComponent << endl;
623
624 // for (int i =0 ; i < num; i++) cout << sizes[i] << " ";
625 // cout << endl;
626
627 ////////////////////////////////////////////////////
628 // remove nodes and edges from smaller components //
629 ////////////////////////////////////////////////////
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800630 for (tie(v, endv) = vertices(m_graph); v != endv; v++) {
631 if (get(components, *v) == largestComponent)
632 continue;
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800633
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800634 clear_vertex(*v, m_graph);
635 }
636
637 // this works only if vertices are organized in listS or setS (iterator is not invalidated on
638 // remove)
639 for (tie(v, endv) = vertices(m_graph); v != endv;) {
640 if (get(components, *v) == largestComponent) {
641 v++;
642 continue;
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800643 }
644
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800645 graph_traits<Graph>::vertex_iterator tmp = v;
646 tmp++;
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800647
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800648 remove_vertex(*v, m_graph);
649 v = tmp;
650 }
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800651
652 int index = 0;
653 // renumber nodes
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800654 for (tie(v, endv) = vertices(m_graph); v != endv; v++) {
655 put(vertex_index, m_graph, *v, index++);
656 }
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800657}
658
659void
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800660RocketfuelMapReader::ConnectBackboneRouters()
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800661{
662 // not the tricky part. we want backbone to be a fully connected component,
663 // so traffic doesn't bounce from backbone to gateway and back
664
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800665 typedef adjacency_list<setS, setS, boost::undirectedS,
666 property<vertex_name_t, Traits::vertex_descriptor,
667 property<vertex_index_t, int, property<vertex_index1_t, int>>>>
668 BbGraph;
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800669 BbGraph bbGraph;
670 map<Traits::vertex_descriptor, graph_traits<BbGraph>::vertex_descriptor> nodeMap;
671
672 int index = 0;
673
674 graph_traits<Graph>::vertex_iterator v, endv;
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800675 for (tie(v, endv) = vertices(m_graph); v != endv; v++) {
676 node_type_t type = get(vertex_rank, m_graph, *v);
677 if (type == BACKBONE) {
678 graph_traits<BbGraph>::vertex_descriptor newv = add_vertex(*v, bbGraph);
679 put(vertex_index, bbGraph, newv, index++);
680 nodeMap[*v] = newv;
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800681 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800682 }
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800683
684 graph_traits<BbGraph>::vertex_iterator bb, endBb;
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800685 for (tie(bb, endBb) = vertices(bbGraph); bb != endBb; bb++) {
686 Traits::vertex_descriptor actualVertex = get(vertex_name, bbGraph, *bb);
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800687
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800688 graph_traits<Graph>::adjacency_iterator u, endu;
689 for (tie(u, endu) = adjacent_vertices(actualVertex, m_graph); u != endu; u++) {
690 if (nodeMap.find(*u) != nodeMap.end()) {
691 add_edge(nodeMap[actualVertex], nodeMap[*u], bbGraph);
692 }
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800693 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800694 }
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800695
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800696 property_map<BbGraph, vertex_index1_t>::type components = get(vertex_index1, bbGraph);
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800697
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800698 int num = connected_components(bbGraph, components);
699 NS_LOG_DEBUG("Backbone has " << num << " components");
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800700 if (num == 1)
701 return; // nothing to do
702
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800703 vector<vector<graph_traits<BbGraph>::vertex_descriptor>> subgraphs(num);
704 for (tie(bb, endBb) = vertices(bbGraph); bb != endBb; bb++) {
705 int component = get(vertex_index1, bbGraph, *bb);
706 subgraphs[component].push_back(*bb);
707 }
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800708
709 UniformVariable randVar;
710
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800711 for (int i = 1; i < num; i++) {
712 int node1 = randVar.GetInteger(0, subgraphs[i - 1].size() - 1);
713 int node2 = randVar.GetInteger(0, subgraphs[i].size() - 1);
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800714
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800715 Traits::vertex_descriptor v1 = get(vertex_name, bbGraph, subgraphs[i - 1][node1]),
716 v2 = get(vertex_name, bbGraph, subgraphs[i][node2]);
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800717
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800718 NS_LOG_DEBUG("Connecting " << get(vertex_name, m_graph, v1) << "[" << node1 << "] with "
719 << get(vertex_name, m_graph, v2) << "[" << node2 << "]");
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800720
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800721 add_edge(v1, v2, m_graph);
722 }
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800723}
724
Alexander Afanasyev957a84a2013-01-23 10:21:06 -0800725} /* namespace ns3 */