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