Loading...
Searching...
No Matches
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
39
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
56using namespace ns3;
57
62
63class SatRtnArqTestCase : public TestCase
64{
65 public:
67 virtual ~SatRtnArqTestCase();
68
73 void TransmitPdus(uint32_t numPackets);
74
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 = nullptr;
185 }
186}
187
188void
190{
191 m_numPackets = 1000;
192 m_numTxOpportunities = 60000;
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
235void
237{
238 // Set simulation output details
239 SatEnvVariables::GetInstance()->DoInitialize();
240 SatEnvVariables::GetInstance()->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 SatEnvVariables::GetInstance()->DoDispose();
265}
266
267void
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
280void
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
323void
325{
326 m_rle->ReceivePdu(p);
327}
328
329bool
330SatRtnArqTestCase::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
349void
350SatRtnArqTestCase::ReceiveAck(Ptr<SatArqAckMessage> ack)
351{
352 m_rle->ReceiveAck(ack);
353}
354
355void
356SatRtnArqTestCase::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
369class 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 = nullptr;
486 }
487}
488
489void
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,
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
537void
539{
540 // Set simulation output details
541 SatEnvVariables::GetInstance()->DoInitialize();
542 SatEnvVariables::GetInstance()->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 SatEnvVariables::GetInstance()->DoDispose();
568}
569
570void
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
583void
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
644void
646{
647 m_gse->ReceivePdu(p);
648}
649
650bool
651SatFwdArqTestCase::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
670void
671SatFwdArqTestCase::ReceiveAck(Ptr<SatArqAckMessage> ack)
672{
673 m_gse->ReceiveAck(ack);
674}
675
676void
677SatFwdArqTestCase::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
690class SatArqTestSuite : public TestSuite
691{
692 public:
694};
695
697 : TestSuite("sat-arq-test", Type::UNIT)
698{
699 AddTestCase(new SatRtnArqTestCase, TestCase::Duration::QUICK);
700 AddTestCase(new SatFwdArqTestCase, TestCase::Duration::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
static Ptr< SatEnvVariables > GetInstance()
SatArqSequenceNumber is handling the sequence numbers for the ARQ process.
static SatArqTestSuite satArqTestSuite