blob: 972f1d806b24e4c8f1f74f30f400b094ce931ec5 [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"
Alexander Afanasyev0c395372014-12-20 15:54:02 -080032#include "ns3/ndn-fib.hpp"
Alexander Afanasyevad3757f2012-04-17 10:27:59 -070033
34#include "ns3/node.h"
Alexander Afanasyevce810142012-04-17 15:50:36 -070035#include "ns3/node-container.h"
Alexander Afanasyevad3757f2012-04-17 10:27:59 -070036#include "ns3/net-device.h"
37#include "ns3/channel.h"
38#include "ns3/log.h"
39#include "ns3/assert.h"
40#include "ns3/names.h"
41#include "ns3/node-list.h"
42#include "ns3/channel-list.h"
Alexander Afanasyevf5c07742012-10-31 13:13:05 -070043#include "ns3/object-factory.h"
Alexander Afanasyevad3757f2012-04-17 10:27:59 -070044
45#include <boost/lexical_cast.hpp>
Alexander Afanasyev8e2f1122012-04-17 15:01:11 -070046#include <boost/foreach.hpp>
Alexander Afanasyeva5abcd92012-04-17 13:34:43 -070047#include <boost/concept/assert.hpp>
48// #include <boost/graph/graph_concepts.hpp>
49// #include <boost/graph/adjacency_list.hpp>
50#include <boost/graph/dijkstra_shortest_paths.hpp>
51
Alexander Afanasyev0c395372014-12-20 15:54:02 -080052#include "boost-graph-ndn-global-routing-helper.hpp"
Alexander Afanasyevad3757f2012-04-17 10:27:59 -070053
Alexander Afanasyev73532512012-11-27 00:42:35 -080054#include <math.h>
55
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080056NS_LOG_COMPONENT_DEFINE("ndn.GlobalRoutingHelper");
Alexander Afanasyevad3757f2012-04-17 10:27:59 -070057
58using namespace std;
59using namespace boost;
60
61namespace ns3 {
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -070062namespace ndn {
Alexander Afanasyevad3757f2012-04-17 10:27:59 -070063
64void
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080065GlobalRoutingHelper::Install(Ptr<Node> node)
Alexander Afanasyevad3757f2012-04-17 10:27:59 -070066{
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080067 NS_LOG_LOGIC("Node: " << node->GetId());
Alexander Afanasyev49165862013-01-31 00:38:20 -080068
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080069 Ptr<L3Protocol> ndn = node->GetObject<L3Protocol>();
70 NS_ASSERT_MSG(ndn != 0, "Cannot install GlobalRoutingHelper before Ndn is installed on a node");
Alexander Afanasyevad3757f2012-04-17 10:27:59 -070071
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080072 Ptr<GlobalRouter> gr = node->GetObject<GlobalRouter>();
73 if (gr != 0) {
74 NS_LOG_DEBUG("GlobalRouter is already installed: " << gr);
75 return; // already installed
76 }
77
78 gr = CreateObject<GlobalRouter>();
79 node->AggregateObject(gr);
80
81 for (uint32_t faceId = 0; faceId < ndn->GetNFaces(); faceId++) {
82 Ptr<NetDeviceFace> face = DynamicCast<NetDeviceFace>(ndn->GetFace(faceId));
83 if (face == 0) {
84 NS_LOG_DEBUG("Skipping non-netdevice face");
85 continue;
Alexander Afanasyevad3757f2012-04-17 10:27:59 -070086 }
Alexander Afanasyev49165862013-01-31 00:38:20 -080087
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080088 Ptr<NetDevice> nd = face->GetNetDevice();
89 if (nd == 0) {
90 NS_LOG_DEBUG("Not a NetDevice associated with NetDeviceFace");
91 continue;
Alexander Afanasyevad3757f2012-04-17 10:27:59 -070092 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080093
94 Ptr<Channel> ch = nd->GetChannel();
95
96 if (ch == 0) {
97 NS_LOG_DEBUG("Channel is not associated with NetDevice");
98 continue;
99 }
100
101 if (ch->GetNDevices() == 2) // e.g., point-to-point channel
102 {
103 for (uint32_t deviceId = 0; deviceId < ch->GetNDevices(); deviceId++) {
104 Ptr<NetDevice> otherSide = ch->GetDevice(deviceId);
105 if (nd == otherSide)
106 continue;
107
108 Ptr<Node> otherNode = otherSide->GetNode();
109 NS_ASSERT(otherNode != 0);
110
111 Ptr<GlobalRouter> otherGr = otherNode->GetObject<GlobalRouter>();
112 if (otherGr == 0) {
113 Install(otherNode);
114 }
115 otherGr = otherNode->GetObject<GlobalRouter>();
116 NS_ASSERT(otherGr != 0);
117 gr->AddIncidency(face, otherGr);
118 }
119 }
120 else {
121 Ptr<GlobalRouter> grChannel = ch->GetObject<GlobalRouter>();
122 if (grChannel == 0) {
123 Install(ch);
124 }
125 grChannel = ch->GetObject<GlobalRouter>();
126
127 gr->AddIncidency(face, grChannel);
128 }
129 }
Alexander Afanasyevad3757f2012-04-17 10:27:59 -0700130}
131
132void
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800133GlobalRoutingHelper::Install(Ptr<Channel> channel)
Alexander Afanasyevad3757f2012-04-17 10:27:59 -0700134{
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800135 NS_LOG_LOGIC("Channel: " << channel->GetId());
Alexander Afanasyevad3757f2012-04-17 10:27:59 -0700136
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800137 Ptr<GlobalRouter> gr = channel->GetObject<GlobalRouter>();
Alexander Afanasyevad3757f2012-04-17 10:27:59 -0700138 if (gr != 0)
139 return;
140
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800141 gr = CreateObject<GlobalRouter>();
142 channel->AggregateObject(gr);
Alexander Afanasyev49165862013-01-31 00:38:20 -0800143
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800144 for (uint32_t deviceId = 0; deviceId < channel->GetNDevices(); deviceId++) {
145 Ptr<NetDevice> dev = channel->GetDevice(deviceId);
Alexander Afanasyevad3757f2012-04-17 10:27:59 -0700146
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800147 Ptr<Node> node = dev->GetNode();
148 NS_ASSERT(node != 0);
Alexander Afanasyevad3757f2012-04-17 10:27:59 -0700149
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800150 Ptr<GlobalRouter> grOther = node->GetObject<GlobalRouter>();
151 if (grOther == 0) {
152 Install(node);
Alexander Afanasyevad3757f2012-04-17 10:27:59 -0700153 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800154 grOther = node->GetObject<GlobalRouter>();
155 NS_ASSERT(grOther != 0);
156
157 gr->AddIncidency(0, grOther);
158 }
Alexander Afanasyevad3757f2012-04-17 10:27:59 -0700159}
160
161void
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800162GlobalRoutingHelper::Install(const NodeContainer& nodes)
Alexander Afanasyevce810142012-04-17 15:50:36 -0700163{
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800164 for (NodeContainer::Iterator node = nodes.Begin(); node != nodes.End(); node++) {
165 Install(*node);
166 }
167}
168
169void
170GlobalRoutingHelper::InstallAll()
171{
172 Install(NodeContainer::GetGlobal());
173}
174
175void
176GlobalRoutingHelper::AddOrigin(const std::string& prefix, Ptr<Node> node)
177{
178 Ptr<GlobalRouter> gr = node->GetObject<GlobalRouter>();
179 NS_ASSERT_MSG(gr != 0, "GlobalRouter is not installed on the node");
180
Spyridon Mastorakis53e922f2014-10-17 17:29:26 -0700181 auto name = make_shared<Name>(prefix);
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800182 gr->AddLocalPrefix(name);
183}
184
185void
186GlobalRoutingHelper::AddOrigins(const std::string& prefix, const NodeContainer& nodes)
187{
188 for (NodeContainer::Iterator node = nodes.Begin(); node != nodes.End(); node++) {
189 AddOrigin(prefix, *node);
190 }
191}
192
193void
194GlobalRoutingHelper::AddOrigin(const std::string& prefix, const std::string& nodeName)
195{
196 Ptr<Node> node = Names::Find<Node>(nodeName);
197 NS_ASSERT_MSG(node != 0, nodeName << "is not a Node");
198
199 AddOrigin(prefix, node);
200}
201
202void
203GlobalRoutingHelper::AddOriginsForAll()
204{
205 for (NodeList::Iterator node = NodeList::Begin(); node != NodeList::End(); node++) {
206 Ptr<GlobalRouter> gr = (*node)->GetObject<GlobalRouter>();
207 string name = Names::FindName(*node);
208
209 if (gr != 0 && !name.empty()) {
210 AddOrigin("/" + name, *node);
Alexander Afanasyevce810142012-04-17 15:50:36 -0700211 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800212 }
Alexander Afanasyevce810142012-04-17 15:50:36 -0700213}
214
215void
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800216GlobalRoutingHelper::CalculateRoutes(bool invalidatedRoutes /* = true*/)
Alexander Afanasyevad3757f2012-04-17 10:27:59 -0700217{
Alexander Afanasyev8e2f1122012-04-17 15:01:11 -0700218 /**
219 * Implementation of route calculation is heavily based on Boost Graph Library
220 * See http://www.boost.org/doc/libs/1_49_0/libs/graph/doc/table_of_contents.html for more details
221 */
Alexander Afanasyev49165862013-01-31 00:38:20 -0800222
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800223 BOOST_CONCEPT_ASSERT((VertexListGraphConcept<NdnGlobalRouterGraph>));
224 BOOST_CONCEPT_ASSERT((IncidenceGraphConcept<NdnGlobalRouterGraph>));
Alexander Afanasyev49165862013-01-31 00:38:20 -0800225
Alexander Afanasyev4aac5572012-08-09 10:49:55 -0700226 NdnGlobalRouterGraph graph;
Zongyi Zhaoc8372632014-04-28 15:36:49 -0700227 // typedef graph_traits < NdnGlobalRouterGraph >::vertex_descriptor vertex_descriptor;
Alexander Afanasyevad3757f2012-04-17 10:27:59 -0700228
Alexander Afanasyev8e2f1122012-04-17 15:01:11 -0700229 // For now we doing Dijkstra for every node. Can be replaced with Bellman-Ford or Floyd-Warshall.
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800230 // Other algorithms should be faster, but they need additional EdgeListGraph concept provided by
231 // the graph, which
Alexander Afanasyev8e2f1122012-04-17 15:01:11 -0700232 // is not obviously how implement in an efficient manner
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800233 for (NodeList::Iterator node = NodeList::Begin(); node != NodeList::End(); node++) {
234 Ptr<GlobalRouter> source = (*node)->GetObject<GlobalRouter>();
235 if (source == 0) {
236 NS_LOG_DEBUG("Node " << (*node)->GetId() << " does not export GlobalRouter interface");
237 continue;
238 }
Alexander Afanasyev49165862013-01-31 00:38:20 -0800239
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800240 DistancesMap distances;
Alexander Afanasyevad3757f2012-04-17 10:27:59 -0700241
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800242 dijkstra_shortest_paths(graph, source,
243 // predecessor_map (boost::ref(predecessors))
244 // .
245 distance_map(boost::ref(distances))
246 .distance_inf(WeightInf)
247 .distance_zero(WeightZero)
248 .distance_compare(boost::WeightCompare())
249 .distance_combine(boost::WeightCombine()));
250
251 // NS_LOG_DEBUG (predecessors.size () << ", " << distances.size ());
252
253 Ptr<Fib> fib = source->GetObject<Fib>();
254 if (invalidatedRoutes) {
255 fib->InvalidateAll();
256 }
257 NS_ASSERT(fib != 0);
258
259 NS_LOG_DEBUG("Reachability from Node: " << source->GetObject<Node>()->GetId());
260 for (DistancesMap::iterator i = distances.begin(); i != distances.end(); i++) {
261 if (i->first == source)
262 continue;
263 else {
264 // cout << " Node " << i->first->GetObject<Node> ()->GetId ();
265 if (i->second.get<0>() == 0) {
266 // cout << " is unreachable" << endl;
267 }
268 else {
Spyridon Mastorakis53e922f2014-10-17 17:29:26 -0700269 BOOST_FOREACH (const std::shared_ptr<const Name>& prefix, i->first->GetLocalPrefixes()) {
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800270 NS_LOG_DEBUG(" prefix " << prefix << " reachable via face " << *i->second.get<0>()
271 << " with distance " << i->second.get<1>() << " with delay "
272 << i->second.get<2>());
273
274 Ptr<fib::Entry> entry = fib->Add(prefix, i->second.get<0>(), i->second.get<1>());
275 entry->SetRealDelayToProducer(i->second.get<0>(), Seconds(i->second.get<2>()));
276
277 Ptr<Limits> faceLimits = i->second.get<0>()->GetObject<Limits>();
278
279 Ptr<Limits> fibLimits = entry->GetObject<Limits>();
280 if (fibLimits != 0) {
281 // if it was created by the forwarding strategy via DidAddFibEntry event
282 fibLimits->SetLimits(faceLimits->GetMaxRate(), 2 * i->second.get<2>() /*exact RTT*/);
283 NS_LOG_DEBUG("Set limit for prefix "
284 << *prefix << " " << faceLimits->GetMaxRate() << " / "
285 << 2 * i->second.get<2>() << "s ("
286 << faceLimits->GetMaxRate() * 2 * i->second.get<2>() << ")");
287 }
288 }
289 }
290 }
291 }
292 }
293}
294
295void
296GlobalRoutingHelper::CalculateAllPossibleRoutes(bool invalidatedRoutes /* = true*/)
297{
298 /**
299 * Implementation of route calculation is heavily based on Boost Graph Library
300 * See http://www.boost.org/doc/libs/1_49_0/libs/graph/doc/table_of_contents.html for more details
301 */
302
303 BOOST_CONCEPT_ASSERT((VertexListGraphConcept<NdnGlobalRouterGraph>));
304 BOOST_CONCEPT_ASSERT((IncidenceGraphConcept<NdnGlobalRouterGraph>));
305
306 NdnGlobalRouterGraph graph;
307 // typedef graph_traits < NdnGlobalRouterGraph >::vertex_descriptor vertex_descriptor;
308
309 // For now we doing Dijkstra for every node. Can be replaced with Bellman-Ford or Floyd-Warshall.
310 // Other algorithms should be faster, but they need additional EdgeListGraph concept provided by
311 // the graph, which
312 // is not obviously how implement in an efficient manner
313 for (NodeList::Iterator node = NodeList::Begin(); node != NodeList::End(); node++) {
314 Ptr<GlobalRouter> source = (*node)->GetObject<GlobalRouter>();
315 if (source == 0) {
316 NS_LOG_DEBUG("Node " << (*node)->GetId() << " does not export GlobalRouter interface");
317 continue;
318 }
319
320 Ptr<Fib> fib = source->GetObject<Fib>();
321 if (invalidatedRoutes) {
322 fib->InvalidateAll();
323 }
324 NS_ASSERT(fib != 0);
325
326 NS_LOG_DEBUG("===========");
327 NS_LOG_DEBUG("Reachability from Node: " << source->GetObject<Node>()->GetId() << " ("
328 << Names::FindName(source->GetObject<Node>()) << ")");
329
330 Ptr<L3Protocol> l3 = source->GetObject<L3Protocol>();
331 NS_ASSERT(l3 != 0);
332
333 // remember interface statuses
334 std::vector<uint16_t> originalMetric(l3->GetNFaces());
335 for (uint32_t faceId = 0; faceId < l3->GetNFaces(); faceId++) {
336 originalMetric[faceId] = l3->GetFace(faceId)->GetMetric();
337 l3->GetFace(faceId)
338 ->SetMetric(std::numeric_limits<uint16_t>::max()
339 - 1); // value std::numeric_limits<uint16_t>::max () MUST NOT be used (reserved)
340 }
341
342 for (uint32_t enabledFaceId = 0; enabledFaceId < l3->GetNFaces(); enabledFaceId++) {
343 if (DynamicCast<ndn::NetDeviceFace>(l3->GetFace(enabledFaceId)) == 0)
344 continue;
345
346 // enabling only faceId
347 l3->GetFace(enabledFaceId)->SetMetric(originalMetric[enabledFaceId]);
348
349 DistancesMap distances;
350
351 NS_LOG_DEBUG("-----------");
352
353 dijkstra_shortest_paths(graph, source,
354 // predecessor_map (boost::ref(predecessors))
355 // .
356 distance_map(boost::ref(distances))
357 .distance_inf(WeightInf)
358 .distance_zero(WeightZero)
359 .distance_compare(boost::WeightCompare())
360 .distance_combine(boost::WeightCombine()));
Alexander Afanasyevad3757f2012-04-17 10:27:59 -0700361
Alexander Afanasyeva5abcd92012-04-17 13:34:43 -0700362 // NS_LOG_DEBUG (predecessors.size () << ", " << distances.size ());
Alexander Afanasyev8e2f1122012-04-17 15:01:11 -0700363
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800364 for (DistancesMap::iterator i = distances.begin(); i != distances.end(); i++) {
365 if (i->first == source)
366 continue;
367 else {
368 // cout << " Node " << i->first->GetObject<Node> ()->GetId ();
369 if (i->second.get<0>() == 0) {
370 // cout << " is unreachable" << endl;
371 }
372 else {
Spyridon Mastorakis53e922f2014-10-17 17:29:26 -0700373 BOOST_FOREACH (const std::shared_ptr<const Name>& prefix,
374 i->first->GetLocalPrefixes()) {
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800375 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