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 "^"
74 #define END "$"
76 #define SPACE "[ \t]+"
78 #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 
295 RocketfuelTopologyReader::GetFileType (const char *line)
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 
336 NodeContainer
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 
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.
std::list< Link >::const_iterator ConstLinksIterator
Constant iterator to the list of the links.
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.
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:923
#define NS_UNUSED(x)
Mark a local variable as unused.
Definition: unused.h:36
#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.