A Discrete-Event Network Simulator
API
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/node-container.h"
24
25#include <cstdlib>
26#include <fstream>
27#include <iostream>
28#include <regex>
29#include <string>
30
37namespace ns3
38{
39
40NS_LOG_COMPONENT_DEFINE("RocketfuelTopologyReader");
41
42NS_OBJECT_ENSURE_REGISTERED(RocketfuelTopologyReader);
43
44TypeId
46{
47 static TypeId tid = TypeId("ns3::RocketfuelTopologyReader")
49 .SetGroupName("TopologyReader")
50 .AddConstructor<RocketfuelTopologyReader>();
51 return tid;
52}
53
55{
56 m_linksNumber = 0;
57 m_nodesNumber = 0;
58 NS_LOG_FUNCTION(this);
59}
60
62{
63 NS_LOG_FUNCTION(this);
64}
65
66/* uid @loc [+] [bb] (num_neigh) [&ext] -> <nuid-1> <nuid-2> ... {-euid} ... =name[!] rn */
67
69#define START "^"
71#define END "$"
73#define SPACE "[ \t]+"
75#define MAYSPACE "[ \t]*"
76
78#define ROCKETFUEL_MAPS_LINE \
79 START "(-*[0-9]+)" SPACE "(@[?A-Za-z0-9,+-]+)" SPACE "(\\+)*" MAYSPACE "(bb)*" MAYSPACE \
80 "\\(([0-9]+)\\)" SPACE "(&[0-9]+)*" MAYSPACE "->" MAYSPACE "(<[0-9 \t<>]+>)*" MAYSPACE \
81 "(\\{-[0-9\\{\\} \t-]+\\})*" SPACE "=([A-Za-z0-9.!-]+)" SPACE "r([0-9])" MAYSPACE END
82
84#define ROCKETFUEL_WEIGHTS_LINE START "([^ \t]+)" SPACE "([^ \t]+)" SPACE "([0-9.]+)" MAYSPACE END
85
91
97
108static inline void
109PrintNodeInfo(std::string& uid,
110 std::string& loc,
111 bool dns,
112 bool bb,
113 std::vector<std::string>::size_type neighListSize,
114 std::string& name,
115 int radius)
116{
117 /* uid @loc [+] [bb] (num_neigh) [&ext] -> <nuid-1> <nuid-2> ... {-euid} ... =name[!] rn */
118 NS_LOG_INFO("Load Node[" << uid << "]: location: " << loc << " dns: " << dns << " bb: " << bb
119 << " neighbors: " << neighListSize << "("
120 << "%d"
121 << ") externals: \"%s\"(%d) "
122 << "name: " << name << " radius: " << radius);
123}
124
125NodeContainer
126RocketfuelTopologyReader::GenerateFromMapsFile(const std::vector<std::string>& argv)
127{
128 std::string uid;
129 std::string loc;
130 std::string ptr;
131 std::string name;
132 bool dns = false;
133 bool bb = false;
134 int num_neigh_s = 0;
135 unsigned int num_neigh = 0;
136 int radius = 0;
137 std::vector<std::string> neigh_list;
139
140 uid = argv[0];
141 loc = argv[1];
142
143 if (!argv[2].empty())
144 {
145 dns = true;
146 }
147
148 if (!argv[3].empty())
149 {
150 bb = true;
151 }
152
153 num_neigh_s = std::stoi(argv[4]);
154 if (num_neigh_s < 0)
155 {
156 num_neigh = 0;
157 NS_LOG_WARN("Negative number of neighbors given");
158 }
159 else
160 {
161 num_neigh = num_neigh_s;
162 }
163
164 /* neighbors */
165 if (!argv[6].empty())
166 {
167 // Each line contains a list <.*>[ |\t]<.*>[ |\t]<.*>[ |\t]
168 // First remove < and >
169 std::string temp;
170 std::regex replace_regex("[<|>]");
171 std::regex_replace(std::back_inserter(temp),
172 argv[6].begin(),
173 argv[6].end(),
174 replace_regex,
175 "");
176
177 // Then split list
178 std::regex split_regex("[ |\t]");
179 std::sregex_token_iterator first{temp.begin(), temp.end(), split_regex, -1};
180 std::sregex_token_iterator last;
181 neigh_list = std::vector<std::string>{first, last};
182 }
183 if (num_neigh != neigh_list.size())
184 {
185 NS_LOG_WARN("Given number of neighbors = " << num_neigh << " != size of neighbors list = "
186 << neigh_list.size());
187 }
188
189 /* externs */
190 if (!argv[7].empty())
191 {
192 // euid = argv[7];
193 }
194
195 /* name */
196 if (!argv[8].empty())
197 {
198 name = argv[8];
199 }
200
201 radius = std::atoi(&argv[9][1]);
202 if (radius > 0)
203 {
204 return nodes;
205 }
206
207 PrintNodeInfo(uid, loc, dns, bb, neigh_list.size(), name, radius);
208
209 // Create node and link
210 if (!uid.empty())
211 {
212 if (!m_nodeMap[uid])
213 {
214 Ptr<Node> tmpNode = CreateObject<Node>();
215 m_nodeMap[uid] = tmpNode;
216 nodes.Add(tmpNode);
218 }
219
220 for (auto& nuid : neigh_list)
221 {
222 if (nuid.empty())
223 {
224 return nodes;
225 }
226
227 if (!m_nodeMap[nuid])
228 {
229 Ptr<Node> tmpNode = CreateObject<Node>();
230 m_nodeMap[nuid] = tmpNode;
231 nodes.Add(tmpNode);
233 }
234 NS_LOG_INFO(m_linksNumber << ":" << m_nodesNumber << " From: " << uid
235 << " to: " << nuid);
236 Link link(m_nodeMap[uid], uid, m_nodeMap[nuid], nuid);
237 AddLink(link);
239 }
240 }
241
242 NS_LOG_INFO("Rocketfuel topology created with " << m_nodesNumber << " nodes and "
243 << m_linksNumber << " links");
244
245 return nodes;
246}
247
249RocketfuelTopologyReader::GenerateFromWeightsFile(const std::vector<std::string>& argv)
250{
251 /* uid @loc [+] [bb] (num_neigh) [&ext] -> <nuid-1> <nuid-2> ... {-euid} ... =name[!] rn */
252 std::string sname;
253 std::string tname;
254 std::string::size_type endptr;
256
257 sname = argv[0];
258 tname = argv[1];
259 std::stod(argv[2], &endptr); // weight
260
261 if (argv[2].size() != endptr)
262 {
263 NS_LOG_WARN("invalid weight: " << argv[2]);
264 return nodes;
265 }
266
267 // Create node and link
268 if (!sname.empty() && !tname.empty())
269 {
270 if (!m_nodeMap[sname])
271 {
272 Ptr<Node> tmpNode = CreateObject<Node>();
273 m_nodeMap[sname] = tmpNode;
274 nodes.Add(tmpNode);
276 }
277
278 if (!m_nodeMap[tname])
279 {
280 Ptr<Node> tmpNode = CreateObject<Node>();
281 m_nodeMap[tname] = tmpNode;
282 nodes.Add(tmpNode);
284 }
285 NS_LOG_INFO(m_linksNumber << ":" << m_nodesNumber << " From: " << sname
286 << " to: " << tname);
288 bool found = false;
289 for (iter = LinksBegin(); iter != LinksEnd(); iter++)
290 {
291 if ((iter->GetFromNode() == m_nodeMap[tname]) &&
292 (iter->GetToNode() == m_nodeMap[sname]))
293 {
294 found = true;
295 break;
296 }
297 }
298
299 if (!found)
300 {
301 Link link(m_nodeMap[sname], sname, m_nodeMap[tname], tname);
302 AddLink(link);
304 }
305 }
306
307 NS_LOG_INFO("Rocketfuel topology created with " << m_nodesNumber << " nodes and "
308 << m_linksNumber << " links");
309
310 return nodes;
311}
312
315{
316 int ret;
317
318 // Check whether Maps file or not
319 std::smatch matches;
320 ret = std::regex_match(line, matches, rocketfuel_maps_regex);
321 if (ret)
322 {
323 return RF_MAPS;
324 }
325
326 // Check whether Weights file or not
327 ret = std::regex_match(line, matches, rocketfuel_weights_regex);
328 if (ret)
329 {
330 return RF_WEIGHTS;
331 }
332
333 return RF_UNKNOWN;
334}
335
338{
339 std::ifstream topgen;
340 topgen.open(GetFileName());
342
343 std::istringstream lineBuffer;
344 std::string line;
345 int lineNumber = 0;
346 enum RF_FileType ftype = RF_UNKNOWN;
347
348 if (!topgen.is_open())
349 {
350 NS_LOG_WARN("Couldn't open the file " << GetFileName());
351 return nodes;
352 }
353
354 while (!topgen.eof())
355 {
356 int ret;
357 std::vector<std::string> argv;
358
359 lineNumber++;
360 line.clear();
361 lineBuffer.clear();
362
363 getline(topgen, line);
364
365 if (lineNumber == 1)
366 {
367 ftype = GetFileType(line);
368 if (ftype == RF_UNKNOWN)
369 {
370 NS_LOG_INFO("Unknown File Format (" << GetFileName() << ")");
371 break;
372 }
373 }
374
375 std::smatch matches;
376
377 if (ftype == RF_MAPS)
378 {
379 ret = std::regex_match(line, matches, rocketfuel_maps_regex);
380 if (ret != true || matches.empty())
381 {
382 NS_LOG_WARN("match failed (maps file): %s" << line);
383 break;
384 }
385 }
386 else if (ftype == RF_WEIGHTS)
387 {
388 ret = std::regex_match(line, matches, rocketfuel_weights_regex);
389 if (ret != true || matches.empty())
390 {
391 NS_LOG_WARN("match failed (weights file): %s" << line);
392 break;
393 }
394 }
395
396 std::string matched_string;
397
398 for (auto it = matches.begin() + 1; it != matches.end(); it++)
399 {
400 if (it->matched)
401 {
402 matched_string = it->str();
403 }
404 else
405 {
406 matched_string = "";
407 }
408 argv.push_back(matched_string);
409 }
410
411 if (ftype == RF_MAPS)
412 {
413 nodes.Add(GenerateFromMapsFile(argv));
414 }
415 else if (ftype == RF_WEIGHTS)
416 {
418 }
419 else
420 {
421 NS_LOG_WARN("Unsupported file format (only Maps/Weights are supported)");
422 }
423 }
424
425 topgen.close();
426
427 return nodes;
428}
429
430} /* namespace ns3 */
keep track of a set of node pointers.
Topology file reader (Rocketfuel-format type).
RF_FileType
Enum of the possible file types.
enum RF_FileType GetFileType(const std::string &buf)
Classifies the file type according to its content.
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.
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:60
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
Empty class, used as a default parent class for SimpleRefCount.
#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:45
NodeContainer nodes
Definition: first.py:1
Every class exported by the ns3 library is enclosed in the ns3 namespace.
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_maps_regex(ROCKETFUEL_MAPS_LINE, std::regex::extended)
Build a Regex object for RocketFuel topology maps file type.
@ extended
Definition: ff-mac-common.h:85
static const std::regex rocketfuel_weights_regex(ROCKETFUEL_WEIGHTS_LINE, std::regex::extended)
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.