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