A Discrete-Event Network Simulator
API
rocketfuel-topology-reader.cc
Go to the documentation of this file.
1/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2010 Hajime Tazaki
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Author: Hajime Tazaki (tazaki@sfc.wide.ad.jp)
19 */
20
21#include <fstream>
22#include <cstdlib>
23#include <iostream>
24#include <sstream>
25#include <regex.h>
26#include "ns3/log.h"
27#include "ns3/node-container.h"
29
36namespace ns3 {
37
38NS_LOG_COMPONENT_DEFINE ("RocketfuelTopologyReader");
39
40NS_OBJECT_ENSURE_REGISTERED (RocketfuelTopologyReader);
41
43{
44 static TypeId tid = TypeId ("ns3::RocketfuelTopologyReader")
46 .SetGroupName ("TopologyReader")
47 .AddConstructor<RocketfuelTopologyReader> ()
48 ;
49 return tid;
50}
51
53{
54 m_linksNumber = 0;
55 m_nodesNumber = 0;
56 NS_LOG_FUNCTION (this);
57}
58
60{
61 NS_LOG_FUNCTION (this);
62}
63
64/* uid @loc [+] [bb] (num_neigh) [&ext] -> <nuid-1> <nuid-2> ... {-euid} ... =name[!] rn */
65
66
68#define REGMATCH_MAX 16
69
71#define START "^"
73#define END "$"
75#define SPACE "[ \t]+"
77#define MAYSPACE "[ \t]*"
78
80#define ROCKETFUEL_MAPS_LINE \
81 START "(-*[0-9]+)" SPACE "(@[?A-Za-z0-9,+]+)" SPACE \
82 "(\\+)*" MAYSPACE "(bb)*" MAYSPACE \
83 "\\(([0-9]+)\\)" SPACE "(&[0-9]+)*" MAYSPACE \
84 "->" MAYSPACE "(<[0-9 \t<>]+>)*" MAYSPACE \
85 "(\\{-[0-9\\{\\} \t-]+\\})*" SPACE \
86 "=([A-Za-z0-9.!-]+)" SPACE "r([0-9])" \
87 MAYSPACE END
88
90#define ROCKETFUEL_WEIGHTS_LINE \
91 START "([^ \t]+)" SPACE "([^ \t]+)" SPACE "([0-9.]+)" MAYSPACE END
92
103static inline void
104PrintNodeInfo (std::string & uid, std::string & loc, bool dns, bool bb,
105 std::vector <std::string>::size_type neighListSize,
106 std::string & name, int radius)
107{
108 /* uid @loc [+] [bb] (num_neigh) [&ext] -> <nuid-1> <nuid-2> ... {-euid} ... =name[!] rn */
109 NS_LOG_INFO ("Load Node[" << uid << "]: location: " << loc << " dns: " << dns
110 << " bb: " << bb << " neighbors: " << neighListSize
111 << "(" << "%d" << ") externals: \"%s\"(%d) "
112 << "name: " << name << " radius: " << radius);
113}
114
115NodeContainer
117{
118 std::string uid;
119 std::string loc;
120 std::string ptr;
121 std::string name;
122 std::string nuid;
123 bool dns = false;
124 bool bb = false;
125 int num_neigh_s = 0;
126 unsigned int num_neigh = 0;
127 int radius = 0;
128 std::vector <std::string> neigh_list;
130
131 uid = argv[0];
132 loc = argv[1];
133
134 if (argv[2])
135 {
136 dns = true;
137 }
138
139 if (argv[3])
140 {
141 bb = true;
142 }
143
144 num_neigh_s = ::atoi (argv[4]);
145 if (num_neigh_s < 0)
146 {
147 num_neigh = 0;
148 NS_LOG_WARN ("Negative number of neighbors given");
149 }
150 else
151 {
152 num_neigh = num_neigh_s;
153 }
154
155 /* neighbors */
156 if (argv[6])
157 {
158 char *nbr;
159 char *stringp = argv[6];
160 while ((nbr = strsep (&stringp, " \t")) != NULL)
161 {
162 nbr[strlen (nbr) - 1] = '\0';
163 neigh_list.push_back (nbr + 1);
164 }
165 }
166 if (num_neigh != neigh_list.size ())
167 {
168 NS_LOG_WARN ("Given number of neighbors = " << num_neigh << " != size of neighbors list = " << neigh_list.size ());
169 }
170
171 /* externs */
172 if (argv[7])
173 {
174 // euid = argv[7];
175 }
176
177 /* name */
178 if (argv[8])
179 {
180 name = argv[8];
181 }
182
183 radius = ::atoi (&argv[9][1]);
184 if (radius > 0)
185 {
186 return nodes;
187 }
188
189 PrintNodeInfo (uid, loc, dns, bb, neigh_list.size (), name, radius);
190
191 // Create node and link
192 if (!uid.empty ())
193 {
194 if (m_nodeMap[uid] == 0)
195 {
196 Ptr<Node> tmpNode = CreateObject<Node> ();
197 m_nodeMap[uid] = tmpNode;
198 nodes.Add (tmpNode);
200 }
201
202 for (uint32_t i = 0; i < neigh_list.size (); ++i)
203 {
204 nuid = neigh_list[i];
205
206 if (nuid.empty ())
207 {
208 return nodes;
209 }
210
211 if (m_nodeMap[nuid] == 0)
212 {
213 Ptr<Node> tmpNode = CreateObject<Node> ();
214 m_nodeMap[nuid] = tmpNode;
215 nodes.Add (tmpNode);
217 }
218 NS_LOG_INFO (m_linksNumber << ":" << m_nodesNumber << " From: " << uid << " to: " << nuid);
219 Link link (m_nodeMap[uid], uid, m_nodeMap[nuid], nuid);
220 AddLink (link);
222 }
223 }
224
225 NS_LOG_INFO ("Rocketfuel topology created with " << m_nodesNumber << " nodes and " << m_linksNumber << " links");
226
227 return nodes;
228}
229
232{
233 /* uid @loc [+] [bb] (num_neigh) [&ext] -> <nuid-1> <nuid-2> ... {-euid} ... =name[!] rn */
234 std::string sname;
235 std::string tname;
236 char *endptr;
238
239 sname = argv[0];
240 tname = argv[1];
241 [[maybe_unused]] double v = strtod (argv[2], &endptr); // weight
242
243 if (*endptr != '\0')
244 {
245 NS_LOG_WARN ("invalid weight: " << argv[2]);
246 return nodes;
247 }
248
249 // Create node and link
250 if (!sname.empty () && !tname.empty ())
251 {
252 if (m_nodeMap[sname] == 0)
253 {
254 Ptr<Node> tmpNode = CreateObject<Node> ();
255 m_nodeMap[sname] = tmpNode;
256 nodes.Add (tmpNode);
258 }
259
260 if (m_nodeMap[tname] == 0)
261 {
262 Ptr<Node> tmpNode = CreateObject<Node> ();
263 m_nodeMap[tname] = tmpNode;
264 nodes.Add (tmpNode);
266 }
267 NS_LOG_INFO (m_linksNumber << ":" << m_nodesNumber << " From: " << sname << " to: " << tname);
269 bool found = false;
270 for (iter = LinksBegin (); iter != LinksEnd (); iter++)
271 {
272 if ((iter->GetFromNode () == m_nodeMap[tname])
273 && (iter->GetToNode () == m_nodeMap[sname]))
274 {
275 found = true;
276 break;
277 }
278 }
279
280 if (!found)
281 {
282 Link link (m_nodeMap[sname], sname, m_nodeMap[tname], tname);
283 AddLink (link);
285 }
286 }
287
288 NS_LOG_INFO ("Rocketfuel topology created with " << m_nodesNumber << " nodes and " << m_linksNumber << " links");
289
290 return nodes;
291}
292
295{
296 int ret;
297 regmatch_t regmatch[REGMATCH_MAX];
298 regex_t regex;
299 char errbuf[512];
300
301 // Check whether MAPS file or not
302 ret = regcomp (&regex, ROCKETFUEL_MAPS_LINE, REG_EXTENDED | REG_NEWLINE);
303 if (ret != 0)
304 {
305 regerror (ret, &regex, errbuf, sizeof (errbuf));
306 return RF_UNKNOWN;
307 }
308 ret = regexec (&regex, line, REGMATCH_MAX, regmatch, 0);
309 if (ret != REG_NOMATCH)
310 {
311 regfree (&regex);
312 return RF_MAPS;
313 }
314 regfree (&regex);
315
316 // Check whether Weights file or not
317 ret = regcomp (&regex, ROCKETFUEL_WEIGHTS_LINE, REG_EXTENDED | REG_NEWLINE);
318 if (ret != 0)
319 {
320 regerror (ret, &regex, errbuf, sizeof (errbuf));
321 return RF_UNKNOWN;
322 }
323 ret = regexec (&regex, line, REGMATCH_MAX, regmatch, 0);
324 if (ret != REG_NOMATCH)
325 {
326 regfree (&regex);
327 return RF_WEIGHTS;
328 }
329 regfree (&regex);
330
331 return RF_UNKNOWN;
332}
333
334
337{
338 std::ifstream topgen;
339 topgen.open (GetFileName ().c_str ());
341
342 std::istringstream lineBuffer;
343 std::string line;
344 int lineNumber = 0;
345 enum RF_FileType ftype = RF_UNKNOWN;
346 char errbuf[512];
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 int argc;
358 char *argv[REGMATCH_MAX];
359 char *buf;
360
361 lineNumber++;
362 line.clear ();
363 lineBuffer.clear ();
364
365 getline (topgen, line);
366 buf = (char *)line.c_str ();
367
368 if (lineNumber == 1)
369 {
370 ftype = GetFileType (buf);
371 if (ftype == RF_UNKNOWN)
372 {
373 NS_LOG_INFO ("Unknown File Format (" << GetFileName () << ")");
374 break;
375 }
376 }
377
378 regmatch_t regmatch[REGMATCH_MAX];
379 regex_t regex;
380
381 if (ftype == RF_MAPS)
382 {
383 ret = regcomp (&regex, ROCKETFUEL_MAPS_LINE, REG_EXTENDED | REG_NEWLINE);
384 if (ret != 0)
385 {
386 regerror (ret, &regex, errbuf, sizeof (errbuf));
387 regfree (&regex);
388 break;
389 }
390
391 ret = regexec (&regex, buf, REGMATCH_MAX, regmatch, 0);
392 if (ret == REG_NOMATCH)
393 {
394 NS_LOG_WARN ("match failed (maps file): %s" << buf);
395 regfree (&regex);
396 break;
397 }
398 }
399 else if (ftype == RF_WEIGHTS)
400 {
401 ret = regcomp (&regex, ROCKETFUEL_WEIGHTS_LINE, REG_EXTENDED | REG_NEWLINE);
402 if (ret != 0)
403 {
404 regerror (ret, &regex, errbuf, sizeof (errbuf));
405 regfree (&regex);
406 break;
407 }
408
409 ret = regexec (&regex, buf, REGMATCH_MAX, regmatch, 0);
410 if (ret == REG_NOMATCH)
411 {
412 NS_LOG_WARN ("match failed (weights file): %s" << buf);
413 regfree (&regex);
414 break;
415 }
416 }
417
418 line = buf;
419 argc = 0;
420
421 /* regmatch[0] is the entire strings that matched */
422 for (int i = 1; i < REGMATCH_MAX; i++)
423 {
424 if (regmatch[i].rm_so == -1)
425 {
426 argv[i - 1] = NULL;
427 }
428 else
429 {
430 line[regmatch[i].rm_eo] = '\0';
431 argv[i - 1] = &line[regmatch[i].rm_so];
432 argc = i;
433 }
434 }
435
436 if (ftype == RF_MAPS)
437 {
438 nodes.Add (GenerateFromMapsFile (argc, argv));
439 }
440 else if (ftype == RF_WEIGHTS)
441 {
442 nodes.Add (GenerateFromWeightsFile (argc, argv));
443 }
444 else
445 {
446 NS_LOG_WARN ("Unsupported file format (only Maps/Weights are supported)");
447 }
448
449 regfree (&regex);
450 }
451
452
453 topgen.close ();
454
455 return nodes;
456}
457
458} /* namespace ns3 */
459
460
keep track of a set of node pointers.
Topology file reader (Rocketfuel-format type).
RF_FileType
Enum of the possible file types.
static TypeId GetTypeId(void)
Get the type ID.
enum RF_FileType GetFileType(const char *buf)
Classifies the file type according to its content.
NodeContainer GenerateFromWeightsFile(int argc, char *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).
NodeContainer GenerateFromMapsFile(int argc, char *argv[])
Topology read function from a file containing the nodes map.
virtual NodeContainer Read(void)
Main topology reading function.
Interface for input file readers management.
ConstLinksIterator LinksBegin(void) const
Returns an iterator to the the first link in this block.
void AddLink(Link link)
Adds a link to the topology.
ConstLinksIterator LinksEnd(void) const
Returns an iterator to the the last link in this block.
std::string GetFileName(void) const
Returns the input file name.
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:922
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#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:265
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:281
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
nodes
Definition: first.py:32
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.
#define ROCKETFUEL_MAPS_LINE
Regex expression matching a MAP line.
#define ROCKETFUEL_WEIGHTS_LINE
Regex expression matching a WEIGHT line.
#define REGMATCH_MAX
Maximum nuber of matches in a regex query.
ns3::RocketfuelTopologyReader declaration.