satellite-arq-test.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  *
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: Jani Puttonen <jani.puttonen@magister.fi>
19  */
20 
40 #include "../model/satellite-generic-stream-encapsulator-arq.h"
41 #include "../model/satellite-queue.h"
42 #include "../model/satellite-return-link-encapsulator-arq.h"
43 #include "../utils/satellite-env-variables.h"
44 
45 #include "ns3/callback.h"
46 #include "ns3/config.h"
47 #include "ns3/log.h"
48 #include "ns3/packet.h"
49 #include "ns3/ptr.h"
50 #include "ns3/random-variable-stream.h"
51 #include "ns3/singleton.h"
52 #include "ns3/test.h"
53 
54 #include <vector>
55 
56 using namespace ns3;
57 
63 class SatRtnArqTestCase : public TestCase
64 {
65  public:
67  virtual ~SatRtnArqTestCase();
68 
73  void TransmitPdus(uint32_t numPackets);
74 
78  void NotifyTxOpportunity();
79 
84  void ReceivePdu(Ptr<Packet> p);
85 
92  bool SendAck(Ptr<SatControlMessage> msg, const Address& dest);
93 
98  void ReceiveAck(Ptr<SatArqAckMessage> ack);
99 
106  void Receive(Ptr<Packet> p, Mac48Address source, Mac48Address dest);
107 
108  private:
113  void Initialize();
114 
115  virtual void DoRun(void);
116 
117  // Same RLE ARQ handles both transmission and reception
118  // operations
119  Ptr<SatReturnLinkEncapsulatorArq> m_rle;
120 
121  // Random variable
122  Ptr<UniformRandomVariable> m_unif;
123 
124  // Addressing
125  Mac48Address m_source;
126  Mac48Address m_dest;
127 
128  // Number of created packets
129  uint32_t m_numPackets;
130 
131  // Number of generated time slots. When we run out of Tx opportunities
132  // the test is finished.
134 
135  // Tx opportunities (RTN time slot Bytes)
138 
139  // Error ratios
142 
143  // Propagation delay of the satellite channel
144  // = constant
146 
147  // RC index for the RLE
148  uint8_t m_rcIndex;
149 
150  // Error probability threshold for HL packets. If the
151  // test results in higher error probability than the threshold
152  // the test is failed.
154 
155  // Interval for creating tx opportunities
157 
158  // Jitter (or addition to static Tx opportunity interval)
161 
162  uint32_t m_txs;
163  uint32_t m_txErrors;
164  uint32_t m_acks;
165  uint32_t m_ackErrors;
166 
167  // Sent packet statistics
168  std::vector<uint32_t> m_sentPacketSizes;
169 
170  // Received packet statistics
171  std::vector<uint32_t> m_rcvdPacketSizes;
172 };
173 
175  : TestCase("Test RLE ARQ.")
176 {
177 }
178 
180 {
181  if (m_rle)
182  {
183  m_rle->DoDispose();
184  m_rle = NULL;
185  }
186 }
187 
188 void
190 {
191  m_numPackets = 1000;
192  m_numTxOpportunities = 60000;
193  m_minTxOpportunity = 38;
194  m_maxTxOpportunity = 599;
195  m_packetErrorRatio = 0.05;
196  m_ackErrorRatio = 0.05;
197  m_propagationDelay = MilliSeconds(270);
198  m_rcIndex = 0;
200  m_txoInterval = MilliSeconds(5);
203  m_txs = 0;
204  m_txErrors = 0;
205  m_acks = 0;
206  m_ackErrors = 0;
207 
208  m_source = Mac48Address::Allocate();
209  m_dest = Mac48Address::Allocate();
210 
211  // The parameters of RLE ARQ may be reconfigured
212  Config::SetDefault("ns3::SatQueue::MaxPackets", UintegerValue(1001));
213  Config::SetDefault("ns3::SatReturnLinkEncapsulatorArq::MaxNoOfRetransmissions",
214  UintegerValue(3));
215  Config::SetDefault("ns3::SatReturnLinkEncapsulatorArq::WindowSize", UintegerValue(50));
216  Config::SetDefault("ns3::SatReturnLinkEncapsulatorArq::RetransmissionTimer",
217  TimeValue(Seconds(0.6)));
218  Config::SetDefault("ns3::SatReturnLinkEncapsulatorArq::RxWaitingTime", TimeValue(Seconds(2.3)));
219 
220  Ptr<SatQueue> queue = CreateObject<SatQueue>(m_rcIndex);
221  m_rle =
222  CreateObject<SatReturnLinkEncapsulatorArq>(m_source, m_dest, m_source, m_dest, m_rcIndex);
223  m_rle->SetQueue(queue);
224 
225  // Create a receive callback to Receive method of this class.
226  m_rle->SetReceiveCallback(MakeCallback(&SatRtnArqTestCase::Receive, this));
227 
228  // Create ACK sending callback
229  m_rle->SetCtrlMsgCallback(MakeCallback(&SatRtnArqTestCase::SendAck, this));
230 
231  // Random variable for sent packet sizes and tx opportunities
232  m_unif = CreateObject<UniformRandomVariable>();
233 }
234 
235 void
237 {
238  // Set simulation output details
239  Singleton<SatEnvVariables>::Get()->DoInitialize();
240  Singleton<SatEnvVariables>::Get()->SetOutputVariables("test-sat-arq", "rtn", true);
241 
242  Initialize();
243 
244  // Enque packets to RLE
246 
247  // Schedule the first TxO
248  Simulator::Schedule(Seconds(0.1), &SatRtnArqTestCase::NotifyTxOpportunity, this);
249 
250  Simulator::Run();
251 
252  // Calculate HL error probability
253  double errorProb = 1.0 - (m_rcvdPacketSizes.size() / (double)m_sentPacketSizes.size());
254  NS_TEST_ASSERT_MSG_LT(errorProb,
256  "HL packet error probability is higher than threshold!");
257 
258  // std::cout << "RTN: Sent packets: " << m_sentPacketSizes.size () << " received packets: " <<
259  // m_rcvdPacketSizes.size () << std::endl; std::cout << "Tx: " << m_txs << " txErrors: " <<
260  // m_txErrors << " Acks: " << m_acks << " ackErrors: " << m_ackErrors << std::endl;
261 
262  Simulator::Destroy();
263 
264  Singleton<SatEnvVariables>::Get()->DoDispose();
265 }
266 
267 void
269 {
270  // Create packets and push them to RLE
271  for (uint32_t i = 0; i < numPackets; ++i)
272  {
273  uint32_t packetSize = m_unif->GetInteger(3, 500);
274  Ptr<Packet> packet = Create<Packet>(packetSize);
275  m_sentPacketSizes.push_back(packetSize);
276  m_rle->EnquePdu(packet, m_dest);
277  }
278 }
279 
280 void
282 {
287  uint32_t nextMinTxO(0);
288  uint32_t bytesLeft(1);
289 
290  uint32_t bytes = m_unif->GetInteger(m_minTxOpportunity, m_maxTxOpportunity);
291  Ptr<Packet> p = m_rle->NotifyTxOpportunity(bytes, bytesLeft, nextMinTxO);
292 
293  // If packet received
294  if (p)
295  {
296  m_txs++;
297 
298  // Packet received after propagation delay
299  if (m_packetErrorRatio < m_unif->GetValue(0.0, 1.0))
300  {
301  // Schedule packet receive
302  Simulator::Schedule(m_propagationDelay, &SatRtnArqTestCase::ReceivePdu, this, p);
303  }
304  // Transmission error for packet
305  else
306  {
307  m_txErrors++;
308  }
309  }
310 
311  if (m_numTxOpportunities > 0)
312  {
313  // Schedule next TxO
314  Time nextTxOTime = m_txoInterval + MilliSeconds(m_unif->GetValue(m_minTimeSlotJitterInMs,
316  Simulator::Schedule(nextTxOTime, &SatRtnArqTestCase::NotifyTxOpportunity, this);
317  }
318 
319  // Reduce count
321 }
322 
323 void
325 {
326  m_rle->ReceivePdu(p);
327 }
328 
329 bool
330 SatRtnArqTestCase::SendAck(Ptr<SatControlMessage> msg, const Address& dest)
331 {
332  m_acks++;
333 
334  // ACK received after propagation delay
335  if (m_ackErrorRatio < m_unif->GetValue(0.0, 1.0))
336  {
337  Ptr<SatArqAckMessage> ack = DynamicCast<SatArqAckMessage>(msg);
338  Simulator::Schedule(m_propagationDelay, &SatRtnArqTestCase::ReceiveAck, this, ack);
339  }
340  // Transmission error for ACK
341  else
342  {
343  m_ackErrors++;
344  }
345 
346  return true;
347 }
348 
349 void
350 SatRtnArqTestCase::ReceiveAck(Ptr<SatArqAckMessage> ack)
351 {
352  m_rle->ReceiveAck(ack);
353 }
354 
355 void
356 SatRtnArqTestCase::Receive(Ptr<Packet> p, Mac48Address source, Mac48Address dest)
357 {
358  uint32_t rcvdPacketSize = p->GetSize();
359  m_rcvdPacketSizes.push_back(rcvdPacketSize);
360 
361  // std::cout << "Now: " << Now ().GetSeconds () << " sent: " << m_sentPacketSizes.at
362  // (m_rcvdPacketSizes.size ()-1) << " Rcvd: " << rcvdPacketSize << std::endl;
363 }
364 
369 class SatFwdArqTestCase : public TestCase
370 {
371  public:
373  virtual ~SatFwdArqTestCase();
374 
379  void TransmitPdus(uint32_t numPackets);
380 
384  void NotifyTxOpportunity();
385 
390  void ReceivePdu(Ptr<Packet> p);
391 
398  bool SendAck(Ptr<SatControlMessage> msg, const Address& dest);
399 
404  void ReceiveAck(Ptr<SatArqAckMessage> ack);
405 
412  void Receive(Ptr<Packet> p, Mac48Address source, Mac48Address dest);
413 
414  private:
419  void Initialize();
420 
421  virtual void DoRun(void);
422 
423  // Same GSE ARQ handles both transmission and reception
424  // operations
425  Ptr<SatGenericStreamEncapsulatorArq> m_gse;
426 
427  // Random variable
428  Ptr<UniformRandomVariable> m_unif;
429 
430  // Addressing
431  Mac48Address m_source;
432  Mac48Address m_dest;
433 
434  // Number of created packets
435  uint32_t m_numPackets;
436 
437  // Short or normal BB frame
438  uint32_t m_frameBytes;
439 
440  // Number of generated time slots. When we run out of Tx opportunities
441  // the test is finished.
443 
444  // Error ratios
447 
448  // Propagation delay of the satellite channel
449  // = constant
451 
452  // Flow index for the GSE
453  uint8_t m_flowIndex;
454 
455  // Error probability threshold for HL packets. If the
456  // test results in higher error probability than the threshold
457  // the test is failed.
459 
460  // Interval for creating tx opportunities
462 
463  uint32_t m_txs;
464  uint32_t m_txErrors;
465  uint32_t m_acks;
466  uint32_t m_ackErrors;
467 
468  // Sent packet statistics
469  std::vector<uint32_t> m_sentPacketSizes;
470 
471  // Received packet statistics
472  std::vector<uint32_t> m_rcvdPacketSizes;
473 };
474 
476  : TestCase("Test GSE ARQ.")
477 {
478 }
479 
481 {
482  if (m_gse)
483  {
484  m_gse->DoDispose();
485  m_gse = NULL;
486  }
487 }
488 
489 void
491 {
492  m_numPackets = 1000;
493  m_frameBytes = 64800 / 8;
494  m_numTxOpportunities = 60000;
495  m_frameErrorRatio = 0.05;
496  m_ackErrorRatio = 0.05;
497  m_propagationDelay = MilliSeconds(270);
498  m_flowIndex = 0;
500  m_txoInterval = MilliSeconds(1);
501  m_txs = 0;
502  m_txErrors = 0;
503  m_acks = 0;
504  m_ackErrors = 0;
505 
506  m_source = Mac48Address::Allocate();
507  m_dest = Mac48Address::Allocate();
508 
509  // The parameters of RLE ARQ may be reconfigured
510  Config::SetDefault("ns3::SatQueue::MaxPackets", UintegerValue(1001));
511  Config::SetDefault("ns3::SatGenericStreamEncapsulatorArq::MaxNoOfRetransmissions",
512  UintegerValue(3));
513  Config::SetDefault("ns3::SatGenericStreamEncapsulatorArq::WindowSize", UintegerValue(50));
514  Config::SetDefault("ns3::SatGenericStreamEncapsulatorArq::RetransmissionTimer",
515  TimeValue(Seconds(0.6)));
516  Config::SetDefault("ns3::SatGenericStreamEncapsulatorArq::RxWaitingTime",
517  TimeValue(Seconds(2.3)));
518 
519  Ptr<SatQueue> queue = CreateObject<SatQueue>(m_flowIndex);
520  m_gse = CreateObject<SatGenericStreamEncapsulatorArq>(m_source,
521  m_dest,
522  m_source,
523  m_dest,
524  m_flowIndex);
525  m_gse->SetQueue(queue);
526 
527  // Create a receive callback to Receive method of this class.
528  m_gse->SetReceiveCallback(MakeCallback(&SatFwdArqTestCase::Receive, this));
529 
530  // Create ACK sending callback
531  m_gse->SetCtrlMsgCallback(MakeCallback(&SatFwdArqTestCase::SendAck, this));
532 
533  // Random variable for sent packet sizes and tx opportunities
534  m_unif = CreateObject<UniformRandomVariable>();
535 }
536 
537 void
539 {
540  // Set simulation output details
541  Singleton<SatEnvVariables>::Get()->DoInitialize();
542  Singleton<SatEnvVariables>::Get()->SetOutputVariables("test-sat-arq", "fwd", true);
543 
544  Initialize();
545 
546  // Enque packets to RLE
548 
549  // Schedule the first TxO
550  Simulator::Schedule(Seconds(0.1), &SatFwdArqTestCase::NotifyTxOpportunity, this);
551 
552  Simulator::Run();
553 
554  // Calculate HL error probability
555  double errorProb = 1.0 - (m_rcvdPacketSizes.size() / (double)m_sentPacketSizes.size());
556 
557  // std::cout << "FWD: Sent packets: " << m_sentPacketSizes.size () << " received packets: " <<
558  // m_rcvdPacketSizes.size () << std::endl; std::cout << "Tx: " << m_txs << " txErrors: " <<
559  // m_txErrors << " Acks: " << m_acks << " ackErrors: " << m_ackErrors << std::endl;
560 
561  NS_TEST_ASSERT_MSG_LT(errorProb,
563  "HL packet error probability is higher than threshold!");
564 
565  Simulator::Destroy();
566 
567  Singleton<SatEnvVariables>::Get()->DoDispose();
568 }
569 
570 void
572 {
573  // Create packets and push them to RLE
574  for (uint32_t i = 0; i < numPackets; ++i)
575  {
576  uint32_t packetSize = m_unif->GetInteger(3, 500);
577  Ptr<Packet> packet = Create<Packet>(packetSize);
578  m_sentPacketSizes.push_back(packetSize);
579  m_gse->EnquePdu(packet, m_dest);
580  }
581 }
582 
583 void
585 {
590  uint32_t nextMinTxO(0);
591 
592  // BB frame load
593  uint32_t frameBytes = m_frameBytes;
594  uint32_t bytesLeft = 1;
595 
596  std::vector<Ptr<Packet>> bbFrame;
597 
598  while (bytesLeft > 0)
599  {
600  Ptr<Packet> p = m_gse->NotifyTxOpportunity(frameBytes, bytesLeft, nextMinTxO);
601  if (p)
602  {
603  bbFrame.push_back(p);
604  frameBytes -= p->GetSize();
605  }
606  // No PDUs anymore
607  else
608  {
609  break;
610  }
611  }
612 
613  // If packet received
614  if (!bbFrame.empty())
615  {
616  m_txs += bbFrame.size();
617 
618  // Packet received after propagation delay
619  if (m_frameErrorRatio < m_unif->GetValue(0.0, 1.0))
620  {
621  for (std::vector<Ptr<Packet>>::iterator it = bbFrame.begin(); it != bbFrame.end(); ++it)
622  {
623  // Schedule packet receive
624  Simulator::Schedule(m_propagationDelay, &SatFwdArqTestCase::ReceivePdu, this, *it);
625  }
626  }
627  // Transmission error for packet
628  else
629  {
630  m_txErrors++;
631  }
632  }
633 
634  if (m_numTxOpportunities > 0)
635  {
636  // Schedule next TxO
637  Simulator::Schedule(m_txoInterval, &SatFwdArqTestCase::NotifyTxOpportunity, this);
638  }
639 
640  // Reduce count
642 }
643 
644 void
646 {
647  m_gse->ReceivePdu(p);
648 }
649 
650 bool
651 SatFwdArqTestCase::SendAck(Ptr<SatControlMessage> msg, const Address& dest)
652 {
653  m_acks++;
654 
655  // ACK received after propagation delay
656  if (m_ackErrorRatio < m_unif->GetValue(0.0, 1.0))
657  {
658  Ptr<SatArqAckMessage> ack = DynamicCast<SatArqAckMessage>(msg);
659  Simulator::Schedule(m_propagationDelay, &SatFwdArqTestCase::ReceiveAck, this, ack);
660  }
661  // Transmission error for ACK
662  else
663  {
664  m_ackErrors++;
665  }
666 
667  return true;
668 }
669 
670 void
671 SatFwdArqTestCase::ReceiveAck(Ptr<SatArqAckMessage> ack)
672 {
673  m_gse->ReceiveAck(ack);
674 }
675 
676 void
677 SatFwdArqTestCase::Receive(Ptr<Packet> p, Mac48Address source, Mac48Address dest)
678 {
679  uint32_t rcvdPacketSize = p->GetSize();
680  m_rcvdPacketSizes.push_back(rcvdPacketSize);
681 
682  // std::cout << "Now: " << Now ().GetSeconds () << " sent: " << m_sentPacketSizes.at
683  // (m_rcvdPacketSizes.size ()-1) << " Rcvd: " << rcvdPacketSize << std::endl;
684 }
685 
690 class SatArqTestSuite : public TestSuite
691 {
692  public:
693  SatArqTestSuite();
694 };
695 
697  : TestSuite("sat-arq-test", UNIT)
698 {
699  AddTestCase(new SatRtnArqTestCase, TestCase::QUICK);
700  AddTestCase(new SatFwdArqTestCase, TestCase::QUICK);
701 }
702 
703 // Do allocate an instance of this TestSuite
Test suite for ARQ.
FWD link ARQ test case.
std::vector< uint32_t > m_sentPacketSizes
void TransmitPdus(uint32_t numPackets)
Transmit/enque a number of packets to GSE/SatQueue.
void Initialize()
Initialize is called in DoRun method, since the test.py calls the test case constructors even if the ...
void NotifyTxOpportunity()
Notify Tx opportunity.
Ptr< UniformRandomVariable > m_unif
bool SendAck(Ptr< SatControlMessage > msg, const Address &dest)
Send ARQ ACK message to the sender (source)
std::vector< uint32_t > m_rcvdPacketSizes
Ptr< SatGenericStreamEncapsulatorArq > m_gse
void Receive(Ptr< Packet > p, Mac48Address source, Mac48Address dest)
Receive packet and check that it is of correct size.
void ReceiveAck(Ptr< SatArqAckMessage > ack)
Receive ARQ ACK message.
virtual void DoRun(void)
void ReceivePdu(Ptr< Packet > p)
Receive packet.
RTN link ARQ test case.
void NotifyTxOpportunity()
Notify Tx opportunity.
void Receive(Ptr< Packet > p, Mac48Address source, Mac48Address dest)
Receive packet and check that it is of correct size.
bool SendAck(Ptr< SatControlMessage > msg, const Address &dest)
Send ARQ ACK message to the sender (source)
Ptr< SatReturnLinkEncapsulatorArq > m_rle
Ptr< UniformRandomVariable > m_unif
void TransmitPdus(uint32_t numPackets)
Transmit/enque a number of packets to RLE/SatQueue.
void ReceiveAck(Ptr< SatArqAckMessage > ack)
Receive ARQ ACK message.
void Initialize()
Initialize is called in DoRun method, since the test.py calls the test case constructors even if the ...
virtual void DoRun(void)
std::vector< uint32_t > m_sentPacketSizes
void ReceivePdu(Ptr< Packet > p)
Receive packet.
std::vector< uint32_t > m_rcvdPacketSizes
SatArqSequenceNumber is handling the sequence numbers for the ARQ process.
static SatArqTestSuite satArqTestSuite