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 #include <ns3/satellite-topology.h>
29 #include <ns3/singleton.h>
30 
31 #include <map>
32 #include <utility>
33 #include <vector>
34 
35 NS_LOG_COMPONENT_DEFINE("SatIslArbiterUnicastHelper");
36 
37 namespace ns3
38 {
39 
40 NS_OBJECT_ENSURE_REGISTERED(SatIslArbiterUnicastHelper);
41 
42 TypeId
44 {
45  static TypeId tid = TypeId("ns3::SatIslArbiterUnicastHelper")
46  .SetParent<Object>()
47  .AddConstructor<SatIslArbiterUnicastHelper>();
48  return tid;
49 }
50 
52 {
53  NS_FATAL_ERROR("Default constructor not in use");
54 }
55 
57  std::vector<std::pair<uint32_t, uint32_t>> isls)
58  : m_isls(isls)
59 {
60  NS_LOG_FUNCTION(this);
61 }
62 
63 void
65 {
66  NS_LOG_FUNCTION(this);
67 
68  std::vector<std::map<uint32_t, uint32_t>> globalState = CalculateGlobalState();
69 
70  for (uint32_t satIndex = 0; satIndex < globalState.size(); satIndex++)
71  {
72  Ptr<Node> satelliteNode = Singleton<SatTopology>::Get()->GetOrbiterNode(satIndex);
73  Ptr<SatOrbiterNetDevice> satelliteOrbiterNetDevice;
74  for (uint32_t ndIndex = 0; ndIndex < satelliteNode->GetNDevices(); ndIndex++)
75  {
76  Ptr<SatOrbiterNetDevice> nd =
77  DynamicCast<SatOrbiterNetDevice>(satelliteNode->GetDevice(ndIndex));
78  if (nd != nullptr)
79  {
80  satelliteOrbiterNetDevice = nd;
81  }
82  }
83 
84  NS_ASSERT_MSG(satelliteOrbiterNetDevice != nullptr,
85  "SatOrbiterNetDevice not found on satellite");
86 
87  std::vector<Ptr<PointToPointIslNetDevice>> islNetDevices =
88  satelliteOrbiterNetDevice->GetIslsNetDevices();
89  Ptr<SatIslArbiterUnicast> arbiter = CreateObject<SatIslArbiterUnicast>(satelliteNode);
90 
91  for (uint32_t islInterfaceIndex = 0; islInterfaceIndex < islNetDevices.size();
92  islInterfaceIndex++)
93  {
94  uint32_t interfaceNextHopNodeId =
95  islNetDevices[islInterfaceIndex]->GetDestinationNode()->GetId();
96  for (std::map<uint32_t, uint32_t>::iterator it = globalState[satIndex].begin();
97  it != globalState[satIndex].end();
98  it++)
99  {
100  uint32_t destinationNodeId = it->first;
101  uint32_t nextHopNodeId = it->second;
102 
103  if (interfaceNextHopNodeId == nextHopNodeId)
104  {
105  arbiter->AddNextHopEntry(destinationNodeId, islInterfaceIndex);
106  }
107  }
108  }
109  satelliteOrbiterNetDevice->SetArbiter(arbiter);
110  }
111 }
112 
113 void
115 {
116  NS_LOG_FUNCTION(this);
117 
118  this->InstallArbiters();
119 }
120 
121 std::vector<std::map<uint32_t, uint32_t>>
123 {
124  NS_LOG_FUNCTION(this);
125 
126  // Final result
127  std::vector<std::vector<std::vector<uint32_t>>> globalCandidateList;
128 
130  // Floyd-Warshall
131 
132  int64_t n = Singleton<SatTopology>::Get()->GetNOrbiterNodes();
133 
134  // Enforce that more than 40000 nodes is not permitted (sqrt(2^31) ~= 46340, so let's call it an
135  // even 40000)
136  if (n > 40000)
137  {
138  NS_FATAL_ERROR("Cannot handle more than 40000 nodes");
139  }
140 
141  // Initialize with 0 distance to itself, and infinite distance to all others
142  int32_t n2 = n * n;
143  int32_t* dist = new int32_t[n2];
144  for (int i = 0; i < n; i++)
145  {
146  for (int j = 0; j < n; j++)
147  {
148  if (i == j)
149  {
150  dist[n * i + j] = 0;
151  }
152  else
153  {
154  dist[n * i + j] = 100000000;
155  }
156  }
157  }
158 
159  // If there is an edge, the distance is 1
160  for (std::pair<uint64_t, uint64_t> edge : m_isls)
161  {
162  dist[n * edge.first + edge.second] = 1;
163  dist[n * edge.second + edge.first] = 1;
164  }
165 
166  // Floyd-Warshall core
167  for (int k = 0; k < n; k++)
168  {
169  for (int i = 0; i < n; i++)
170  {
171  for (int j = 0; j < n; j++)
172  {
173  if (dist[n * i + j] > dist[n * i + k] + dist[n * k + j])
174  {
175  dist[n * i + j] = dist[n * i + k] + dist[n * k + j];
176  }
177  }
178  }
179  }
180 
182  // Determine from the shortest path distances
183  // the possible next hops
184 
185  // ECMP candidate list: candidate_list[current][destination] = [ list of next hops ]
186  globalCandidateList.reserve(n);
187  for (int i = 0; i < n; i++)
188  {
189  std::vector<std::vector<uint32_t>> v;
190  v.reserve(n);
191  for (int j = 0; j < n; j++)
192  {
193  v.push_back(std::vector<uint32_t>());
194  }
195  globalCandidateList.push_back(v);
196  }
197 
198  // Candidate next hops are determined in the following way:
199  // For each edge a -> b, for a destination t:
200  // If the shortest_path_distance(b, t) == shortest_path_distance(a, t) - 1
201  // then a -> b must be part of a shortest path from a towards t.
202  for (std::pair<uint64_t, uint64_t> edge : m_isls)
203  {
204  for (int j = 0; j < n; j++)
205  {
206  if (dist[edge.first * n + j] - 1 == dist[edge.second * n + j])
207  {
208  globalCandidateList[edge.first][j].push_back(edge.second);
209  }
210  if (dist[edge.second * n + j] - 1 == dist[edge.first * n + j])
211  {
212  globalCandidateList[edge.second][j].push_back(edge.first);
213  }
214  }
215  }
216 
217  // Free up the distance matrix
218  delete[] dist;
219 
220  std::vector<std::map<uint32_t, uint32_t>> returnList;
221  for (uint32_t i = 0; i < globalCandidateList.size(); i++)
222  {
223  returnList.push_back(std::map<uint32_t, uint32_t>());
224  std::vector<std::vector<uint32_t>> v = globalCandidateList[i];
225  for (uint32_t j = 0; j < v.size(); j++)
226  {
227  if (v[j].size() > 0)
228  {
229  returnList[i].insert(
230  std::make_pair(j, v[j][0])); // TODO for ECMP, keep all values in v[j]
231  }
232  }
233  }
234 
235  // Return the final global candidate list
236  return returnList;
237 }
238 
239 } // 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.