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