blob: 246d1b068d9e8e49cc08f3d8c118b72b820ed7c6 [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
Alexander Afanasyev07827182011-12-13 01:07:32 -080022#include "rocketfuel-weights-reader.h"
23
24#include "ns3/nstime.h"
25#include "ns3/log.h"
26#include "ns3/assert.h"
27#include "ns3/names.h"
28#include "ns3/net-device-container.h"
29#include "ns3/point-to-point-helper.h"
30#include "ns3/point-to-point-net-device.h"
31#include "ns3/internet-stack-helper.h"
32#include "ns3/ipv4-address-helper.h"
33#include "ns3/ipv4-global-routing-helper.h"
34#include "ns3/drop-tail-queue.h"
35#include "ns3/ipv4-interface.h"
36#include "ns3/ipv4.h"
37#include "ns3/string.h"
38#include "ns3/pointer.h"
39#include "ns3/uinteger.h"
40#include "ns3/ipv4-address.h"
41
42#include "ns3/constant-position-mobility-model.h"
43#include "ns3/random-variable.h"
44
Ilya Moiseenko58d26672011-12-08 13:48:06 -080045#include <regex.h>
46
Alexander Afanasyev07827182011-12-13 01:07:32 -080047#include <boost/foreach.hpp>
48#include <boost/lexical_cast.hpp>
49
50#include <iomanip>
51#include <set>
52
Ilya Moiseenko58d26672011-12-08 13:48:06 -080053
54namespace ns3 {
55
56 NS_LOG_COMPONENT_DEFINE ("RocketfuelWeightsReader");
57
58 NS_OBJECT_ENSURE_REGISTERED (RocketfuelWeightsReader);
59
60 TypeId RocketfuelWeightsReader::GetTypeId (void)
61 {
62 static TypeId tid = TypeId ("ns3::RocketfuelWeightsReader")
63 .SetParent<Object> ()
64 ;
65 return tid;
66 }
67
68 RocketfuelWeightsReader::RocketfuelWeightsReader ()
69 {
70 NS_LOG_FUNCTION (this);
71 }
72
73 RocketfuelWeightsReader::~RocketfuelWeightsReader ()
74 {
75 NS_LOG_FUNCTION (this);
76 }
77
78 /* uid @loc [+] [bb] (num_neigh) [&ext] -> <nuid-1> <nuid-2> ... {-euid} ... =name[!] rn */
79
80#define REGMATCH_MAX 16
81
82#define START "^"
83#define END "$"
84#define SPACE "[ \t]+"
85#define MAYSPACE "[ \t]*"
86
87#define ROCKETFUEL_MAPS_LINE \
88START "(-*[0-9]+)" SPACE "(@[?A-Za-z0-9,+]+)" SPACE \
89"(\\+)*" MAYSPACE "(bb)*" MAYSPACE \
90"\\(([0-9]+)\\)" SPACE "(&[0-9]+)*" MAYSPACE \
91"->" MAYSPACE "(<[0-9 \t<>]+>)*" MAYSPACE \
92"(\\{-[0-9\\{\\} \t-]+\\})*" SPACE \
93"=([A-Za-z0-9.!-]+)" SPACE "r([0-9])" \
94MAYSPACE END
95
96#define ROCKETFUEL_WEIGHTS_LINE \
97START "([^ \t]+)" SPACE "([^ \t]+)" SPACE "([0-9.]+)" MAYSPACE END
98
99 int linksNumber = 0;
100 int nodesNumber = 0;
101 std::map<std::string, Ptr<Node> > nodeMap;
102
103 NodeContainer
Ilya Moiseenko09ac8992011-12-12 17:55:42 -0800104 RocketfuelWeightsReader::GenerateFromWeightsFile (int argc, char *argv[], char *argl[])
Ilya Moiseenko58d26672011-12-08 13:48:06 -0800105 {
106 /* uid @loc [+] [bb] (num_neigh) [&ext] -> <nuid-1> <nuid-2> ... {-euid} ... =name[!] rn */
107 std::string sname;
108 std::string tname;
109 char *endptr;
110 NodeContainer nodes;
111
112 sname = argv[0];
113 tname = argv[1];
114 double v = strtod (argv[2], &endptr); // weight
Ilya Moiseenko09ac8992011-12-12 17:55:42 -0800115 double l = strtod (argl[2], &endptr); //latency
Ilya Moiseenko58d26672011-12-08 13:48:06 -0800116 // cast v to void , to suppress 'v' set but not used compiler warning
117 //(void) v;
118
119
120
121 if (*endptr != '\0')
122 {
123 NS_LOG_WARN ("invalid weight: " << argv[2]);
124 return nodes;
125 }
126
127 // Create node and link
128 if (!sname.empty () && !tname.empty ())
129 {
130 if (nodeMap[sname] == 0)
131 {
132 Ptr<Node> tmpNode = CreateObject<Node> ();
133 nodeMap[sname] = tmpNode;
134 nodes.Add (tmpNode);
135 nodesNumber++;
136 }
137
138 if (nodeMap[tname] == 0)
139 {
140 Ptr<Node> tmpNode = CreateObject<Node> ();
141 nodeMap[tname] = tmpNode;
142 nodes.Add (tmpNode);
143 nodesNumber++;
144 }
145 NS_LOG_INFO (linksNumber << ":" << nodesNumber << " From: " << sname << " to: " << tname);
146 TopologyReader::ConstLinksIterator iter;
147 bool found = false;
148 for (iter = LinksBegin (); iter != LinksEnd (); iter++)
149 {
150 if ((iter->GetFromNode () == nodeMap[tname])
151 && (iter->GetToNode () == nodeMap[sname]))
152 {
153 found = true;
154 break;
155 }
156 }
157
158 if (!found)
159 {
160 Link link (nodeMap[sname], sname, nodeMap[tname], tname);
Ilya Moiseenko09ac8992011-12-12 17:55:42 -0800161
Ilya Moiseenko58d26672011-12-08 13:48:06 -0800162 std::ostringstream s;
163 s << std::setprecision(2) << v;
164 std::string ss = s.str();
165 link.SetAttribute ("OSPF", ss);
Ilya Moiseenko09ac8992011-12-12 17:55:42 -0800166
167 std::ostringstream s2;
168 s2 << std::setprecision(2) << l;
169 std::string ss2 = s2.str();
170 link.SetAttribute("Latency", ss2);
171 NS_LOG_INFO("Written Latency = " << ss2);
172
173
Ilya Moiseenko58d26672011-12-08 13:48:06 -0800174 AddLink (link);
175 linksNumber++;
176 }
177 }
178 return nodes;
179 }
180
181 enum RocketfuelWeightsReader::RF_FileType
182 RocketfuelWeightsReader::GetFileType (const char *line)
183 {
184 int ret;
185 regmatch_t regmatch[REGMATCH_MAX];
186 regex_t regex;
187 char errbuf[512];
188
189 // Check whether MAPS file or not
190 ret = regcomp (&regex, ROCKETFUEL_MAPS_LINE, REG_EXTENDED | REG_NEWLINE);
191 if (ret != 0)
192 {
193 regerror (ret, &regex, errbuf, sizeof (errbuf));
194 return RF_UNKNOWN;
195 }
196 ret = regexec (&regex, line, REGMATCH_MAX, regmatch, 0);
197 if (ret != REG_NOMATCH)
198 {
199 regfree (&regex);
200 return RF_MAPS;
201 }
202 regfree (&regex);
203
204 // Check whether Weights file or not
205 ret = regcomp (&regex, ROCKETFUEL_WEIGHTS_LINE, REG_EXTENDED | REG_NEWLINE);
206 if (ret != 0)
207 {
208 regerror (ret, &regex, errbuf, sizeof (errbuf));
209 return RF_UNKNOWN;
210 }
211 ret = regexec (&regex, line, REGMATCH_MAX, regmatch, 0);
212 if (ret != REG_NOMATCH)
213 {
214 regfree (&regex);
215 return RF_WEIGHTS;
216 }
217 regfree (&regex);
218
219 return RF_UNKNOWN;
220 }
221
Ilya Moiseenko58d26672011-12-08 13:48:06 -0800222 NodeContainer
223 RocketfuelWeightsReader::Read (void)
224 {
Ilya Moiseenko09ac8992011-12-12 17:55:42 -0800225 NodeContainer nodes;
226 NS_LOG_INFO("Not implemented");
227 return nodes;
228 }
229
230 NodeContainer
231 RocketfuelWeightsReader::Read (std::string latenciesFile)
232 {
Ilya Moiseenko58d26672011-12-08 13:48:06 -0800233 std::ifstream topgen;
234 topgen.open (GetFileName ().c_str ());
235 NodeContainer nodes;
236
Ilya Moiseenko09ac8992011-12-12 17:55:42 -0800237 std::ifstream latencies;
238 latencies.open(latenciesFile.c_str());
239
Ilya Moiseenko58d26672011-12-08 13:48:06 -0800240 std::istringstream lineBuffer;
Ilya Moiseenko09ac8992011-12-12 17:55:42 -0800241 std::istringstream lineBuffer2;
Ilya Moiseenko58d26672011-12-08 13:48:06 -0800242 std::string line;
Ilya Moiseenko09ac8992011-12-12 17:55:42 -0800243 std::string line2;
244
Ilya Moiseenko58d26672011-12-08 13:48:06 -0800245 int lineNumber = 0;
246 enum RF_FileType ftype = RF_UNKNOWN;
247 char errbuf[512];
248
249 if (!topgen.is_open ())
250 {
251 NS_LOG_WARN ("Couldn't open the file " << GetFileName ());
252 return nodes;
253 }
254
Ilya Moiseenko09ac8992011-12-12 17:55:42 -0800255 if (!latencies.is_open ())
256 {
257 NS_LOG_WARN ("Couldn't open Latencies file " << latenciesFile);
258 return nodes;
259 }
260
Ilya Moiseenko58d26672011-12-08 13:48:06 -0800261 while (!topgen.eof ())
262 {
263 int ret;
264 int argc;
265 char *argv[REGMATCH_MAX];
Ilya Moiseenko09ac8992011-12-12 17:55:42 -0800266 char *argl[REGMATCH_MAX];
Ilya Moiseenko58d26672011-12-08 13:48:06 -0800267 char *buf;
Ilya Moiseenko09ac8992011-12-12 17:55:42 -0800268 char *buf2;
Ilya Moiseenko58d26672011-12-08 13:48:06 -0800269
270 lineNumber++;
271 line.clear ();
Ilya Moiseenko09ac8992011-12-12 17:55:42 -0800272 line2.clear ();
Ilya Moiseenko58d26672011-12-08 13:48:06 -0800273 lineBuffer.clear ();
Ilya Moiseenko09ac8992011-12-12 17:55:42 -0800274 lineBuffer2.clear ();
Ilya Moiseenko58d26672011-12-08 13:48:06 -0800275
276 getline (topgen, line);
Ilya Moiseenko09ac8992011-12-12 17:55:42 -0800277 getline (latencies, line2);
Ilya Moiseenko58d26672011-12-08 13:48:06 -0800278 buf = (char *)line.c_str ();
Ilya Moiseenko09ac8992011-12-12 17:55:42 -0800279 buf2 = (char *)line2.c_str ();
Ilya Moiseenko58d26672011-12-08 13:48:06 -0800280
281 if (lineNumber == 1)
282 {
283 ftype = GetFileType (buf);
284 if (ftype == RF_UNKNOWN)
285 {
286 NS_LOG_INFO ("Unknown File Format (" << GetFileName () << ")");
287 break;
288 }
289 }
290
291 regmatch_t regmatch[REGMATCH_MAX];
292 regex_t regex;
293
294 if (ftype == RF_MAPS)
295 {
296 ret = regcomp (&regex, ROCKETFUEL_MAPS_LINE, REG_EXTENDED | REG_NEWLINE);
297 if (ret != 0)
298 {
299 regerror (ret, &regex, errbuf, sizeof (errbuf));
300 regfree (&regex);
301 break;
302 }
303
304 ret = regexec (&regex, buf, REGMATCH_MAX, regmatch, 0);
305 if (ret == REG_NOMATCH)
306 {
307 NS_LOG_WARN ("match failed (maps file): %s" << buf);
308 regfree (&regex);
309 break;
310 }
311 }
312 else if (ftype == RF_WEIGHTS)
313 {
314 ret = regcomp (&regex, ROCKETFUEL_WEIGHTS_LINE, REG_EXTENDED | REG_NEWLINE);
315 if (ret != 0)
316 {
317 regerror (ret, &regex, errbuf, sizeof (errbuf));
318 regfree (&regex);
319 break;
320 }
321
322 ret = regexec (&regex, buf, REGMATCH_MAX, regmatch, 0);
Ilya Moiseenko09ac8992011-12-12 17:55:42 -0800323 regexec (&regex, buf2, REGMATCH_MAX, regmatch, 0);
Ilya Moiseenko58d26672011-12-08 13:48:06 -0800324 if (ret == REG_NOMATCH)
325 {
326 NS_LOG_WARN ("match failed (weights file): %s" << buf);
327 regfree (&regex);
328 break;
329 }
330 }
331
332 line = buf;
Ilya Moiseenko09ac8992011-12-12 17:55:42 -0800333 line2 = buf2;
Ilya Moiseenko58d26672011-12-08 13:48:06 -0800334 argc = 0;
335
336 /* regmatch[0] is the entire strings that matched */
337 for (int i = 1; i < REGMATCH_MAX; i++)
338 {
339 if (regmatch[i].rm_so == -1)
340 {
341 argv[i - 1] = NULL;
Ilya Moiseenko09ac8992011-12-12 17:55:42 -0800342 argl[i - 1] = NULL;
Ilya Moiseenko58d26672011-12-08 13:48:06 -0800343 }
344 else
345 {
346 line[regmatch[i].rm_eo] = '\0';
Ilya Moiseenko09ac8992011-12-12 17:55:42 -0800347 line2[regmatch[i].rm_eo] = '\0';
Ilya Moiseenko58d26672011-12-08 13:48:06 -0800348 argv[i - 1] = &line[regmatch[i].rm_so];
Ilya Moiseenko09ac8992011-12-12 17:55:42 -0800349 argl[i - 1] = &line2[regmatch[i].rm_so];
Ilya Moiseenko58d26672011-12-08 13:48:06 -0800350 argc = i;
351 }
352 }
353
354 if (ftype == RF_MAPS)
355 {
Ilya Moiseenko09ac8992011-12-12 17:55:42 -0800356 NS_LOG_INFO("MAPS FILE is not supported");
357 //nodes.Add (GenerateFromMapsFile (argc, argv));
Ilya Moiseenko58d26672011-12-08 13:48:06 -0800358 }
359 else if (ftype == RF_WEIGHTS)
360 {
Ilya Moiseenko09ac8992011-12-12 17:55:42 -0800361 nodes.Add (GenerateFromWeightsFile (argc, argv, argl));
Ilya Moiseenko58d26672011-12-08 13:48:06 -0800362 }
363 else
364 {
365 NS_LOG_WARN ("Unsupported file format (only Maps/Weights are supported)");
366 }
367
368 regfree (&regex);
369 }
370
371
372 topgen.close ();
Ilya Moiseenko09ac8992011-12-12 17:55:42 -0800373 latencies.close ();
Ilya Moiseenko58d26672011-12-08 13:48:06 -0800374 NS_LOG_INFO ("Rocketfuel topology created with " << nodesNumber << " nodes and " << linksNumber << " links");
375 return nodes;
376 }
377
378
379void
380RocketfuelWeightsReader::ApplySettings(NetDeviceContainer* ndc, NodeContainer* nc)
381{
382 InternetStackHelper stack;
383 Ipv4AddressHelper address;
384 address.SetBase ("10.1.0.0", "255.255.0.0");
385
386 Ipv4GlobalRoutingHelper ipv4RoutingHelper ("ns3::Ipv4GlobalRoutingOrderedNexthops");
387 stack.SetRoutingHelper (ipv4RoutingHelper);
388
389 //This loop passes all links and checks if ipv4 is installed on the node
390 // if not, it installs.
391 // We can't use stack.Install(nc) because in nc there are duplicates and assertion fails
392 TopologyReader::ConstLinksIterator iter;
393 int j = 0;
394 for ( iter = this->LinksBegin (); iter != this->LinksEnd (); iter++, j++ )
395 {
396 NodeContainer twoNodes = nc[j];
397
398 Ptr<Node> nd = twoNodes.Get(0);
399 if(nd==NULL)
400 NS_LOG_INFO("nd = null");
401
402 Ptr<Node> nd2 = twoNodes.Get(1);
403 if(nd2==NULL)
404 NS_LOG_INFO("nd2 = null");
405
406 Ptr<Ipv4> ipv4 = nd->GetObject<Ipv4>();
407 if(ipv4 == 0)
408 {
409 NS_LOG_INFO("ipv4 = null");
410 stack.Install(nd);
411 }
412
413 Ptr<Ipv4> ipv42 = nd2->GetObject<Ipv4>();
414 if(ipv42 == 0)
415 {
416 NS_LOG_INFO("ipv42 = null");
417 stack.Install(nd2);
418 }
419
420 //NS_LOG_INFO("#netdevices = " << nd->GetNDevices());
421 //NS_LOG_INFO("#netdevices = " << nd2->GetNDevices());
422 }
423
424 NS_LOG_INFO("ITER2");
425
426 PointToPointHelper p2p;
427 TopologyReader::ConstLinksIterator iter2;
428 int i = 0;
429 for ( iter2 = this->LinksBegin (); iter2 != this->LinksEnd (); iter2++, i++ )
430 {
431 p2p.SetDeviceAttribute("DataRate", StringValue("9920000Kbps"));
Ilya Moiseenko09ac8992011-12-12 17:55:42 -0800432 //p2p.SetChannelAttribute("Delay", StringValue("10ms"));
433 NS_LOG_INFO("Latency = " + iter2->GetAttribute("Latency")+"ms");
434 p2p.SetChannelAttribute("Delay", StringValue(iter2->GetAttribute("Latency")+"ms"));
435
436
Ilya Moiseenko58d26672011-12-08 13:48:06 -0800437 p2p.SetQueue("ns3::DropTailQueue","MaxPackets",StringValue("100"));
438 ndc[i] = p2p.Install(nc[i]);
439
440
441 NodeContainer twoNodes = nc[i];
442
443 Ptr<Node> nd = twoNodes.Get(0);
444 if(nd==NULL)
445 NS_LOG_INFO("nd = null");
446
447
448
449 Ptr<Node> nd2 = twoNodes.Get(1);
450 if(nd2==NULL)
451 NS_LOG_INFO("nd2 = null");
452
453 //NS_LOG_INFO("1");
454 NS_LOG_INFO("#netdevices = " << nd->GetNDevices());
455 NS_LOG_INFO("#netdevices = " << nd2->GetNDevices());
456
457 Ptr<NetDevice> device = nd->GetDevice(nd->GetNDevices()-1)->GetObject<PointToPointNetDevice> ();
458
459 if(device==NULL)
460 NS_LOG_INFO("device = 0");
461
462 std::string ospf = iter2->GetAttribute("OSPF");
463 double metric_d = atof(ospf.c_str());
464 uint16_t metric = static_cast<int>(metric_d * 10);
465 NS_LOG_INFO("OSPF metric = " << metric);
466
467 {
468 NetDeviceContainer* temp = new NetDeviceContainer[1];
469 temp->Add(device);
470 address.Assign (*temp);
471 }
472
473 Ptr<Ipv4> ipv4 = nd->GetObject<Ipv4>();
474 if(ipv4 == 0)
475 {
476 NS_LOG_INFO("ipv4 = null");
477 //stack.Install(nd);
478 /*NetDeviceContainer* temp = new NetDeviceContainer[1];
479 temp->Add(device);
480 address.Assign (*temp);
481 ipv4 = nd->GetObject<Ipv4>();*/
482 }
483
484 NS_LOG_INFO("Before GetID");
485 int32_t interfaceId = ipv4->GetInterfaceForDevice(device);
486 NS_LOG_INFO("InterfaceID = " << interfaceId);
487 ipv4->SetMetric(interfaceId,metric);
488
489
490
491
492
493 /*Ptr<Ipv4> ipv4 = nd->GetObject<Ipv4>();
494
495 if(ipv4 == 0)
496 NS_LOG_INFO("ipv4 = null");
497 int32_t interfaceId = ipv4->GetInterfaceForDevice(device);
498 ipv4->SetMetric(interfaceId,metric);*/
499
500 //Ptr<Ipv4Interface> interface = nd->GetDevice(nd->GetNDevices()-1)->GetObject<Ipv4Interface> ();
501 //ipv4->SetMetric(metric);
502
503 //NS_LOG_INFO("2");
504
505 Ptr<NetDevice> device2 = nd2->GetDevice(nd2->GetNDevices()-1)->GetObject<PointToPointNetDevice> ();
506
507 if(device2==NULL)
508 NS_LOG_INFO("device2 = 0");
509
510 {
511 NetDeviceContainer* temp = new NetDeviceContainer[1];
512 temp->Add(device2);
513 address.Assign (*temp);
514 }
515
516 Ptr<Ipv4> ipv42 = nd2->GetObject<Ipv4>();
517 if(ipv42 == 0)
518 {
519 NS_LOG_INFO("ipv42 = null");
520 /*stack.Install(nd2);
521 NetDeviceContainer* temp = new NetDeviceContainer[1];
522 temp->Add(device2);
523 address.Assign (*temp);
524 ipv42 = nd2->GetObject<Ipv4>();*/
525 }
526
527 NS_LOG_INFO("Before GetID");
528 interfaceId = ipv42->GetInterfaceForDevice(device2);
529 NS_LOG_INFO("InterfaceID = " << interfaceId);
530 ipv42->SetMetric(interfaceId,metric);
531
532
533
534 /*PointerValue tmp1;
535 device->GetAttribute ("TxQueue", tmp1);
536 //NS_LOG_INFO("2.5");
537 Ptr<Object> txQueue1 = tmp1.GetObject ();
538
539 PointerValue tmp2;
540 device2->GetAttribute ("TxQueue", tmp2);
541 Ptr<Object> txQueue2 = tmp2.GetObject ();
542 //NS_LOG_INFO("3");
543 Ptr<DropTailQueue> dtq1 = txQueue1->GetObject <DropTailQueue> ();
544 NS_ASSERT (dtq1 != 0);
545
546 Ptr<DropTailQueue> dtq2 = txQueue2->GetObject <DropTailQueue> ();
547 NS_ASSERT (dtq2 != 0);
548
549 std::string queuesize1 = iter2->GetAttribute("QueueSizeNode1");
550 std::string queuesize2 = iter2->GetAttribute("QueueSizeNode2");
551 //NS_LOG_INFO("4");
552 txQueue1->SetAttribute("MaxPackets", UintegerValue (atoi(queuesize1.c_str())));
553 txQueue2->SetAttribute("MaxPackets", UintegerValue (atoi(queuesize2.c_str())));
554
555 UintegerValue limit;
556 txQueue1->GetAttribute ("MaxPackets", limit);
557 NS_LOG_INFO ("NetDevice #"<< device->GetIfIndex() << "has queue limit " << limit.Get () << " packets");
558
559 txQueue2->GetAttribute ("MaxPackets", limit);
560 NS_LOG_INFO ("NetDevice #"<< device2->GetIfIndex() << "has queue limit " << limit.Get () << " packets");*/
561 }
562 }
563
564
565} /* namespace ns3 */
566
567