A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
lorawan-test-suite.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2017 University of Padova
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Author: Davide Magrin <magrinda@dei.unipd.it>
18 */
19
20// Include headers of classes to test
21#include "ns3/constant-position-mobility-model.h"
22#include "ns3/log.h"
23#include "ns3/lora-helper.h"
24#include "ns3/mobility-helper.h"
25#include "ns3/one-shot-sender-helper.h"
26#include "ns3/simple-end-device-lora-phy.h"
27#include "ns3/simple-gateway-lora-phy.h"
28
29// An essential include is test.h
30#include "ns3/test.h"
31
32using namespace ns3;
33using namespace lorawan;
34
35NS_LOG_COMPONENT_DEFINE("LorawanTestSuite");
36
37/**
38 * \ingroup lorawan
39 *
40 * It tests interference computations in a number of possible scenarios using the
41 * LoraInterferenceHelper class
42 */
44{
45 public:
46 InterferenceTest(); //!< Default constructor
47 ~InterferenceTest() override; //!< Destructor
48
49 private:
50 void DoRun() override;
51};
52
53// Add some help text to this case to describe what it is intended to test
55 : TestCase("Verify that LoraInterferenceHelper works as expected")
56{
57}
58
59// Reminder that the test case should clean up after itself
61{
62}
63
64// This method is the pure virtual method from class TestCase that every
65// TestCase must implement
66void
68{
69 NS_LOG_DEBUG("InterferenceTest");
70
71 LoraInterferenceHelper interferenceHelper;
72
73 double frequency = 868.1;
74 double differentFrequency = 868.3;
75
78
79 // Test overlap duration
80 event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequency);
81 event1 = interferenceHelper.Add(Seconds(1), 14, 12, nullptr, frequency);
82 NS_TEST_EXPECT_MSG_EQ(interferenceHelper.GetOverlapTime(event, event1),
83 Seconds(1),
84 "Overlap computation didn't give the expected result");
85 interferenceHelper.ClearAllEvents();
86
87 event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequency);
88 event1 = interferenceHelper.Add(Seconds(1.5), 14, 12, nullptr, frequency);
89 NS_TEST_EXPECT_MSG_EQ(interferenceHelper.GetOverlapTime(event, event1),
90 Seconds(1.5),
91 "Overlap computation didn't give the expected result");
92 interferenceHelper.ClearAllEvents();
93
94 event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequency);
95 event1 = interferenceHelper.Add(Seconds(3), 14, 12, nullptr, frequency);
96 NS_TEST_EXPECT_MSG_EQ(interferenceHelper.GetOverlapTime(event, event1),
97 Seconds(2),
98 "Overlap computation didn't give the expected result");
99 interferenceHelper.ClearAllEvents();
100
101 event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequency);
102 event1 = interferenceHelper.Add(Seconds(2), 14, 12, nullptr, frequency);
103 // Because of some strange behavior, this test would get stuck if we used the same syntax of the
104 // previous ones. This works instead.
105 bool retval = interferenceHelper.GetOverlapTime(event, event1) == Seconds(2);
106 NS_TEST_EXPECT_MSG_EQ(retval, true, "Overlap computation didn't give the expected result");
107 interferenceHelper.ClearAllEvents();
108
109 // Perfect overlap, packet survives
110 event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequency);
111 interferenceHelper.Add(Seconds(2), 14, 12, nullptr, frequency);
112 NS_TEST_EXPECT_MSG_EQ(interferenceHelper.IsDestroyedByInterference(event),
113 0,
114 "Packet did not survive interference as expected");
115 interferenceHelper.ClearAllEvents();
116
117 // Perfect overlap, packet survives
118 event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequency);
119 interferenceHelper.Add(Seconds(2), 14 - 7, 7, nullptr, frequency);
120 NS_TEST_EXPECT_MSG_EQ(interferenceHelper.IsDestroyedByInterference(event),
121 0,
122 "Packet did not survive interference as expected");
123 interferenceHelper.ClearAllEvents();
124
125 // Perfect overlap, packet destroyed
126 event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequency);
127 interferenceHelper.Add(Seconds(2), 14 - 6, 7, nullptr, frequency);
128 NS_TEST_EXPECT_MSG_EQ(interferenceHelper.IsDestroyedByInterference(event),
129 7,
130 "Packet was not destroyed by interference as expected");
131 interferenceHelper.ClearAllEvents();
132
133 // Partial overlap, packet survives
134 event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequency);
135 interferenceHelper.Add(Seconds(1), 14 - 6, 7, nullptr, frequency);
136 NS_TEST_EXPECT_MSG_EQ(interferenceHelper.IsDestroyedByInterference(event),
137 0,
138 "Packet did not survive interference as expected");
139 interferenceHelper.ClearAllEvents();
140
141 // Different frequencys
142 // Packet would be destroyed if they were on the same frequency, but survives
143 // since they are on different frequencies
144 event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequency);
145 interferenceHelper.Add(Seconds(2), 14, 7, nullptr, differentFrequency);
146 NS_TEST_EXPECT_MSG_EQ(interferenceHelper.IsDestroyedByInterference(event),
147 0,
148 "Packet did not survive interference as expected");
149 interferenceHelper.ClearAllEvents();
150
151 // Different SFs
152 // Packet would be destroyed if they both were SF7, but survives thanks to spreading factor
153 // semi-orthogonality
154 event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequency);
155 interferenceHelper.Add(Seconds(2), 14 + 16, 8, nullptr, frequency);
156 NS_TEST_EXPECT_MSG_EQ(interferenceHelper.IsDestroyedByInterference(event),
157 0,
158 "Packet did not survive interference as expected");
159 interferenceHelper.ClearAllEvents();
160
161 // Spreading factor imperfect orthogonality
162 // Different SFs are orthogonal only up to a point
163 event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequency);
164 interferenceHelper.Add(Seconds(2), 14 + 17, 8, nullptr, frequency);
165 NS_TEST_EXPECT_MSG_EQ(interferenceHelper.IsDestroyedByInterference(event),
166 8,
167 "Packet was not destroyed by interference as expected");
168 interferenceHelper.ClearAllEvents();
169
170 // If a more 'distant' spreading factor is used, isolation gets better
171 event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequency);
172 interferenceHelper.Add(Seconds(2), 14 + 17, 10, nullptr, frequency);
173 NS_TEST_EXPECT_MSG_EQ(interferenceHelper.IsDestroyedByInterference(event),
174 0,
175 "Packet was destroyed by interference while it should have survived");
176 interferenceHelper.ClearAllEvents();
177
178 // Cumulative interference
179 // Same spreading factor interference is cumulative
180 event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequency);
181 interferenceHelper.Add(Seconds(2), 14 + 16, 8, nullptr, frequency);
182 interferenceHelper.Add(Seconds(2), 14 + 16, 8, nullptr, frequency);
183 interferenceHelper.Add(Seconds(2), 14 + 16, 8, nullptr, frequency);
184 NS_TEST_EXPECT_MSG_EQ(interferenceHelper.IsDestroyedByInterference(event),
185 8,
186 "Packet was not destroyed by interference as expected");
187 interferenceHelper.ClearAllEvents();
188
189 // Cumulative interference
190 // Interference is not cumulative between different SFs
191 event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequency);
192 interferenceHelper.Add(Seconds(2), 14 + 16, 8, nullptr, frequency);
193 interferenceHelper.Add(Seconds(2), 14 + 16, 9, nullptr, frequency);
194 interferenceHelper.Add(Seconds(2), 14 + 16, 10, nullptr, frequency);
195 NS_TEST_EXPECT_MSG_EQ(interferenceHelper.IsDestroyedByInterference(event),
196 0,
197 "Packet did not survive interference as expected");
198 interferenceHelper.ClearAllEvents();
199}
200
201/**
202 * \ingroup lorawan
203 *
204 * It tests LoraDeviceAddress comparison operators overrides and generation of new addresses with
205 * LoraDeviceAddressGenerator
206 */
207class AddressTest : public TestCase
208{
209 public:
210 AddressTest(); //!< Default constructor
211 ~AddressTest() override; //!< Destructor
212
213 private:
214 void DoRun() override;
215};
216
217// Add some help text to this case to describe what it is intended to test
219 : TestCase("Verify that LoraDeviceAddress works as expected")
220{
221}
222
223// Reminder that the test case should clean up after itself
225{
226}
227
228// This method is the pure virtual method from class TestCase that every
229// TestCase must implement
230void
232{
233 NS_LOG_DEBUG("AddressTest");
234
235 //////////////////////////////////////
236 // Test the LoraDeviceAddress class //
237 //////////////////////////////////////
238
239 // Address equality
240 LoraDeviceAddress firstAddress(0xFFFFFFFF);
241 LoraDeviceAddress secondAddress(0xFFFFFFFF);
242 NS_TEST_EXPECT_MSG_EQ((firstAddress == secondAddress), true, "Addresses don't match");
243
244 // Address ordering
245 LoraDeviceAddress bigAddress(0xFFFFFF00);
246 LoraDeviceAddress smallAddress(0xFFF00000);
247 NS_TEST_EXPECT_MSG_EQ((bigAddress > smallAddress),
248 true,
249 "> function for addresses doesn't work correctly");
250
251 // Setting and getting
252 LoraDeviceAddress referenceAddress(0xFFFFFFFF);
253 LoraDeviceAddress address(0x00000000);
254 NS_TEST_EXPECT_MSG_EQ((address != referenceAddress), true, "Different addresses match!");
255 address.SetNwkAddr(0xFFFFFFF);
256 address.SetNwkID(0b1111111);
257 NS_TEST_EXPECT_MSG_EQ((address == referenceAddress),
258 true,
259 "Addresses set to be equal don't match");
260
261 // Serialization and deserialization
262 uint8_t buffer[4];
263 LoraDeviceAddress toSerialize(0x0F0F0F0F);
264 toSerialize.Serialize(buffer);
266 NS_TEST_EXPECT_MSG_EQ((toSerialize == deserialized),
267 true,
268 "Serialization + Deserialization doesn't yield an equal address");
269
270 ///////////////////////////////////
271 // Test the address generator class
272 ///////////////////////////////////
273
274 LoraDeviceAddressGenerator addressGenerator;
275 for (int i = 0; i < 200; i++)
276 {
277 addressGenerator.NextAddress();
278 }
279 // After 200 iterations, the address should be 0xC9
280 NS_TEST_EXPECT_MSG_EQ((addressGenerator.GetNextAddress() == LoraDeviceAddress(0xC9)),
281 true,
282 "LoraDeviceAddressGenerator doesn't increment as expected");
283}
284
285/**
286 * \ingroup lorawan
287 *
288 * It tests serialization/deserialization of LoRaWAN headers (the LorawanMacHeader and
289 * LoraFrameHeader classes) on packets
290 */
291class HeaderTest : public TestCase
292{
293 public:
294 HeaderTest(); //!< Default constructor
295 ~HeaderTest() override; //!< Destructor
296
297 private:
298 void DoRun() override;
299};
300
301// Add some help text to this case to describe what it is intended to test
303 : TestCase("Verify that LorawanMacHeader and LoraFrameHeader work as expected")
304{
305}
306
307// Reminder that the test case should clean up after itself
309{
310}
311
312// This method is the pure virtual method from class TestCase that every
313// TestCase must implement
314void
316{
317 NS_LOG_DEBUG("HeaderTest");
318
319 //////////////////////////////////
320 // Test the LorawanMacHeader class //
321 //////////////////////////////////
322 LorawanMacHeader macHdr;
324 macHdr.SetMajor(1);
325
326 Buffer macBuf;
327 macBuf.AddAtStart(100);
328 Buffer::Iterator macSerialized = macBuf.Begin();
329 macHdr.Serialize(macSerialized);
330
331 macHdr.Deserialize(macSerialized);
332
334 true,
335 "MType changes in the serialization/deserialization process");
336 NS_TEST_EXPECT_MSG_EQ((macHdr.GetMajor() == 1),
337 true,
338 "MType changes in the serialization/deserialization process");
339
340 ////////////////////////////////////
341 // Test the LoraFrameHeader class //
342 ////////////////////////////////////
343 LoraFrameHeader frameHdr;
344 frameHdr.SetAsDownlink();
345 frameHdr.SetAck(true);
346 frameHdr.SetAdr(false);
347 frameHdr.SetFCnt(1);
348 frameHdr.SetAddress(LoraDeviceAddress(56, 1864));
349 frameHdr.AddLinkCheckAns(10, 1);
350
351 // Serialization
352 Buffer buf;
353 buf.AddAtStart(100);
354 Buffer::Iterator serialized = buf.Begin();
355 frameHdr.Serialize(serialized);
356
357 // Deserialization
358 frameHdr.Deserialize(serialized);
359
360 Ptr<LinkCheckAns> command = (*(frameHdr.GetCommands().begin()))->GetObject<LinkCheckAns>();
361 uint8_t margin = command->GetMargin();
362 uint8_t gwCnt = command->GetGwCnt();
363
364 NS_TEST_EXPECT_MSG_EQ(frameHdr.GetAck(),
365 true,
366 "ACK bit changes in the serialization/deserialization process");
367 NS_TEST_EXPECT_MSG_EQ(frameHdr.GetAdr(),
368 false,
369 "ADR bit changes in the serialization/deserialization process");
371 1,
372 "FCnt changes in the serialization/deserialization process");
373 NS_TEST_EXPECT_MSG_EQ((frameHdr.GetAddress() == LoraDeviceAddress(56, 1864)),
374 true,
375 "Address changes in the serialization/deserialization process");
377 10,
378 "Margin changes in the serialization/deserialization process");
379 NS_TEST_EXPECT_MSG_EQ(gwCnt, 1, "GwCnt changes in the serialization/deserialization process");
380
381 /////////////////////////////////////////////////
382 // Test a combination of the two above classes //
383 /////////////////////////////////////////////////
384 Ptr<Packet> pkt = Create<Packet>(10);
385 pkt->AddHeader(frameHdr);
386 pkt->AddHeader(macHdr);
387
388 // Length = Payload + FrameHeader + MacHeader
389 // = 10 + (8+3) + 1 = 22
390 NS_TEST_EXPECT_MSG_EQ((pkt->GetSize()), 22, "Wrong size of packet + headers");
391
392 LorawanMacHeader macHdr1;
393
394 pkt->RemoveHeader(macHdr1);
395
396 NS_TEST_EXPECT_MSG_EQ((pkt->GetSize()), 21, "Wrong size of packet + headers - macHeader");
397
398 LoraFrameHeader frameHdr1;
399 frameHdr1.SetAsDownlink();
400
401 pkt->RemoveHeader(frameHdr1);
402 Ptr<LinkCheckAns> linkCheckAns =
403 (*(frameHdr1.GetCommands().begin()))->GetObject<LinkCheckAns>();
404
405 NS_TEST_EXPECT_MSG_EQ((pkt->GetSize()),
406 10,
407 "Wrong size of packet + headers - macHeader - frameHeader");
408
409 // Verify contents of removed MAC header
411 macHdr.GetMType(),
412 "Removed header contents don't match");
414 macHdr.GetMajor(),
415 "Removed header contents don't match");
416
417 // Verify contents of removed frame header
418 NS_TEST_EXPECT_MSG_EQ(frameHdr1.GetAck(),
419 frameHdr.GetAck(),
420 "Removed header contents don't match");
421 NS_TEST_EXPECT_MSG_EQ(frameHdr1.GetAdr(),
422 frameHdr.GetAdr(),
423 "Removed header contents don't match");
424 NS_TEST_EXPECT_MSG_EQ(frameHdr1.GetFCnt(),
425 frameHdr.GetFCnt(),
426 "Removed header contents don't match");
427 NS_TEST_EXPECT_MSG_EQ((frameHdr1.GetAddress() == frameHdr.GetAddress()),
428 true,
429 "Removed header contents don't match");
430 NS_TEST_EXPECT_MSG_EQ(linkCheckAns->GetMargin(),
431 10,
432 "Removed header's MAC command contents don't match");
433 NS_TEST_EXPECT_MSG_EQ(linkCheckAns->GetGwCnt(),
434 1,
435 "Removed header's MAC command contents don't match");
436}
437
438/**
439 * \ingroup lorawan
440 *
441 * It tests a number of cases related to SimpleGatewayLoraPhy's parallel reception paths
442 *
443 * \todo The test is commented out. To be fixed.
444 */
446{
447 public:
448 ReceivePathTest(); //!< Default constructor
449 ~ReceivePathTest() override; //!< Destructor
450
451 private:
452 void DoRun() override;
453 /**
454 * Reset counters and gateway PHY for new sub test case.
455 */
456 void Reset();
457 /**
458 * Callback for tracing OccupiedReceptionPaths.
459 *
460 * \param oldValue The old value.
461 * \param newValue The new value.
462 */
463 void OccupiedReceptionPaths(int oldValue, int newValue);
464 /**
465 * Callback for tracing LostPacketBecauseNoMoreReceivers.
466 *
467 * \param packet The packet lost.
468 * \param node The receiver node id if any, 0 otherwise.
469 */
471 /**
472 * Callback for tracing LostPacketBecauseInterference.
473 *
474 * \param packet The packet lost.
475 * \param node The receiver node id if any, 0 otherwise.
476 */
477 void Interference(Ptr<const Packet> packet, uint32_t node);
478 /**
479 * Callback for tracing ReceivedPacket.
480 *
481 * \param packet The packet received.
482 * \param node The receiver node id if any, 0 otherwise.
483 */
484 void ReceivedPacket(Ptr<const Packet> packet, uint32_t node);
485
486 Ptr<SimpleGatewayLoraPhy> gatewayPhy; //!< PHY layer of a gateway to be tested
487
488 int m_noMoreDemodulatorsCalls = 0; //!< Counter for LostPacketBecauseNoMoreReceivers calls
489 int m_interferenceCalls = 0; //!< Counter for LostPacketBecauseInterference calls
490 int m_receivedPacketCalls = 0; //!< Counter for ReceivedPacket calls
491 int m_maxOccupiedReceptionPaths = 0; //!< Max number of concurrent OccupiedReceptionPaths
492};
493
494// Add some help text to this case to describe what it is intended to test
496 : TestCase("Verify that ReceivePaths work as expected")
497{
498}
499
500// Reminder that the test case should clean up after itself
502{
503}
504
505void
507{
508 // FIXME
509 // m_noMoreDemodulatorsCalls = 0;
510 // m_interferenceCalls = 0;
511 // m_receivedPacketCalls = 0;
512 // m_maxOccupiedReceptionPaths = 0;
513
514 // gatewayPhy = CreateObject<SimpleGatewayLoraPhy> ();
515 // gatewayPhy->TraceConnectWithoutContext (
516 // "LostPacketBecauseNoMoreReceivers",
517 // MakeCallback (&ReceivePathTest::NoMoreDemodulators, this));
518 // gatewayPhy->TraceConnectWithoutContext ("LostPacketBecauseInterference",
519 // MakeCallback (&ReceivePathTest::Interference, this));
520 // gatewayPhy->TraceConnectWithoutContext ("ReceivedPacket",
521 // MakeCallback (&ReceivePathTest::ReceivedPacket,
522 // this));
523 // gatewayPhy->TraceConnectWithoutContext (
524 // "OccupiedReceptionPaths", MakeCallback (&ReceivePathTest::OccupiedReceptionPaths, this));
525
526 // // Add receive paths
527 // gatewayPhy->AddReceptionPath ();
528 // gatewayPhy->AddReceptionPath ();
529 // gatewayPhy->AddReceptionPath ();
530 // gatewayPhy->AddReceptionPath ();
531 // gatewayPhy->AddReceptionPath ();
532 // gatewayPhy->AddReceptionPath ();
533}
534
535void
537{
538 NS_LOG_FUNCTION(oldValue << newValue);
539
540 if (m_maxOccupiedReceptionPaths < newValue)
541 {
543 }
544}
545
546void
548{
549 NS_LOG_FUNCTION(packet << node);
550
552}
553
554void
556{
557 NS_LOG_FUNCTION(packet << node);
558
560}
561
562void
564{
565 NS_LOG_FUNCTION(packet << node);
566
568}
569
570// This method is the pure virtual method from class TestCase that every
571// TestCase must implement
572void
574{
575 NS_LOG_DEBUG("ReceivePathTest");
576
577 Ptr<Packet> packet = Create<Packet>();
578
579 Reset();
580
581 // FIXME
582 // //////////////////////////////////////////////////////////////////////////////////
583 // // If no ReceptionPath is configured to listen on a frequency, no packet is received
584 // //////////////////////////////////////////////////////////////////////////////////
585
586 // Simulator::Schedule (Seconds (1), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
587 // 14, 7,
588 // Seconds (1), frequency4);
589
590 // Simulator::Stop (Hours (2));
591 // Simulator::Run ();
592 // Simulator::Destroy ();
593
594 // NS_TEST_EXPECT_MSG_EQ (m_noMoreDemodulatorsCalls, 1, "Unexpected value");
595
596 // Reset ();
597
598 // //////////////////////////////////////////////////////////////////////////////
599 // // A ReceptionPath can receive a packet of any spreading factor without any preconfiguration
600 // //////////////////////////////////////////////////////////////////////////////
601
602 // Simulator::Schedule (Seconds (1), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
603 // 14, 7,
604 // Seconds (1), frequency1);
605 // Simulator::Schedule (Seconds (3), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
606 // 14, 8,
607 // Seconds (1), frequency1);
608 // Simulator::Schedule (Seconds (5), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
609 // 14, 9,
610 // Seconds (1), frequency1);
611 // Simulator::Schedule (Seconds (7), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
612 // 14, 10,
613 // Seconds (1), frequency1);
614 // Simulator::Schedule (Seconds (9), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
615 // 14, 11,
616 // Seconds (1), frequency1);
617 // Simulator::Schedule (Seconds (11), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
618 // 14,
619 // 12, Seconds (1), frequency1);
620
621 // Simulator::Stop (Hours (2));
622 // Simulator::Run ();
623 // Simulator::Destroy ();
624
625 // NS_TEST_EXPECT_MSG_EQ (m_noMoreDemodulatorsCalls, 0, "Unexpected value");
626 // NS_TEST_EXPECT_MSG_EQ (m_receivedPacketCalls, 6, "Unexpected value");
627
628 // Reset ();
629
630 // ///////////////////////////////////////////////////////////////////////////
631 // // Schedule two reception events at the first frequency, where there are two
632 // // reception paths listening. Each packet should be received correctly.
633 // ///////////////////////////////////////////////////////////////////////////
634 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
635 // 14, 7,
636 // Seconds (4), frequency1);
637 // Simulator::Schedule (Seconds (3), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
638 // 14, 9,
639 // Seconds (4), frequency1);
640
641 // Simulator::Stop (Hours (2));
642 // Simulator::Run ();
643 // Simulator::Destroy ();
644
645 // NS_TEST_EXPECT_MSG_EQ (m_noMoreDemodulatorsCalls, 0, "Unexpected value");
646 // NS_TEST_EXPECT_MSG_EQ (m_receivedPacketCalls, 2, "Unexpected value");
647
648 // Reset ();
649
650 // ///////////////////////////////////////////////////////////////////////////
651 // // Interference between packets on the same frequency and different ReceptionPaths
652 // ///////////////////////////////////////////////////////////////////////////
653 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
654 // 14, 7,
655 // Seconds (4), frequency1);
656 // Simulator::Schedule (Seconds (3), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
657 // 14, 7,
658 // Seconds (4), frequency1);
659
660 // Simulator::Stop (Hours (2));
661 // Simulator::Run ();
662 // Simulator::Destroy ();
663
664 // NS_TEST_EXPECT_MSG_EQ (m_noMoreDemodulatorsCalls, 0, "Unexpected value");
665 // NS_TEST_EXPECT_MSG_EQ (m_interferenceCalls, 2, "Unexpected value");
666
667 // Reset ();
668
669 // ///////////////////////////////////////////////////////////////////////////
670 // // Three receptions where only two receivePaths are available
671 // ///////////////////////////////////////////////////////////////////////////
672 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
673 // 14, 7,
674 // Seconds (4), frequency1);
675 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
676 // 14, 7,
677 // Seconds (4), frequency1);
678 // Simulator::Schedule (Seconds (3), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
679 // 14, 7,
680 // Seconds (4), frequency1);
681
682 // Simulator::Stop (Hours (2));
683 // Simulator::Run ();
684 // Simulator::Destroy ();
685
686 // NS_TEST_EXPECT_MSG_EQ (m_noMoreDemodulatorsCalls, 1, "Unexpected value");
687
688 // Reset ();
689
690 // ///////////////////////////////////////////////////////////////////////////
691 // // Packets that are on different frequencys do not interfere
692 // ///////////////////////////////////////////////////////////////////////////
693 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
694 // 14, 7,
695 // Seconds (4), frequency1);
696 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
697 // 14, 7,
698 // Seconds (4), frequency2);
699
700 // Simulator::Stop (Hours (2));
701 // Simulator::Run ();
702 // Simulator::Destroy ();
703
704 // NS_TEST_EXPECT_MSG_EQ (m_interferenceCalls, 0, "Unexpected value");
705
706 // Reset ();
707
708 // ///////////////////////////////////////////////////////////////////////////
709 // // Full capacity
710 // ///////////////////////////////////////////////////////////////////////////
711 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
712 // 14, 7,
713 // Seconds (4), frequency1);
714 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
715 // 14, 8,
716 // Seconds (4), frequency1);
717 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
718 // 14, 9,
719 // Seconds (4), frequency2);
720 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
721 // 14, 10,
722 // Seconds (4), frequency2);
723 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
724 // 14, 11,
725 // Seconds (4), frequency3);
726 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
727 // 14, 12,
728 // Seconds (4), frequency3);
729
730 // Simulator::Stop (Hours (2));
731 // Simulator::Run ();
732 // Simulator::Destroy ();
733
734 // NS_TEST_EXPECT_MSG_EQ (m_noMoreDemodulatorsCalls, 0, "Unexpected value");
735 // NS_TEST_EXPECT_MSG_EQ (m_interferenceCalls, 0, "Unexpected value");
736 // NS_TEST_EXPECT_MSG_EQ (m_receivedPacketCalls, 6, "Unexpected value");
737
738 // Reset ();
739
740 // ///////////////////////////////////////////////////////////////////////////
741 // // Full capacity + 1
742 // ///////////////////////////////////////////////////////////////////////////
743 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
744 // 14, 7,
745 // Seconds (4), frequency1);
746 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
747 // 14, 8,
748 // Seconds (4), frequency1);
749 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
750 // 14, 9,
751 // Seconds (4), frequency2);
752 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
753 // 14, 10,
754 // Seconds (4), frequency2);
755 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
756 // 14, 11,
757 // Seconds (4), frequency3);
758 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
759 // 14, 12,
760 // Seconds (4), frequency3);
761 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
762 // 14, 10,
763 // Seconds (4), frequency3);
764
765 // Simulator::Stop (Hours (2));
766 // Simulator::Run ();
767 // Simulator::Destroy ();
768
769 // NS_TEST_EXPECT_MSG_EQ (m_noMoreDemodulatorsCalls, 1, "Unexpected value");
770 // NS_TEST_EXPECT_MSG_EQ (m_interferenceCalls, 0, "Unexpected value");
771 // NS_TEST_EXPECT_MSG_EQ (m_receivedPacketCalls, 6, "Unexpected value");
772
773 // Reset ();
774
775 // ///////////////////////////////////////////////////////////////////////////
776 // // Receive Paths are correctly freed
777 // ///////////////////////////////////////////////////////////////////////////
778 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
779 // 14, 7,
780 // Seconds (4), frequency1);
781 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
782 // 14, 8,
783 // Seconds (4), frequency1);
784 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
785 // 14, 9,
786 // Seconds (4), frequency2);
787 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
788 // 14, 10,
789 // Seconds (4), frequency2);
790 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
791 // 14, 11,
792 // Seconds (4), frequency3);
793 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
794 // 14, 12,
795 // Seconds (4), frequency3);
796
797 // Simulator::Schedule (Seconds (8), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
798 // 14, 7,
799 // Seconds (4), frequency1);
800 // Simulator::Schedule (Seconds (8), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
801 // 14, 8,
802 // Seconds (4), frequency1);
803 // Simulator::Schedule (Seconds (8), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
804 // 14, 9,
805 // Seconds (4), frequency2);
806 // Simulator::Schedule (Seconds (8), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
807 // 14, 10,
808 // Seconds (4), frequency2);
809 // Simulator::Schedule (Seconds (8), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
810 // 14, 11,
811 // Seconds (4), frequency3);
812 // Simulator::Schedule (Seconds (8), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
813 // 14, 12,
814 // Seconds (4), frequency3);
815
816 // Simulator::Stop (Hours (2));
817 // Simulator::Run ();
818 // Simulator::Destroy ();
819
820 // NS_TEST_EXPECT_MSG_EQ (m_noMoreDemodulatorsCalls, 0, "Unexpected value");
821 // NS_TEST_EXPECT_MSG_EQ (m_interferenceCalls, 0, "Unexpected value");
822 // NS_TEST_EXPECT_MSG_EQ (m_receivedPacketCalls, 12, "Unexpected value");
823
824 // Reset ();
825
826 // ///////////////////////////////////////////////////////////////////////////
827 // // Receive Paths stay occupied exactly for the necessary time
828 // // Occupy both ReceptionPaths centered at frequency1
829 // ///////////////////////////////////////////////////////////////////////////
830 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
831 // 14, 7,
832 // Seconds (4), frequency1);
833 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
834 // 14, 8,
835 // Seconds (4), frequency1);
836
837 // // This packet will find no free ReceptionPaths
838 // Simulator::Schedule (Seconds (2 + 4) - NanoSeconds (1), &SimpleGatewayLoraPhy::StartReceive,
839 // gatewayPhy, packet, 14, 9, Seconds (4), frequency1);
840
841 // // This packet will find a free ReceptionPath
842 // Simulator::Schedule (Seconds (2 + 4) + NanoSeconds (1), &SimpleGatewayLoraPhy::StartReceive,
843 // gatewayPhy, packet, 14, 10, Seconds (4), frequency1);
844
845 // Simulator::Stop (Hours (2));
846 // Simulator::Run ();
847 // Simulator::Destroy ();
848
849 // NS_TEST_EXPECT_MSG_EQ (m_noMoreDemodulatorsCalls, 1, "Unexpected value");
850 // NS_TEST_EXPECT_MSG_EQ (m_interferenceCalls, 0, "Unexpected value");
851 // NS_TEST_EXPECT_MSG_EQ (m_receivedPacketCalls, 3, "Unexpected value");
852
853 // Reset ();
854
855 // ///////////////////////////////////////////////////////////////////////////
856 // // Only one ReceivePath locks on the incoming packet
857 // ///////////////////////////////////////////////////////////////////////////
858 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
859 // 14, 7,
860 // Seconds (4), frequency1);
861
862 // Simulator::Stop (Hours (2));
863 // Simulator::Run ();
864 // Simulator::Destroy ();
865
866 // NS_TEST_EXPECT_MSG_EQ (m_noMoreDemodulatorsCalls, 0, "Unexpected value");
867 // NS_TEST_EXPECT_MSG_EQ (m_interferenceCalls, 0, "Unexpected value");
868 // NS_TEST_EXPECT_MSG_EQ (m_receivedPacketCalls, 1, "Unexpected value");
869 // NS_TEST_EXPECT_MSG_EQ (m_maxOccupiedReceptionPaths, 1, "Unexpected value");
870}
871
872/**
873 * \ingroup lorawan
874 *
875 * It tests functionality of the LogicalLoraChannel, SubBand and LogicalLoraChannelHelper classes
876 */
878{
879 public:
880 LogicalLoraChannelTest(); //!< Default constructor
881 ~LogicalLoraChannelTest() override; //!< Destructor
882
883 private:
884 void DoRun() override;
885};
886
887// Add some help text to this case to describe what it is intended to test
889 : TestCase("Verify that LogicalLoraChannel and LogicalLoraChannelHelper work as expected")
890{
891}
892
893// Reminder that the test case should clean up after itself
895{
896}
897
898// This method is the pure virtual method from class TestCase that every
899// TestCase must implement
900void
902{
903 NS_LOG_DEBUG("LogicalLoraChannelTest");
904
905 /////////////////////////////
906 // Test LogicalLoraChannel //
907 /////////////////////////////
908
909 // Setup
910 Ptr<LogicalLoraChannel> channel1 = CreateObject<LogicalLoraChannel>(868);
911 Ptr<LogicalLoraChannel> channel2 = CreateObject<LogicalLoraChannel>(868);
912 Ptr<LogicalLoraChannel> channel3 = CreateObject<LogicalLoraChannel>(868.1);
913 Ptr<LogicalLoraChannel> channel4 = CreateObject<LogicalLoraChannel>(868.001);
914
915 // Equality between channels
916 // Test the == and != operators
917 NS_TEST_EXPECT_MSG_EQ(channel1, channel2, "== operator doesn't work as expected");
918 NS_TEST_EXPECT_MSG_NE(channel1, channel3, "!= operator doesn't work as expected");
919 NS_TEST_EXPECT_MSG_NE(channel1, channel4, "!= operator doesn't work as expected");
920
921 //////////////////
922 // Test SubBand //
923 //////////////////
924
925 // Setup
926 SubBand subBand(868, 868.7, 0.01, 14);
927 Ptr<LogicalLoraChannel> channel5 = CreateObject<LogicalLoraChannel>(870);
928
929 // Test BelongsToSubBand
930 NS_TEST_EXPECT_MSG_EQ(subBand.BelongsToSubBand(channel3),
931 true,
932 "BelongsToSubBand does not behave as expected");
933 NS_TEST_EXPECT_MSG_EQ(subBand.BelongsToSubBand(channel3->GetFrequency()),
934 true,
935 "BelongsToSubBand does not behave as expected");
936 NS_TEST_EXPECT_MSG_EQ(subBand.BelongsToSubBand(channel5),
937 false,
938 "BelongsToSubBand does not behave as expected");
939
940 ///////////////////////////////////
941 // Test LogicalLoraChannelHelper //
942 ///////////////////////////////////
943
944 // Setup
945 Ptr<LogicalLoraChannelHelper> channelHelper = CreateObject<LogicalLoraChannelHelper>();
946 SubBand subBand1(869, 869.4, 0.1, 27);
947 channel1 = CreateObject<LogicalLoraChannel>(868.1);
948 channel2 = CreateObject<LogicalLoraChannel>(868.3);
949 channel3 = CreateObject<LogicalLoraChannel>(868.5);
950 channel4 = CreateObject<LogicalLoraChannel>(869.1);
951 channel5 = CreateObject<LogicalLoraChannel>(869.3);
952
953 // Channel diagram
954 //
955 // Channels 1 2 3 4 5
956 // SubBands 868 ----- 0.1% ----- 868.7 869 ----- 1% ----- 869.4
957
958 // Add SubBands and LogicalLoraChannels to the helper
959 channelHelper->AddSubBand(&subBand);
960 channelHelper->AddSubBand(&subBand1);
961 channelHelper->AddChannel(channel1);
962 channelHelper->AddChannel(channel2);
963 channelHelper->AddChannel(channel3);
964 channelHelper->AddChannel(channel4);
965 channelHelper->AddChannel(channel5);
966
967 // Duty Cycle tests
968 // (high level duty cycle behavior)
969 ///////////////////////////////////
970
971 channelHelper->AddEvent(Seconds(2), channel1);
972 Time expectedTimeOff = Seconds(2 / 0.01 - 2);
973
974 // Waiting time is computed correctly
975 NS_TEST_EXPECT_MSG_EQ(channelHelper->GetWaitingTime(channel1),
976 expectedTimeOff,
977 "Waiting time doesn't behave as expected");
978
979 // Duty Cycle involves the whole SubBand, not just a channel
980 NS_TEST_EXPECT_MSG_EQ(channelHelper->GetWaitingTime(channel2),
981 expectedTimeOff,
982 "Waiting time doesn't behave as expected");
983 NS_TEST_EXPECT_MSG_EQ(channelHelper->GetWaitingTime(channel3),
984 expectedTimeOff,
985 "Waiting time doesn't behave as expected");
986
987 // Other bands are not affected by this transmission
988 NS_TEST_EXPECT_MSG_EQ(channelHelper->GetWaitingTime(channel4),
989 Time(0),
990 "Waiting time affects other subbands");
991 NS_TEST_EXPECT_MSG_EQ(channelHelper->GetWaitingTime(channel5),
992 Time(0),
993 "Waiting time affects other subbands");
994}
995
996/**
997 * \ingroup lorawan
998 *
999 * It tests the correctness of the LoraPhy::GetOnAirTime calculator against a number of pre-sourced
1000 * time values of known scenarios
1001 */
1003{
1004 public:
1005 TimeOnAirTest(); //!< Default constructor
1006 ~TimeOnAirTest() override; //!< Destructor
1007
1008 private:
1009 void DoRun() override;
1010};
1011
1012// Add some help text to this case to describe what it is intended to test
1014 : TestCase(
1015 "Verify that LoraPhy's function to compute the time on air of a packet works as expected")
1016{
1017}
1018
1019// Reminder that the test case should clean up after itself
1021{
1022}
1023
1024// This method is the pure virtual method from class TestCase that every
1025// TestCase must implement
1026void
1028{
1029 NS_LOG_DEBUG("TimeOnAirTest");
1030
1031 Ptr<Packet> packet;
1032 Time duration;
1033
1034 // Available parameters:
1035 // PayloadSize, SF, HeaderDisabled, CodingRate, Bandwidth, nPreambleSyms, crcEnabled,
1036 // lowDROptimization
1037
1038 // Starting parameters
1039 packet = Create<Packet>(10);
1040 LoraTxParameters txParams;
1041 txParams.sf = 7;
1042 txParams.headerDisabled = false;
1043 txParams.codingRate = 1;
1044 txParams.bandwidthHz = 125000;
1045 txParams.nPreamble = 8;
1046 txParams.crcEnabled = true;
1047 txParams.lowDataRateOptimizationEnabled = false;
1048
1049 duration = LoraPhy::GetOnAirTime(packet, txParams);
1050 NS_TEST_EXPECT_MSG_EQ_TOL(duration.GetSeconds(), 0.041216, 0.0001, "Unexpected duration");
1051
1052 txParams.sf = 8;
1053 duration = LoraPhy::GetOnAirTime(packet, txParams);
1054 NS_TEST_EXPECT_MSG_EQ_TOL(duration.GetSeconds(), 0.072192, 0.0001, "Unexpected duration");
1055
1056 txParams.headerDisabled = true;
1057 duration = LoraPhy::GetOnAirTime(packet, txParams);
1058 NS_TEST_EXPECT_MSG_EQ_TOL(duration.GetSeconds(), 0.072192, 0.0001, "Unexpected duration");
1059
1060 txParams.codingRate = 2;
1061 duration = LoraPhy::GetOnAirTime(packet, txParams);
1062 NS_TEST_EXPECT_MSG_EQ_TOL(duration.GetSeconds(), 0.078336, 0.0001, "Unexpected duration");
1063
1064 txParams.nPreamble = 10;
1065 duration = LoraPhy::GetOnAirTime(packet, txParams);
1066 NS_TEST_EXPECT_MSG_EQ_TOL(duration.GetSeconds(), 0.082432, 0.0001, "Unexpected duration");
1067
1068 txParams.lowDataRateOptimizationEnabled = true;
1069 duration = LoraPhy::GetOnAirTime(packet, txParams);
1070 NS_TEST_EXPECT_MSG_EQ_TOL(duration.GetSeconds(), 0.082432, 0.0001, "Unexpected duration");
1071
1072 txParams.sf = 10;
1073 duration = LoraPhy::GetOnAirTime(packet, txParams);
1074 NS_TEST_EXPECT_MSG_EQ_TOL(duration.GetSeconds(), 0.280576, 0.0001, "Unexpected duration");
1075
1076 txParams.bandwidthHz = 250000;
1077 duration = LoraPhy::GetOnAirTime(packet, txParams);
1078 NS_TEST_EXPECT_MSG_EQ_TOL(duration.GetSeconds(), 0.14028, 0.0001, "Unexpected duration");
1079
1080 txParams.bandwidthHz = 500000;
1081 duration = LoraPhy::GetOnAirTime(packet, txParams);
1082 NS_TEST_EXPECT_MSG_EQ_TOL(duration.GetSeconds(), 0.070144, 0.0001, "Unexpected duration");
1083
1084 txParams.headerDisabled = false;
1085 duration = LoraPhy::GetOnAirTime(packet, txParams);
1086 NS_TEST_EXPECT_MSG_EQ_TOL(duration.GetSeconds(), 0.082432, 0.0001, "Unexpected duration");
1087
1088 txParams.nPreamble = 8;
1089 duration = LoraPhy::GetOnAirTime(packet, txParams);
1090 NS_TEST_EXPECT_MSG_EQ_TOL(duration.GetSeconds(), 0.078336, 0.0001, "Unexpected duration");
1091
1092 txParams.sf = 12;
1093 duration = LoraPhy::GetOnAirTime(packet, txParams);
1094 NS_TEST_EXPECT_MSG_EQ_TOL(duration.GetSeconds(), 0.264192, 0.0001, "Unexpected duration");
1095
1096 packet = Create<Packet>(50);
1097 duration = LoraPhy::GetOnAirTime(packet, txParams);
1098 NS_TEST_EXPECT_MSG_EQ_TOL(duration.GetSeconds(), 0.657408, 0.0001, "Unexpected duration");
1099
1100 txParams.bandwidthHz = 125000;
1101 duration = LoraPhy::GetOnAirTime(packet, txParams);
1102 NS_TEST_EXPECT_MSG_EQ_TOL(duration.GetSeconds(), 2.629632, 0.0001, "Unexpected duration");
1103
1104 txParams.codingRate = 1;
1105 duration = LoraPhy::GetOnAirTime(packet, txParams);
1106 NS_TEST_EXPECT_MSG_EQ_TOL(duration.GetSeconds(), 2.301952, 0.0001, "Unexpected duration");
1107}
1108
1109/**
1110 * \ingroup lorawan
1111 *
1112 * It tests sending packets over a LoRa physical channel between multiple devices and the resulting
1113 * possible outcomes
1114 */
1116{
1117 public:
1118 PhyConnectivityTest(); //!< Default constructor
1119 ~PhyConnectivityTest() override; //!< Destructor
1120
1121 /**
1122 * Reset counters and end devices' PHYs for new sub test case.
1123 */
1124 void Reset();
1125
1126 /**
1127 * Callback for tracing ReceivedPacket.
1128 *
1129 * \param packet The packet received.
1130 * \param node The receiver node id if any, 0 otherwise.
1131 */
1132 void ReceivedPacket(Ptr<const Packet> packet, uint32_t node);
1133
1134 /**
1135 * Callback for tracing LostPacketBecauseUnderSensitivity.
1136 *
1137 * \param packet The packet lost.
1138 * \param node The receiver node id if any, 0 otherwise.
1139 */
1140 void UnderSensitivity(Ptr<const Packet> packet, uint32_t node);
1141
1142 /**
1143 * Callback for tracing LostPacketBecauseInterference.
1144 *
1145 * \param packet The packet lost.
1146 * \param node The receiver node id if any, 0 otherwise.
1147 */
1148 void Interference(Ptr<const Packet> packet, uint32_t node);
1149
1150 /**
1151 * Callback for tracing LostPacketBecauseWrongFrequency.
1152 *
1153 * \param packet The packet lost.
1154 * \param node The receiver node id if any, 0 otherwise.
1155 */
1156 void WrongFrequency(Ptr<const Packet> packet, uint32_t node);
1157
1158 /**
1159 * Callback for tracing LostPacketBecauseWrongSpreadingFactor.
1160 *
1161 * \param packet The packet lost.
1162 * \param node The receiver node id if any, 0 otherwise.
1163 */
1164 void WrongSf(Ptr<const Packet> packet, uint32_t node);
1165
1166 /**
1167 * Compare two packets to check if they are equal.
1168 *
1169 * \param packet1 A first packet.
1170 * \param packet2 A second packet.
1171 * \return True if their unique identifiers are equal,
1172 * \return false otherwise.
1173 */
1174 bool IsSamePacket(Ptr<Packet> packet1, Ptr<Packet> packet2);
1175
1176 private:
1177 void DoRun() override;
1178
1179 Ptr<LoraChannel> channel; //!< The LoRa channel used for tests
1180 Ptr<SimpleEndDeviceLoraPhy> edPhy1; //!< The first end device's PHY layer used in tests
1181 Ptr<SimpleEndDeviceLoraPhy> edPhy2; //!< The second end device's PHY layer used in tests
1182 Ptr<SimpleEndDeviceLoraPhy> edPhy3; //!< The third end device's PHY layer used in tests
1183
1184 Ptr<Packet> m_latestReceivedPacket; //!< Pointer to track the last received packet
1185 int m_receivedPacketCalls = 0; //!< Counter for ReceivedPacket calls
1186 int m_underSensitivityCalls = 0; //!< Counter for LostPacketBecauseUnderSensitivity calls
1187 int m_interferenceCalls = 0; //!< Counter for LostPacketBecauseInterference calls
1188 int m_wrongSfCalls = 0; //!< Counter for LostPacketBecauseWrongSpreadingFactor calls
1189 int m_wrongFrequencyCalls = 0; //!< Counter for LostPacketBecauseWrongFrequency calls
1190};
1191
1192// Add some help text to this case to describe what it is intended to test
1194 : TestCase("Verify that PhyConnectivity works as expected")
1195{
1196}
1197
1198// Reminder that the test case should clean up after itself
1200{
1201}
1202
1203void
1205{
1206 NS_LOG_FUNCTION(packet << node);
1207
1209
1210 m_latestReceivedPacket = packet->Copy();
1211}
1212
1213void
1215{
1216 NS_LOG_FUNCTION(packet << node);
1217
1219}
1220
1221void
1223{
1224 NS_LOG_FUNCTION(packet << node);
1225
1227}
1228
1229void
1231{
1232 NS_LOG_FUNCTION(packet << node);
1233
1235}
1236
1237void
1239{
1240 NS_LOG_FUNCTION(packet << node);
1241
1243}
1244
1245bool
1247{
1248 return packet1->GetUid() == packet2->GetUid();
1249}
1250
1251void
1253{
1257 m_wrongSfCalls = 0;
1259
1260 Ptr<LogDistancePropagationLossModel> loss = CreateObject<LogDistancePropagationLossModel>();
1261 loss->SetPathLossExponent(3.76);
1262 loss->SetReference(1, 7.7);
1263
1264 Ptr<PropagationDelayModel> delay = CreateObject<ConstantSpeedPropagationDelayModel>();
1265
1266 // Create the channel
1267 channel = CreateObject<LoraChannel>(loss, delay);
1268
1269 // Connect PHYs
1270 edPhy1 = CreateObject<SimpleEndDeviceLoraPhy>();
1271 edPhy2 = CreateObject<SimpleEndDeviceLoraPhy>();
1272 edPhy3 = CreateObject<SimpleEndDeviceLoraPhy>();
1273
1274 edPhy1->SetFrequency(868.1);
1275 edPhy2->SetFrequency(868.1);
1276 edPhy3->SetFrequency(868.1);
1277
1278 Ptr<ConstantPositionMobilityModel> mob1 = CreateObject<ConstantPositionMobilityModel>();
1279 Ptr<ConstantPositionMobilityModel> mob2 = CreateObject<ConstantPositionMobilityModel>();
1280 Ptr<ConstantPositionMobilityModel> mob3 = CreateObject<ConstantPositionMobilityModel>();
1281
1282 mob1->SetPosition(Vector(0.0, 0.0, 0.0));
1283 mob2->SetPosition(Vector(10.0, 0.0, 0.0));
1284 mob3->SetPosition(Vector(20.0, 0.0, 0.0));
1285
1286 edPhy1->SetMobility(mob1);
1287 edPhy2->SetMobility(mob2);
1288 edPhy3->SetMobility(mob3);
1289
1293
1294 channel->Add(edPhy1);
1295 channel->Add(edPhy2);
1296 channel->Add(edPhy3);
1297
1301
1302 // Listen for a specific SpreadingFactor
1306
1307 // Listen on a specific frequency
1308 edPhy1->SetFrequency(868.1);
1309 edPhy2->SetFrequency(868.1);
1310 edPhy3->SetFrequency(868.1);
1311
1312 edPhy1->TraceConnectWithoutContext("ReceivedPacket",
1314 edPhy2->TraceConnectWithoutContext("ReceivedPacket",
1316 edPhy3->TraceConnectWithoutContext("ReceivedPacket",
1318
1319 edPhy1->TraceConnectWithoutContext("LostPacketBecauseUnderSensitivity",
1321 edPhy2->TraceConnectWithoutContext("LostPacketBecauseUnderSensitivity",
1323 edPhy3->TraceConnectWithoutContext("LostPacketBecauseUnderSensitivity",
1325
1326 edPhy1->TraceConnectWithoutContext("LostPacketBecauseInterference",
1328 edPhy2->TraceConnectWithoutContext("LostPacketBecauseInterference",
1330 edPhy3->TraceConnectWithoutContext("LostPacketBecauseInterference",
1332
1333 edPhy1->TraceConnectWithoutContext("LostPacketBecauseWrongFrequency",
1335 edPhy2->TraceConnectWithoutContext("LostPacketBecauseWrongFrequency",
1337 edPhy3->TraceConnectWithoutContext("LostPacketBecauseWrongFrequency",
1339
1340 edPhy1->TraceConnectWithoutContext("LostPacketBecauseWrongSpreadingFactor",
1342 edPhy2->TraceConnectWithoutContext("LostPacketBecauseWrongSpreadingFactor",
1344 edPhy3->TraceConnectWithoutContext("LostPacketBecauseWrongSpreadingFactor",
1346}
1347
1348// This method is the pure virtual method from class TestCase that every
1349// TestCase must implement
1350void
1352{
1353 NS_LOG_DEBUG("PhyConnectivityTest");
1354
1355 // Setup
1356 ////////
1357
1358 Reset();
1359
1360 LoraTxParameters txParams;
1361 txParams.sf = 12;
1362
1363 uint8_t buffer[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
1364 Ptr<Packet> packet = Create<Packet>(buffer, 10);
1365
1366 // Testing
1367 //////////
1368
1369 // Basic packet delivery test
1370 /////////////////////////////
1371
1374 edPhy1,
1375 packet,
1376 txParams,
1377 868.1,
1378 14);
1379
1383
1386 2,
1387 "Channel skipped some PHYs when delivering a packet"); // All PHYs except the sender
1388
1389 Reset();
1390
1391 // Sleeping PHYs do not receive the packet
1392
1394
1397 edPhy1,
1398 packet,
1399 txParams,
1400 868.1,
1401 14);
1402
1406
1409 1,
1410 "Packet was received by a PHY in SLEEP mode"); // All PHYs in Standby except the sender
1411
1412 Reset();
1413
1414 // Packet that arrives under sensitivity is received correctly if the spreading factor increases
1415
1416 txParams.sf = 7;
1419 Vector(2990, 0, 0));
1420
1423 edPhy1,
1424 packet,
1425 txParams,
1426 868.1,
1427 14);
1428
1432
1435 1,
1436 "Packet that should have been lost because of low receive power was received");
1437
1438 Reset();
1439
1440 // Try again using a packet with higher spreading factor
1441 txParams.sf = 8;
1444 Vector(2990, 0, 0));
1445
1448 edPhy1,
1449 packet,
1450 txParams,
1451 868.1,
1452 14);
1453
1457
1459 0,
1460 "Packets that should have arrived above sensitivity were under it");
1461
1462 Reset();
1463
1464 // Packets can be destroyed by interference
1465
1466 txParams.sf = 12;
1469 edPhy1,
1470 packet,
1471 txParams,
1472 868.1,
1473 14);
1476 edPhy3,
1477 packet,
1478 txParams,
1479 868.1,
1480 14);
1481
1485
1487 1,
1488 "Packets that should be destroyed by interference weren't");
1489
1490 Reset();
1491
1492 // Packets can be lost because the PHY is not listening on the right frequency
1493
1496 edPhy1,
1497 packet,
1498 txParams,
1499 868.3,
1500 14);
1501
1505
1507 2,
1508 "Packets were received even though PHY was on a different frequency");
1509
1510 Reset();
1511
1512 // Packets can be lost because the PHY is not listening for the right spreading factor
1513
1514 txParams.sf = 8; // Send with 8, listening for 12
1517 edPhy1,
1518 packet,
1519 txParams,
1520 868.1,
1521 14);
1522
1526
1529 2,
1530 "Packets were received even though PHY was listening for a different spreading factor.");
1531
1532 Reset();
1533
1534 // Sending of packets
1535 /////////////////////
1536
1537 // The very same packet arrives at the other PHY
1540 edPhy1,
1541 packet,
1542 txParams,
1543 868.1,
1544 14);
1545
1549
1551 true,
1552 "Packet changed contents when going through the channel");
1553
1554 Reset();
1555
1556 // Correct state transitions
1557 ////////////////////////////
1558
1559 // PHY switches to STANDBY after TX and RX
1560
1563 edPhy1,
1564 packet,
1565 txParams,
1566 868.1,
1567 14);
1568
1572
1574 SimpleEndDeviceLoraPhy::STANDBY,
1575 "State didn't switch to STANDBY as expected");
1577 SimpleEndDeviceLoraPhy::STANDBY,
1578 "State didn't switch to STANDBY as expected");
1579}
1580
1581/**
1582 * \ingroup lorawan
1583 *
1584 * It tests the functionalities of the MAC layer of LoRaWAN devices
1585 *
1586 * \todo Not implemented yet.
1587 */
1589{
1590 public:
1591 LorawanMacTest(); //!< Default constructor
1592 ~LorawanMacTest() override; //!< Destructor
1593
1594 private:
1595 void DoRun() override;
1596};
1597
1598// Add some help text to this case to describe what it is intended to test
1600 : TestCase("Verify that the MAC layer of end devices behaves as expected")
1601{
1602}
1603
1604// Reminder that the test case should clean up after itself
1606{
1607}
1608
1609// This method is the pure virtual method from class TestCase that every
1610// TestCase must implement
1611void
1613{
1614 NS_LOG_DEBUG("LorawanMacTest");
1615}
1616
1617/**
1618 * \ingroup lorawan
1619 *
1620 * The TestSuite class names the TestSuite, identifies what type of TestSuite, and enables the
1621 * TestCases to be run. Typically, only the constructor for this class must be defined
1622 */
1624{
1625 public:
1626 LorawanTestSuite(); //!< Default constructor
1627};
1628
1630 : TestSuite("lorawan", Type::UNIT)
1631{
1632 LogComponentEnable("LorawanTestSuite", LOG_LEVEL_DEBUG);
1633 // TestDuration for TestCase can be QUICK, EXTENSIVE or TAKES_FOREVER
1641}
1642
1643// Do not forget to allocate an instance of this TestSuite
It tests LoraDeviceAddress comparison operators overrides and generation of new addresses with LoraDe...
AddressTest()
Default constructor.
void DoRun() override
Implementation to actually run this TestCase.
~AddressTest() override
Destructor.
It tests serialization/deserialization of LoRaWAN headers (the LorawanMacHeader and LoraFrameHeader c...
void DoRun() override
Implementation to actually run this TestCase.
HeaderTest()
Default constructor.
~HeaderTest() override
Destructor.
It tests interference computations in a number of possible scenarios using the LoraInterferenceHelper...
~InterferenceTest() override
Destructor.
void DoRun() override
Implementation to actually run this TestCase.
InterferenceTest()
Default constructor.
It tests functionality of the LogicalLoraChannel, SubBand and LogicalLoraChannelHelper classes.
LogicalLoraChannelTest()
Default constructor.
~LogicalLoraChannelTest() override
Destructor.
void DoRun() override
Implementation to actually run this TestCase.
It tests the functionalities of the MAC layer of LoRaWAN devices.
~LorawanMacTest() override
Destructor.
LorawanMacTest()
Default constructor.
void DoRun() override
Implementation to actually run this TestCase.
The TestSuite class names the TestSuite, identifies what type of TestSuite, and enables the TestCases...
LorawanTestSuite()
Default constructor.
It tests sending packets over a LoRa physical channel between multiple devices and the resulting poss...
int m_interferenceCalls
Counter for LostPacketBecauseInterference calls.
void Reset()
Reset counters and end devices' PHYs for new sub test case.
Ptr< SimpleEndDeviceLoraPhy > edPhy2
The second end device's PHY layer used in tests.
void WrongFrequency(Ptr< const Packet > packet, uint32_t node)
Callback for tracing LostPacketBecauseWrongFrequency.
void DoRun() override
Implementation to actually run this TestCase.
void UnderSensitivity(Ptr< const Packet > packet, uint32_t node)
Callback for tracing LostPacketBecauseUnderSensitivity.
bool IsSamePacket(Ptr< Packet > packet1, Ptr< Packet > packet2)
Compare two packets to check if they are equal.
Ptr< SimpleEndDeviceLoraPhy > edPhy3
The third end device's PHY layer used in tests.
Ptr< SimpleEndDeviceLoraPhy > edPhy1
The first end device's PHY layer used in tests.
int m_wrongSfCalls
Counter for LostPacketBecauseWrongSpreadingFactor calls.
int m_wrongFrequencyCalls
Counter for LostPacketBecauseWrongFrequency calls.
~PhyConnectivityTest() override
Destructor.
int m_underSensitivityCalls
Counter for LostPacketBecauseUnderSensitivity calls.
int m_receivedPacketCalls
Counter for ReceivedPacket calls.
void WrongSf(Ptr< const Packet > packet, uint32_t node)
Callback for tracing LostPacketBecauseWrongSpreadingFactor.
Ptr< LoraChannel > channel
The LoRa channel used for tests.
PhyConnectivityTest()
Default constructor.
void Interference(Ptr< const Packet > packet, uint32_t node)
Callback for tracing LostPacketBecauseInterference.
Ptr< Packet > m_latestReceivedPacket
Pointer to track the last received packet.
void ReceivedPacket(Ptr< const Packet > packet, uint32_t node)
Callback for tracing ReceivedPacket.
It tests a number of cases related to SimpleGatewayLoraPhy's parallel reception paths.
~ReceivePathTest() override
Destructor.
ReceivePathTest()
Default constructor.
int m_receivedPacketCalls
Counter for ReceivedPacket calls.
void OccupiedReceptionPaths(int oldValue, int newValue)
Callback for tracing OccupiedReceptionPaths.
Ptr< SimpleGatewayLoraPhy > gatewayPhy
PHY layer of a gateway to be tested.
void ReceivedPacket(Ptr< const Packet > packet, uint32_t node)
Callback for tracing ReceivedPacket.
void Interference(Ptr< const Packet > packet, uint32_t node)
Callback for tracing LostPacketBecauseInterference.
void NoMoreDemodulators(Ptr< const Packet > packet, uint32_t node)
Callback for tracing LostPacketBecauseNoMoreReceivers.
void DoRun() override
Implementation to actually run this TestCase.
int m_noMoreDemodulatorsCalls
Counter for LostPacketBecauseNoMoreReceivers calls.
void Reset()
Reset counters and gateway PHY for new sub test case.
int m_interferenceCalls
Counter for LostPacketBecauseInterference calls.
int m_maxOccupiedReceptionPaths
Max number of concurrent OccupiedReceptionPaths.
It tests the correctness of the LoraPhy::GetOnAirTime calculator against a number of pre-sourced time...
void DoRun() override
Implementation to actually run this TestCase.
~TimeOnAirTest() override
Destructor.
TimeOnAirTest()
Default constructor.
iterator in a Buffer instance
Definition: buffer.h:100
automatically resized byte buffer
Definition: buffer.h:94
void AddAtStart(uint32_t start)
Definition: buffer.cc:314
Buffer::Iterator Begin() const
Definition: buffer.h:1074
Mobility model for which the current position does not change once it has been set and until it is se...
bool TraceConnectWithoutContext(std::string name, const CallbackBase &cb)
Connect a TraceSource to a Callback without a context.
Definition: object-base.cc:322
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition: object.h:522
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:571
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition: simulator.cc:142
static void Run()
Run the simulation.
Definition: simulator.cc:178
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Definition: simulator.cc:186
encapsulates test code
Definition: test.h:1061
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:302
A suite of tests to run.
Definition: test.h:1273
Type
Type of test.
Definition: test.h:1280
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:403
void SwitchToSleep()
Switch to the SLEEP state.
EndDeviceLoraPhy::State GetState()
Return the state this end device is currently in.
void SetFrequency(double frequencyMHz)
Set the frequency this end device will listen on.
void SwitchToStandby()
Switch to the STANDBY state.
void SetSpreadingFactor(uint8_t sf)
Set the Spreading Factor this end device will listen for.
void Add(Ptr< LoraPhy > phy)
Connect a LoraPhy object to the LoraChannel.
Definition: lora-channel.cc:83
This class generates sequential LoraDeviceAddress instances.
LoraDeviceAddress NextAddress()
Allocate the next LoraDeviceAddress.
LoraDeviceAddress GetNextAddress()
Get the LoraDeviceAddress that will be allocated upon a call to NextAddress.
This class represents the device address of a LoraWAN end device.
static LoraDeviceAddress Deserialize(const uint8_t buf[4])
Convert the input buffer into a new address.
void Serialize(uint8_t buf[4]) const
Convert this address to a buffer.
This class represents the Frame header (FHDR) used in a LoraWAN network.
bool GetAck() const
Get the value of the ACK bit field.
uint32_t Deserialize(Buffer::Iterator start) override
Deserialize the contents of the buffer into a LoraFrameHeader object.
void SetFCnt(uint16_t fCnt)
Set the FCnt value.
bool GetAdr() const
Get the value of the ADR bit field.
void SetAck(bool ack)
Set the value of the ACK bit field.
void SetAdr(bool adr)
Set the value of the ADR bit field.
void SetAddress(LoraDeviceAddress address)
Set the address.
uint16_t GetFCnt() const
Get the FCnt value.
LoraDeviceAddress GetAddress() const
Get this header's device address value.
void Serialize(Buffer::Iterator start) const override
Serialize the header.
void AddLinkCheckAns(uint8_t margin, uint8_t gwCnt)
Add a LinkCheckAns command.
std::list< Ptr< MacCommand > > GetCommands()
Return a list of pointers to all the MAC commands saved in this header.
void SetAsDownlink()
State that this is a downlink message.
Helper for LoraPhy that manages interference calculations.
Ptr< LoraInterferenceHelper::Event > Add(Time duration, double rxPower, uint8_t spreadingFactor, Ptr< Packet > packet, double frequencyMHz)
Add an event to the InterferenceHelper.
Time GetOverlapTime(Ptr< LoraInterferenceHelper::Event > event1, Ptr< LoraInterferenceHelper::Event > event2)
Compute the time duration in which two given events are overlapping.
void ClearAllEvents()
Delete all events in the LoraInterferenceHelper.
uint8_t IsDestroyedByInterference(Ptr< LoraInterferenceHelper::Event > event)
Determine whether the event was destroyed by interference or not.
static Time GetOnAirTime(Ptr< Packet > packet, LoraTxParameters txParams)
Compute the time that a packet with certain characteristics will take to be transmitted.
Definition: lora-phy.cc:167
void SetMobility(Ptr< MobilityModel > mobility)
Set the mobility model associated to this PHY.
Definition: lora-phy.cc:127
void SetChannel(Ptr< LoraChannel > channel)
Set the LoraChannel instance PHY transmits on.
Definition: lora-phy.cc:135
Ptr< MobilityModel > GetMobility()
Get the mobility model associated to this PHY.
Definition: lora-phy.cc:110
This class represents the Mac header of a LoRaWAN packet.
void SetMajor(uint8_t major)
Set the major version of this header.
uint32_t Deserialize(Buffer::Iterator start) override
Deserialize the header.
uint8_t GetMType() const
Get the message type from the header.
void Serialize(Buffer::Iterator start) const override
Serialize the header.
void SetMType(enum MType mtype)
Set the message type.
uint8_t GetMajor() const
Get the major version from the header.
void Send(Ptr< Packet > packet, LoraTxParameters txParams, double frequencyMHz, double txPowerDbm) override
Instruct the PHY to send a packet according to some parameters.
Class representing a SubBand, i.e., a frequency band subject to some regulations on duty cycle and tr...
Definition: sub-band.h:42
bool BelongsToSubBand(double frequency) const
Return whether or not a frequency belongs to this SubBand.
Definition: sub-band.cc:76
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_TEST_EXPECT_MSG_NE(actual, limit, msg)
Test that an actual and expected (limit) value are not equal and report if not.
Definition: test.h:667
#define NS_TEST_EXPECT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report if not.
Definition: test.h:252
#define NS_TEST_EXPECT_MSG_EQ_TOL(actual, limit, tol, msg)
Test that actual and expected (limit) values are equal to plus or minus some tolerance and report if ...
Definition: test.h:511
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1319
Time Hours(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1295
static LorawanTestSuite lorawanTestSuite
Every class exported by the ns3 library is enclosed in the ns3 namespace.
void LogComponentEnable(const std::string &name, LogLevel level)
Enable the logging output associated with that log component.
Definition: log.cc:302
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:700
@ LOG_LEVEL_DEBUG
LOG_DEBUG and above.
Definition: log.h:113
Structure to collect all parameters that are used to compute the duration of a packet (excluding payl...
Definition: lora-phy.h:49
uint8_t codingRate
Code rate (obtained as 4/(codingRate+4))
Definition: lora-phy.h:52
uint32_t nPreamble
Number of preamble symbols.
Definition: lora-phy.h:54
bool headerDisabled
Whether to use implicit header mode.
Definition: lora-phy.h:51
double bandwidthHz
Bandwidth in Hz.
Definition: lora-phy.h:53
bool lowDataRateOptimizationEnabled
Whether low data rate optimization is enabled.
Definition: lora-phy.h:56
bool crcEnabled
Whether Cyclic Redundancy Check (CRC) is enabled.
Definition: lora-phy.h:55
uint8_t sf
Spreading Factor.
Definition: lora-phy.h:50