satellite-handover-test.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2014 Magister Solutions Ltd
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: Bastien Tauran <bastien.tauran@viveris.fr>
19  */
20 
29 #include "ns3/cbr-application.h"
30 #include "ns3/cbr-helper.h"
31 #include "ns3/config.h"
32 #include "ns3/log.h"
33 #include "ns3/packet-sink-helper.h"
34 #include "ns3/packet-sink.h"
35 #include "ns3/satellite-env-variables.h"
36 #include "ns3/satellite-gw-mac.h"
37 #include "ns3/satellite-helper.h"
38 #include "ns3/satellite-id-mapper.h"
39 #include "ns3/satellite-isl-arbiter-unicast.h"
40 #include "ns3/satellite-isl-arbiter.h"
41 #include "ns3/satellite-orbiter-feeder-phy.h"
42 #include "ns3/satellite-orbiter-net-device.h"
43 #include "ns3/satellite-orbiter-user-phy.h"
44 #include "ns3/satellite-phy-rx-carrier.h"
45 #include "ns3/satellite-topology.h"
46 #include "ns3/satellite-ut-mac-state.h"
47 #include "ns3/simulation-helper.h"
48 #include "ns3/simulator.h"
49 #include "ns3/singleton.h"
50 #include "ns3/string.h"
51 #include "ns3/test.h"
52 
53 #include <fstream>
54 #include <iostream>
55 
56 using namespace ns3;
57 
87 class SatHandoverTest1 : public TestCase
88 {
89  public:
91  virtual ~SatHandoverTest1();
92 
93  private:
94  virtual void DoRun(void);
95 
96  std::vector<std::string> Split(std::string s, char del);
97  void TestFileValue(std::string path, uint32_t time, double expectedValue);
98 };
99 
100 // Add some help text to this case to describe what it is intended to test
102  : TestCase("This case tests that a application throughputs PerEntity are correct.")
103 {
104 }
105 
106 // This destructor does nothing but we include it as a reminder that
107 // the test case should clean up after itself
109 {
110 }
111 
112 std::vector<std::string>
113 SatHandoverTest1::Split(std::string s, char del)
114 {
115  std::stringstream ss(s);
116  std::string word;
117  std::vector<std::string> tokens;
118  while (!ss.eof())
119  {
120  std::getline(ss, word, del);
121  tokens.push_back(word);
122  }
123  return tokens;
124 }
125 
126 void
127 SatHandoverTest1::TestFileValue(std::string path, uint32_t time, double expectedValue)
128 {
129  std::string line;
130  std::ifstream myfile(path);
131  std::string delimiter = " ";
132  std::string token;
133  bool valueFound;
134 
135  if (myfile.is_open())
136  {
137  valueFound = false;
138  while (std::getline(myfile, line))
139  {
140  std::vector<std::string> tokens = Split(line, ' ');
141  if (tokens.size() == 2)
142  {
143  if ((uint32_t)std::stoi(tokens[0]) == time)
144  {
145  NS_TEST_ASSERT_MSG_EQ_TOL(std::stof(tokens[1]),
146  expectedValue,
147  expectedValue / 10,
148  "Incorrect throughput for statistic " << path);
149  valueFound = true;
150  break;
151  }
152  }
153  }
154  myfile.close();
155  if (!valueFound)
156  {
157  NS_TEST_ASSERT_MSG_EQ(0, 1, "Cannot find time " << time << " for trace file " << path);
158  }
159  }
160  else
161  {
162  NS_TEST_ASSERT_MSG_EQ(0, 1, "Cannot read trace file " << path);
163  }
164 }
165 
166 //
167 // SatHandoverTest1 TestCase implementation
168 //
169 void
171 {
172  Config::Reset();
173  Singleton<SatIdMapper>::Get()->Reset();
174 
175  // Set simulation output details
176  Singleton<SatEnvVariables>::Get()->DoInitialize();
177  Singleton<SatEnvVariables>::Get()->SetOutputVariables("test-sat-handover", "test1", true);
178 
180  Config::SetDefault("ns3::SatConf::ForwardLinkRegenerationMode",
181  EnumValue(SatEnums::REGENERATION_NETWORK));
182  Config::SetDefault("ns3::SatConf::ReturnLinkRegenerationMode",
183  EnumValue(SatEnums::REGENERATION_NETWORK));
184 
185  Config::SetDefault("ns3::SatOrbiterFeederPhy::QueueSize", UintegerValue(100000));
186 
187  Config::SetDefault("ns3::SatHelper::HandoversEnabled", BooleanValue(true));
188  Config::SetDefault("ns3::SatHandoverModule::NumberClosestSats", UintegerValue(2));
189 
190  Config::SetDefault("ns3::SatGwMac::DisableSchedulingIfNoDeviceConnected", BooleanValue(true));
191  Config::SetDefault("ns3::SatOrbiterMac::DisableSchedulingIfNoDeviceConnected",
192  BooleanValue(true));
193 
195  Config::SetDefault("ns3::SatEnvVariables::EnableSimulationOutputOverwrite", BooleanValue(true));
196 
198  Config::SetDefault("ns3::SatHelper::PacketTraceEnabled", BooleanValue(true));
199  Ptr<SimulationHelper> simulationHelper =
200  CreateObject<SimulationHelper>("test-sat-handover/test1");
201  Ptr<SimulationHelperConf> simulationConf = CreateObject<SimulationHelperConf>();
202  simulationHelper->SetGwUserCount(1);
203  simulationHelper->SetUserCountPerUt(1);
204  simulationHelper->SetBeamSet({0, 20, 21, 22, 32, 33, 34, 35, 36, 37, 44, 45, 46,
205  47, 53, 54, 55, 56, 59, 60, 61, 66, 67, 68, 71, 72});
206  simulationHelper->SetUserCountPerMobileUt(simulationConf->m_utMobileUserCount);
207 
208  simulationHelper->LoadScenario("constellation-eutelsat-geo-2-sats-handovers");
209 
210  std::string mobileUtFolder = Singleton<SatEnvVariables>::Get()->LocateDataDirectory() +
211  "/additional-input/utpositions/mobiles/scenario6";
212  simulationHelper->CreateSatScenario(SatHelper::NONE, mobileUtFolder);
213 
214  simulationHelper->GetTrafficHelper()->AddCbrTraffic(
215  SatTrafficHelper::FWD_LINK,
216  SatTrafficHelper::UDP,
217  MilliSeconds(100),
218  512,
219  NodeContainer(Singleton<SatTopology>::Get()->GetGwUserNode(0)),
220  Singleton<SatTopology>::Get()->GetUtUserNodes(),
221  Seconds(1),
222  Seconds(25),
223  Seconds(0));
224 
225  Ptr<SatStatsHelperContainer> s = simulationHelper->GetStatisticsContainer();
226 
227  s->AddPerSatFwdAppThroughput(SatStatsHelper::OUTPUT_SCATTER_FILE);
228  s->AddPerBeamFwdAppThroughput(SatStatsHelper::OUTPUT_SCATTER_FILE);
229  s->AddPerUtFwdAppThroughput(SatStatsHelper::OUTPUT_SCATTER_FILE);
230  s->AddPerGwFwdAppThroughput(SatStatsHelper::OUTPUT_SCATTER_FILE);
231 
232  s->AddPerSatFwdUserMacThroughput(SatStatsHelper::OUTPUT_SCATTER_FILE);
233  s->AddPerBeamFwdUserMacThroughput(SatStatsHelper::OUTPUT_SCATTER_FILE);
234  s->AddPerUtFwdUserMacThroughput(SatStatsHelper::OUTPUT_SCATTER_FILE);
235  s->AddPerGwFwdUserMacThroughput(SatStatsHelper::OUTPUT_SCATTER_FILE);
236 
237  simulationHelper->SetSimulationTime(Seconds(30));
238  simulationHelper->RunSimulation();
239 
240  Simulator::Destroy();
241 
242  // Per satellite APP throughput
243  TestFileValue("contrib/satellite/data/sims/test-sat-handover/test1/"
244  "stat-per-sat-fwd-app-throughput-scatter-1.txt",
245  8,
246  122.88);
247  TestFileValue("contrib/satellite/data/sims/test-sat-handover/test1/"
248  "stat-per-sat-fwd-app-throughput-scatter-2.txt",
249  8,
250  40.96);
251  TestFileValue("contrib/satellite/data/sims/test-sat-handover/test1/"
252  "stat-per-sat-fwd-app-throughput-scatter-1.txt",
253  18,
254  81.92);
255  TestFileValue("contrib/satellite/data/sims/test-sat-handover/test1/"
256  "stat-per-sat-fwd-app-throughput-scatter-2.txt",
257  18,
258  81.92);
259 
260  // Per satellite MAC throughput
261  TestFileValue("contrib/satellite/data/sims/test-sat-handover/test1/"
262  "stat-per-sat-fwd-user-mac-throughput-scatter-1.txt",
263  8,
264  122.88);
265  TestFileValue("contrib/satellite/data/sims/test-sat-handover/test1/"
266  "stat-per-sat-fwd-user-mac-throughput-scatter-2.txt",
267  8,
268  40.96);
269  TestFileValue("contrib/satellite/data/sims/test-sat-handover/test1/"
270  "stat-per-sat-fwd-user-mac-throughput-scatter-1.txt",
271  18,
272  81.92);
273  TestFileValue("contrib/satellite/data/sims/test-sat-handover/test1/"
274  "stat-per-sat-fwd-user-mac-throughput-scatter-2.txt",
275  18,
276  81.92);
277 
278  // Per beam APP throughput
279  TestFileValue("contrib/satellite/data/sims/test-sat-handover/test1/"
280  "stat-per-beam-fwd-app-throughput-scatter-1-35.txt",
281  8,
282  40.96);
283  TestFileValue("contrib/satellite/data/sims/test-sat-handover/test1/"
284  "stat-per-beam-fwd-app-throughput-scatter-2-20.txt",
285  8,
286  0);
287  TestFileValue("contrib/satellite/data/sims/test-sat-handover/test1/"
288  "stat-per-beam-fwd-app-throughput-scatter-1-35.txt",
289  18,
290  0);
291  TestFileValue("contrib/satellite/data/sims/test-sat-handover/test1/"
292  "stat-per-beam-fwd-app-throughput-scatter-2-20.txt",
293  18,
294  40.96);
295 
296  // Per beam MAC throughput
297  TestFileValue("contrib/satellite/data/sims/test-sat-handover/test1/"
298  "stat-per-beam-fwd-user-mac-throughput-scatter-1-35.txt",
299  8,
300  40.96);
301  TestFileValue("contrib/satellite/data/sims/test-sat-handover/test1/"
302  "stat-per-beam-fwd-user-mac-throughput-scatter-2-20.txt",
303  8,
304  0);
305  TestFileValue("contrib/satellite/data/sims/test-sat-handover/test1/"
306  "stat-per-beam-fwd-user-mac-throughput-scatter-1-35.txt",
307  18,
308  0);
309  TestFileValue("contrib/satellite/data/sims/test-sat-handover/test1/"
310  "stat-per-beam-fwd-user-mac-throughput-scatter-2-20.txt",
311  18,
312  40.96);
313 
314  // Per GW APP throughput
315  TestFileValue("contrib/satellite/data/sims/test-sat-handover/test1/"
316  "stat-per-gw-fwd-app-throughput-scatter-1.txt",
317  8,
318  81.92);
319  TestFileValue("contrib/satellite/data/sims/test-sat-handover/test1/"
320  "stat-per-gw-fwd-app-throughput-scatter-2.txt",
321  8,
322  81.92);
323  TestFileValue("contrib/satellite/data/sims/test-sat-handover/test1/"
324  "stat-per-gw-fwd-app-throughput-scatter-1.txt",
325  18,
326  40.96);
327  TestFileValue("contrib/satellite/data/sims/test-sat-handover/test1/"
328  "stat-per-gw-fwd-app-throughput-scatter-2.txt",
329  18,
330  122.88);
331 
332  // Per GW MAC throughput
333  TestFileValue("contrib/satellite/data/sims/test-sat-handover/test1/"
334  "stat-per-gw-fwd-user-mac-throughput-scatter-1.txt",
335  8,
336  81.92);
337  TestFileValue("contrib/satellite/data/sims/test-sat-handover/test1/"
338  "stat-per-gw-fwd-user-mac-throughput-scatter-2.txt",
339  8,
340  81.92);
341  TestFileValue("contrib/satellite/data/sims/test-sat-handover/test1/"
342  "stat-per-gw-fwd-user-mac-throughput-scatter-1.txt",
343  18,
344  40.96);
345  TestFileValue("contrib/satellite/data/sims/test-sat-handover/test1/"
346  "stat-per-gw-fwd-user-mac-throughput-scatter-2.txt",
347  18,
348  122.88);
349 
350  // Per UT APP throughput
351  TestFileValue("contrib/satellite/data/sims/test-sat-handover/test1/"
352  "stat-per-ut-fwd-app-throughput-scatter-1.txt",
353  8,
354  40.96);
355  TestFileValue("contrib/satellite/data/sims/test-sat-handover/test1/"
356  "stat-per-ut-fwd-app-throughput-scatter-2.txt",
357  8,
358  40.96);
359  TestFileValue("contrib/satellite/data/sims/test-sat-handover/test1/"
360  "stat-per-ut-fwd-app-throughput-scatter-3.txt",
361  8,
362  40.96);
363  TestFileValue("contrib/satellite/data/sims/test-sat-handover/test1/"
364  "stat-per-ut-fwd-app-throughput-scatter-4.txt",
365  8,
366  40.96);
367  TestFileValue("contrib/satellite/data/sims/test-sat-handover/test1/"
368  "stat-per-ut-fwd-app-throughput-scatter-1.txt",
369  18,
370  40.96);
371  TestFileValue("contrib/satellite/data/sims/test-sat-handover/test1/"
372  "stat-per-ut-fwd-app-throughput-scatter-2.txt",
373  18,
374  40.96);
375  TestFileValue("contrib/satellite/data/sims/test-sat-handover/test1/"
376  "stat-per-ut-fwd-app-throughput-scatter-3.txt",
377  18,
378  40.96);
379  TestFileValue("contrib/satellite/data/sims/test-sat-handover/test1/"
380  "stat-per-ut-fwd-app-throughput-scatter-4.txt",
381  18,
382  40.96);
383 
384  // Per UT MAC throughput
385  TestFileValue("contrib/satellite/data/sims/test-sat-handover/test1/"
386  "stat-per-ut-fwd-user-mac-throughput-scatter-1.txt",
387  8,
388  40.96);
389  TestFileValue("contrib/satellite/data/sims/test-sat-handover/test1/"
390  "stat-per-ut-fwd-user-mac-throughput-scatter-2.txt",
391  8,
392  40.96);
393  TestFileValue("contrib/satellite/data/sims/test-sat-handover/test1/"
394  "stat-per-ut-fwd-user-mac-throughput-scatter-3.txt",
395  8,
396  40.96);
397  TestFileValue("contrib/satellite/data/sims/test-sat-handover/test1/"
398  "stat-per-ut-fwd-user-mac-throughput-scatter-4.txt",
399  8,
400  40.96);
401  TestFileValue("contrib/satellite/data/sims/test-sat-handover/test1/"
402  "stat-per-ut-fwd-user-mac-throughput-scatter-1.txt",
403  18,
404  40.96);
405  TestFileValue("contrib/satellite/data/sims/test-sat-handover/test1/"
406  "stat-per-ut-fwd-user-mac-throughput-scatter-2.txt",
407  18,
408  40.96);
409  TestFileValue("contrib/satellite/data/sims/test-sat-handover/test1/"
410  "stat-per-ut-fwd-user-mac-throughput-scatter-3.txt",
411  18,
412  40.96);
413  TestFileValue("contrib/satellite/data/sims/test-sat-handover/test1/"
414  "stat-per-ut-fwd-user-mac-throughput-scatter-4.txt",
415  18,
416  40.96);
417 }
418 
425 class SatHandoverTest2 : public TestCase
426 {
427  public:
429  virtual ~SatHandoverTest2();
430 
431  private:
432  bool HasSinkInstalled(Ptr<Node> node, uint16_t port);
433  virtual void DoRun(void);
434 };
435 
436 // Add some help text to this case to describe what it is intended to test
438  : TestCase("This case tests that communication remains after GW handover.")
439 {
440 }
441 
442 // This destructor does nothing but we include it as a reminder that
443 // the test case should clean up after itself
445 {
446 }
447 
448 bool
449 SatHandoverTest2::HasSinkInstalled(Ptr<Node> node, uint16_t port)
450 {
451  for (uint32_t i = 0; i < node->GetNApplications(); i++)
452  {
453  auto sink = DynamicCast<PacketSink>(node->GetApplication(i));
454  if (sink != nullptr)
455  {
456  AddressValue av;
457  sink->GetAttribute("Local", av);
458  if (InetSocketAddress::ConvertFrom(av.Get()).GetPort() == port)
459  {
460  return true;
461  }
462  }
463  }
464  return false;
465 }
466 
467 //
468 // SatHandoverTest2 TestCase implementation
469 //
470 void
472 {
473  Config::Reset();
474  Singleton<SatIdMapper>::Get()->Reset();
475 
476  // Set simulation output details
477  Singleton<SatEnvVariables>::Get()->DoInitialize();
478  Singleton<SatEnvVariables>::Get()->SetOutputVariables("test-sat-handover", "test2", true);
479 
481  Config::SetDefault("ns3::SatConf::ForwardLinkRegenerationMode",
482  EnumValue(SatEnums::REGENERATION_NETWORK));
483  Config::SetDefault("ns3::SatConf::ReturnLinkRegenerationMode",
484  EnumValue(SatEnums::REGENERATION_NETWORK));
485 
486  Config::SetDefault("ns3::SatOrbiterFeederPhy::QueueSize", UintegerValue(100000));
487 
488  Config::SetDefault("ns3::SatHelper::HandoversEnabled", BooleanValue(true));
489  Config::SetDefault("ns3::SatHandoverModule::NumberClosestSats", UintegerValue(2));
490 
491  Config::SetDefault("ns3::SatGwMac::DisableSchedulingIfNoDeviceConnected", BooleanValue(true));
492  Config::SetDefault("ns3::SatOrbiterMac::DisableSchedulingIfNoDeviceConnected",
493  BooleanValue(true));
494 
496  Config::SetDefault("ns3::SatEnvVariables::EnableSimulationOutputOverwrite", BooleanValue(true));
497 
499  Config::SetDefault("ns3::SatHelper::PacketTraceEnabled", BooleanValue(true));
500  Ptr<SimulationHelper> simulationHelper =
501  CreateObject<SimulationHelper>("test-sat-handover/test2");
502  Ptr<SimulationHelperConf> simulationConf = CreateObject<SimulationHelperConf>();
503  simulationHelper->SetSimulationTime(Seconds(50));
504  simulationHelper->SetGwUserCount(1);
505  simulationHelper->SetUserCountPerUt(1);
506  std::set<uint32_t> beamSetAll = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
507  16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
508  31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
509  46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
510  61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72};
511  simulationHelper->SetBeamSet(beamSetAll);
512  simulationHelper->SetUserCountPerMobileUt(simulationConf->m_utMobileUserCount);
513 
514  simulationHelper->LoadScenario("constellation-leo-2-satellites");
515 
516  Ptr<SatHelper> helper = simulationHelper->CreateSatScenario(SatHelper::NONE);
517 
518  NodeContainer utUsers = Singleton<SatTopology>::Get()->GetUtUserNodes();
519  NodeContainer gwUsers = Singleton<SatTopology>::Get()->GetGwUserNodes();
520 
521  Config::SetDefault("ns3::CbrApplication::Interval", StringValue("100ms"));
522  Config::SetDefault("ns3::CbrApplication::PacketSize", UintegerValue(512));
523 
524  uint16_t port = 9;
525  PacketSinkHelper sinkHelper("ns3::UdpSocketFactory", Address());
526  CbrHelper cbrHelper("ns3::UdpSocketFactory", Address());
527  ApplicationContainer sinkContainer;
528  ApplicationContainer cbrContainer;
529  // create CBR applications on UT users
530  for (uint32_t i = 0; i < utUsers.GetN(); i++)
531  {
532  InetSocketAddress utUserAddr =
533  InetSocketAddress(helper->GetUserAddress(utUsers.Get(i)), port);
534  if (!HasSinkInstalled(utUsers.Get(i), port))
535  {
536  sinkHelper.SetAttribute("Local", AddressValue(Address(utUserAddr)));
537  sinkContainer.Add(sinkHelper.Install(utUsers.Get(i)));
538  }
539 
540  cbrHelper.SetAttribute("Remote", AddressValue(Address(utUserAddr)));
541  auto app = cbrHelper.Install(gwUsers.Get(0)).Get(0);
542  app->SetStartTime(Seconds(1.0));
543  cbrContainer.Add(app);
544  }
545  sinkContainer.Start(Seconds(1.0));
546  sinkContainer.Stop(Seconds(45.0));
547 
548  simulationHelper->RunSimulation();
549 
550  Simulator::Destroy();
551 
552  for (uint32_t i = 0; i < 5; i++)
553  {
554  Ptr<PacketSink> utReceiver = DynamicCast<PacketSink>(sinkContainer.Get(i));
555  Ptr<CbrApplication> gwSender = DynamicCast<CbrApplication>(cbrContainer.Get(i));
556 
557  NS_TEST_ASSERT_MSG_NE(gwSender->GetSent(), 0, "Nothing sent by GW app " << i << "!");
558 
559  NS_TEST_ASSERT_MSG_EQ_TOL(utReceiver->GetTotalRx(),
560  gwSender->GetSent(),
561  gwSender->GetSent() / 5,
562  "Too many packets were lost to UT!");
563  }
564 }
565 
566 // The TestSuite class names the TestSuite as sat-handover-test, identifies what type of
567 // TestSuite (Type::SYSTEM), and enables the TestCases to be run. Typically, only the constructor
568 // for this class must be defined
569 //
570 class SatHandoverTestSuite : public TestSuite
571 {
572  public:
574 };
575 
577  : TestSuite("sat-handover-test", Type::SYSTEM)
578 {
579  AddTestCase(new SatHandoverTest1,
580  TestCase::Duration::QUICK); // This case tests that a application throughputs
581  // PerEntity are correct.
582  AddTestCase(
583  new SatHandoverTest2,
584  TestCase::Duration::QUICK); // This case tests that communication remains after GW handover.
585 }
586 
587 // Allocate an instance of this TestSuite
'Handover, test 1 test case implementation.
virtual void DoRun(void)
std::vector< std::string > Split(std::string s, char del)
void TestFileValue(std::string path, uint32_t time, double expectedValue)
'Handover, test 2 test case implementation.
virtual void DoRun(void)
bool HasSinkInstalled(Ptr< Node > node, uint16_t port)
SatArqSequenceNumber is handling the sequence numbers for the ARQ process.
static SatHandoverTestSuite satHandoverTestSuite