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