blob: 67559d50f377dff3d831e47e085137d91ee8bd27 [file] [log] [blame]
Ilya Moiseenko58d26672011-12-08 13:48:06 -08001/* -*- 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 * Ilya Moiseenko <iliamo@cs.ucla.edu>
20 */
21
22#include <fstream>
23#include <cstdlib>
24#include <iostream>
25#include <sstream>
26#include <regex.h>
27
28#include "ns3/log.h"
29#include "rocketfuel-weights-reader.h"
30
31namespace ns3 {
32
33 NS_LOG_COMPONENT_DEFINE ("RocketfuelWeightsReader");
34
35 NS_OBJECT_ENSURE_REGISTERED (RocketfuelWeightsReader);
36
37 TypeId RocketfuelWeightsReader::GetTypeId (void)
38 {
39 static TypeId tid = TypeId ("ns3::RocketfuelWeightsReader")
40 .SetParent<Object> ()
41 ;
42 return tid;
43 }
44
45 RocketfuelWeightsReader::RocketfuelWeightsReader ()
46 {
47 NS_LOG_FUNCTION (this);
48 }
49
50 RocketfuelWeightsReader::~RocketfuelWeightsReader ()
51 {
52 NS_LOG_FUNCTION (this);
53 }
54
55 /* uid @loc [+] [bb] (num_neigh) [&ext] -> <nuid-1> <nuid-2> ... {-euid} ... =name[!] rn */
56
57#define REGMATCH_MAX 16
58
59#define START "^"
60#define END "$"
61#define SPACE "[ \t]+"
62#define MAYSPACE "[ \t]*"
63
64#define ROCKETFUEL_MAPS_LINE \
65START "(-*[0-9]+)" SPACE "(@[?A-Za-z0-9,+]+)" SPACE \
66"(\\+)*" MAYSPACE "(bb)*" MAYSPACE \
67"\\(([0-9]+)\\)" SPACE "(&[0-9]+)*" MAYSPACE \
68"->" MAYSPACE "(<[0-9 \t<>]+>)*" MAYSPACE \
69"(\\{-[0-9\\{\\} \t-]+\\})*" SPACE \
70"=([A-Za-z0-9.!-]+)" SPACE "r([0-9])" \
71MAYSPACE END
72
73#define ROCKETFUEL_WEIGHTS_LINE \
74START "([^ \t]+)" SPACE "([^ \t]+)" SPACE "([0-9.]+)" MAYSPACE END
75
76 int linksNumber = 0;
77 int nodesNumber = 0;
78 std::map<std::string, Ptr<Node> > nodeMap;
79
80 NodeContainer
81 RocketfuelWeightsReader::GenerateFromMapsFile (int argc, char *argv[])
82 {
83 std::string uid;
84 std::string loc;
85 std::string ptr;
86 std::string name;
87 std::string nuid;
88 bool dns = false;
89 bool bb = false;
90 int num_neigh_s = 0;
91 unsigned int num_neigh = 0;
92 int radius = 0;
93 std::vector <std::string> neigh_list;
94 NodeContainer nodes;
95
96 uid = argv[0];
97 loc = argv[1];
98
99 if (argv[2])
100 {
101 dns = true;
102 }
103
104 if (argv[3])
105 {
106 bb = true;
107 }
108
109 num_neigh_s = ::atoi (argv[4]);
110 if (num_neigh_s < 0)
111 {
112 num_neigh = 0;
113 NS_LOG_WARN ("Negative number of neighbors given");
114 }
115 else
116 {
117 num_neigh = num_neigh_s;
118 }
119
120 /* neighbors */
121 if (argv[6])
122 {
123 char *nbr;
124 char *stringp = argv[6];
125 while ((nbr = strsep (&stringp, " \t")) != NULL)
126 {
127 nbr[strlen (nbr) - 1] = '\0';
128 neigh_list.push_back (nbr + 1);
129 }
130 }
131 if (num_neigh != neigh_list.size ())
132 {
133 NS_LOG_WARN ("Given number of neighbors = " << num_neigh << " != size of neighbors list = " << neigh_list.size ());
134 }
135
136 /* externs */
137 if (argv[7])
138 {
139 // euid = argv[7];
140 }
141
142 /* name */
143 if (argv[8])
144 {
145 name = argv[8];
146 }
147
148 radius = ::atoi (&argv[9][1]);
149 if (radius > 0)
150 {
151 return nodes;
152 }
153
154 /* uid @loc [+] [bb] (num_neigh) [&ext] -> <nuid-1> <nuid-2> ... {-euid} ... =name[!] rn */
155 NS_LOG_INFO ("Load Node[" << uid << "]: location: " << loc << " dns: " << dns
156 << " bb: " << bb << " neighbors: " << neigh_list.size ()
157 << "(" << "%d" << ") externals: \"%s\"(%d) "
158 << "name: " << name << " radius: " << radius);
159
160 //cast bb and dns to void, to suppress variable set but not used compiler warning
161 //in optimized builds
162 (void) bb;
163 (void) dns;
164
165 // Create node and link
166 if (!uid.empty ())
167 {
168 if (nodeMap[uid] == 0)
169 {
170 Ptr<Node> tmpNode = CreateObject<Node> ();
171 nodeMap[uid] = tmpNode;
172 nodes.Add (tmpNode);
173 nodesNumber++;
174 }
175
176 for (uint32_t i = 0; i < neigh_list.size (); ++i)
177 {
178 nuid = neigh_list[i];
179
180 if (nuid.empty ())
181 {
182 return nodes;
183 }
184
185 if (nodeMap[nuid] == 0)
186 {
187 Ptr<Node> tmpNode = CreateObject<Node> ();
188 nodeMap[nuid] = tmpNode;
189 nodes.Add (tmpNode);
190 nodesNumber++;
191 }
192 NS_LOG_INFO (linksNumber << ":" << nodesNumber << " From: " << uid << " to: " << nuid);
193 Link link (nodeMap[uid], uid, nodeMap[nuid], nuid);
194 AddLink (link);
195 linksNumber++;
196 }
197 }
198 return nodes;
199 }
200
201 NodeContainer
202 RocketfuelWeightsReader::GenerateFromWeightsFile (int argc, char *argv[])
203 {
204 /* uid @loc [+] [bb] (num_neigh) [&ext] -> <nuid-1> <nuid-2> ... {-euid} ... =name[!] rn */
205 std::string sname;
206 std::string tname;
207 char *endptr;
208 NodeContainer nodes;
209
210 sname = argv[0];
211 tname = argv[1];
212 double v = strtod (argv[2], &endptr); // weight
213 // cast v to void , to suppress 'v' set but not used compiler warning
214 //(void) v;
215
216
217
218 if (*endptr != '\0')
219 {
220 NS_LOG_WARN ("invalid weight: " << argv[2]);
221 return nodes;
222 }
223
224 // Create node and link
225 if (!sname.empty () && !tname.empty ())
226 {
227 if (nodeMap[sname] == 0)
228 {
229 Ptr<Node> tmpNode = CreateObject<Node> ();
230 nodeMap[sname] = tmpNode;
231 nodes.Add (tmpNode);
232 nodesNumber++;
233 }
234
235 if (nodeMap[tname] == 0)
236 {
237 Ptr<Node> tmpNode = CreateObject<Node> ();
238 nodeMap[tname] = tmpNode;
239 nodes.Add (tmpNode);
240 nodesNumber++;
241 }
242 NS_LOG_INFO (linksNumber << ":" << nodesNumber << " From: " << sname << " to: " << tname);
243 TopologyReader::ConstLinksIterator iter;
244 bool found = false;
245 for (iter = LinksBegin (); iter != LinksEnd (); iter++)
246 {
247 if ((iter->GetFromNode () == nodeMap[tname])
248 && (iter->GetToNode () == nodeMap[sname]))
249 {
250 found = true;
251 break;
252 }
253 }
254
255 if (!found)
256 {
257 Link link (nodeMap[sname], sname, nodeMap[tname], tname);
258 std::ostringstream s;
259 s << std::setprecision(2) << v;
260 std::string ss = s.str();
261 link.SetAttribute ("OSPF", ss);
262 AddLink (link);
263 linksNumber++;
264 }
265 }
266 return nodes;
267 }
268
269 enum RocketfuelWeightsReader::RF_FileType
270 RocketfuelWeightsReader::GetFileType (const char *line)
271 {
272 int ret;
273 regmatch_t regmatch[REGMATCH_MAX];
274 regex_t regex;
275 char errbuf[512];
276
277 // Check whether MAPS file or not
278 ret = regcomp (&regex, ROCKETFUEL_MAPS_LINE, REG_EXTENDED | REG_NEWLINE);
279 if (ret != 0)
280 {
281 regerror (ret, &regex, errbuf, sizeof (errbuf));
282 return RF_UNKNOWN;
283 }
284 ret = regexec (&regex, line, REGMATCH_MAX, regmatch, 0);
285 if (ret != REG_NOMATCH)
286 {
287 regfree (&regex);
288 return RF_MAPS;
289 }
290 regfree (&regex);
291
292 // Check whether Weights file or not
293 ret = regcomp (&regex, ROCKETFUEL_WEIGHTS_LINE, REG_EXTENDED | REG_NEWLINE);
294 if (ret != 0)
295 {
296 regerror (ret, &regex, errbuf, sizeof (errbuf));
297 return RF_UNKNOWN;
298 }
299 ret = regexec (&regex, line, REGMATCH_MAX, regmatch, 0);
300 if (ret != REG_NOMATCH)
301 {
302 regfree (&regex);
303 return RF_WEIGHTS;
304 }
305 regfree (&regex);
306
307 return RF_UNKNOWN;
308 }
309
310
311 NodeContainer
312 RocketfuelWeightsReader::Read (void)
313 {
314 std::ifstream topgen;
315 topgen.open (GetFileName ().c_str ());
316 NodeContainer nodes;
317
318 std::istringstream lineBuffer;
319 std::string line;
320 int lineNumber = 0;
321 enum RF_FileType ftype = RF_UNKNOWN;
322 char errbuf[512];
323
324 if (!topgen.is_open ())
325 {
326 NS_LOG_WARN ("Couldn't open the file " << GetFileName ());
327 return nodes;
328 }
329
330 while (!topgen.eof ())
331 {
332 int ret;
333 int argc;
334 char *argv[REGMATCH_MAX];
335 char *buf;
336
337 lineNumber++;
338 line.clear ();
339 lineBuffer.clear ();
340
341 getline (topgen, line);
342 buf = (char *)line.c_str ();
343
344 if (lineNumber == 1)
345 {
346 ftype = GetFileType (buf);
347 if (ftype == RF_UNKNOWN)
348 {
349 NS_LOG_INFO ("Unknown File Format (" << GetFileName () << ")");
350 break;
351 }
352 }
353
354 regmatch_t regmatch[REGMATCH_MAX];
355 regex_t regex;
356
357 if (ftype == RF_MAPS)
358 {
359 ret = regcomp (&regex, ROCKETFUEL_MAPS_LINE, REG_EXTENDED | REG_NEWLINE);
360 if (ret != 0)
361 {
362 regerror (ret, &regex, errbuf, sizeof (errbuf));
363 regfree (&regex);
364 break;
365 }
366
367 ret = regexec (&regex, buf, REGMATCH_MAX, regmatch, 0);
368 if (ret == REG_NOMATCH)
369 {
370 NS_LOG_WARN ("match failed (maps file): %s" << buf);
371 regfree (&regex);
372 break;
373 }
374 }
375 else if (ftype == RF_WEIGHTS)
376 {
377 ret = regcomp (&regex, ROCKETFUEL_WEIGHTS_LINE, REG_EXTENDED | REG_NEWLINE);
378 if (ret != 0)
379 {
380 regerror (ret, &regex, errbuf, sizeof (errbuf));
381 regfree (&regex);
382 break;
383 }
384
385 ret = regexec (&regex, buf, REGMATCH_MAX, regmatch, 0);
386 if (ret == REG_NOMATCH)
387 {
388 NS_LOG_WARN ("match failed (weights file): %s" << buf);
389 regfree (&regex);
390 break;
391 }
392 }
393
394 line = buf;
395 argc = 0;
396
397 /* regmatch[0] is the entire strings that matched */
398 for (int i = 1; i < REGMATCH_MAX; i++)
399 {
400 if (regmatch[i].rm_so == -1)
401 {
402 argv[i - 1] = NULL;
403 }
404 else
405 {
406 line[regmatch[i].rm_eo] = '\0';
407 argv[i - 1] = &line[regmatch[i].rm_so];
408 argc = i;
409 }
410 }
411
412 if (ftype == RF_MAPS)
413 {
414 nodes.Add (GenerateFromMapsFile (argc, argv));
415 }
416 else if (ftype == RF_WEIGHTS)
417 {
418 nodes.Add (GenerateFromWeightsFile (argc, argv));
419 }
420 else
421 {
422 NS_LOG_WARN ("Unsupported file format (only Maps/Weights are supported)");
423 }
424
425 regfree (&regex);
426 }
427
428
429 topgen.close ();
430
431 NS_LOG_INFO ("Rocketfuel topology created with " << nodesNumber << " nodes and " << linksNumber << " links");
432 return nodes;
433 }
434
435
436void
437RocketfuelWeightsReader::ApplySettings(NetDeviceContainer* ndc, NodeContainer* nc)
438{
439 InternetStackHelper stack;
440 Ipv4AddressHelper address;
441 address.SetBase ("10.1.0.0", "255.255.0.0");
442
443 Ipv4GlobalRoutingHelper ipv4RoutingHelper ("ns3::Ipv4GlobalRoutingOrderedNexthops");
444 stack.SetRoutingHelper (ipv4RoutingHelper);
445
446 //This loop passes all links and checks if ipv4 is installed on the node
447 // if not, it installs.
448 // We can't use stack.Install(nc) because in nc there are duplicates and assertion fails
449 TopologyReader::ConstLinksIterator iter;
450 int j = 0;
451 for ( iter = this->LinksBegin (); iter != this->LinksEnd (); iter++, j++ )
452 {
453 NodeContainer twoNodes = nc[j];
454
455 Ptr<Node> nd = twoNodes.Get(0);
456 if(nd==NULL)
457 NS_LOG_INFO("nd = null");
458
459 Ptr<Node> nd2 = twoNodes.Get(1);
460 if(nd2==NULL)
461 NS_LOG_INFO("nd2 = null");
462
463 Ptr<Ipv4> ipv4 = nd->GetObject<Ipv4>();
464 if(ipv4 == 0)
465 {
466 NS_LOG_INFO("ipv4 = null");
467 stack.Install(nd);
468 }
469
470 Ptr<Ipv4> ipv42 = nd2->GetObject<Ipv4>();
471 if(ipv42 == 0)
472 {
473 NS_LOG_INFO("ipv42 = null");
474 stack.Install(nd2);
475 }
476
477 //NS_LOG_INFO("#netdevices = " << nd->GetNDevices());
478 //NS_LOG_INFO("#netdevices = " << nd2->GetNDevices());
479 }
480
481 NS_LOG_INFO("ITER2");
482
483 PointToPointHelper p2p;
484 TopologyReader::ConstLinksIterator iter2;
485 int i = 0;
486 for ( iter2 = this->LinksBegin (); iter2 != this->LinksEnd (); iter2++, i++ )
487 {
488 p2p.SetDeviceAttribute("DataRate", StringValue("9920000Kbps"));
489 p2p.SetChannelAttribute("Delay", StringValue("10ms"));
490 p2p.SetQueue("ns3::DropTailQueue","MaxPackets",StringValue("100"));
491 ndc[i] = p2p.Install(nc[i]);
492
493
494 NodeContainer twoNodes = nc[i];
495
496 Ptr<Node> nd = twoNodes.Get(0);
497 if(nd==NULL)
498 NS_LOG_INFO("nd = null");
499
500
501
502 Ptr<Node> nd2 = twoNodes.Get(1);
503 if(nd2==NULL)
504 NS_LOG_INFO("nd2 = null");
505
506 //NS_LOG_INFO("1");
507 NS_LOG_INFO("#netdevices = " << nd->GetNDevices());
508 NS_LOG_INFO("#netdevices = " << nd2->GetNDevices());
509
510 Ptr<NetDevice> device = nd->GetDevice(nd->GetNDevices()-1)->GetObject<PointToPointNetDevice> ();
511
512 if(device==NULL)
513 NS_LOG_INFO("device = 0");
514
515 std::string ospf = iter2->GetAttribute("OSPF");
516 double metric_d = atof(ospf.c_str());
517 uint16_t metric = static_cast<int>(metric_d * 10);
518 NS_LOG_INFO("OSPF metric = " << metric);
519
520 {
521 NetDeviceContainer* temp = new NetDeviceContainer[1];
522 temp->Add(device);
523 address.Assign (*temp);
524 }
525
526 Ptr<Ipv4> ipv4 = nd->GetObject<Ipv4>();
527 if(ipv4 == 0)
528 {
529 NS_LOG_INFO("ipv4 = null");
530 //stack.Install(nd);
531 /*NetDeviceContainer* temp = new NetDeviceContainer[1];
532 temp->Add(device);
533 address.Assign (*temp);
534 ipv4 = nd->GetObject<Ipv4>();*/
535 }
536
537 NS_LOG_INFO("Before GetID");
538 int32_t interfaceId = ipv4->GetInterfaceForDevice(device);
539 NS_LOG_INFO("InterfaceID = " << interfaceId);
540 ipv4->SetMetric(interfaceId,metric);
541
542
543
544
545
546 /*Ptr<Ipv4> ipv4 = nd->GetObject<Ipv4>();
547
548 if(ipv4 == 0)
549 NS_LOG_INFO("ipv4 = null");
550 int32_t interfaceId = ipv4->GetInterfaceForDevice(device);
551 ipv4->SetMetric(interfaceId,metric);*/
552
553 //Ptr<Ipv4Interface> interface = nd->GetDevice(nd->GetNDevices()-1)->GetObject<Ipv4Interface> ();
554 //ipv4->SetMetric(metric);
555
556 //NS_LOG_INFO("2");
557
558 Ptr<NetDevice> device2 = nd2->GetDevice(nd2->GetNDevices()-1)->GetObject<PointToPointNetDevice> ();
559
560 if(device2==NULL)
561 NS_LOG_INFO("device2 = 0");
562
563 {
564 NetDeviceContainer* temp = new NetDeviceContainer[1];
565 temp->Add(device2);
566 address.Assign (*temp);
567 }
568
569 Ptr<Ipv4> ipv42 = nd2->GetObject<Ipv4>();
570 if(ipv42 == 0)
571 {
572 NS_LOG_INFO("ipv42 = null");
573 /*stack.Install(nd2);
574 NetDeviceContainer* temp = new NetDeviceContainer[1];
575 temp->Add(device2);
576 address.Assign (*temp);
577 ipv42 = nd2->GetObject<Ipv4>();*/
578 }
579
580 NS_LOG_INFO("Before GetID");
581 interfaceId = ipv42->GetInterfaceForDevice(device2);
582 NS_LOG_INFO("InterfaceID = " << interfaceId);
583 ipv42->SetMetric(interfaceId,metric);
584
585
586
587 /*PointerValue tmp1;
588 device->GetAttribute ("TxQueue", tmp1);
589 //NS_LOG_INFO("2.5");
590 Ptr<Object> txQueue1 = tmp1.GetObject ();
591
592 PointerValue tmp2;
593 device2->GetAttribute ("TxQueue", tmp2);
594 Ptr<Object> txQueue2 = tmp2.GetObject ();
595 //NS_LOG_INFO("3");
596 Ptr<DropTailQueue> dtq1 = txQueue1->GetObject <DropTailQueue> ();
597 NS_ASSERT (dtq1 != 0);
598
599 Ptr<DropTailQueue> dtq2 = txQueue2->GetObject <DropTailQueue> ();
600 NS_ASSERT (dtq2 != 0);
601
602 std::string queuesize1 = iter2->GetAttribute("QueueSizeNode1");
603 std::string queuesize2 = iter2->GetAttribute("QueueSizeNode2");
604 //NS_LOG_INFO("4");
605 txQueue1->SetAttribute("MaxPackets", UintegerValue (atoi(queuesize1.c_str())));
606 txQueue2->SetAttribute("MaxPackets", UintegerValue (atoi(queuesize2.c_str())));
607
608 UintegerValue limit;
609 txQueue1->GetAttribute ("MaxPackets", limit);
610 NS_LOG_INFO ("NetDevice #"<< device->GetIfIndex() << "has queue limit " << limit.Get () << " packets");
611
612 txQueue2->GetAttribute ("MaxPackets", limit);
613 NS_LOG_INFO ("NetDevice #"<< device2->GetIfIndex() << "has queue limit " << limit.Get () << " packets");*/
614 }
615 }
616
617
618} /* namespace ns3 */
619
620