blob: b214d168960b36a00f6150e6ffb8bb091c033a6c [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
21#include "ccnx-global-routing-helper.h"
22
23#include "ns3/ccnx.h"
24#include "../model/ccnx-net-device-face.h"
25#include "../model/ccnx-global-router.h"
26#include "ns3/ccnx-name-components.h"
Alexander Afanasyev8e2f1122012-04-17 15:01:11 -070027#include "ns3/ccnx-fib.h"
Alexander Afanasyevad3757f2012-04-17 10:27:59 -070028
29#include "ns3/node.h"
30#include "ns3/net-device.h"
31#include "ns3/channel.h"
32#include "ns3/log.h"
33#include "ns3/assert.h"
34#include "ns3/names.h"
35#include "ns3/node-list.h"
36#include "ns3/channel-list.h"
37
38#include <boost/lexical_cast.hpp>
Alexander Afanasyev8e2f1122012-04-17 15:01:11 -070039#include <boost/foreach.hpp>
Alexander Afanasyeva5abcd92012-04-17 13:34:43 -070040#include <boost/concept/assert.hpp>
41// #include <boost/graph/graph_concepts.hpp>
42// #include <boost/graph/adjacency_list.hpp>
43#include <boost/graph/dijkstra_shortest_paths.hpp>
44
Alexander Afanasyevad3757f2012-04-17 10:27:59 -070045#include "boost-graph-ccnx-global-routing-helper.h"
46
47NS_LOG_COMPONENT_DEFINE ("CcnxGlobalRoutingHelper");
48
49using namespace std;
50using namespace boost;
51
52namespace ns3 {
53
54void
55CcnxGlobalRoutingHelper::Install (Ptr<Node> node)
56{
57 NS_LOG_LOGIC ("Node: " << node->GetId ());
58
59 Ptr<Ccnx> ccnx = node->GetObject<Ccnx> ();
60 NS_ASSERT_MSG (ccnx != 0, "Cannot install CcnxGlobalRoutingHelper before Ccnx is installed on a node");
61
62 Ptr<CcnxGlobalRouter> gr = node->GetObject<CcnxGlobalRouter> ();
63 if (gr != 0)
64 {
65 NS_LOG_DEBUG ("CcnxGlobalRouter is already installed: " << gr);
66 return; // already installed
67 }
68
69 gr = CreateObject<CcnxGlobalRouter> ();
70 node->AggregateObject (gr);
71
72 for (uint32_t faceId = 0; faceId < ccnx->GetNFaces (); faceId++)
73 {
74 Ptr<CcnxNetDeviceFace> face = DynamicCast<CcnxNetDeviceFace> (ccnx->GetFace (faceId));
75 if (face == 0)
76 {
77 NS_LOG_DEBUG ("Skipping non-netdevice face");
78 continue;
79 }
80
81 Ptr<NetDevice> nd = face->GetNetDevice ();
82 if (nd == 0)
83 {
84 NS_LOG_DEBUG ("Not a NetDevice associated with CcnxNetDeviceFace");
85 continue;
86 }
87
88 Ptr<Channel> ch = nd->GetChannel ();
89
90 if (ch == 0)
91 {
92 NS_LOG_DEBUG ("Channel is not associated with NetDevice");
93 continue;
94 }
95
96 if (ch->GetNDevices () == 2) // e.g., point-to-point channel
97 {
98 for (uint32_t deviceId = 0; deviceId < ch->GetNDevices (); deviceId ++)
99 {
100 Ptr<NetDevice> otherSide = ch->GetDevice (deviceId);
101 if (nd == otherSide) continue;
102
103 Ptr<Node> otherNode = otherSide->GetNode ();
104 NS_ASSERT (otherNode != 0);
105
106 Ptr<CcnxGlobalRouter> otherGr = otherNode->GetObject<CcnxGlobalRouter> ();
107 if (otherGr == 0)
108 {
109 Install (otherNode);
110 }
111 otherGr = otherNode->GetObject<CcnxGlobalRouter> ();
112 NS_ASSERT (otherGr != 0);
113 gr->AddIncidency (face, otherGr);
114 }
115 }
116 else
117 {
118 Ptr<CcnxGlobalRouter> grChannel = ch->GetObject<CcnxGlobalRouter> ();
119 if (grChannel == 0)
120 {
121 Install (ch);
122 }
123 grChannel = ch->GetObject<CcnxGlobalRouter> ();
124
125 gr->AddIncidency (0, grChannel);
126 }
127 }
128}
129
130void
131CcnxGlobalRoutingHelper::Install (Ptr<Channel> channel)
132{
133 NS_LOG_LOGIC ("Channel: " << channel->GetId ());
134
135 Ptr<CcnxGlobalRouter> gr = channel->GetObject<CcnxGlobalRouter> ();
136 if (gr != 0)
137 return;
138
139 gr = CreateObject<CcnxGlobalRouter> ();
140 channel->AggregateObject (gr);
141
142 for (uint32_t deviceId = 0; deviceId < channel->GetNDevices (); deviceId ++)
143 {
144 Ptr<NetDevice> dev = channel->GetDevice (deviceId);
145
146 Ptr<Node> node = dev->GetNode ();
147 NS_ASSERT (node != 0);
148
149 Ptr<CcnxGlobalRouter> grOther = node->GetObject<CcnxGlobalRouter> ();
150 if (grOther == 0)
151 {
152 Install (node);
153 }
154 grOther = node->GetObject<CcnxGlobalRouter> ();
155 NS_ASSERT (grOther != 0);
156
157 gr->AddIncidency (0, grOther);
158 }
159}
160
161void
162CcnxGlobalRoutingHelper::AddOrigin (const std::string &prefix, Ptr<Node> node)
163{
164 Ptr<CcnxGlobalRouter> gr = node->GetObject<CcnxGlobalRouter> ();
165 NS_ASSERT_MSG (gr != 0,
166 "CcnxGlobalRouter is not installed on the node");
167
168 Ptr<CcnxNameComponents> name = Create<CcnxNameComponents> (boost::lexical_cast<CcnxNameComponents> (prefix));
169 gr->AddLocalPrefix (name);
170}
171
172void
173CcnxGlobalRoutingHelper::AddOrigin (const std::string &prefix, const std::string &nodeName)
174{
175 Ptr<Node> node = Names::Find<Node> (nodeName);
176 NS_ASSERT_MSG (node != 0, nodeName << "is not a Node");
177
178 AddOrigin (prefix, node);
179}
180
Alexander Afanasyevad3757f2012-04-17 10:27:59 -0700181void
182CcnxGlobalRoutingHelper::CalculateRoutes ()
183{
Alexander Afanasyev8e2f1122012-04-17 15:01:11 -0700184 /**
185 * Implementation of route calculation is heavily based on Boost Graph Library
186 * See http://www.boost.org/doc/libs/1_49_0/libs/graph/doc/table_of_contents.html for more details
187 */
188
Alexander Afanasyevad3757f2012-04-17 10:27:59 -0700189 BOOST_CONCEPT_ASSERT(( VertexListGraphConcept< CcnxGlobalRouterGraph > ));
190 BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept< CcnxGlobalRouterGraph > ));
Alexander Afanasyevad3757f2012-04-17 10:27:59 -0700191
192 CcnxGlobalRouterGraph graph;
Alexander Afanasyevad3757f2012-04-17 10:27:59 -0700193 typedef graph_traits < CcnxGlobalRouterGraph >::vertex_descriptor vertex_descriptor;
194
Alexander Afanasyev8e2f1122012-04-17 15:01:11 -0700195 // For now we doing Dijkstra for every node. Can be replaced with Bellman-Ford or Floyd-Warshall.
196 // Other algorithms should be faster, but they need additional EdgeListGraph concept provided by the graph, which
197 // is not obviously how implement in an efficient manner
Alexander Afanasyeva5abcd92012-04-17 13:34:43 -0700198 for (NodeList::Iterator node = NodeList::Begin (); node != NodeList::End (); node++)
199 {
200 Ptr<CcnxGlobalRouter> source = (*node)->GetObject<CcnxGlobalRouter> ();
201 if (source == 0)
202 {
203 NS_LOG_DEBUG ("Node " << (*node)->GetId () << " does not export CcnxGlobalRouter interface");
204 continue;
205 }
Alexander Afanasyevad3757f2012-04-17 10:27:59 -0700206
Alexander Afanasyeva5abcd92012-04-17 13:34:43 -0700207 DistancesMap distances;
Alexander Afanasyevad3757f2012-04-17 10:27:59 -0700208
Alexander Afanasyeva5abcd92012-04-17 13:34:43 -0700209 dijkstra_shortest_paths (graph, source,
210 // predecessor_map (boost::ref(predecessors))
211 // .
212 distance_map (boost::ref(distances))
213 .
214 distance_inf (WeightInf)
215 .
216 distance_zero (WeightZero)
217 .
218 distance_compare (boost::WeightCompare ())
219 .
220 distance_combine (boost::WeightCombine ())
221 );
Alexander Afanasyevad3757f2012-04-17 10:27:59 -0700222
Alexander Afanasyeva5abcd92012-04-17 13:34:43 -0700223 // NS_LOG_DEBUG (predecessors.size () << ", " << distances.size ());
Alexander Afanasyev8e2f1122012-04-17 15:01:11 -0700224
225 Ptr<CcnxFib> fib = source->GetObject<CcnxFib> ();
226 fib->InvalidateAll ();
227 NS_ASSERT (fib != 0);
228
229 // cout << "Reachability from Node: " << source->GetObject<Node> ()->GetId () << endl;
Alexander Afanasyeva5abcd92012-04-17 13:34:43 -0700230 for (DistancesMap::iterator i = distances.begin ();
231 i != distances.end ();
232 i++)
233 {
234 if (i->first == source)
235 continue;
236 else
237 {
Alexander Afanasyev8e2f1122012-04-17 15:01:11 -0700238 // cout << " Node " << i->first->GetObject<Node> ()->GetId ();
239 if (i->second.get<0> () == 0)
240 {
241 // cout << " is unreachable" << endl;
242 }
Alexander Afanasyeva5abcd92012-04-17 13:34:43 -0700243 else
Alexander Afanasyev8e2f1122012-04-17 15:01:11 -0700244 {
245 // cout << " reachable via face " << *i->second.get<0> ()
246 // << " with distance " << i->second.get<1> () << endl;
247
248 BOOST_FOREACH (const Ptr<const CcnxNameComponents> &prefix, i->first->GetLocalPrefixes ())
249 {
250 fib->Add (prefix, i->second.get<0> (), i->second.get<1> ());
251 }
252 }
Alexander Afanasyeva5abcd92012-04-17 13:34:43 -0700253 }
254 }
Alexander Afanasyeva5abcd92012-04-17 13:34:43 -0700255 }
Alexander Afanasyevad3757f2012-04-17 10:27:59 -0700256}
257
258
259}