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 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Hajime Tazaki (tazaki@sfc.wide.ad.jp)
7 */
8
10
11#include "ns3/log.h"
12#include "ns3/names.h"
13#include "ns3/node-container.h"
14
15#include <cstdlib>
16#include <fstream>
17#include <iostream>
18#include <regex>
19#include <string>
20
21/**
22 * @file
23 * @ingroup topology
24 * ns3::RocketfuelTopologyReader implementation.
25 */
26
27namespace ns3
28{
29
30NS_LOG_COMPONENT_DEFINE("RocketfuelTopologyReader");
31
32NS_OBJECT_ENSURE_REGISTERED(RocketfuelTopologyReader);
33
34TypeId
36{
37 static TypeId tid = TypeId("ns3::RocketfuelTopologyReader")
39 .SetGroupName("TopologyReader")
40 .AddConstructor<RocketfuelTopologyReader>();
41 return tid;
42}
43
50
55
56/* uid @loc [+] [bb] (num_neigh) [&ext] -> <nuid-1> <nuid-2> ... {-euid} ... =name[!] rn */
57
58/// Start of a line
59#define START "^"
60/// End of a line
61#define END "$"
62/// One or more spaces
63#define SPACE "[ \t]+"
64/// Zero or more spaces
65#define MAYSPACE "[ \t]*"
66
67/// Regex expression matching a MAP line
68#define ROCKETFUEL_MAPS_LINE \
69 START "(-*[0-9]+)" SPACE "(@[?A-Za-z0-9,+-]+)" SPACE "(\\+)*" MAYSPACE "(bb)*" MAYSPACE \
70 "\\(([0-9]+)\\)" SPACE "(&[0-9]+)*" MAYSPACE "->" MAYSPACE "(<[0-9 \t<>]+>)*" MAYSPACE \
71 "(\\{-[0-9\\{\\} \t-]+\\})*" SPACE "=([A-Za-z0-9.!-]+)" SPACE "r([0-9])" MAYSPACE END
72
73/// Regex expression matching a WEIGHT line
74#define ROCKETFUEL_WEIGHTS_LINE START "([^ \t]+)" SPACE "([^ \t]+)" SPACE "([0-9.]+)" MAYSPACE END
75
76/**
77 * Build a Regex object for RocketFuel topology maps file type
78 * @return a static regex object for maps file type
79 */
81
82/**
83 * Build a Regex object for RocketFuel topology weights file type
84 * @return a static regex object for weights file type
85 */
87
88/**
89 * @brief Print node info
90 * @param uid node ID
91 * @param loc node location
92 * @param dns is a DNS node ?
93 * @param bb is a BB node ?
94 * @param neighListSize size of neighbor list
95 * @param name node name
96 * @param radius node radius
97 */
98static inline void
99PrintNodeInfo(std::string& uid,
100 std::string& loc,
101 bool dns,
102 bool bb,
103 std::vector<std::string>::size_type neighListSize,
104 std::string& name,
105 int radius)
106{
107 /* uid @loc [+] [bb] (num_neigh) [&ext] -> <nuid-1> <nuid-2> ... {-euid} ... =name[!] rn */
108 NS_LOG_INFO("Load Node[" << uid << "]: location: " << loc << " dns: " << dns << " bb: " << bb
109 << " neighbors: " << neighListSize << "(%d) externals: \"%s\"(%d) "
110 << "name: " << name << " radius: " << radius);
111}
112
113NodeContainer
114RocketfuelTopologyReader::GenerateFromMapsFile(const std::vector<std::string>& argv)
115{
116 std::string uid;
117 std::string loc;
118 std::string ptr;
119 std::string name;
120 bool dns = false;
121 bool bb = false;
122 int num_neigh_s = 0;
123 unsigned int num_neigh = 0;
124 int radius = 0;
125 std::vector<std::string> neigh_list;
127
128 uid = argv[0];
129 loc = argv[1];
130
131 if (!argv[2].empty())
132 {
133 dns = true;
134 }
135
136 if (!argv[3].empty())
137 {
138 bb = true;
139 }
140
141 num_neigh_s = std::stoi(argv[4]);
142 if (num_neigh_s < 0)
143 {
144 num_neigh = 0;
145 NS_LOG_WARN("Negative number of neighbors given");
146 }
147 else
148 {
149 num_neigh = num_neigh_s;
150 }
151
152 /* neighbors */
153 if (!argv[6].empty())
154 {
155 // Each line contains a list <.*>[ |\t]<.*>[ |\t]<.*>[ |\t]
156 // First remove < and >
157 std::string temp;
158 std::regex replace_regex("[<|>]");
159 std::regex_replace(std::back_inserter(temp),
160 argv[6].begin(),
161 argv[6].end(),
162 replace_regex,
163 "");
164
165 // Then split list
166 std::regex split_regex("[ |\t]");
167 std::sregex_token_iterator first{temp.begin(), temp.end(), split_regex, -1};
168 std::sregex_token_iterator last;
169 neigh_list = std::vector<std::string>{first, last};
170 }
171 if (num_neigh != neigh_list.size())
172 {
173 NS_LOG_WARN("Given number of neighbors = " << num_neigh << " != size of neighbors list = "
174 << neigh_list.size());
175 }
176
177 /* externs */
178 if (!argv[7].empty())
179 {
180 // euid = argv[7];
181 }
182
183 /* name */
184 if (!argv[8].empty())
185 {
186 name = argv[8];
187 }
188
189 radius = std::atoi(&argv[9][1]);
190 if (radius > 0)
191 {
192 return nodes;
193 }
194
195 PrintNodeInfo(uid, loc, dns, bb, neigh_list.size(), name, radius);
196
197 // Create node and link
198 if (!uid.empty())
199 {
200 if (!m_nodeMap[uid])
201 {
202 Ptr<Node> tmpNode = CreateObject<Node>();
203 std::string nodename = "RocketFuelTopology/NodeName/" + uid;
204 Names::Add(nodename, tmpNode);
205 m_nodeMap[uid] = tmpNode;
206 nodes.Add(tmpNode);
208 }
209
210 for (auto& nuid : neigh_list)
211 {
212 if (nuid.empty())
213 {
214 return nodes;
215 }
216
217 if (!m_nodeMap[nuid])
218 {
219 Ptr<Node> tmpNode = CreateObject<Node>();
220 std::string nodename = "RocketFuelTopology/NodeName/" + nuid;
221 Names::Add(nodename, tmpNode);
222 m_nodeMap[nuid] = tmpNode;
223 nodes.Add(tmpNode);
225 }
226 NS_LOG_INFO(m_linksNumber << ":" << m_nodesNumber << " From: " << uid
227 << " to: " << nuid);
228 Link link(m_nodeMap[uid], uid, m_nodeMap[nuid], nuid);
229 AddLink(link);
231 }
232 }
233
234 NS_LOG_INFO("Rocketfuel topology created with " << m_nodesNumber << " nodes and "
235 << m_linksNumber << " links");
236
237 return nodes;
238}
239
241RocketfuelTopologyReader::GenerateFromWeightsFile(const std::vector<std::string>& argv)
242{
243 /* uid @loc [+] [bb] (num_neigh) [&ext] -> <nuid-1> <nuid-2> ... {-euid} ... =name[!] rn */
244 std::string sname;
245 std::string tname;
246 std::string::size_type endptr;
248
249 sname = argv[0];
250 tname = argv[1];
251 double weight [[maybe_unused]] = std::stod(argv[2], &endptr);
252
253 if (argv[2].size() != endptr)
254 {
255 NS_LOG_WARN("invalid weight: " << argv[2]);
256 return nodes;
257 }
258
259 // Create node and link
260 if (!sname.empty() && !tname.empty())
261 {
262 if (!m_nodeMap[sname])
263 {
264 Ptr<Node> tmpNode = CreateObject<Node>();
265 std::string nodename = "RocketFuelTopology/NodeName/" + sname;
266 Names::Add(nodename, tmpNode);
267 m_nodeMap[sname] = tmpNode;
268 nodes.Add(tmpNode);
270 }
271
272 if (!m_nodeMap[tname])
273 {
274 Ptr<Node> tmpNode = CreateObject<Node>();
275 std::string nodename = "RocketFuelTopology/NodeName/" + tname;
276 Names::Add(nodename, tmpNode);
277 m_nodeMap[tname] = tmpNode;
278 nodes.Add(tmpNode);
280 }
281 NS_LOG_INFO(m_linksNumber << ":" << m_nodesNumber << " From: " << sname
282 << " to: " << tname);
284 bool found = false;
285 for (iter = LinksBegin(); iter != LinksEnd(); iter++)
286 {
287 if ((iter->GetFromNode() == m_nodeMap[tname]) &&
288 (iter->GetToNode() == m_nodeMap[sname]))
289 {
290 found = true;
291 break;
292 }
293 }
294
295 if (!found)
296 {
297 Link link(m_nodeMap[sname], sname, m_nodeMap[tname], tname);
298 AddLink(link);
300 }
301 }
302
303 NS_LOG_INFO("Rocketfuel topology created with " << m_nodesNumber << " nodes and "
304 << m_linksNumber << " links");
305
306 return nodes;
307}
308
311{
312 // Check whether Maps file or not
313 std::smatch matches;
314 if (std::regex_match(line, matches, rocketfuel_maps_regex))
315 {
316 return RF_MAPS;
317 }
318
319 // Check whether Weights file or not
320 if (std::regex_match(line, matches, rocketfuel_weights_regex))
321 {
322 return RF_WEIGHTS;
323 }
324
325 return RF_UNKNOWN;
326}
327
330{
331 std::ifstream topgen;
332 topgen.open(GetFileName());
334
335 std::istringstream lineBuffer;
336 std::string line;
337 int lineNumber = 0;
338 RF_FileType ftype = RF_UNKNOWN;
339
340 if (!topgen.is_open())
341 {
342 NS_LOG_WARN("Couldn't open the file " << GetFileName());
343 return nodes;
344 }
345
346 while (!topgen.eof())
347 {
348 std::vector<std::string> argv;
349
350 lineNumber++;
351 line.clear();
352 lineBuffer.clear();
353
354 getline(topgen, line);
355
356 if (lineNumber == 1)
357 {
358 ftype = GetFileType(line);
359 if (ftype == RF_UNKNOWN)
360 {
361 NS_LOG_INFO("Unknown File Format (" << GetFileName() << ")");
362 break;
363 }
364 }
365
366 std::smatch matches;
367
368 if (ftype == RF_MAPS)
369 {
370 bool ret = std::regex_match(line, matches, rocketfuel_maps_regex);
371 if (!ret || matches.empty())
372 {
373 NS_LOG_WARN("match failed (maps file): %s" << line);
374 break;
375 }
376 }
377 else if (ftype == RF_WEIGHTS)
378 {
379 bool ret = std::regex_match(line, matches, rocketfuel_weights_regex);
380 if (!ret || matches.empty())
381 {
382 NS_LOG_WARN("match failed (weights file): %s" << line);
383 break;
384 }
385 }
386
387 std::string matched_string;
388
389 for (auto it = matches.begin() + 1; it != matches.end(); it++)
390 {
391 if (it->matched)
392 {
393 matched_string = it->str();
394 }
395 else
396 {
397 matched_string = "";
398 }
399 argv.push_back(matched_string);
400 }
401
402 if (ftype == RF_MAPS)
403 {
404 nodes.Add(GenerateFromMapsFile(argv));
405 }
406 else if (ftype == RF_WEIGHTS)
407 {
409 }
410 else
411 {
412 NS_LOG_WARN("Unsupported file format (only Maps/Weights are supported)");
413 }
414 }
415
416 topgen.close();
417
418 return nodes;
419}
420
421} /* 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:764
keep track of a set of node pointers.
Smart pointer class similar to boost::intrusive_ptr.
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:49
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#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:250
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition log.h:264
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition object-base.h:35
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.