Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ |
Alexander Afanasyev | 60a7b62 | 2014-12-20 17:04:07 -0800 | [diff] [blame] | 2 | /** |
| 3 | * Copyright (c) 2011-2015 Regents of the University of California. |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 4 | * |
Alexander Afanasyev | 60a7b62 | 2014-12-20 17:04:07 -0800 | [diff] [blame] | 5 | * This file is part of ndnSIM. See AUTHORS for complete list of ndnSIM authors and |
| 6 | * contributors. |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 7 | * |
Alexander Afanasyev | 60a7b62 | 2014-12-20 17:04:07 -0800 | [diff] [blame] | 8 | * ndnSIM is free software: you can redistribute it and/or modify it under the terms |
| 9 | * of the GNU General Public License as published by the Free Software Foundation, |
| 10 | * either version 3 of the License, or (at your option) any later version. |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 11 | * |
Alexander Afanasyev | 60a7b62 | 2014-12-20 17:04:07 -0800 | [diff] [blame] | 12 | * ndnSIM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; |
| 13 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
| 14 | * PURPOSE. See the GNU General Public License for more details. |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 15 | * |
Alexander Afanasyev | 60a7b62 | 2014-12-20 17:04:07 -0800 | [diff] [blame] | 16 | * You should have received a copy of the GNU General Public License along with |
| 17 | * ndnSIM, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>. |
| 18 | **/ |
| 19 | |
| 20 | // Based on the code by Hajime Tazaki <tazaki@sfc.wide.ad.jp> |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 21 | |
Alexander Afanasyev | 0c39537 | 2014-12-20 15:54:02 -0800 | [diff] [blame] | 22 | #include "rocketfuel-map-reader.hpp" |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 23 | |
| 24 | #include "ns3/nstime.h" |
| 25 | #include "ns3/log.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" |
| 37 | #include "ns3/ipv4.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" |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 43 | |
| 44 | #include "ns3/mobility-model.h" |
| 45 | |
| 46 | #include <regex.h> |
| 47 | |
| 48 | #include <boost/foreach.hpp> |
| 49 | #include <boost/lexical_cast.hpp> |
| 50 | |
| 51 | #include <boost/graph/graphviz.hpp> |
| 52 | #include <boost/graph/connected_components.hpp> |
| 53 | |
| 54 | #include <iomanip> |
| 55 | |
| 56 | using namespace std; |
| 57 | using namespace boost; |
| 58 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 59 | NS_LOG_COMPONENT_DEFINE("RocketfuelMapReader"); |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 60 | |
| 61 | namespace ns3 { |
| 62 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 63 | RocketfuelMapReader::RocketfuelMapReader(const std::string& path /*=""*/, double scale /*=1.0*/, |
| 64 | const std::string& referenceOspfRate) |
| 65 | : AnnotatedTopologyReader(path, scale) |
Alexander Afanasyev | d6453cd | 2015-08-20 21:45:36 -0700 | [diff] [blame] | 66 | , m_randVar(CreateObject<UniformRandomVariable>()) |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 67 | , m_referenceOspfRate(boost::lexical_cast<DataRate>(referenceOspfRate)) |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 68 | { |
| 69 | } |
| 70 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 71 | RocketfuelMapReader::~RocketfuelMapReader() |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 72 | { |
| 73 | } |
| 74 | |
| 75 | NodeContainer |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 76 | RocketfuelMapReader::Read() |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 77 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 78 | NS_FATAL_ERROR("Deprecated call. Use the other overloaded method instead"); |
| 79 | return NodeContainer(); |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 80 | } |
| 81 | |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 82 | /* uid @loc [+] [bb] (num_neigh) [&ext] -> <nuid-1> <nuid-2> ... {-euid} ... =name[!] rn */ |
| 83 | |
| 84 | #define REGMATCH_MAX 16 |
| 85 | |
| 86 | #define START "^" |
| 87 | #define END "$" |
| 88 | #define SPACE "[ \t]+" |
| 89 | #define MAYSPACE "[ \t]*" |
| 90 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 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 |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 95 | |
| 96 | void |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 97 | RocketfuelMapReader::CreateLink(string nodeName1, string nodeName2, double averageRtt, |
| 98 | const string& minBw, const string& maxBw, const string& minDelay, |
| 99 | const string& maxDelay) |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 100 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 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); |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 104 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 105 | DataRate randBandwidth( |
Alexander Afanasyev | d6453cd | 2015-08-20 21:45:36 -0700 | [diff] [blame] | 106 | m_randVar->GetInteger(static_cast<uint32_t>(lexical_cast<DataRate>(minBw).GetBitRate()), |
| 107 | static_cast<uint32_t>(lexical_cast<DataRate>(maxBw).GetBitRate()))); |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 108 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 109 | int32_t metric = std::max(1, static_cast<int32_t>(1.0 * m_referenceOspfRate.GetBitRate() |
| 110 | / randBandwidth.GetBitRate())); |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 111 | |
| 112 | Time randDelay = |
Alexander Afanasyev | d6453cd | 2015-08-20 21:45:36 -0700 | [diff] [blame] | 113 | Time::FromDouble((m_randVar->GetValue(lexical_cast<Time>(minDelay).ToDouble(Time::US), |
| 114 | lexical_cast<Time>(maxDelay).ToDouble(Time::US))), |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 115 | Time::US); |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 116 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 117 | uint32_t queue = ceil(averageRtt * (randBandwidth.GetBitRate() / 8.0 / 1100.0)); |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 118 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 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)); |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 124 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 125 | AddLink(link); |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 126 | } |
| 127 | |
| 128 | // NodeContainer |
| 129 | void |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 130 | RocketfuelMapReader::GenerateFromMapsFile(int argc, char* argv[]) |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 131 | { |
| 132 | string uid; |
| 133 | string loc; |
| 134 | string ptr; |
| 135 | string name; |
| 136 | string nuid; |
Alexander Afanasyev | 29c10ed | 2013-01-23 18:26:07 -0800 | [diff] [blame] | 137 | // bool dns = false; |
| 138 | // bool bb = false; |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 139 | int num_neigh_s = 0; |
| 140 | unsigned int num_neigh = 0; |
| 141 | int radius = 0; |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 142 | vector<string> neigh_list; |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 143 | |
| 144 | uid = argv[0]; |
| 145 | loc = argv[1]; |
| 146 | |
Alexander Afanasyev | 29c10ed | 2013-01-23 18:26:07 -0800 | [diff] [blame] | 147 | // if (argv[2]) |
| 148 | // { |
| 149 | // dns = true; |
| 150 | // } |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 151 | |
Alexander Afanasyev | 29c10ed | 2013-01-23 18:26:07 -0800 | [diff] [blame] | 152 | // if (argv[3]) |
| 153 | // { |
| 154 | // bb = true; |
| 155 | // } |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 156 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 157 | num_neigh_s = ::atoi(argv[4]); |
| 158 | if (num_neigh_s < 0) { |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 159 | num_neigh = 0; |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 160 | NS_LOG_WARN("Negative number of neighbors given"); |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 161 | } |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 162 | else { |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 163 | num_neigh = num_neigh_s; |
| 164 | } |
| 165 | |
| 166 | /* neighbors */ |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 167 | if (argv[6]) { |
| 168 | char* nbr; |
| 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); |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 173 | } |
| 174 | } |
| 175 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 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()); |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 179 | } |
| 180 | |
| 181 | /* externs */ |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 182 | if (argv[7]) { |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 183 | // euid = argv[7]; |
| 184 | } |
| 185 | |
| 186 | /* name */ |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 187 | if (argv[8]) { |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 188 | name = argv[8]; |
| 189 | } |
| 190 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 191 | radius = ::atoi(&argv[9][1]); |
| 192 | if (radius > 0) { |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 193 | return; |
| 194 | } |
| 195 | |
| 196 | // Create node and link |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 197 | if (uid.empty()) |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 198 | return; |
| 199 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 200 | node_map_t::iterator node = m_graphNodes.find(uid); |
| 201 | if (node == m_graphNodes.end()) { |
| 202 | bool ok; |
| 203 | tie(node, ok) = m_graphNodes.insert(make_pair(uid, add_vertex(nodeProperty(uid), m_graph))); |
| 204 | NS_ASSERT(ok == true); |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 205 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 206 | put(vertex_index, m_graph, node->second, m_maxNodeId); |
| 207 | m_maxNodeId++; |
| 208 | } |
| 209 | |
| 210 | for (uint32_t i = 0; i < neigh_list.size(); ++i) { |
| 211 | nuid = neigh_list[i]; |
| 212 | |
| 213 | if (nuid.empty()) { |
| 214 | continue; |
| 215 | } |
| 216 | |
| 217 | node_map_t::iterator otherNode = m_graphNodes.find(nuid); |
| 218 | if (otherNode == m_graphNodes.end()) { |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 219 | bool ok; |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 220 | tie(otherNode, ok) = |
| 221 | m_graphNodes.insert(make_pair(nuid, add_vertex(nodeProperty(nuid), m_graph))); |
| 222 | NS_ASSERT(ok == true); |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 223 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 224 | put(vertex_index, m_graph, otherNode->second, m_maxNodeId); |
| 225 | m_maxNodeId++; |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 226 | } |
| 227 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 228 | // cout << node->second << " <-> " << otherNode->second << endl; |
| 229 | // parallel edges are disabled in the graph, so no need to worry |
| 230 | add_edge(node->second, otherNode->second, m_graph); |
| 231 | } |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 232 | } |
| 233 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 234 | void |
| 235 | RocketfuelMapReader::assignGw(Traits::vertex_descriptor vertex, uint32_t degree, |
| 236 | node_type_t nodeType) |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 237 | { |
| 238 | graph_traits<Graph>::adjacency_iterator u, endu; |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 239 | for (tie(u, endu) = adjacent_vertices(vertex, m_graph); u != endu; u++) { |
| 240 | if (get(vertex_rank, m_graph, *u) != UNKNOWN) |
| 241 | continue; |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 242 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 243 | put(vertex_rank, m_graph, *u, nodeType); |
| 244 | put(vertex_color, m_graph, *u, "green"); |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 245 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 246 | uint32_t u_degree = out_degree(*u, m_graph); |
| 247 | if (u_degree < degree) |
| 248 | assignGw(*u, degree, BACKBONE); |
| 249 | } |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 250 | }; |
| 251 | |
| 252 | void |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 253 | RocketfuelMapReader::AssignClients(uint32_t clientDegree, uint32_t gwDegree) |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 254 | { |
| 255 | graph_traits<Graph>::vertex_iterator v, endv; |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 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"); |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 261 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 262 | assignGw(*v, gwDegree + 1, GATEWAY); |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 263 | } |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 264 | } |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 265 | }; |
| 266 | |
| 267 | NodeContainer |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 268 | RocketfuelMapReader::Read(RocketfuelParams params, bool keepOneComponent /*=true*/, |
| 269 | bool connectBackbones /*=true*/) |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 270 | { |
| 271 | m_maxNodeId = 0; |
| 272 | |
| 273 | ifstream topgen; |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 274 | topgen.open(GetFileName().c_str()); |
| 275 | // NodeContainer nodes; |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 276 | |
| 277 | istringstream lineBuffer; |
| 278 | string line; |
| 279 | int lineNumber = 0; |
| 280 | char errbuf[512]; |
| 281 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 282 | if (!topgen.is_open()) { |
| 283 | NS_LOG_WARN("Couldn't open the file " << GetFileName()); |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 284 | return m_nodes; |
| 285 | } |
| 286 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 287 | while (!topgen.eof()) { |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 288 | int ret; |
| 289 | int argc; |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 290 | char* argv[REGMATCH_MAX]; |
| 291 | char* buf; |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 292 | |
| 293 | lineNumber++; |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 294 | line.clear(); |
| 295 | lineBuffer.clear(); |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 296 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 297 | getline(topgen, line); |
| 298 | buf = (char*)line.c_str(); |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 299 | |
| 300 | regmatch_t regmatch[REGMATCH_MAX]; |
| 301 | regex_t regex; |
| 302 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 303 | ret = regcomp(®ex, ROCKETFUEL_MAPS_LINE, REG_EXTENDED | REG_NEWLINE); |
| 304 | if (ret != 0) { |
| 305 | regerror(ret, ®ex, errbuf, sizeof(errbuf)); |
| 306 | regfree(®ex); |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 307 | continue; |
| 308 | } |
| 309 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 310 | ret = regexec(®ex, buf, REGMATCH_MAX, regmatch, 0); |
| 311 | if (ret == REG_NOMATCH) { |
| 312 | NS_LOG_WARN("match failed (maps file): %s" << buf); |
| 313 | regfree(®ex); |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 314 | continue; |
| 315 | } |
| 316 | |
| 317 | line = buf; |
| 318 | argc = 0; |
| 319 | |
| 320 | /* regmatch[0] is the entire strings that matched */ |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 321 | for (int i = 1; i < REGMATCH_MAX; i++) { |
| 322 | if (regmatch[i].rm_so == -1) { |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 323 | argv[i - 1] = NULL; |
| 324 | } |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 325 | else { |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 326 | line[regmatch[i].rm_eo] = '\0'; |
| 327 | argv[i - 1] = &line[regmatch[i].rm_so]; |
| 328 | argc = i; |
| 329 | } |
| 330 | } |
| 331 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 332 | GenerateFromMapsFile(argc, argv); |
| 333 | regfree(®ex); |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 334 | } |
| 335 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 336 | if (keepOneComponent) { |
| 337 | NS_LOG_DEBUG("Before eliminating disconnected nodes: " << num_vertices(m_graph)); |
| 338 | KeepOnlyBiggestConnectedComponent(); |
| 339 | NS_LOG_DEBUG("After eliminating disconnected nodes: " << num_vertices(m_graph)); |
| 340 | } |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 341 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 342 | for (int clientDegree = 1; clientDegree <= params.clientNodeDegrees; clientDegree++) { |
| 343 | AssignClients(clientDegree, std::min(clientDegree, 3)); |
| 344 | } |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 345 | |
| 346 | graph_traits<Graph>::vertex_iterator v, endv; |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 347 | for (tie(v, endv) = vertices(m_graph); v != endv; v++) { |
| 348 | node_type_t type = get(vertex_rank, m_graph, *v); |
| 349 | if (type == UNKNOWN) { |
| 350 | put(vertex_rank, m_graph, *v, BACKBONE); |
| 351 | put(vertex_color, m_graph, *v, "blue"); |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 352 | } |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 353 | } |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 354 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 355 | if (connectBackbones) { |
| 356 | ConnectBackboneRouters(); |
| 357 | } |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 358 | |
| 359 | graph_traits<Graph>::edge_iterator e, ende; |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 360 | for (tie(e, ende) = edges(m_graph); e != ende;) { |
| 361 | Traits::vertex_descriptor u = source(*e, m_graph), v = target(*e, m_graph); |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 362 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 363 | node_type_t u_type = get(vertex_rank, m_graph, u), v_type = get(vertex_rank, m_graph, v); |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 364 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 365 | if (u_type == BACKBONE && v_type == BACKBONE) { |
| 366 | // ok |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 367 | } |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 368 | else if ((u_type == GATEWAY && v_type == BACKBONE) |
| 369 | || (u_type == BACKBONE && v_type == GATEWAY)) { |
| 370 | // ok |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 371 | } |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 372 | else if (u_type == GATEWAY && v_type == GATEWAY) { |
| 373 | // ok |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 374 | } |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 375 | else if ((u_type == GATEWAY && v_type == CLIENT) || (u_type == CLIENT && v_type == GATEWAY)) { |
| 376 | // ok |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 377 | } |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 378 | else { |
| 379 | // not ok |
| 380 | NS_LOG_DEBUG("Wrong link type between nodes: " << u_type << " <-> " << v_type |
| 381 | << " (deleting the link)"); |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 382 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 383 | graph_traits<Graph>::edge_iterator tmp = e; |
| 384 | tmp++; |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 385 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 386 | remove_edge(*e, m_graph); |
| 387 | e = tmp; |
| 388 | continue; |
| 389 | } |
| 390 | e++; |
| 391 | } |
| 392 | |
| 393 | if (keepOneComponent) { |
| 394 | NS_LOG_DEBUG("Before 2 eliminating disconnected nodes: " << num_vertices(m_graph)); |
| 395 | KeepOnlyBiggestConnectedComponent(); |
| 396 | NS_LOG_DEBUG("After 2 eliminating disconnected nodes: " << num_vertices(m_graph)); |
| 397 | } |
| 398 | |
| 399 | for (tie(v, endv) = vertices(m_graph); v != endv; v++) { |
| 400 | string nodeName = get(vertex_name, m_graph, *v); |
| 401 | Ptr<Node> node = CreateNode(nodeName, 0); |
| 402 | |
| 403 | node_type_t type = get(vertex_rank, m_graph, *v); |
| 404 | switch (type) { |
| 405 | case BACKBONE: |
| 406 | Names::Rename(nodeName, "bb-" + nodeName); |
| 407 | put(vertex_name, m_graph, *v, "bb-" + nodeName); |
| 408 | m_backboneRouters.Add(node); |
| 409 | break; |
| 410 | case CLIENT: |
| 411 | Names::Rename(nodeName, "leaf-" + nodeName); |
| 412 | put(vertex_name, m_graph, *v, "leaf-" + nodeName); |
| 413 | m_customerRouters.Add(node); |
| 414 | break; |
| 415 | case GATEWAY: |
| 416 | Names::Rename(nodeName, "gw-" + nodeName); |
| 417 | put(vertex_name, m_graph, *v, "gw-" + nodeName); |
| 418 | m_gatewayRouters.Add(node); |
| 419 | break; |
| 420 | case UNKNOWN: |
| 421 | NS_FATAL_ERROR("Should not happen"); |
| 422 | break; |
| 423 | } |
| 424 | } |
| 425 | |
| 426 | for (tie(e, ende) = edges(m_graph); e != ende; e++) { |
| 427 | Traits::vertex_descriptor u = source(*e, m_graph), v = target(*e, m_graph); |
| 428 | |
| 429 | node_type_t u_type = get(vertex_rank, m_graph, u), v_type = get(vertex_rank, m_graph, v); |
| 430 | |
| 431 | string u_name = get(vertex_name, m_graph, u), v_name = get(vertex_name, m_graph, v); |
| 432 | |
| 433 | if (u_type == BACKBONE && v_type == BACKBONE) { |
| 434 | CreateLink(u_name, v_name, params.averageRtt, params.minb2bBandwidth, params.maxb2bBandwidth, |
| 435 | params.minb2bDelay, params.maxb2bDelay); |
| 436 | } |
| 437 | else if ((u_type == GATEWAY && v_type == BACKBONE) |
| 438 | || (u_type == BACKBONE && v_type == GATEWAY)) { |
| 439 | CreateLink(u_name, v_name, params.averageRtt, params.minb2gBandwidth, params.maxb2gBandwidth, |
| 440 | params.minb2gDelay, params.maxb2gDelay); |
| 441 | } |
| 442 | else if (u_type == GATEWAY && v_type == GATEWAY) { |
| 443 | CreateLink(u_name, v_name, params.averageRtt, params.minb2gBandwidth, params.maxb2gBandwidth, |
| 444 | params.minb2gDelay, params.maxb2gDelay); |
| 445 | } |
| 446 | else if ((u_type == GATEWAY && v_type == CLIENT) || (u_type == CLIENT && v_type == GATEWAY)) { |
| 447 | CreateLink(u_name, v_name, params.averageRtt, params.ming2cBandwidth, params.maxg2cBandwidth, |
| 448 | params.ming2cDelay, params.maxg2cDelay); |
| 449 | } |
| 450 | else { |
| 451 | NS_FATAL_ERROR("Wrong link type between nodes: " << u_type << " <-> " << v_type); |
| 452 | } |
| 453 | } |
| 454 | |
| 455 | ApplySettings(); |
| 456 | |
| 457 | NS_LOG_INFO("Clients: " << m_customerRouters.GetN()); |
| 458 | NS_LOG_INFO("Gateways: " << m_gatewayRouters.GetN()); |
| 459 | NS_LOG_INFO("Backbones: " << m_backboneRouters.GetN()); |
| 460 | NS_LOG_INFO("Links: " << GetLinks().size()); |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 461 | |
| 462 | return m_nodes; |
| 463 | } |
| 464 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 465 | const NodeContainer& |
| 466 | RocketfuelMapReader::GetBackboneRouters() const |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 467 | { |
| 468 | return m_backboneRouters; |
| 469 | } |
| 470 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 471 | const NodeContainer& |
| 472 | RocketfuelMapReader::GetGatewayRouters() const |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 473 | { |
| 474 | return m_gatewayRouters; |
| 475 | } |
| 476 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 477 | const NodeContainer& |
| 478 | RocketfuelMapReader::GetCustomerRouters() const |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 479 | { |
| 480 | return m_customerRouters; |
| 481 | } |
| 482 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 483 | static void |
| 484 | nodeWriter(std::ostream& os, NodeContainer& m) |
Alexander Afanasyev | 29c10ed | 2013-01-23 18:26:07 -0800 | [diff] [blame] | 485 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 486 | for (NodeContainer::Iterator node = m.Begin(); node != m.End(); node++) { |
| 487 | std::string name = Names::FindName(*node); |
Alexander Afanasyev | 29c10ed | 2013-01-23 18:26:07 -0800 | [diff] [blame] | 488 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 489 | os << name << "\t" |
| 490 | << "NA" |
| 491 | << "\t" << 0 << "\t" << 0 << "\n"; |
| 492 | } |
Alexander Afanasyev | 29c10ed | 2013-01-23 18:26:07 -0800 | [diff] [blame] | 493 | }; |
| 494 | |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 495 | void |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 496 | RocketfuelMapReader::SaveTopology(const std::string& file) |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 497 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 498 | ofstream os(file.c_str(), ios::trunc); |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 499 | os << "# any empty lines and lines starting with '#' symbol is ignored\n" |
| 500 | << "\n" |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 501 | << "# The file should contain exactly two sections: router and link, each starting with the " |
| 502 | "corresponding keyword\n" |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 503 | << "\n" |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 504 | << "# router section defines topology nodes and their relative positions (e.g., to use in " |
| 505 | "visualizer)\n" |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 506 | << "router\n" |
| 507 | << "\n" |
| 508 | << "# each line in this section represents one router and should have the following data\n" |
| 509 | << "# node comment yPos xPos\n"; |
| 510 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 511 | nodeWriter(os, m_backboneRouters); |
| 512 | nodeWriter(os, m_gatewayRouters); |
| 513 | nodeWriter(os, m_customerRouters); |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 514 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 515 | os << "# link section defines point-to-point links between nodes and characteristics of these " |
| 516 | "links\n" |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 517 | << "\n" |
| 518 | << "link\n" |
| 519 | << "\n" |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 520 | << "# Each line should be in the following format (only first two are required, the rest can " |
| 521 | "be omitted)\n" |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 522 | << "# srcNode dstNode bandwidth metric delay queue\n" |
| 523 | << "# bandwidth: link bandwidth\n" |
| 524 | << "# metric: routing metric\n" |
| 525 | << "# delay: link delay\n" |
| 526 | << "# queue: MaxPackets for transmission queue on the link (both directions)\n"; |
| 527 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 528 | for (std::list<Link>::iterator link = m_linksList.begin(); link != m_linksList.end(); link++) { |
| 529 | string src = Names::FindName(link->GetFromNode()); |
| 530 | string dst = Names::FindName(link->GetToNode()); |
| 531 | os << src << "\t"; |
| 532 | os << dst << "\t"; |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 533 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 534 | string tmp; |
| 535 | if (link->GetAttributeFailSafe("DataRate", tmp)) |
| 536 | os << link->GetAttribute("DataRate") << "\t"; |
| 537 | else |
| 538 | NS_FATAL_ERROR("DataRate must be specified for the link"); |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 539 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 540 | if (link->GetAttributeFailSafe("OSPF", tmp)) |
| 541 | os << link->GetAttribute("OSPF") << "\t"; |
| 542 | else { |
| 543 | DataRate rate = boost::lexical_cast<DataRate>(link->GetAttribute("DataRate")); |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 544 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 545 | int32_t cost = std::max(1, static_cast<int32_t>(1.0 * m_referenceOspfRate.GetBitRate() |
| 546 | / rate.GetBitRate())); |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 547 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 548 | os << cost << "\t"; |
Alexander Afanasyev | 29c10ed | 2013-01-23 18:26:07 -0800 | [diff] [blame] | 549 | } |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 550 | |
| 551 | if (link->GetAttributeFailSafe("Delay", tmp)) { |
| 552 | os << link->GetAttribute("Delay") << "\t"; |
| 553 | |
| 554 | if (link->GetAttributeFailSafe("MaxPackets", tmp)) { |
| 555 | os << link->GetAttribute("MaxPackets") << "\t"; |
| 556 | } |
| 557 | } |
| 558 | os << "\n"; |
| 559 | } |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 560 | } |
| 561 | |
Spyridon Mastorakis | 460f57c | 2014-12-17 00:44:14 -0800 | [diff] [blame] | 562 | /// @cond include_hidden |
| 563 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 564 | template<class Names, class Colors> |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 565 | class name_color_writer { |
| 566 | public: |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 567 | name_color_writer(Names _names, Colors _colors) |
| 568 | : names(_names) |
| 569 | , colors(_colors) |
| 570 | { |
| 571 | } |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 572 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 573 | template<class VertexOrEdge> |
| 574 | void |
| 575 | operator()(std::ostream& out, const VertexOrEdge& v) const |
| 576 | { |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 577 | // out << "[label=\"" << names[v] << "\",style=filled,fillcolor=\"" << colors[v] << "\"]"; |
| 578 | out << "[shape=\"circle\",width=0.1,label=\"\",style=filled,fillcolor=\"" << colors[v] << "\"]"; |
| 579 | } |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 580 | |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 581 | private: |
| 582 | Names names; |
| 583 | Colors colors; |
| 584 | }; |
| 585 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 586 | template<class Names, class Colors> |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 587 | inline name_color_writer<Names, Colors> |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 588 | make_name_color_writer(Names n, Colors c) |
| 589 | { |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 590 | return name_color_writer<Names, Colors>(n, c); |
| 591 | } |
| 592 | |
Spyridon Mastorakis | 460f57c | 2014-12-17 00:44:14 -0800 | [diff] [blame] | 593 | /// @endcond |
| 594 | |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 595 | void |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 596 | RocketfuelMapReader::SaveGraphviz(const std::string& file) |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 597 | { |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 598 | ofstream of(file.c_str()); |
| 599 | property_map<Graph, vertex_name_t>::type names = get(vertex_name, m_graph); |
| 600 | property_map<Graph, vertex_color_t>::type colors = get(vertex_color, m_graph); |
| 601 | write_graphviz(of, m_graph, make_name_color_writer(names, colors)); |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 602 | } |
| 603 | |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 604 | void |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 605 | RocketfuelMapReader::KeepOnlyBiggestConnectedComponent() |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 606 | { |
| 607 | std::map<graph_traits<Graph>::vertex_descriptor, int> temp; |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 608 | associative_property_map<std::map<graph_traits<Graph>::vertex_descriptor, int>> components(temp); |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 609 | |
| 610 | // //check if topology has breaks in its structure and trim it if yes |
| 611 | // property_map<Graph, vertex_index1_t>::type components = get (vertex_index1, m_graph); |
| 612 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 613 | int num = connected_components(m_graph, components); |
| 614 | NS_LOG_DEBUG("Topology has " << num << " components"); |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 615 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 616 | vector<int> sizes(num, 0); |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 617 | |
| 618 | graph_traits<Graph>::vertex_iterator v, endv; |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 619 | for (tie(v, endv) = vertices(m_graph); v != endv; v++) { |
| 620 | sizes[get(components, *v)]++; |
| 621 | } |
| 622 | int largestComponent = max_element(sizes.begin(), sizes.end()) - sizes.begin(); |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 623 | // cout << "Largest: " << largestComponent << endl; |
| 624 | |
| 625 | // for (int i =0 ; i < num; i++) cout << sizes[i] << " "; |
| 626 | // cout << endl; |
| 627 | |
| 628 | //////////////////////////////////////////////////// |
| 629 | // remove nodes and edges from smaller components // |
| 630 | //////////////////////////////////////////////////// |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 631 | for (tie(v, endv) = vertices(m_graph); v != endv; v++) { |
| 632 | if (get(components, *v) == largestComponent) |
| 633 | continue; |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 634 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 635 | clear_vertex(*v, m_graph); |
| 636 | } |
| 637 | |
| 638 | // this works only if vertices are organized in listS or setS (iterator is not invalidated on |
| 639 | // remove) |
| 640 | for (tie(v, endv) = vertices(m_graph); v != endv;) { |
| 641 | if (get(components, *v) == largestComponent) { |
| 642 | v++; |
| 643 | continue; |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 644 | } |
| 645 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 646 | graph_traits<Graph>::vertex_iterator tmp = v; |
| 647 | tmp++; |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 648 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 649 | remove_vertex(*v, m_graph); |
| 650 | v = tmp; |
| 651 | } |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 652 | |
| 653 | int index = 0; |
| 654 | // renumber nodes |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 655 | for (tie(v, endv) = vertices(m_graph); v != endv; v++) { |
| 656 | put(vertex_index, m_graph, *v, index++); |
| 657 | } |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 658 | } |
| 659 | |
| 660 | void |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 661 | RocketfuelMapReader::ConnectBackboneRouters() |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 662 | { |
| 663 | // not the tricky part. we want backbone to be a fully connected component, |
| 664 | // so traffic doesn't bounce from backbone to gateway and back |
| 665 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 666 | typedef adjacency_list<setS, setS, boost::undirectedS, |
| 667 | property<vertex_name_t, Traits::vertex_descriptor, |
| 668 | property<vertex_index_t, int, property<vertex_index1_t, int>>>> |
| 669 | BbGraph; |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 670 | BbGraph bbGraph; |
| 671 | map<Traits::vertex_descriptor, graph_traits<BbGraph>::vertex_descriptor> nodeMap; |
| 672 | |
| 673 | int index = 0; |
| 674 | |
| 675 | graph_traits<Graph>::vertex_iterator v, endv; |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 676 | for (tie(v, endv) = vertices(m_graph); v != endv; v++) { |
| 677 | node_type_t type = get(vertex_rank, m_graph, *v); |
| 678 | if (type == BACKBONE) { |
| 679 | graph_traits<BbGraph>::vertex_descriptor newv = add_vertex(*v, bbGraph); |
| 680 | put(vertex_index, bbGraph, newv, index++); |
| 681 | nodeMap[*v] = newv; |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 682 | } |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 683 | } |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 684 | |
| 685 | graph_traits<BbGraph>::vertex_iterator bb, endBb; |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 686 | for (tie(bb, endBb) = vertices(bbGraph); bb != endBb; bb++) { |
| 687 | Traits::vertex_descriptor actualVertex = get(vertex_name, bbGraph, *bb); |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 688 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 689 | graph_traits<Graph>::adjacency_iterator u, endu; |
| 690 | for (tie(u, endu) = adjacent_vertices(actualVertex, m_graph); u != endu; u++) { |
| 691 | if (nodeMap.find(*u) != nodeMap.end()) { |
| 692 | add_edge(nodeMap[actualVertex], nodeMap[*u], bbGraph); |
| 693 | } |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 694 | } |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 695 | } |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 696 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 697 | property_map<BbGraph, vertex_index1_t>::type components = get(vertex_index1, bbGraph); |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 698 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 699 | int num = connected_components(bbGraph, components); |
| 700 | NS_LOG_DEBUG("Backbone has " << num << " components"); |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 701 | if (num == 1) |
| 702 | return; // nothing to do |
| 703 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 704 | vector<vector<graph_traits<BbGraph>::vertex_descriptor>> subgraphs(num); |
| 705 | for (tie(bb, endBb) = vertices(bbGraph); bb != endBb; bb++) { |
| 706 | int component = get(vertex_index1, bbGraph, *bb); |
| 707 | subgraphs[component].push_back(*bb); |
| 708 | } |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 709 | |
Alexander Afanasyev | d6453cd | 2015-08-20 21:45:36 -0700 | [diff] [blame] | 710 | Ptr<UniformRandomVariable> randVar = CreateObject<UniformRandomVariable>(); |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 711 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 712 | for (int i = 1; i < num; i++) { |
Alexander Afanasyev | d6453cd | 2015-08-20 21:45:36 -0700 | [diff] [blame] | 713 | int node1 = randVar->GetInteger(0, subgraphs[i - 1].size() - 1); |
| 714 | int node2 = randVar->GetInteger(0, subgraphs[i].size() - 1); |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 715 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 716 | Traits::vertex_descriptor v1 = get(vertex_name, bbGraph, subgraphs[i - 1][node1]), |
| 717 | v2 = get(vertex_name, bbGraph, subgraphs[i][node2]); |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 718 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 719 | NS_LOG_DEBUG("Connecting " << get(vertex_name, m_graph, v1) << "[" << node1 << "] with " |
| 720 | << get(vertex_name, m_graph, v2) << "[" << node2 << "]"); |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 721 | |
Alexander Afanasyev | be55cf6 | 2014-12-20 17:51:09 -0800 | [diff] [blame] | 722 | add_edge(v1, v2, m_graph); |
| 723 | } |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 724 | } |
| 725 | |
Alexander Afanasyev | 957a84a | 2013-01-23 10:21:06 -0800 | [diff] [blame] | 726 | } /* namespace ns3 */ |