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 
31 namespace ns3 {
32 
33 NS_LOG_COMPONENT_DEFINE ("RocketfuelTopologyReader");
34 
35 NS_OBJECT_ENSURE_REGISTERED (RocketfuelTopologyReader);
36 
38 {
39  static TypeId tid = TypeId ("ns3::RocketfuelTopologyReader")
41  .SetGroupName ("TopologyReader")
42  .AddConstructor<RocketfuelTopologyReader> ()
43  ;
44  return tid;
45 }
46 
48 {
49  m_linksNumber = 0;
50  m_nodesNumber = 0;
51  NS_LOG_FUNCTION (this);
52 }
53 
55 {
56  NS_LOG_FUNCTION (this);
57 }
58 
59 /* uid @loc [+] [bb] (num_neigh) [&ext] -> <nuid-1> <nuid-2> ... {-euid} ... =name[!] rn */
60 
61 
62 #define REGMATCH_MAX 16
63 
64 #define START "^"
65 #define END "$"
66 #define SPACE "[ \t]+"
67 #define MAYSPACE "[ \t]*"
68 
69 #define ROCKETFUEL_MAPS_LINE \
70  START "(-*[0-9]+)" SPACE "(@[?A-Za-z0-9,+]+)" SPACE \
71  "(\\+)*" MAYSPACE "(bb)*" MAYSPACE \
72  "\\(([0-9]+)\\)" SPACE "(&[0-9]+)*" MAYSPACE \
73  "->" MAYSPACE "(<[0-9 \t<>]+>)*" MAYSPACE \
74  "(\\{-[0-9\\{\\} \t-]+\\})*" SPACE \
75  "=([A-Za-z0-9.!-]+)" SPACE "r([0-9])" \
76  MAYSPACE END
77 
78 #define ROCKETFUEL_WEIGHTS_LINE \
79  START "([^ \t]+)" SPACE "([^ \t]+)" SPACE "([0-9.]+)" MAYSPACE END
80 
91 static inline void
92 PrintNodeInfo (std::string & uid, std::string & loc, bool dns, bool bb,
93  std::vector <std::string>::size_type neighListSize,
94  std::string & name, int radius)
95 {
96  /* uid @loc [+] [bb] (num_neigh) [&ext] -> <nuid-1> <nuid-2> ... {-euid} ... =name[!] rn */
97  NS_LOG_INFO ("Load Node[" << uid << "]: location: " << loc << " dns: " << dns
98  << " bb: " << bb << " neighbors: " << neighListSize
99  << "(" << "%d" << ") externals: \"%s\"(%d) "
100  << "name: " << name << " radius: " << radius);
101 }
102 
103 NodeContainer
105 {
106  std::string uid;
107  std::string loc;
108  std::string ptr;
109  std::string name;
110  std::string nuid;
111  bool dns = false;
112  bool bb = false;
113  int num_neigh_s = 0;
114  unsigned int num_neigh = 0;
115  int radius = 0;
116  std::vector <std::string> neigh_list;
118 
119  uid = argv[0];
120  loc = argv[1];
121 
122  if (argv[2])
123  {
124  dns = true;
125  }
126 
127  if (argv[3])
128  {
129  bb = true;
130  }
131 
132  num_neigh_s = ::atoi (argv[4]);
133  if (num_neigh_s < 0)
134  {
135  num_neigh = 0;
136  NS_LOG_WARN ("Negative number of neighbors given");
137  }
138  else
139  {
140  num_neigh = num_neigh_s;
141  }
142 
143  /* neighbors */
144  if (argv[6])
145  {
146  char *nbr;
147  char *stringp = argv[6];
148  while ((nbr = strsep (&stringp, " \t")) != NULL)
149  {
150  nbr[strlen (nbr) - 1] = '\0';
151  neigh_list.push_back (nbr + 1);
152  }
153  }
154  if (num_neigh != neigh_list.size ())
155  {
156  NS_LOG_WARN ("Given number of neighbors = " << num_neigh << " != size of neighbors list = " << neigh_list.size ());
157  }
158 
159  /* externs */
160  if (argv[7])
161  {
162  // euid = argv[7];
163  }
164 
165  /* name */
166  if (argv[8])
167  {
168  name = argv[8];
169  }
170 
171  radius = ::atoi (&argv[9][1]);
172  if (radius > 0)
173  {
174  return nodes;
175  }
176 
177  PrintNodeInfo (uid, loc, dns, bb, neigh_list.size (), name, radius);
178 
179  // Create node and link
180  if (!uid.empty ())
181  {
182  if (m_nodeMap[uid] == 0)
183  {
184  Ptr<Node> tmpNode = CreateObject<Node> ();
185  m_nodeMap[uid] = tmpNode;
186  nodes.Add (tmpNode);
187  m_nodesNumber++;
188  }
189 
190  for (uint32_t i = 0; i < neigh_list.size (); ++i)
191  {
192  nuid = neigh_list[i];
193 
194  if (nuid.empty ())
195  {
196  return nodes;
197  }
198 
199  if (m_nodeMap[nuid] == 0)
200  {
201  Ptr<Node> tmpNode = CreateObject<Node> ();
202  m_nodeMap[nuid] = tmpNode;
203  nodes.Add (tmpNode);
204  m_nodesNumber++;
205  }
206  NS_LOG_INFO (m_linksNumber << ":" << m_nodesNumber << " From: " << uid << " to: " << nuid);
207  Link link (m_nodeMap[uid], uid, m_nodeMap[nuid], nuid);
208  AddLink (link);
209  m_linksNumber++;
210  }
211  }
212 
213  NS_LOG_INFO ("Rocketfuel topology created with " << m_nodesNumber << " nodes and " << m_linksNumber << " links");
214 
215  return nodes;
216 }
217 
220 {
221  /* uid @loc [+] [bb] (num_neigh) [&ext] -> <nuid-1> <nuid-2> ... {-euid} ... =name[!] rn */
222  std::string sname;
223  std::string tname;
224  char *endptr;
226 
227  sname = argv[0];
228  tname = argv[1];
229  double v = strtod (argv[2], &endptr); // weight
230  NS_UNUSED (v); // suppress "set but not used" compiler warning in optimized builds
231  if (*endptr != '\0')
232  {
233  NS_LOG_WARN ("invalid weight: " << argv[2]);
234  return nodes;
235  }
236 
237  // Create node and link
238  if (!sname.empty () && !tname.empty ())
239  {
240  if (m_nodeMap[sname] == 0)
241  {
242  Ptr<Node> tmpNode = CreateObject<Node> ();
243  m_nodeMap[sname] = tmpNode;
244  nodes.Add (tmpNode);
245  m_nodesNumber++;
246  }
247 
248  if (m_nodeMap[tname] == 0)
249  {
250  Ptr<Node> tmpNode = CreateObject<Node> ();
251  m_nodeMap[tname] = tmpNode;
252  nodes.Add (tmpNode);
253  m_nodesNumber++;
254  }
255  NS_LOG_INFO (m_linksNumber << ":" << m_nodesNumber << " From: " << sname << " to: " << tname);
257  bool found = false;
258  for (iter = LinksBegin (); iter != LinksEnd (); iter++)
259  {
260  if ((iter->GetFromNode () == m_nodeMap[tname])
261  && (iter->GetToNode () == m_nodeMap[sname]))
262  {
263  found = true;
264  break;
265  }
266  }
267 
268  if (!found)
269  {
270  Link link (m_nodeMap[sname], sname, m_nodeMap[tname], tname);
271  AddLink (link);
272  m_linksNumber++;
273  }
274  }
275 
276  NS_LOG_INFO ("Rocketfuel topology created with " << m_nodesNumber << " nodes and " << m_linksNumber << " links");
277 
278  return nodes;
279 }
280 
283 {
284  int ret;
285  regmatch_t regmatch[REGMATCH_MAX];
286  regex_t regex;
287  char errbuf[512];
288 
289  // Check whether MAPS file or not
290  ret = regcomp (&regex, ROCKETFUEL_MAPS_LINE, REG_EXTENDED | REG_NEWLINE);
291  if (ret != 0)
292  {
293  regerror (ret, &regex, errbuf, sizeof (errbuf));
294  return RF_UNKNOWN;
295  }
296  ret = regexec (&regex, line, REGMATCH_MAX, regmatch, 0);
297  if (ret != REG_NOMATCH)
298  {
299  regfree (&regex);
300  return RF_MAPS;
301  }
302  regfree (&regex);
303 
304  // Check whether Weights file or not
305  ret = regcomp (&regex, ROCKETFUEL_WEIGHTS_LINE, REG_EXTENDED | REG_NEWLINE);
306  if (ret != 0)
307  {
308  regerror (ret, &regex, errbuf, sizeof (errbuf));
309  return RF_UNKNOWN;
310  }
311  ret = regexec (&regex, line, REGMATCH_MAX, regmatch, 0);
312  if (ret != REG_NOMATCH)
313  {
314  regfree (&regex);
315  return RF_WEIGHTS;
316  }
317  regfree (&regex);
318 
319  return RF_UNKNOWN;
320 }
321 
322 
325 {
326  std::ifstream topgen;
327  topgen.open (GetFileName ().c_str ());
329 
330  std::istringstream lineBuffer;
331  std::string line;
332  int lineNumber = 0;
333  enum RF_FileType ftype = RF_UNKNOWN;
334  char errbuf[512];
335 
336  if (!topgen.is_open ())
337  {
338  NS_LOG_WARN ("Couldn't open the file " << GetFileName ());
339  return nodes;
340  }
341 
342  while (!topgen.eof ())
343  {
344  int ret;
345  int argc;
346  char *argv[REGMATCH_MAX];
347  char *buf;
348 
349  lineNumber++;
350  line.clear ();
351  lineBuffer.clear ();
352 
353  getline (topgen, line);
354  buf = (char *)line.c_str ();
355 
356  if (lineNumber == 1)
357  {
358  ftype = GetFileType (buf);
359  if (ftype == RF_UNKNOWN)
360  {
361  NS_LOG_INFO ("Unknown File Format (" << GetFileName () << ")");
362  break;
363  }
364  }
365 
366  regmatch_t regmatch[REGMATCH_MAX];
367  regex_t regex;
368 
369  if (ftype == RF_MAPS)
370  {
371  ret = regcomp (&regex, ROCKETFUEL_MAPS_LINE, REG_EXTENDED | REG_NEWLINE);
372  if (ret != 0)
373  {
374  regerror (ret, &regex, errbuf, sizeof (errbuf));
375  regfree (&regex);
376  break;
377  }
378 
379  ret = regexec (&regex, buf, REGMATCH_MAX, regmatch, 0);
380  if (ret == REG_NOMATCH)
381  {
382  NS_LOG_WARN ("match failed (maps file): %s" << buf);
383  regfree (&regex);
384  break;
385  }
386  }
387  else if (ftype == RF_WEIGHTS)
388  {
389  ret = regcomp (&regex, ROCKETFUEL_WEIGHTS_LINE, REG_EXTENDED | REG_NEWLINE);
390  if (ret != 0)
391  {
392  regerror (ret, &regex, errbuf, sizeof (errbuf));
393  regfree (&regex);
394  break;
395  }
396 
397  ret = regexec (&regex, buf, REGMATCH_MAX, regmatch, 0);
398  if (ret == REG_NOMATCH)
399  {
400  NS_LOG_WARN ("match failed (weights file): %s" << buf);
401  regfree (&regex);
402  break;
403  }
404  }
405 
406  line = buf;
407  argc = 0;
408 
409  /* regmatch[0] is the entire strings that matched */
410  for (int i = 1; i < REGMATCH_MAX; i++)
411  {
412  if (regmatch[i].rm_so == -1)
413  {
414  argv[i - 1] = NULL;
415  }
416  else
417  {
418  line[regmatch[i].rm_eo] = '\0';
419  argv[i - 1] = &line[regmatch[i].rm_so];
420  argc = i;
421  }
422  }
423 
424  if (ftype == RF_MAPS)
425  {
426  nodes.Add (GenerateFromMapsFile (argc, argv));
427  }
428  else if (ftype == RF_WEIGHTS)
429  {
430  nodes.Add (GenerateFromWeightsFile (argc, argv));
431  }
432  else
433  {
434  NS_LOG_WARN ("Unsupported file format (only Maps/Weights are supported)");
435  }
436 
437  regfree (&regex);
438  }
439 
440 
441  topgen.close ();
442 
443  return nodes;
444 }
445 
446 } /* namespace ns3 */
447 
448 
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:204
#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:280
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:25
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:264
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:915