blob: 0528be37c3cc2fa02b2558f6478579377cfb4994 [file] [log] [blame]
Alexander Afanasyevad3757f2012-04-17 10:27:59 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2/*
3 * Copyright (c) 2011 UCLA
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: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
19 */
20
Alexander Afanasyev3898e1b2013-07-27 12:03:17 -070021#if __clang__
22#pragma clang diagnostic push
23#pragma clang diagnostic ignored "-Wunused-variable"
24#pragma clang diagnostic ignored "-Wunneeded-internal-declaration"
25#endif
26
Alexander Afanasyev0c395372014-12-20 15:54:02 -080027#include "ndn-global-routing-helper.hpp"
Alexander Afanasyevad3757f2012-04-17 10:27:59 -070028
Alexander Afanasyev0c395372014-12-20 15:54:02 -080029#include "ns3/ndn-l3-protocol.hpp"
30#include "../model/ndn-net-device-face.hpp"
31#include "../model/ndn-global-router.hpp"
32#include "ns3/ndn-name.hpp"
33#include "ns3/ndn-fib.hpp"
Alexander Afanasyevad3757f2012-04-17 10:27:59 -070034
35#include "ns3/node.h"
Alexander Afanasyevce810142012-04-17 15:50:36 -070036#include "ns3/node-container.h"
Alexander Afanasyevad3757f2012-04-17 10:27:59 -070037#include "ns3/net-device.h"
38#include "ns3/channel.h"
39#include "ns3/log.h"
40#include "ns3/assert.h"
41#include "ns3/names.h"
42#include "ns3/node-list.h"
43#include "ns3/channel-list.h"
Alexander Afanasyevf5c07742012-10-31 13:13:05 -070044#include "ns3/object-factory.h"
Alexander Afanasyevad3757f2012-04-17 10:27:59 -070045
46#include <boost/lexical_cast.hpp>
Alexander Afanasyev8e2f1122012-04-17 15:01:11 -070047#include <boost/foreach.hpp>
Alexander Afanasyeva5abcd92012-04-17 13:34:43 -070048#include <boost/concept/assert.hpp>
49// #include <boost/graph/graph_concepts.hpp>
50// #include <boost/graph/adjacency_list.hpp>
51#include <boost/graph/dijkstra_shortest_paths.hpp>
52
Alexander Afanasyev0c395372014-12-20 15:54:02 -080053#include "boost-graph-ndn-global-routing-helper.hpp"
Alexander Afanasyevad3757f2012-04-17 10:27:59 -070054
Alexander Afanasyev73532512012-11-27 00:42:35 -080055#include <math.h>
56
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080057NS_LOG_COMPONENT_DEFINE("ndn.GlobalRoutingHelper");
Alexander Afanasyevad3757f2012-04-17 10:27:59 -070058
59using namespace std;
60using namespace boost;
61
62namespace ns3 {
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -070063namespace ndn {
Alexander Afanasyevad3757f2012-04-17 10:27:59 -070064
65void
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080066GlobalRoutingHelper::Install(Ptr<Node> node)
Alexander Afanasyevad3757f2012-04-17 10:27:59 -070067{
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080068 NS_LOG_LOGIC("Node: " << node->GetId());
Alexander Afanasyev49165862013-01-31 00:38:20 -080069
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080070 Ptr<L3Protocol> ndn = node->GetObject<L3Protocol>();
71 NS_ASSERT_MSG(ndn != 0, "Cannot install GlobalRoutingHelper before Ndn is installed on a node");
Alexander Afanasyevad3757f2012-04-17 10:27:59 -070072
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080073 Ptr<GlobalRouter> gr = node->GetObject<GlobalRouter>();
74 if (gr != 0) {
75 NS_LOG_DEBUG("GlobalRouter is already installed: " << gr);
76 return; // already installed
77 }
78
79 gr = CreateObject<GlobalRouter>();
80 node->AggregateObject(gr);
81
82 for (uint32_t faceId = 0; faceId < ndn->GetNFaces(); faceId++) {
83 Ptr<NetDeviceFace> face = DynamicCast<NetDeviceFace>(ndn->GetFace(faceId));
84 if (face == 0) {
85 NS_LOG_DEBUG("Skipping non-netdevice face");
86 continue;
Alexander Afanasyevad3757f2012-04-17 10:27:59 -070087 }
Alexander Afanasyev49165862013-01-31 00:38:20 -080088
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080089 Ptr<NetDevice> nd = face->GetNetDevice();
90 if (nd == 0) {
91 NS_LOG_DEBUG("Not a NetDevice associated with NetDeviceFace");
92 continue;
Alexander Afanasyevad3757f2012-04-17 10:27:59 -070093 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080094
95 Ptr<Channel> ch = nd->GetChannel();
96
97 if (ch == 0) {
98 NS_LOG_DEBUG("Channel is not associated with NetDevice");
99 continue;
100 }
101
102 if (ch->GetNDevices() == 2) // e.g., point-to-point channel
103 {
104 for (uint32_t deviceId = 0; deviceId < ch->GetNDevices(); deviceId++) {
105 Ptr<NetDevice> otherSide = ch->GetDevice(deviceId);
106 if (nd == otherSide)
107 continue;
108
109 Ptr<Node> otherNode = otherSide->GetNode();
110 NS_ASSERT(otherNode != 0);
111
112 Ptr<GlobalRouter> otherGr = otherNode->GetObject<GlobalRouter>();
113 if (otherGr == 0) {
114 Install(otherNode);
115 }
116 otherGr = otherNode->GetObject<GlobalRouter>();
117 NS_ASSERT(otherGr != 0);
118 gr->AddIncidency(face, otherGr);
119 }
120 }
121 else {
122 Ptr<GlobalRouter> grChannel = ch->GetObject<GlobalRouter>();
123 if (grChannel == 0) {
124 Install(ch);
125 }
126 grChannel = ch->GetObject<GlobalRouter>();
127
128 gr->AddIncidency(face, grChannel);
129 }
130 }
Alexander Afanasyevad3757f2012-04-17 10:27:59 -0700131}
132
133void
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800134GlobalRoutingHelper::Install(Ptr<Channel> channel)
Alexander Afanasyevad3757f2012-04-17 10:27:59 -0700135{
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800136 NS_LOG_LOGIC("Channel: " << channel->GetId());
Alexander Afanasyevad3757f2012-04-17 10:27:59 -0700137
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800138 Ptr<GlobalRouter> gr = channel->GetObject<GlobalRouter>();
Alexander Afanasyevad3757f2012-04-17 10:27:59 -0700139 if (gr != 0)
140 return;
141
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800142 gr = CreateObject<GlobalRouter>();
143 channel->AggregateObject(gr);
Alexander Afanasyev49165862013-01-31 00:38:20 -0800144
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800145 for (uint32_t deviceId = 0; deviceId < channel->GetNDevices(); deviceId++) {
146 Ptr<NetDevice> dev = channel->GetDevice(deviceId);
Alexander Afanasyevad3757f2012-04-17 10:27:59 -0700147
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800148 Ptr<Node> node = dev->GetNode();
149 NS_ASSERT(node != 0);
Alexander Afanasyevad3757f2012-04-17 10:27:59 -0700150
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800151 Ptr<GlobalRouter> grOther = node->GetObject<GlobalRouter>();
152 if (grOther == 0) {
153 Install(node);
Alexander Afanasyevad3757f2012-04-17 10:27:59 -0700154 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800155 grOther = node->GetObject<GlobalRouter>();
156 NS_ASSERT(grOther != 0);
157
158 gr->AddIncidency(0, grOther);
159 }
Alexander Afanasyevad3757f2012-04-17 10:27:59 -0700160}
161
162void
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800163GlobalRoutingHelper::Install(const NodeContainer& nodes)
Alexander Afanasyevce810142012-04-17 15:50:36 -0700164{
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800165 for (NodeContainer::Iterator node = nodes.Begin(); node != nodes.End(); node++) {
166 Install(*node);
167 }
168}
169
170void
171GlobalRoutingHelper::InstallAll()
172{
173 Install(NodeContainer::GetGlobal());
174}
175
176void
177GlobalRoutingHelper::AddOrigin(const std::string& prefix, Ptr<Node> node)
178{
179 Ptr<GlobalRouter> gr = node->GetObject<GlobalRouter>();
180 NS_ASSERT_MSG(gr != 0, "GlobalRouter is not installed on the node");
181
182 Ptr<Name> name = Create<Name>(boost::lexical_cast<Name>(prefix));
183 gr->AddLocalPrefix(name);
184}
185
186void
187GlobalRoutingHelper::AddOrigins(const std::string& prefix, const NodeContainer& nodes)
188{
189 for (NodeContainer::Iterator node = nodes.Begin(); node != nodes.End(); node++) {
190 AddOrigin(prefix, *node);
191 }
192}
193
194void
195GlobalRoutingHelper::AddOrigin(const std::string& prefix, const std::string& nodeName)
196{
197 Ptr<Node> node = Names::Find<Node>(nodeName);
198 NS_ASSERT_MSG(node != 0, nodeName << "is not a Node");
199
200 AddOrigin(prefix, node);
201}
202
203void
204GlobalRoutingHelper::AddOriginsForAll()
205{
206 for (NodeList::Iterator node = NodeList::Begin(); node != NodeList::End(); node++) {
207 Ptr<GlobalRouter> gr = (*node)->GetObject<GlobalRouter>();
208 string name = Names::FindName(*node);
209
210 if (gr != 0 && !name.empty()) {
211 AddOrigin("/" + name, *node);
Alexander Afanasyevce810142012-04-17 15:50:36 -0700212 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800213 }
Alexander Afanasyevce810142012-04-17 15:50:36 -0700214}
215
216void
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800217GlobalRoutingHelper::CalculateRoutes(bool invalidatedRoutes /* = true*/)
Alexander Afanasyevad3757f2012-04-17 10:27:59 -0700218{
Alexander Afanasyev8e2f1122012-04-17 15:01:11 -0700219 /**
220 * Implementation of route calculation is heavily based on Boost Graph Library
221 * See http://www.boost.org/doc/libs/1_49_0/libs/graph/doc/table_of_contents.html for more details
222 */
Alexander Afanasyev49165862013-01-31 00:38:20 -0800223
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800224 BOOST_CONCEPT_ASSERT((VertexListGraphConcept<NdnGlobalRouterGraph>));
225 BOOST_CONCEPT_ASSERT((IncidenceGraphConcept<NdnGlobalRouterGraph>));
Alexander Afanasyev49165862013-01-31 00:38:20 -0800226
Alexander Afanasyev4aac5572012-08-09 10:49:55 -0700227 NdnGlobalRouterGraph graph;
Zongyi Zhaoc8372632014-04-28 15:36:49 -0700228 // typedef graph_traits < NdnGlobalRouterGraph >::vertex_descriptor vertex_descriptor;
Alexander Afanasyevad3757f2012-04-17 10:27:59 -0700229
Alexander Afanasyev8e2f1122012-04-17 15:01:11 -0700230 // For now we doing Dijkstra for every node. Can be replaced with Bellman-Ford or Floyd-Warshall.
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800231 // Other algorithms should be faster, but they need additional EdgeListGraph concept provided by
232 // the graph, which
Alexander Afanasyev8e2f1122012-04-17 15:01:11 -0700233 // is not obviously how implement in an efficient manner
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800234 for (NodeList::Iterator node = NodeList::Begin(); node != NodeList::End(); node++) {
235 Ptr<GlobalRouter> source = (*node)->GetObject<GlobalRouter>();
236 if (source == 0) {
237 NS_LOG_DEBUG("Node " << (*node)->GetId() << " does not export GlobalRouter interface");
238 continue;
239 }
Alexander Afanasyev49165862013-01-31 00:38:20 -0800240
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800241 DistancesMap distances;
Alexander Afanasyevad3757f2012-04-17 10:27:59 -0700242
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800243 dijkstra_shortest_paths(graph, source,
244 // predecessor_map (boost::ref(predecessors))
245 // .
246 distance_map(boost::ref(distances))
247 .distance_inf(WeightInf)
248 .distance_zero(WeightZero)
249 .distance_compare(boost::WeightCompare())
250 .distance_combine(boost::WeightCombine()));
251
252 // NS_LOG_DEBUG (predecessors.size () << ", " << distances.size ());
253
254 Ptr<Fib> fib = source->GetObject<Fib>();
255 if (invalidatedRoutes) {
256 fib->InvalidateAll();
257 }
258 NS_ASSERT(fib != 0);
259
260 NS_LOG_DEBUG("Reachability from Node: " << source->GetObject<Node>()->GetId());
261 for (DistancesMap::iterator i = distances.begin(); i != distances.end(); i++) {
262 if (i->first == source)
263 continue;
264 else {
265 // cout << " Node " << i->first->GetObject<Node> ()->GetId ();
266 if (i->second.get<0>() == 0) {
267 // cout << " is unreachable" << endl;
268 }
269 else {
270 BOOST_FOREACH (const Ptr<const Name>& prefix, i->first->GetLocalPrefixes()) {
271 NS_LOG_DEBUG(" prefix " << prefix << " reachable via face " << *i->second.get<0>()
272 << " with distance " << i->second.get<1>() << " with delay "
273 << i->second.get<2>());
274
275 Ptr<fib::Entry> entry = fib->Add(prefix, i->second.get<0>(), i->second.get<1>());
276 entry->SetRealDelayToProducer(i->second.get<0>(), Seconds(i->second.get<2>()));
277
278 Ptr<Limits> faceLimits = i->second.get<0>()->GetObject<Limits>();
279
280 Ptr<Limits> fibLimits = entry->GetObject<Limits>();
281 if (fibLimits != 0) {
282 // if it was created by the forwarding strategy via DidAddFibEntry event
283 fibLimits->SetLimits(faceLimits->GetMaxRate(), 2 * i->second.get<2>() /*exact RTT*/);
284 NS_LOG_DEBUG("Set limit for prefix "
285 << *prefix << " " << faceLimits->GetMaxRate() << " / "
286 << 2 * i->second.get<2>() << "s ("
287 << faceLimits->GetMaxRate() * 2 * i->second.get<2>() << ")");
288 }
289 }
290 }
291 }
292 }
293 }
294}
295
296void
297GlobalRoutingHelper::CalculateAllPossibleRoutes(bool invalidatedRoutes /* = true*/)
298{
299 /**
300 * Implementation of route calculation is heavily based on Boost Graph Library
301 * See http://www.boost.org/doc/libs/1_49_0/libs/graph/doc/table_of_contents.html for more details
302 */
303
304 BOOST_CONCEPT_ASSERT((VertexListGraphConcept<NdnGlobalRouterGraph>));
305 BOOST_CONCEPT_ASSERT((IncidenceGraphConcept<NdnGlobalRouterGraph>));
306
307 NdnGlobalRouterGraph graph;
308 // typedef graph_traits < NdnGlobalRouterGraph >::vertex_descriptor vertex_descriptor;
309
310 // For now we doing Dijkstra for every node. Can be replaced with Bellman-Ford or Floyd-Warshall.
311 // Other algorithms should be faster, but they need additional EdgeListGraph concept provided by
312 // the graph, which
313 // is not obviously how implement in an efficient manner
314 for (NodeList::Iterator node = NodeList::Begin(); node != NodeList::End(); node++) {
315 Ptr<GlobalRouter> source = (*node)->GetObject<GlobalRouter>();
316 if (source == 0) {
317 NS_LOG_DEBUG("Node " << (*node)->GetId() << " does not export GlobalRouter interface");
318 continue;
319 }
320
321 Ptr<Fib> fib = source->GetObject<Fib>();
322 if (invalidatedRoutes) {
323 fib->InvalidateAll();
324 }
325 NS_ASSERT(fib != 0);
326
327 NS_LOG_DEBUG("===========");
328 NS_LOG_DEBUG("Reachability from Node: " << source->GetObject<Node>()->GetId() << " ("
329 << Names::FindName(source->GetObject<Node>()) << ")");
330
331 Ptr<L3Protocol> l3 = source->GetObject<L3Protocol>();
332 NS_ASSERT(l3 != 0);
333
334 // remember interface statuses
335 std::vector<uint16_t> originalMetric(l3->GetNFaces());
336 for (uint32_t faceId = 0; faceId < l3->GetNFaces(); faceId++) {
337 originalMetric[faceId] = l3->GetFace(faceId)->GetMetric();
338 l3->GetFace(faceId)
339 ->SetMetric(std::numeric_limits<uint16_t>::max()
340 - 1); // value std::numeric_limits<uint16_t>::max () MUST NOT be used (reserved)
341 }
342
343 for (uint32_t enabledFaceId = 0; enabledFaceId < l3->GetNFaces(); enabledFaceId++) {
344 if (DynamicCast<ndn::NetDeviceFace>(l3->GetFace(enabledFaceId)) == 0)
345 continue;
346
347 // enabling only faceId
348 l3->GetFace(enabledFaceId)->SetMetric(originalMetric[enabledFaceId]);
349
350 DistancesMap distances;
351
352 NS_LOG_DEBUG("-----------");
353
354 dijkstra_shortest_paths(graph, source,
355 // predecessor_map (boost::ref(predecessors))
356 // .
357 distance_map(boost::ref(distances))
358 .distance_inf(WeightInf)
359 .distance_zero(WeightZero)
360 .distance_compare(boost::WeightCompare())
361 .distance_combine(boost::WeightCombine()));
Alexander Afanasyevad3757f2012-04-17 10:27:59 -0700362
Alexander Afanasyeva5abcd92012-04-17 13:34:43 -0700363 // NS_LOG_DEBUG (predecessors.size () << ", " << distances.size ());
Alexander Afanasyev8e2f1122012-04-17 15:01:11 -0700364
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800365 for (DistancesMap::iterator i = distances.begin(); i != distances.end(); i++) {
366 if (i->first == source)
367 continue;
368 else {
369 // cout << " Node " << i->first->GetObject<Node> ()->GetId ();
370 if (i->second.get<0>() == 0) {
371 // cout << " is unreachable" << endl;
372 }
373 else {
374 BOOST_FOREACH (const Ptr<const Name>& prefix, i->first->GetLocalPrefixes()) {
375 NS_LOG_DEBUG(" prefix " << *prefix << " reachable via face " << *i->second.get<0>()
376 << " with distance " << i->second.get<1>() << " with delay "
377 << i->second.get<2>());
Alexander Afanasyev49165862013-01-31 00:38:20 -0800378
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800379 if (i->second.get<0>()->GetMetric() == std::numeric_limits<uint16_t>::max() - 1)
Alexander Afanasyevf484fb92013-03-04 10:37:27 -0800380 continue;
Alexander Afanasyevf484fb92013-03-04 10:37:27 -0800381
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800382 Ptr<fib::Entry> entry = fib->Add(prefix, i->second.get<0>(), i->second.get<1>());
383 entry->SetRealDelayToProducer(i->second.get<0>(), Seconds(i->second.get<2>()));
Alexander Afanasyevf484fb92013-03-04 10:37:27 -0800384
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800385 Ptr<Limits> faceLimits = i->second.get<0>()->GetObject<Limits>();
Alexander Afanasyevf484fb92013-03-04 10:37:27 -0800386
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800387 Ptr<Limits> fibLimits = entry->GetObject<Limits>();
388 if (fibLimits != 0) {
389 // if it was created by the forwarding strategy via DidAddFibEntry event
390 fibLimits->SetLimits(faceLimits->GetMaxRate(),
391 2 * i->second.get<2>() /*exact RTT*/);
392 NS_LOG_DEBUG("Set limit for prefix "
393 << *prefix << " " << faceLimits->GetMaxRate() << " / "
394 << 2 * i->second.get<2>() << "s ("
395 << faceLimits->GetMaxRate() * 2 * i->second.get<2>() << ")");
396 }
Alexander Afanasyevf484fb92013-03-04 10:37:27 -0800397 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800398 }
Alexander Afanasyevf484fb92013-03-04 10:37:27 -0800399 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800400 }
Alexander Afanasyevf484fb92013-03-04 10:37:27 -0800401
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800402 // disabling the face again
403 l3->GetFace(enabledFaceId)->SetMetric(std::numeric_limits<uint16_t>::max() - 1);
Alexander Afanasyevf484fb92013-03-04 10:37:27 -0800404 }
Alexander Afanasyevf484fb92013-03-04 10:37:27 -0800405
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800406 // recover original interface statuses
407 for (uint32_t faceId = 0; faceId < l3->GetNFaces(); faceId++) {
408 l3->GetFace(faceId)->SetMetric(originalMetric[faceId]);
409 }
410 }
411}
Alexander Afanasyevad3757f2012-04-17 10:27:59 -0700412
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -0700413} // namespace ndn
414} // namespace ns3