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 << "("
110 << "%d"
111 << ") externals: \"%s\"(%d) "
112 << "name: " << name << " radius: " << radius);
113}
114
115NodeContainer
116RocketfuelTopologyReader::GenerateFromMapsFile(const std::vector<std::string>& argv)
117{
118 std::string uid;
119 std::string loc;
120 std::string ptr;
121 std::string name;
122 bool dns = false;
123 bool bb = false;
124 int num_neigh_s = 0;
125 unsigned int num_neigh = 0;
126 int radius = 0;
127 std::vector<std::string> neigh_list;
129
130 uid = argv[0];
131 loc = argv[1];
132
133 if (!argv[2].empty())
134 {
135 dns = true;
136 }
137
138 if (!argv[3].empty())
139 {
140 bb = true;
141 }
142
143 num_neigh_s = std::stoi(argv[4]);
144 if (num_neigh_s < 0)
145 {
146 num_neigh = 0;
147 NS_LOG_WARN("Negative number of neighbors given");
148 }
149 else
150 {
151 num_neigh = num_neigh_s;
152 }
153
154 /* neighbors */
155 if (!argv[6].empty())
156 {
157 // Each line contains a list <.*>[ |\t]<.*>[ |\t]<.*>[ |\t]
158 // First remove < and >
159 std::string temp;
160 std::regex replace_regex("[<|>]");
161 std::regex_replace(std::back_inserter(temp),
162 argv[6].begin(),
163 argv[6].end(),
164 replace_regex,
165 "");
166
167 // Then split list
168 std::regex split_regex("[ |\t]");
169 std::sregex_token_iterator first{temp.begin(), temp.end(), split_regex, -1};
170 std::sregex_token_iterator last;
171 neigh_list = std::vector<std::string>{first, last};
172 }
173 if (num_neigh != neigh_list.size())
174 {
175 NS_LOG_WARN("Given number of neighbors = " << num_neigh << " != size of neighbors list = "
176 << neigh_list.size());
177 }
178
179 /* externs */
180 if (!argv[7].empty())
181 {
182 // euid = argv[7];
183 }
184
185 /* name */
186 if (!argv[8].empty())
187 {
188 name = argv[8];
189 }
190
191 radius = std::atoi(&argv[9][1]);
192 if (radius > 0)
193 {
194 return nodes;
195 }
196
197 PrintNodeInfo(uid, loc, dns, bb, neigh_list.size(), name, radius);
198
199 // Create node and link
200 if (!uid.empty())
201 {
202 if (!m_nodeMap[uid])
203 {
204 Ptr<Node> tmpNode = CreateObject<Node>();
205 std::string nodename = "RocketFuelTopology/NodeName/" + uid;
206 Names::Add(nodename, tmpNode);
207 m_nodeMap[uid] = tmpNode;
208 nodes.Add(tmpNode);
210 }
211
212 for (auto& nuid : neigh_list)
213 {
214 if (nuid.empty())
215 {
216 return nodes;
217 }
218
219 if (!m_nodeMap[nuid])
220 {
221 Ptr<Node> tmpNode = CreateObject<Node>();
222 std::string nodename = "RocketFuelTopology/NodeName/" + nuid;
223 Names::Add(nodename, tmpNode);
224 m_nodeMap[nuid] = tmpNode;
225 nodes.Add(tmpNode);
227 }
228 NS_LOG_INFO(m_linksNumber << ":" << m_nodesNumber << " From: " << uid
229 << " to: " << nuid);
230 Link link(m_nodeMap[uid], uid, m_nodeMap[nuid], nuid);
231 AddLink(link);
233 }
234 }
235
236 NS_LOG_INFO("Rocketfuel topology created with " << m_nodesNumber << " nodes and "
237 << m_linksNumber << " links");
238
239 return nodes;
240}
241
243RocketfuelTopologyReader::GenerateFromWeightsFile(const std::vector<std::string>& argv)
244{
245 /* uid @loc [+] [bb] (num_neigh) [&ext] -> <nuid-1> <nuid-2> ... {-euid} ... =name[!] rn */
246 std::string sname;
247 std::string tname;
248 std::string::size_type endptr;
250
251 sname = argv[0];
252 tname = argv[1];
253 std::stod(argv[2], &endptr); // weight
254
255 if (argv[2].size() != endptr)
256 {
257 NS_LOG_WARN("invalid weight: " << argv[2]);
258 return nodes;
259 }
260
261 // Create node and link
262 if (!sname.empty() && !tname.empty())
263 {
264 if (!m_nodeMap[sname])
265 {
266 Ptr<Node> tmpNode = CreateObject<Node>();
267 std::string nodename = "RocketFuelTopology/NodeName/" + sname;
268 Names::Add(nodename, tmpNode);
269 m_nodeMap[sname] = tmpNode;
270 nodes.Add(tmpNode);
272 }
273
274 if (!m_nodeMap[tname])
275 {
276 Ptr<Node> tmpNode = CreateObject<Node>();
277 std::string nodename = "RocketFuelTopology/NodeName/" + tname;
278 Names::Add(nodename, tmpNode);
279 m_nodeMap[tname] = tmpNode;
280 nodes.Add(tmpNode);
282 }
283 NS_LOG_INFO(m_linksNumber << ":" << m_nodesNumber << " From: " << sname
284 << " to: " << tname);
286 bool found = false;
287 for (iter = LinksBegin(); iter != LinksEnd(); iter++)
288 {
289 if ((iter->GetFromNode() == m_nodeMap[tname]) &&
290 (iter->GetToNode() == m_nodeMap[sname]))
291 {
292 found = true;
293 break;
294 }
295 }
296
297 if (!found)
298 {
299 Link link(m_nodeMap[sname], sname, m_nodeMap[tname], tname);
300 AddLink(link);
302 }
303 }
304
305 NS_LOG_INFO("Rocketfuel topology created with " << m_nodesNumber << " nodes and "
306 << m_linksNumber << " links");
307
308 return nodes;
309}
310
313{
314 // Check whether Maps file or not
315 std::smatch matches;
316 if (std::regex_match(line, matches, rocketfuel_maps_regex))
317 {
318 return RF_MAPS;
319 }
320
321 // Check whether Weights file or not
322 if (std::regex_match(line, matches, rocketfuel_weights_regex))
323 {
324 return RF_WEIGHTS;
325 }
326
327 return RF_UNKNOWN;
328}
329
332{
333 std::ifstream topgen;
334 topgen.open(GetFileName());
336
337 std::istringstream lineBuffer;
338 std::string line;
339 int lineNumber = 0;
340 RF_FileType ftype = RF_UNKNOWN;
341
342 if (!topgen.is_open())
343 {
344 NS_LOG_WARN("Couldn't open the file " << GetFileName());
345 return nodes;
346 }
347
348 while (!topgen.eof())
349 {
350 std::vector<std::string> argv;
351
352 lineNumber++;
353 line.clear();
354 lineBuffer.clear();
355
356 getline(topgen, line);
357
358 if (lineNumber == 1)
359 {
360 ftype = GetFileType(line);
361 if (ftype == RF_UNKNOWN)
362 {
363 NS_LOG_INFO("Unknown File Format (" << GetFileName() << ")");
364 break;
365 }
366 }
367
368 std::smatch matches;
369
370 if (ftype == RF_MAPS)
371 {
372 bool ret = std::regex_match(line, matches, rocketfuel_maps_regex);
373 if (!ret || matches.empty())
374 {
375 NS_LOG_WARN("match failed (maps file): %s" << line);
376 break;
377 }
378 }
379 else if (ftype == RF_WEIGHTS)
380 {
381 bool ret = std::regex_match(line, matches, rocketfuel_weights_regex);
382 if (!ret || matches.empty())
383 {
384 NS_LOG_WARN("match failed (weights file): %s" << line);
385 break;
386 }
387 }
388
389 std::string matched_string;
390
391 for (auto it = matches.begin() + 1; it != matches.end(); it++)
392 {
393 if (it->matched)
394 {
395 matched_string = it->str();
396 }
397 else
398 {
399 matched_string = "";
400 }
401 argv.push_back(matched_string);
402 }
403
404 if (ftype == RF_MAPS)
405 {
406 nodes.Add(GenerateFromMapsFile(argv));
407 }
408 else if (ftype == RF_WEIGHTS)
409 {
411 }
412 else
413 {
414 NS_LOG_WARN("Unsupported file format (only Maps/Weights are supported)");
415 }
416 }
417
418 topgen.close();
419
420 return nodes;
421}
422
423} /* 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:48
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.