A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
rocketfuel-topology-reader.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2010 Hajime Tazaki
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Author: Hajime Tazaki (tazaki@sfc.wide.ad.jp)
18 */
19
21
22#include "ns3/log.h"
23#include "ns3/names.h"
24#include "ns3/node-container.h"
25
26#include <cstdlib>
27#include <fstream>
28#include <iostream>
29#include <regex>
30#include <string>
31
32/**
33 * \file
34 * \ingroup topology
35 * ns3::RocketfuelTopologyReader implementation.
36 */
37
38namespace ns3
39{
40
41NS_LOG_COMPONENT_DEFINE("RocketfuelTopologyReader");
42
43NS_OBJECT_ENSURE_REGISTERED(RocketfuelTopologyReader);
44
45TypeId
47{
48 static TypeId tid = TypeId("ns3::RocketfuelTopologyReader")
50 .SetGroupName("TopologyReader")
51 .AddConstructor<RocketfuelTopologyReader>();
52 return tid;
53}
54
56{
57 m_linksNumber = 0;
58 m_nodesNumber = 0;
59 NS_LOG_FUNCTION(this);
60}
61
63{
64 NS_LOG_FUNCTION(this);
65}
66
67/* uid @loc [+] [bb] (num_neigh) [&ext] -> <nuid-1> <nuid-2> ... {-euid} ... =name[!] rn */
68
69/// Start of a line
70#define START "^"
71/// End of a line
72#define END "$"
73/// One or more spaces
74#define SPACE "[ \t]+"
75/// Zero or more spaces
76#define MAYSPACE "[ \t]*"
77
78/// Regex expression matching a MAP line
79#define ROCKETFUEL_MAPS_LINE \
80 START "(-*[0-9]+)" SPACE "(@[?A-Za-z0-9,+-]+)" SPACE "(\\+)*" MAYSPACE "(bb)*" MAYSPACE \
81 "\\(([0-9]+)\\)" SPACE "(&[0-9]+)*" MAYSPACE "->" MAYSPACE "(<[0-9 \t<>]+>)*" MAYSPACE \
82 "(\\{-[0-9\\{\\} \t-]+\\})*" SPACE "=([A-Za-z0-9.!-]+)" SPACE "r([0-9])" MAYSPACE END
83
84/// Regex expression matching a WEIGHT line
85#define ROCKETFUEL_WEIGHTS_LINE START "([^ \t]+)" SPACE "([^ \t]+)" SPACE "([0-9.]+)" MAYSPACE END
86
87/**
88 * Build a Regex object for RocketFuel topology maps file type
89 * \return a static regex object for maps file type
90 */
92
93/**
94 * Build a Regex object for RocketFuel topology weights file type
95 * \return a static regex object for weights file type
96 */
98
99/**
100 * \brief Print node info
101 * \param uid node ID
102 * \param loc node location
103 * \param dns is a DNS node ?
104 * \param bb is a BB node ?
105 * \param neighListSize size of neighbor list
106 * \param name node name
107 * \param radius node radius
108 */
109static inline void
110PrintNodeInfo(std::string& uid,
111 std::string& loc,
112 bool dns,
113 bool bb,
114 std::vector<std::string>::size_type neighListSize,
115 std::string& name,
116 int radius)
117{
118 /* uid @loc [+] [bb] (num_neigh) [&ext] -> <nuid-1> <nuid-2> ... {-euid} ... =name[!] rn */
119 NS_LOG_INFO("Load Node[" << uid << "]: location: " << loc << " dns: " << dns << " bb: " << bb
120 << " neighbors: " << neighListSize << "("
121 << "%d"
122 << ") externals: \"%s\"(%d) "
123 << "name: " << name << " radius: " << radius);
124}
125
126NodeContainer
127RocketfuelTopologyReader::GenerateFromMapsFile(const std::vector<std::string>& argv)
128{
129 std::string uid;
130 std::string loc;
131 std::string ptr;
132 std::string name;
133 bool dns = false;
134 bool bb = false;
135 int num_neigh_s = 0;
136 unsigned int num_neigh = 0;
137 int radius = 0;
138 std::vector<std::string> neigh_list;
140
141 uid = argv[0];
142 loc = argv[1];
143
144 if (!argv[2].empty())
145 {
146 dns = true;
147 }
148
149 if (!argv[3].empty())
150 {
151 bb = true;
152 }
153
154 num_neigh_s = std::stoi(argv[4]);
155 if (num_neigh_s < 0)
156 {
157 num_neigh = 0;
158 NS_LOG_WARN("Negative number of neighbors given");
159 }
160 else
161 {
162 num_neigh = num_neigh_s;
163 }
164
165 /* neighbors */
166 if (!argv[6].empty())
167 {
168 // Each line contains a list <.*>[ |\t]<.*>[ |\t]<.*>[ |\t]
169 // First remove < and >
170 std::string temp;
171 std::regex replace_regex("[<|>]");
172 std::regex_replace(std::back_inserter(temp),
173 argv[6].begin(),
174 argv[6].end(),
175 replace_regex,
176 "");
177
178 // Then split list
179 std::regex split_regex("[ |\t]");
180 std::sregex_token_iterator first{temp.begin(), temp.end(), split_regex, -1};
181 std::sregex_token_iterator last;
182 neigh_list = std::vector<std::string>{first, last};
183 }
184 if (num_neigh != neigh_list.size())
185 {
186 NS_LOG_WARN("Given number of neighbors = " << num_neigh << " != size of neighbors list = "
187 << neigh_list.size());
188 }
189
190 /* externs */
191 if (!argv[7].empty())
192 {
193 // euid = argv[7];
194 }
195
196 /* name */
197 if (!argv[8].empty())
198 {
199 name = argv[8];
200 }
201
202 radius = std::atoi(&argv[9][1]);
203 if (radius > 0)
204 {
205 return nodes;
206 }
207
208 PrintNodeInfo(uid, loc, dns, bb, neigh_list.size(), name, radius);
209
210 // Create node and link
211 if (!uid.empty())
212 {
213 if (!m_nodeMap[uid])
214 {
215 Ptr<Node> tmpNode = CreateObject<Node>();
216 std::string nodename = "RocketFuelTopology/NodeName/" + uid;
217 Names::Add(nodename, tmpNode);
218 m_nodeMap[uid] = tmpNode;
219 nodes.Add(tmpNode);
221 }
222
223 for (auto& nuid : neigh_list)
224 {
225 if (nuid.empty())
226 {
227 return nodes;
228 }
229
230 if (!m_nodeMap[nuid])
231 {
232 Ptr<Node> tmpNode = CreateObject<Node>();
233 std::string nodename = "RocketFuelTopology/NodeName/" + nuid;
234 Names::Add(nodename, tmpNode);
235 m_nodeMap[nuid] = tmpNode;
236 nodes.Add(tmpNode);
238 }
239 NS_LOG_INFO(m_linksNumber << ":" << m_nodesNumber << " From: " << uid
240 << " to: " << nuid);
241 Link link(m_nodeMap[uid], uid, m_nodeMap[nuid], nuid);
242 AddLink(link);
244 }
245 }
246
247 NS_LOG_INFO("Rocketfuel topology created with " << m_nodesNumber << " nodes and "
248 << m_linksNumber << " links");
249
250 return nodes;
251}
252
254RocketfuelTopologyReader::GenerateFromWeightsFile(const std::vector<std::string>& argv)
255{
256 /* uid @loc [+] [bb] (num_neigh) [&ext] -> <nuid-1> <nuid-2> ... {-euid} ... =name[!] rn */
257 std::string sname;
258 std::string tname;
259 std::string::size_type endptr;
261
262 sname = argv[0];
263 tname = argv[1];
264 std::stod(argv[2], &endptr); // weight
265
266 if (argv[2].size() != endptr)
267 {
268 NS_LOG_WARN("invalid weight: " << argv[2]);
269 return nodes;
270 }
271
272 // Create node and link
273 if (!sname.empty() && !tname.empty())
274 {
275 if (!m_nodeMap[sname])
276 {
277 Ptr<Node> tmpNode = CreateObject<Node>();
278 std::string nodename = "RocketFuelTopology/NodeName/" + sname;
279 Names::Add(nodename, tmpNode);
280 m_nodeMap[sname] = tmpNode;
281 nodes.Add(tmpNode);
283 }
284
285 if (!m_nodeMap[tname])
286 {
287 Ptr<Node> tmpNode = CreateObject<Node>();
288 std::string nodename = "RocketFuelTopology/NodeName/" + tname;
289 Names::Add(nodename, tmpNode);
290 m_nodeMap[tname] = tmpNode;
291 nodes.Add(tmpNode);
293 }
294 NS_LOG_INFO(m_linksNumber << ":" << m_nodesNumber << " From: " << sname
295 << " to: " << tname);
297 bool found = false;
298 for (iter = LinksBegin(); iter != LinksEnd(); iter++)
299 {
300 if ((iter->GetFromNode() == m_nodeMap[tname]) &&
301 (iter->GetToNode() == m_nodeMap[sname]))
302 {
303 found = true;
304 break;
305 }
306 }
307
308 if (!found)
309 {
310 Link link(m_nodeMap[sname], sname, m_nodeMap[tname], tname);
311 AddLink(link);
313 }
314 }
315
316 NS_LOG_INFO("Rocketfuel topology created with " << m_nodesNumber << " nodes and "
317 << m_linksNumber << " links");
318
319 return nodes;
320}
321
324{
325 // Check whether Maps file or not
326 std::smatch matches;
327 if (std::regex_match(line, matches, rocketfuel_maps_regex))
328 {
329 return RF_MAPS;
330 }
331
332 // Check whether Weights file or not
333 if (std::regex_match(line, matches, rocketfuel_weights_regex))
334 {
335 return RF_WEIGHTS;
336 }
337
338 return RF_UNKNOWN;
339}
340
343{
344 std::ifstream topgen;
345 topgen.open(GetFileName());
347
348 std::istringstream lineBuffer;
349 std::string line;
350 int lineNumber = 0;
351 RF_FileType ftype = RF_UNKNOWN;
352
353 if (!topgen.is_open())
354 {
355 NS_LOG_WARN("Couldn't open the file " << GetFileName());
356 return nodes;
357 }
358
359 while (!topgen.eof())
360 {
361 std::vector<std::string> argv;
362
363 lineNumber++;
364 line.clear();
365 lineBuffer.clear();
366
367 getline(topgen, line);
368
369 if (lineNumber == 1)
370 {
371 ftype = GetFileType(line);
372 if (ftype == RF_UNKNOWN)
373 {
374 NS_LOG_INFO("Unknown File Format (" << GetFileName() << ")");
375 break;
376 }
377 }
378
379 std::smatch matches;
380
381 if (ftype == RF_MAPS)
382 {
383 bool ret = std::regex_match(line, matches, rocketfuel_maps_regex);
384 if (!ret || matches.empty())
385 {
386 NS_LOG_WARN("match failed (maps file): %s" << line);
387 break;
388 }
389 }
390 else if (ftype == RF_WEIGHTS)
391 {
392 bool ret = std::regex_match(line, matches, rocketfuel_weights_regex);
393 if (!ret || matches.empty())
394 {
395 NS_LOG_WARN("match failed (weights file): %s" << line);
396 break;
397 }
398 }
399
400 std::string matched_string;
401
402 for (auto it = matches.begin() + 1; it != matches.end(); it++)
403 {
404 if (it->matched)
405 {
406 matched_string = it->str();
407 }
408 else
409 {
410 matched_string = "";
411 }
412 argv.push_back(matched_string);
413 }
414
415 if (ftype == RF_MAPS)
416 {
417 nodes.Add(GenerateFromMapsFile(argv));
418 }
419 else if (ftype == RF_WEIGHTS)
420 {
422 }
423 else
424 {
425 NS_LOG_WARN("Unsupported file format (only Maps/Weights are supported)");
426 }
427 }
428
429 topgen.close();
430
431 return nodes;
432}
433
434} /* namespace ns3 */
static void Add(std::string name, Ptr< Object > object)
Add the association between the string "name" and the Ptr<Object> obj.
Definition: names.cc:775
keep track of a set of node pointers.
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
Topology file reader (Rocketfuel-format type).
RF_FileType
Enum of the possible file types.
NodeContainer GenerateFromWeightsFile(const std::vector< std::string > &argv)
Topology read function from a file containing the nodes weights.
std::map< std::string, Ptr< Node > > m_nodeMap
Map of the nodes (name, node).
static TypeId GetTypeId()
Get the type ID.
RF_FileType GetFileType(const std::string &buf)
Classifies the file type according to its content.
NodeContainer GenerateFromMapsFile(const std::vector< std::string > &argv)
Topology read function from a file containing the nodes map.
NodeContainer Read() override
Main topology reading function.
Interface for input file readers management.
void AddLink(Link link)
Adds a link to the topology.
ConstLinksIterator LinksEnd() const
Returns an iterator to the the last link in this block.
std::string GetFileName() const
Returns the input file name.
ConstLinksIterator LinksBegin() const
Returns an iterator to the the first link in this block.
std::list< Link >::const_iterator ConstLinksIterator
Constant iterator to the list of the links.
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:932
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:261
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:275
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
NodeContainer nodes
Definition: first.py:1
Every class exported by the ns3 library is enclosed in the ns3 namespace.
static const std::regex rocketfuel_maps_regex(ROCKETFUEL_MAPS_LINE)
Build a Regex object for RocketFuel topology maps file type.
static void PrintNodeInfo(std::string &uid, std::string &loc, bool dns, bool bb, std::vector< std::string >::size_type neighListSize, std::string &name, int radius)
Print node info.
static const std::regex rocketfuel_weights_regex(ROCKETFUEL_WEIGHTS_LINE)
Build a Regex object for RocketFuel topology weights file type.
#define ROCKETFUEL_MAPS_LINE
Regex expression matching a MAP line.
#define ROCKETFUEL_WEIGHTS_LINE
Regex expression matching a WEIGHT line.
ns3::RocketfuelTopologyReader declaration.