blob: 13f86abb2d72f6024203096e5cb8d841fe5de1d6 [file] [log] [blame]
Klaus Schneider38784302019-08-31 18:26:36 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2019 Klaus Schneider, The University of Arizona
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: Klaus Schneider <klaus@cs.arizona.edu>
19 */
20
21#include "ns3/ndnSIM/helper/ndn-global-routing-helper.hpp"
22
23#include <boost/graph/dijkstra_shortest_paths.hpp>
24#include <boost/graph/graph_utility.hpp>
25
26#include "ns3/ndnSIM/helper/boost-graph-ndn-global-routing-helper.hpp"
27#include "ns3/ndnSIM/helper/lfid/abstract-fib.hpp"
28#include "ns3/ndnSIM/helper/lfid/remove-loops.hpp"
29#include "ns3/ndnSIM/helper/ndn-fib-helper.hpp"
30#include "ns3/ndnSIM/model/ndn-global-router.hpp"
31
32NS_LOG_COMPONENT_DEFINE("ndn.GlobalRoutingHelperLfid");
33
34namespace ns3 {
35namespace ndn {
36
37using std::get;
38using std::unordered_map;
39
40void
41GlobalRoutingHelper::CalculateLfidRoutes()
42{
43 BOOST_CONCEPT_ASSERT((boost::VertexListGraphConcept<boost::NdnGlobalRouterGraph>));
44 BOOST_CONCEPT_ASSERT((boost::IncidenceGraphConcept<boost::NdnGlobalRouterGraph>));
45
46 // Creates graph from nodeList:
47 boost::NdnGlobalRouterGraph graph{};
48
49 AbstractFib::AllNodeFib allNodeFIB;
50
51 // Store mapping nodeId -> faceId -> Ptr<Face>
52 unordered_map<int, unordered_map<nfd::FaceId, shared_ptr<Face>>> faceMap;
53
54 // For all existing nodes:
55 for (auto node = NodeList::Begin(); node != NodeList::End(); node++) {
56
57 int nodeId = static_cast<int>((*node)->GetId());
58 const Ptr<GlobalRouter>& source = (*node)->GetObject<GlobalRouter>();
59
60 AbstractFib nodeFib = AbstractFib{source, static_cast<int>(NodeList::GetNNodes())};
61
62 if (source == nullptr) {
63 NS_LOG_ERROR("Node " << (*node)->GetId() << " does not export GlobalRouter interface");
64 continue;
65 }
66
67 // map: neighborId -> DistancesMap
68 unordered_map<int, boost::DistancesMap> nbSp;
69
70 // map: Destination (GlobalRouter) -> Distance
71 boost::DistancesMap distMap;
72 unordered_map<int, boost::DistancesMap> neighborSpMap;
73
74 dijkstra_shortest_paths(graph, source,
75 distance_map(boost::ref(distMap))
76 .distance_inf(boost::WeightInf)
77 .distance_zero(boost::WeightZero)
78 .distance_compare(boost::WeightCompare())
79 .distance_combine(boost::WeightCombine()));
80
81 // 1. Get all neighbors of node.
82 unordered_map<nfd::FaceId, uint64_t> originalMetrics;
83 auto& originalFace = faceMap[nodeId];
84
85 const GlobalRouter::IncidencyList& neighbors = source->GetIncidencies();
86 // Set link weight of all neighbors to infinity
87 for (const auto& neighbor : neighbors) {
88 int nbId = get<2>(neighbor)->GetObject<ns3::Node>()->GetId();
89 NS_ABORT_UNLESS(nbId != nodeId);
90
91 auto& face = get<shared_ptr<Face>>(neighbor);
92 NS_ABORT_UNLESS(face != nullptr);
93
94 originalMetrics[nbId] = face->getMetric();
95 originalFace[nbId] = face; // Is only a copy
96 face->setMetric(get<uint16_t>(boost::WeightInf));
97 }
98
99 // 2. Calculate Dijkstra for neighbors
100 for (const auto& neighbor : neighbors) {
101 const auto& nSource = get<0>(neighbor);
102 const auto& target = get<2>(neighbor);
103
104 int nbId = target->GetObject<ns3::Node>()->GetId();
105 Ptr<GlobalRouter> nbRouter = target;
106
107 NS_ABORT_UNLESS(target != source && nbId != nodeId);
108 NS_ABORT_UNLESS(nSource == source);
109
110 dijkstra_shortest_paths(graph, nbRouter,
111 distance_map(boost::ref(neighborSpMap[nbId]))
112 .distance_inf(boost::WeightInf)
113 .distance_zero(boost::WeightZero)
114 .distance_compare(boost::WeightCompare())
115 .distance_combine(boost::WeightCombine()));
116 }
117
118 // 3. Reset link weights
119 for (const auto& neighbor : neighbors) {
120 int nbId = get<2>(neighbor)->GetObject<ns3::Node>()->GetId();
121 NS_ABORT_UNLESS(nbId != nodeId);
122
123 const auto& face = get<shared_ptr<Face>>(neighbor);
124 NS_ABORT_UNLESS(face->getMetric() == get<uint16_t>(boost::WeightInf));
125 face->setMetric(originalMetrics.at(nbId));
126 }
127
128 // 4. Fill Abstract FIB:
129 // For each destination:
130 for (const auto& dstEntry : distMap) {
131 Ptr<GlobalRouter> dstRouter = dstEntry.first;
132 int dstId = dstRouter->GetObject<ns3::Node>()->GetId();
133 if (dstRouter == source)
134 continue; // Skip destination == source.
135
136 int spTotalCost = static_cast<int>(get<uint32_t>(dstEntry.second));
137
138 // For each neighbor:
139 for (const auto& nb : neighborSpMap) {
140 int neighborId = nb.first;
141 const uint32_t nbDist{get<uint32_t>(nb.second.at(dstRouter))};
142
143 int neighborCost = static_cast<int>(nbDist);
144 int neighborTotalCost = neighborCost + static_cast<int>(originalFace.at(neighborId)->getMetric());
145
146 NS_ABORT_UNLESS(neighborTotalCost >= spTotalCost);
147
148 // Skip routers that would loop back
149 if (neighborTotalCost >= static_cast<int>(get<uint16_t>(boost::WeightInf)))
150 continue;
151
152 NextHopType nbType;
153 if (neighborCost < spTotalCost) {
154 nbType = NextHopType::DOWNWARD;
155 }
156 else {
157 nbType = NextHopType::UPWARD;
158 }
159
160 int costDelta = neighborTotalCost - spTotalCost;
161 FibNextHop nh = {neighborTotalCost, neighborId, costDelta, nbType};
162 nodeFib.insert(dstId, nh);
163 }
164
165 } // End for all dsts
166
167 nodeFib.checkFib();
168 allNodeFIB.emplace(nodeId, nodeFib);
169 } // End for all nodes
170
171 /// 4. Remove loops and Deadends ///
172 removeLoops(allNodeFIB, true);
173 removeDeadEnds(allNodeFIB, true);
174
175 // 5. Insert from AbsFIB into real FIB!
176 // For each node in the AbsFIB: Insert into real fib.
177 for (const auto& nodeEntry : allNodeFIB) {
178 int nodeId = nodeEntry.first;
179 const auto& fib = nodeEntry.second;
180
181 // For each destination:
182 for (const auto& dst : fib) {
183 int dstId = dst.first;
184 const auto& dstRouter = allNodeFIB.at(dstId).getGR();
185
186 // Each fibNexthop
187 for (const auto& nh : dst.second) {
188 int neighborId = nh.getNexthopId();
189 int neighborTotalCost = nh.getCost();
190
191 for (const auto& prefix : dstRouter->GetLocalPrefixes()) {
192 Ptr<Node> node = NodeList::GetNode(static_cast<uint32_t>(nodeId));
193 FibHelper::AddRoute(node, *prefix, faceMap.at(nodeId).at(neighborId), neighborTotalCost);
194 }
195 }
196 }
197 }
198}
199
200} // namespace ndn
201} // namespace ns3