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