A Discrete-Event Network Simulator
API
rocketfuel-topology-reader.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010 Hajime Tazaki
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Author: Hajime Tazaki (tazaki@sfc.wide.ad.jp)
18  */
19 
21 
22 #include "ns3/log.h"
23 #include "ns3/names.h"
24 #include "ns3/node-container.h"
25 
26 #include <cstdlib>
27 #include <fstream>
28 #include <iostream>
29 #include <regex>
30 #include <string>
31 
38 namespace ns3
39 {
40 
41 NS_LOG_COMPONENT_DEFINE("RocketfuelTopologyReader");
42 
43 NS_OBJECT_ENSURE_REGISTERED(RocketfuelTopologyReader);
44 
45 TypeId
47 {
48  static TypeId tid = TypeId("ns3::RocketfuelTopologyReader")
50  .SetGroupName("TopologyReader")
51  .AddConstructor<RocketfuelTopologyReader>();
52  return tid;
53 }
54 
56 {
57  m_linksNumber = 0;
58  m_nodesNumber = 0;
59  NS_LOG_FUNCTION(this);
60 }
61 
63 {
64  NS_LOG_FUNCTION(this);
65 }
66 
67 /* uid @loc [+] [bb] (num_neigh) [&ext] -> <nuid-1> <nuid-2> ... {-euid} ... =name[!] rn */
68 
70 #define START "^"
72 #define END "$"
74 #define SPACE "[ \t]+"
76 #define MAYSPACE "[ \t]*"
77 
79 #define ROCKETFUEL_MAPS_LINE \
80  START "(-*[0-9]+)" SPACE "(@[?A-Za-z0-9,+-]+)" SPACE "(\\+)*" MAYSPACE "(bb)*" MAYSPACE \
81  "\\(([0-9]+)\\)" SPACE "(&[0-9]+)*" MAYSPACE "->" MAYSPACE "(<[0-9 \t<>]+>)*" MAYSPACE \
82  "(\\{-[0-9\\{\\} \t-]+\\})*" SPACE "=([A-Za-z0-9.!-]+)" SPACE "r([0-9])" MAYSPACE END
83 
85 #define ROCKETFUEL_WEIGHTS_LINE START "([^ \t]+)" SPACE "([^ \t]+)" SPACE "([0-9.]+)" MAYSPACE END
86 
92 
98 
109 static inline void
110 PrintNodeInfo(std::string& uid,
111  std::string& loc,
112  bool dns,
113  bool bb,
114  std::vector<std::string>::size_type neighListSize,
115  std::string& name,
116  int radius)
117 {
118  /* uid @loc [+] [bb] (num_neigh) [&ext] -> <nuid-1> <nuid-2> ... {-euid} ... =name[!] rn */
119  NS_LOG_INFO("Load Node[" << uid << "]: location: " << loc << " dns: " << dns << " bb: " << bb
120  << " neighbors: " << neighListSize << "("
121  << "%d"
122  << ") externals: \"%s\"(%d) "
123  << "name: " << name << " radius: " << radius);
124 }
125 
126 NodeContainer
127 RocketfuelTopologyReader::GenerateFromMapsFile(const std::vector<std::string>& argv)
128 {
129  std::string uid;
130  std::string loc;
131  std::string ptr;
132  std::string name;
133  bool dns = false;
134  bool bb = false;
135  int num_neigh_s = 0;
136  unsigned int num_neigh = 0;
137  int radius = 0;
138  std::vector<std::string> neigh_list;
140 
141  uid = argv[0];
142  loc = argv[1];
143 
144  if (!argv[2].empty())
145  {
146  dns = true;
147  }
148 
149  if (!argv[3].empty())
150  {
151  bb = true;
152  }
153 
154  num_neigh_s = std::stoi(argv[4]);
155  if (num_neigh_s < 0)
156  {
157  num_neigh = 0;
158  NS_LOG_WARN("Negative number of neighbors given");
159  }
160  else
161  {
162  num_neigh = num_neigh_s;
163  }
164 
165  /* neighbors */
166  if (!argv[6].empty())
167  {
168  // Each line contains a list <.*>[ |\t]<.*>[ |\t]<.*>[ |\t]
169  // First remove < and >
170  std::string temp;
171  std::regex replace_regex("[<|>]");
172  std::regex_replace(std::back_inserter(temp),
173  argv[6].begin(),
174  argv[6].end(),
175  replace_regex,
176  "");
177 
178  // Then split list
179  std::regex split_regex("[ |\t]");
180  std::sregex_token_iterator first{temp.begin(), temp.end(), split_regex, -1};
181  std::sregex_token_iterator last;
182  neigh_list = std::vector<std::string>{first, last};
183  }
184  if (num_neigh != neigh_list.size())
185  {
186  NS_LOG_WARN("Given number of neighbors = " << num_neigh << " != size of neighbors list = "
187  << neigh_list.size());
188  }
189 
190  /* externs */
191  if (!argv[7].empty())
192  {
193  // euid = argv[7];
194  }
195 
196  /* name */
197  if (!argv[8].empty())
198  {
199  name = argv[8];
200  }
201 
202  radius = std::atoi(&argv[9][1]);
203  if (radius > 0)
204  {
205  return nodes;
206  }
207 
208  PrintNodeInfo(uid, loc, dns, bb, neigh_list.size(), name, radius);
209 
210  // Create node and link
211  if (!uid.empty())
212  {
213  if (!m_nodeMap[uid])
214  {
215  Ptr<Node> tmpNode = CreateObject<Node>();
216  std::string nodename = "RocketFuelTopology/NodeName/" + uid;
217  Names::Add(nodename, tmpNode);
218  m_nodeMap[uid] = tmpNode;
219  nodes.Add(tmpNode);
220  m_nodesNumber++;
221  }
222 
223  for (auto& nuid : neigh_list)
224  {
225  if (nuid.empty())
226  {
227  return nodes;
228  }
229 
230  if (!m_nodeMap[nuid])
231  {
232  Ptr<Node> tmpNode = CreateObject<Node>();
233  std::string nodename = "RocketFuelTopology/NodeName/" + nuid;
234  Names::Add(nodename, tmpNode);
235  m_nodeMap[nuid] = tmpNode;
236  nodes.Add(tmpNode);
237  m_nodesNumber++;
238  }
239  NS_LOG_INFO(m_linksNumber << ":" << m_nodesNumber << " From: " << uid
240  << " to: " << nuid);
241  Link link(m_nodeMap[uid], uid, m_nodeMap[nuid], nuid);
242  AddLink(link);
243  m_linksNumber++;
244  }
245  }
246 
247  NS_LOG_INFO("Rocketfuel topology created with " << m_nodesNumber << " nodes and "
248  << m_linksNumber << " links");
249 
250  return nodes;
251 }
252 
254 RocketfuelTopologyReader::GenerateFromWeightsFile(const std::vector<std::string>& argv)
255 {
256  /* uid @loc [+] [bb] (num_neigh) [&ext] -> <nuid-1> <nuid-2> ... {-euid} ... =name[!] rn */
257  std::string sname;
258  std::string tname;
259  std::string::size_type endptr;
261 
262  sname = argv[0];
263  tname = argv[1];
264  std::stod(argv[2], &endptr); // weight
265 
266  if (argv[2].size() != endptr)
267  {
268  NS_LOG_WARN("invalid weight: " << argv[2]);
269  return nodes;
270  }
271 
272  // Create node and link
273  if (!sname.empty() && !tname.empty())
274  {
275  if (!m_nodeMap[sname])
276  {
277  Ptr<Node> tmpNode = CreateObject<Node>();
278  std::string nodename = "RocketFuelTopology/NodeName/" + sname;
279  Names::Add(nodename, tmpNode);
280  m_nodeMap[sname] = tmpNode;
281  nodes.Add(tmpNode);
282  m_nodesNumber++;
283  }
284 
285  if (!m_nodeMap[tname])
286  {
287  Ptr<Node> tmpNode = CreateObject<Node>();
288  std::string nodename = "RocketFuelTopology/NodeName/" + tname;
289  Names::Add(nodename, tmpNode);
290  m_nodeMap[tname] = tmpNode;
291  nodes.Add(tmpNode);
292  m_nodesNumber++;
293  }
294  NS_LOG_INFO(m_linksNumber << ":" << m_nodesNumber << " From: " << sname
295  << " to: " << tname);
297  bool found = false;
298  for (iter = LinksBegin(); iter != LinksEnd(); iter++)
299  {
300  if ((iter->GetFromNode() == m_nodeMap[tname]) &&
301  (iter->GetToNode() == m_nodeMap[sname]))
302  {
303  found = true;
304  break;
305  }
306  }
307 
308  if (!found)
309  {
310  Link link(m_nodeMap[sname], sname, m_nodeMap[tname], tname);
311  AddLink(link);
312  m_linksNumber++;
313  }
314  }
315 
316  NS_LOG_INFO("Rocketfuel topology created with " << m_nodesNumber << " nodes and "
317  << m_linksNumber << " links");
318 
319  return nodes;
320 }
321 
324 {
325  // Check whether Maps file or not
326  std::smatch matches;
327  if (std::regex_match(line, matches, rocketfuel_maps_regex))
328  {
329  return RF_MAPS;
330  }
331 
332  // Check whether Weights file or not
333  if (std::regex_match(line, matches, rocketfuel_weights_regex))
334  {
335  return RF_WEIGHTS;
336  }
337 
338  return RF_UNKNOWN;
339 }
340 
343 {
344  std::ifstream topgen;
345  topgen.open(GetFileName());
347 
348  std::istringstream lineBuffer;
349  std::string line;
350  int lineNumber = 0;
351  RF_FileType ftype = RF_UNKNOWN;
352 
353  if (!topgen.is_open())
354  {
355  NS_LOG_WARN("Couldn't open the file " << GetFileName());
356  return nodes;
357  }
358 
359  while (!topgen.eof())
360  {
361  std::vector<std::string> argv;
362 
363  lineNumber++;
364  line.clear();
365  lineBuffer.clear();
366 
367  getline(topgen, line);
368 
369  if (lineNumber == 1)
370  {
371  ftype = GetFileType(line);
372  if (ftype == RF_UNKNOWN)
373  {
374  NS_LOG_INFO("Unknown File Format (" << GetFileName() << ")");
375  break;
376  }
377  }
378 
379  std::smatch matches;
380 
381  if (ftype == RF_MAPS)
382  {
383  bool ret = std::regex_match(line, matches, rocketfuel_maps_regex);
384  if (!ret || matches.empty())
385  {
386  NS_LOG_WARN("match failed (maps file): %s" << line);
387  break;
388  }
389  }
390  else if (ftype == RF_WEIGHTS)
391  {
392  bool ret = std::regex_match(line, matches, rocketfuel_weights_regex);
393  if (!ret || matches.empty())
394  {
395  NS_LOG_WARN("match failed (weights file): %s" << line);
396  break;
397  }
398  }
399 
400  std::string matched_string;
401 
402  for (auto it = matches.begin() + 1; it != matches.end(); it++)
403  {
404  if (it->matched)
405  {
406  matched_string = it->str();
407  }
408  else
409  {
410  matched_string = "";
411  }
412  argv.push_back(matched_string);
413  }
414 
415  if (ftype == RF_MAPS)
416  {
417  nodes.Add(GenerateFromMapsFile(argv));
418  }
419  else if (ftype == RF_WEIGHTS)
420  {
421  nodes.Add(GenerateFromWeightsFile(argv));
422  }
423  else
424  {
425  NS_LOG_WARN("Unsupported file format (only Maps/Weights are supported)");
426  }
427  }
428 
429  topgen.close();
430 
431  return nodes;
432 }
433 
434 } /* namespace ns3 */
static void Add(std::string name, Ptr< Object > object)
Add the association between the string "name" and the Ptr<Object> obj.
Definition: names.cc:775
keep track of a set of node pointers.
Topology file reader (Rocketfuel-format type).
RF_FileType
Enum of the possible file types.
NodeContainer GenerateFromWeightsFile(const std::vector< std::string > &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).
static TypeId GetTypeId()
Get the type ID.
RF_FileType GetFileType(const std::string &buf)
Classifies the file type according to its content.
NodeContainer GenerateFromMapsFile(const std::vector< std::string > &argv)
Topology read function from a file containing the nodes map.
NodeContainer Read() override
Main topology reading function.
Interface for input file readers management.
void AddLink(Link link)
Adds a link to the topology.
ConstLinksIterator LinksEnd() const
Returns an iterator to the the last link in this block.
std::string GetFileName() const
Returns the input file name.
ConstLinksIterator LinksBegin() const
Returns an iterator to the the first link in this block.
std::list< Link >::const_iterator ConstLinksIterator
Constant iterator to the list of the links.
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:931
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#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:261
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:275
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
NodeContainer nodes
Definition: first.py:1
Every class exported by the ns3 library is enclosed in the ns3 namespace.
static const std::regex rocketfuel_maps_regex(ROCKETFUEL_MAPS_LINE)
Build a Regex object for RocketFuel topology maps file type.
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.
static const std::regex rocketfuel_weights_regex(ROCKETFUEL_WEIGHTS_LINE)
Build a Regex object for RocketFuel topology weights file type.
#define ROCKETFUEL_MAPS_LINE
Regex expression matching a MAP line.
#define ROCKETFUEL_WEIGHTS_LINE
Regex expression matching a WEIGHT line.
ns3::RocketfuelTopologyReader declaration.