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/unused.h"
28 #include "ns3/node-container.h"
30 
37 namespace ns3 {
38 
39 NS_LOG_COMPONENT_DEFINE ("RocketfuelTopologyReader");
40 
41 NS_OBJECT_ENSURE_REGISTERED (RocketfuelTopologyReader);
42 
44 {
45  static TypeId tid = TypeId ("ns3::RocketfuelTopologyReader")
47  .SetGroupName ("TopologyReader")
48  .AddConstructor<RocketfuelTopologyReader> ()
49  ;
50  return tid;
51 }
52 
54 {
55  m_linksNumber = 0;
56  m_nodesNumber = 0;
57  NS_LOG_FUNCTION (this);
58 }
59 
61 {
62  NS_LOG_FUNCTION (this);
63 }
64 
65 /* uid @loc [+] [bb] (num_neigh) [&ext] -> <nuid-1> <nuid-2> ... {-euid} ... =name[!] rn */
66 
67 
68 #define REGMATCH_MAX 16
69 
70 #define START "^"
71 #define END "$"
72 #define SPACE "[ \t]+"
73 #define MAYSPACE "[ \t]*"
74 
75 #define ROCKETFUEL_MAPS_LINE \
76  START "(-*[0-9]+)" SPACE "(@[?A-Za-z0-9,+]+)" SPACE \
77  "(\\+)*" MAYSPACE "(bb)*" MAYSPACE \
78  "\\(([0-9]+)\\)" SPACE "(&[0-9]+)*" MAYSPACE \
79  "->" MAYSPACE "(<[0-9 \t<>]+>)*" MAYSPACE \
80  "(\\{-[0-9\\{\\} \t-]+\\})*" SPACE \
81  "=([A-Za-z0-9.!-]+)" SPACE "r([0-9])" \
82  MAYSPACE END
83 
84 #define ROCKETFUEL_WEIGHTS_LINE \
85  START "([^ \t]+)" SPACE "([^ \t]+)" SPACE "([0-9.]+)" MAYSPACE END
86 
97 static inline void
98 PrintNodeInfo (std::string & uid, std::string & loc, bool dns, bool bb,
99  std::vector <std::string>::size_type neighListSize,
100  std::string & name, int radius)
101 {
102  /* uid @loc [+] [bb] (num_neigh) [&ext] -> <nuid-1> <nuid-2> ... {-euid} ... =name[!] rn */
103  NS_LOG_INFO ("Load Node[" << uid << "]: location: " << loc << " dns: " << dns
104  << " bb: " << bb << " neighbors: " << neighListSize
105  << "(" << "%d" << ") externals: \"%s\"(%d) "
106  << "name: " << name << " radius: " << radius);
107 }
108 
109 NodeContainer
111 {
112  std::string uid;
113  std::string loc;
114  std::string ptr;
115  std::string name;
116  std::string nuid;
117  bool dns = false;
118  bool bb = false;
119  int num_neigh_s = 0;
120  unsigned int num_neigh = 0;
121  int radius = 0;
122  std::vector <std::string> neigh_list;
124 
125  uid = argv[0];
126  loc = argv[1];
127 
128  if (argv[2])
129  {
130  dns = true;
131  }
132 
133  if (argv[3])
134  {
135  bb = true;
136  }
137 
138  num_neigh_s = ::atoi (argv[4]);
139  if (num_neigh_s < 0)
140  {
141  num_neigh = 0;
142  NS_LOG_WARN ("Negative number of neighbors given");
143  }
144  else
145  {
146  num_neigh = num_neigh_s;
147  }
148 
149  /* neighbors */
150  if (argv[6])
151  {
152  char *nbr;
153  char *stringp = argv[6];
154  while ((nbr = strsep (&stringp, " \t")) != NULL)
155  {
156  nbr[strlen (nbr) - 1] = '\0';
157  neigh_list.push_back (nbr + 1);
158  }
159  }
160  if (num_neigh != neigh_list.size ())
161  {
162  NS_LOG_WARN ("Given number of neighbors = " << num_neigh << " != size of neighbors list = " << neigh_list.size ());
163  }
164 
165  /* externs */
166  if (argv[7])
167  {
168  // euid = argv[7];
169  }
170 
171  /* name */
172  if (argv[8])
173  {
174  name = argv[8];
175  }
176 
177  radius = ::atoi (&argv[9][1]);
178  if (radius > 0)
179  {
180  return nodes;
181  }
182 
183  PrintNodeInfo (uid, loc, dns, bb, neigh_list.size (), name, radius);
184 
185  // Create node and link
186  if (!uid.empty ())
187  {
188  if (m_nodeMap[uid] == 0)
189  {
190  Ptr<Node> tmpNode = CreateObject<Node> ();
191  m_nodeMap[uid] = tmpNode;
192  nodes.Add (tmpNode);
193  m_nodesNumber++;
194  }
195 
196  for (uint32_t i = 0; i < neigh_list.size (); ++i)
197  {
198  nuid = neigh_list[i];
199 
200  if (nuid.empty ())
201  {
202  return nodes;
203  }
204 
205  if (m_nodeMap[nuid] == 0)
206  {
207  Ptr<Node> tmpNode = CreateObject<Node> ();
208  m_nodeMap[nuid] = tmpNode;
209  nodes.Add (tmpNode);
210  m_nodesNumber++;
211  }
212  NS_LOG_INFO (m_linksNumber << ":" << m_nodesNumber << " From: " << uid << " to: " << nuid);
213  Link link (m_nodeMap[uid], uid, m_nodeMap[nuid], nuid);
214  AddLink (link);
215  m_linksNumber++;
216  }
217  }
218 
219  NS_LOG_INFO ("Rocketfuel topology created with " << m_nodesNumber << " nodes and " << m_linksNumber << " links");
220 
221  return nodes;
222 }
223 
226 {
227  /* uid @loc [+] [bb] (num_neigh) [&ext] -> <nuid-1> <nuid-2> ... {-euid} ... =name[!] rn */
228  std::string sname;
229  std::string tname;
230  char *endptr;
232 
233  sname = argv[0];
234  tname = argv[1];
235  double v = strtod (argv[2], &endptr); // weight
236  NS_UNUSED (v); // suppress "set but not used" compiler warning in optimized builds
237  if (*endptr != '\0')
238  {
239  NS_LOG_WARN ("invalid weight: " << argv[2]);
240  return nodes;
241  }
242 
243  // Create node and link
244  if (!sname.empty () && !tname.empty ())
245  {
246  if (m_nodeMap[sname] == 0)
247  {
248  Ptr<Node> tmpNode = CreateObject<Node> ();
249  m_nodeMap[sname] = tmpNode;
250  nodes.Add (tmpNode);
251  m_nodesNumber++;
252  }
253 
254  if (m_nodeMap[tname] == 0)
255  {
256  Ptr<Node> tmpNode = CreateObject<Node> ();
257  m_nodeMap[tname] = tmpNode;
258  nodes.Add (tmpNode);
259  m_nodesNumber++;
260  }
261  NS_LOG_INFO (m_linksNumber << ":" << m_nodesNumber << " From: " << sname << " to: " << tname);
263  bool found = false;
264  for (iter = LinksBegin (); iter != LinksEnd (); iter++)
265  {
266  if ((iter->GetFromNode () == m_nodeMap[tname])
267  && (iter->GetToNode () == m_nodeMap[sname]))
268  {
269  found = true;
270  break;
271  }
272  }
273 
274  if (!found)
275  {
276  Link link (m_nodeMap[sname], sname, m_nodeMap[tname], tname);
277  AddLink (link);
278  m_linksNumber++;
279  }
280  }
281 
282  NS_LOG_INFO ("Rocketfuel topology created with " << m_nodesNumber << " nodes and " << m_linksNumber << " links");
283 
284  return nodes;
285 }
286 
289 {
290  int ret;
291  regmatch_t regmatch[REGMATCH_MAX];
292  regex_t regex;
293  char errbuf[512];
294 
295  // Check whether MAPS file or not
296  ret = regcomp (&regex, ROCKETFUEL_MAPS_LINE, REG_EXTENDED | REG_NEWLINE);
297  if (ret != 0)
298  {
299  regerror (ret, &regex, errbuf, sizeof (errbuf));
300  return RF_UNKNOWN;
301  }
302  ret = regexec (&regex, line, REGMATCH_MAX, regmatch, 0);
303  if (ret != REG_NOMATCH)
304  {
305  regfree (&regex);
306  return RF_MAPS;
307  }
308  regfree (&regex);
309 
310  // Check whether Weights file or not
311  ret = regcomp (&regex, ROCKETFUEL_WEIGHTS_LINE, REG_EXTENDED | REG_NEWLINE);
312  if (ret != 0)
313  {
314  regerror (ret, &regex, errbuf, sizeof (errbuf));
315  return RF_UNKNOWN;
316  }
317  ret = regexec (&regex, line, REGMATCH_MAX, regmatch, 0);
318  if (ret != REG_NOMATCH)
319  {
320  regfree (&regex);
321  return RF_WEIGHTS;
322  }
323  regfree (&regex);
324 
325  return RF_UNKNOWN;
326 }
327 
328 
331 {
332  std::ifstream topgen;
333  topgen.open (GetFileName ().c_str ());
335 
336  std::istringstream lineBuffer;
337  std::string line;
338  int lineNumber = 0;
339  enum RF_FileType ftype = RF_UNKNOWN;
340  char errbuf[512];
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  int ret;
351  int argc;
352  char *argv[REGMATCH_MAX];
353  char *buf;
354 
355  lineNumber++;
356  line.clear ();
357  lineBuffer.clear ();
358 
359  getline (topgen, line);
360  buf = (char *)line.c_str ();
361 
362  if (lineNumber == 1)
363  {
364  ftype = GetFileType (buf);
365  if (ftype == RF_UNKNOWN)
366  {
367  NS_LOG_INFO ("Unknown File Format (" << GetFileName () << ")");
368  break;
369  }
370  }
371 
372  regmatch_t regmatch[REGMATCH_MAX];
373  regex_t regex;
374 
375  if (ftype == RF_MAPS)
376  {
377  ret = regcomp (&regex, ROCKETFUEL_MAPS_LINE, REG_EXTENDED | REG_NEWLINE);
378  if (ret != 0)
379  {
380  regerror (ret, &regex, errbuf, sizeof (errbuf));
381  regfree (&regex);
382  break;
383  }
384 
385  ret = regexec (&regex, buf, REGMATCH_MAX, regmatch, 0);
386  if (ret == REG_NOMATCH)
387  {
388  NS_LOG_WARN ("match failed (maps file): %s" << buf);
389  regfree (&regex);
390  break;
391  }
392  }
393  else if (ftype == RF_WEIGHTS)
394  {
395  ret = regcomp (&regex, ROCKETFUEL_WEIGHTS_LINE, REG_EXTENDED | REG_NEWLINE);
396  if (ret != 0)
397  {
398  regerror (ret, &regex, errbuf, sizeof (errbuf));
399  regfree (&regex);
400  break;
401  }
402 
403  ret = regexec (&regex, buf, REGMATCH_MAX, regmatch, 0);
404  if (ret == REG_NOMATCH)
405  {
406  NS_LOG_WARN ("match failed (weights file): %s" << buf);
407  regfree (&regex);
408  break;
409  }
410  }
411 
412  line = buf;
413  argc = 0;
414 
415  /* regmatch[0] is the entire strings that matched */
416  for (int i = 1; i < REGMATCH_MAX; i++)
417  {
418  if (regmatch[i].rm_so == -1)
419  {
420  argv[i - 1] = NULL;
421  }
422  else
423  {
424  line[regmatch[i].rm_eo] = '\0';
425  argv[i - 1] = &line[regmatch[i].rm_so];
426  argc = i;
427  }
428  }
429 
430  if (ftype == RF_MAPS)
431  {
432  nodes.Add (GenerateFromMapsFile (argc, argv));
433  }
434  else if (ftype == RF_WEIGHTS)
435  {
436  nodes.Add (GenerateFromWeightsFile (argc, argv));
437  }
438  else
439  {
440  NS_LOG_WARN ("Unsupported file format (only Maps/Weights are supported)");
441  }
442 
443  regfree (&regex);
444  }
445 
446 
447  topgen.close ();
448 
449  return nodes;
450 }
451 
452 } /* namespace ns3 */
453 
454 
static TypeId GetTypeId(void)
Get the type ID.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define ROCKETFUEL_MAPS_LINE
#define NS_UNUSED(x)
Mark a local variable as unused.
Definition: unused.h:36
NodeContainer GenerateFromMapsFile(int argc, char *argv[])
Topology read function from a file containing the nodes map.
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:281
ns3::RocketfuelTopologyReader declaration.
void AddLink(Link link)
Adds a link to the topology.
enum RF_FileType GetFileType(const char *)
Classifies the file type according to its content.
NodeContainer GenerateFromWeightsFile(int argc, char *argv[])
Topology read function from a file containing the nodes weights.
Interface for input file readers management.
nodes
Definition: first.py:32
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.
ConstLinksIterator LinksEnd(void) const
Returns an iterator to the the last link in this block.
#define ROCKETFUEL_WEIGHTS_LINE
std::map< std::string, Ptr< Node > > m_nodeMap
Map of the nodes (name, node).
std::list< Link >::const_iterator ConstLinksIterator
Constant iterator to the list of the links.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
keep track of a set of node pointers.
#define REGMATCH_MAX
virtual NodeContainer Read(void)
Main topology reading function.
RF_FileType
Enum of the possible file types.
std::string GetFileName(void) const
Returns the input file name.
Topology file reader (Rocketfuel-format type).
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:265
a unique identifier for an interface.
Definition: type-id.h:58
ConstLinksIterator LinksBegin(void) const
Returns an iterator to the the first link in this block.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:923