satellite-isl-arbiter-unicast-helper.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2013 Magister Solutions Ltd
4  * Copyright (c) 2018 CNES
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation;
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  *
19  * Inspired and adapted from Hypatia: https://github.com/snkas/hypatia
20  *
21  * Author: Bastien Tauran <bastien.tauran@viveris.fr>
22  */
23 
25 
26 #include <ns3/node-container.h>
27 #include <ns3/node.h>
28 
29 NS_LOG_COMPONENT_DEFINE("SatIslArbiterUnicastHelper");
30 
31 namespace ns3
32 {
33 
34 NS_OBJECT_ENSURE_REGISTERED(SatIslArbiterUnicastHelper);
35 
36 TypeId
38 {
39  static TypeId tid = TypeId("ns3::SatIslArbiterUnicastHelper")
40  .SetParent<Object>()
41  .AddConstructor<SatIslArbiterUnicastHelper>();
42  return tid;
43 }
44 
46 {
47  NS_FATAL_ERROR("Default constructor not in use");
48 }
49 
51  NodeContainer geoNodes,
52  std::vector<std::pair<uint32_t, uint32_t>> isls)
53  : m_geoNodes(geoNodes),
54  m_isls(isls)
55 {
56  NS_LOG_FUNCTION(this);
57 }
58 
59 void
61 {
62  NS_LOG_FUNCTION(this);
63 
64  std::vector<std::map<uint32_t, uint32_t>> globalState = CalculateGlobalState();
65 
66  for (uint32_t satIndex = 0; satIndex < globalState.size(); satIndex++)
67  {
68  Ptr<Node> satelliteNode = m_geoNodes.Get(satIndex);
69  Ptr<SatGeoNetDevice> satelliteGeoNetDevice;
70  for (uint32_t ndIndex = 0; ndIndex < satelliteNode->GetNDevices(); ndIndex++)
71  {
72  Ptr<SatGeoNetDevice> nd =
73  DynamicCast<SatGeoNetDevice>(satelliteNode->GetDevice(ndIndex));
74  if (nd != nullptr)
75  {
76  satelliteGeoNetDevice = nd;
77  }
78  }
79 
80  NS_ASSERT_MSG(satelliteGeoNetDevice != nullptr, "SatGeoNetDevice not found on satellite");
81 
82  std::vector<Ptr<PointToPointIslNetDevice>> islNetDevices =
83  satelliteGeoNetDevice->GetIslsNetDevices();
84  Ptr<SatIslArbiterUnicast> arbiter = CreateObject<SatIslArbiterUnicast>(satelliteNode);
85 
86  for (uint32_t islInterfaceIndex = 0; islInterfaceIndex < islNetDevices.size();
87  islInterfaceIndex++)
88  {
89  uint32_t interfaceNextHopNodeId =
90  islNetDevices[islInterfaceIndex]->GetDestinationNode()->GetId();
91  for (std::map<uint32_t, uint32_t>::iterator it = globalState[satIndex].begin();
92  it != globalState[satIndex].end();
93  it++)
94  {
95  uint32_t destinationNodeId = it->first;
96  uint32_t nextHopNodeId = it->second;
97 
98  if (interfaceNextHopNodeId == nextHopNodeId)
99  {
100  arbiter->AddNextHopEntry(destinationNodeId, islInterfaceIndex);
101  }
102  }
103  }
104  satelliteGeoNetDevice->SetArbiter(arbiter);
105  }
106 }
107 
108 void
110 {
111  NS_LOG_FUNCTION(this);
112 
113  this->InstallArbiters();
114 }
115 
116 std::vector<std::map<uint32_t, uint32_t>>
118 {
119  NS_LOG_FUNCTION(this);
120 
121  // Final result
122  std::vector<std::vector<std::vector<uint32_t>>> globalCandidateList;
123 
125  // Floyd-Warshall
126 
127  int64_t n = m_geoNodes.GetN();
128 
129  // Enforce that more than 40000 nodes is not permitted (sqrt(2^31) ~= 46340, so let's call it an
130  // even 40000)
131  if (n > 40000)
132  {
133  NS_FATAL_ERROR("Cannot handle more than 40000 nodes");
134  }
135 
136  // Initialize with 0 distance to itself, and infinite distance to all others
137  int32_t n2 = n * n;
138  int32_t* dist = new int32_t[n2];
139  for (int i = 0; i < n; i++)
140  {
141  for (int j = 0; j < n; j++)
142  {
143  if (i == j)
144  {
145  dist[n * i + j] = 0;
146  }
147  else
148  {
149  dist[n * i + j] = 100000000;
150  }
151  }
152  }
153 
154  // If there is an edge, the distance is 1
155  for (std::pair<uint64_t, uint64_t> edge : m_isls)
156  {
157  dist[n * edge.first + edge.second] = 1;
158  dist[n * edge.second + edge.first] = 1;
159  }
160 
161  // Floyd-Warshall core
162  for (int k = 0; k < n; k++)
163  {
164  for (int i = 0; i < n; i++)
165  {
166  for (int j = 0; j < n; j++)
167  {
168  if (dist[n * i + j] > dist[n * i + k] + dist[n * k + j])
169  {
170  dist[n * i + j] = dist[n * i + k] + dist[n * k + j];
171  }
172  }
173  }
174  }
175 
177  // Determine from the shortest path distances
178  // the possible next hops
179 
180  // ECMP candidate list: candidate_list[current][destination] = [ list of next hops ]
181  globalCandidateList.reserve(n);
182  for (int i = 0; i < n; i++)
183  {
184  std::vector<std::vector<uint32_t>> v;
185  v.reserve(n);
186  for (int j = 0; j < n; j++)
187  {
188  v.push_back(std::vector<uint32_t>());
189  }
190  globalCandidateList.push_back(v);
191  }
192 
193  // Candidate next hops are determined in the following way:
194  // For each edge a -> b, for a destination t:
195  // If the shortest_path_distance(b, t) == shortest_path_distance(a, t) - 1
196  // then a -> b must be part of a shortest path from a towards t.
197  for (std::pair<uint64_t, uint64_t> edge : m_isls)
198  {
199  for (int j = 0; j < n; j++)
200  {
201  if (dist[edge.first * n + j] - 1 == dist[edge.second * n + j])
202  {
203  globalCandidateList[edge.first][j].push_back(edge.second);
204  }
205  if (dist[edge.second * n + j] - 1 == dist[edge.first * n + j])
206  {
207  globalCandidateList[edge.second][j].push_back(edge.first);
208  }
209  }
210  }
211 
212  // Free up the distance matrix
213  delete[] dist;
214 
215  std::vector<std::map<uint32_t, uint32_t>> returnList;
216  for (uint32_t i = 0; i < globalCandidateList.size(); i++)
217  {
218  returnList.push_back(std::map<uint32_t, uint32_t>());
219  std::vector<std::vector<uint32_t>> v = globalCandidateList[i];
220  for (uint32_t j = 0; j < v.size(); j++)
221  {
222  if (v[j].size() > 0)
223  {
224  returnList[i].insert(
225  std::make_pair(j, v[j][0])); // TODO for ECMP, keep all values in v[j]
226  }
227  }
228  }
229 
230  // Return the final global candidate list
231  return returnList;
232 }
233 
234 } // namespace ns3
std::vector< std::pair< uint32_t, uint32_t > > m_isls
void InstallArbiters()
Install arbiter on all satellite nodes.
void UpdateArbiters()
Update arbiter on all satellite nodes.
std::vector< std::map< uint32_t, uint32_t > > CalculateGlobalState()
Compute routing tables for all satellite nodes.
SatArqSequenceNumber is handling the sequence numbers for the ARQ process.