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// An essential include is test.h
10#include "ns3/constant-position-mobility-model.h"
11#include "ns3/simulator.h"
12#include "ns3/test.h"
13
14// Include headers of classes to test
15#include "ns3/lorawan-module.h"
16
17using namespace ns3;
18using namespace lorawan;
19
20NS_LOG_COMPONENT_DEFINE("LorawanTestSuite");
21
22/**
23 * @ingroup lorawan
24 *
25 * It tests interference computations in a number of possible scenarios using the
26 * LoraInterferenceHelper class
27 */
29{
30 public:
31 InterferenceTest(); //!< Default constructor
32 ~InterferenceTest() override; //!< Destructor
33
34 private:
35 void DoRun() override;
36};
37
38// Add some help text to this case to describe what it is intended to test
40 : TestCase("Verify that LoraInterferenceHelper works as expected")
41{
42}
43
44// Reminder that the test case should clean up after itself
48
49// This method is the pure virtual method from class TestCase that every
50// TestCase must implement
51void
53{
54 NS_LOG_DEBUG("InterferenceTest");
55
56 LoraInterferenceHelper interferenceHelper;
57
58 uint32_t frequencyHz = 868100000;
59 uint32_t differentFrequencyHz = 868300000;
60
63
64 // Test overlap duration
65 event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequencyHz);
66 event1 = interferenceHelper.Add(Seconds(1), 14, 12, nullptr, frequencyHz);
67 NS_TEST_EXPECT_MSG_EQ(interferenceHelper.GetOverlapTime(event, event1),
68 Seconds(1),
69 "Overlap computation didn't give the expected result");
70 interferenceHelper.ClearAllEvents();
71
72 event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequencyHz);
73 event1 = interferenceHelper.Add(Seconds(1.5), 14, 12, nullptr, frequencyHz);
74 NS_TEST_EXPECT_MSG_EQ(interferenceHelper.GetOverlapTime(event, event1),
75 Seconds(1.5),
76 "Overlap computation didn't give the expected result");
77 interferenceHelper.ClearAllEvents();
78
79 event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequencyHz);
80 event1 = interferenceHelper.Add(Seconds(3), 14, 12, nullptr, frequencyHz);
81 NS_TEST_EXPECT_MSG_EQ(interferenceHelper.GetOverlapTime(event, event1),
82 Seconds(2),
83 "Overlap computation didn't give the expected result");
84 interferenceHelper.ClearAllEvents();
85
86 event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequencyHz);
87 event1 = interferenceHelper.Add(Seconds(2), 14, 12, nullptr, frequencyHz);
88 // Because of some strange behavior, this test would get stuck if we used the same syntax of the
89 // previous ones. This works instead.
90 bool retval = interferenceHelper.GetOverlapTime(event, event1) == Seconds(2);
91 NS_TEST_EXPECT_MSG_EQ(retval, true, "Overlap computation didn't give the expected result");
92 interferenceHelper.ClearAllEvents();
93
94 // Perfect overlap, packet survives
95 event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequencyHz);
96 interferenceHelper.Add(Seconds(2), 14, 12, nullptr, frequencyHz);
97 NS_TEST_EXPECT_MSG_EQ(interferenceHelper.IsDestroyedByInterference(event),
98 0,
99 "Packet did not survive interference as expected");
100 interferenceHelper.ClearAllEvents();
101
102 // Perfect overlap, packet survives
103 event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequencyHz);
104 interferenceHelper.Add(Seconds(2), 14 - 7, 7, nullptr, frequencyHz);
105 NS_TEST_EXPECT_MSG_EQ(interferenceHelper.IsDestroyedByInterference(event),
106 0,
107 "Packet did not survive interference as expected");
108 interferenceHelper.ClearAllEvents();
109
110 // Perfect overlap, packet destroyed
111 event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequencyHz);
112 interferenceHelper.Add(Seconds(2), 14 - 6, 7, nullptr, frequencyHz);
113 NS_TEST_EXPECT_MSG_EQ(interferenceHelper.IsDestroyedByInterference(event),
114 7,
115 "Packet was not destroyed by interference as expected");
116 interferenceHelper.ClearAllEvents();
117
118 // Partial overlap, packet survives
119 event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequencyHz);
120 interferenceHelper.Add(Seconds(1), 14 - 6, 7, nullptr, frequencyHz);
121 NS_TEST_EXPECT_MSG_EQ(interferenceHelper.IsDestroyedByInterference(event),
122 0,
123 "Packet did not survive interference as expected");
124 interferenceHelper.ClearAllEvents();
125
126 // Different frequencys
127 // Packet would be destroyed if they were on the same frequency, but survives
128 // since they are on different frequencies
129 event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequencyHz);
130 interferenceHelper.Add(Seconds(2), 14, 7, nullptr, differentFrequencyHz);
131 NS_TEST_EXPECT_MSG_EQ(interferenceHelper.IsDestroyedByInterference(event),
132 0,
133 "Packet did not survive interference as expected");
134 interferenceHelper.ClearAllEvents();
135
136 // Different SFs
137 // Packet would be destroyed if they both were SF7, but survives thanks to spreading factor
138 // semi-orthogonality
139 event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequencyHz);
140 interferenceHelper.Add(Seconds(2), 14 + 16, 8, nullptr, frequencyHz);
141 NS_TEST_EXPECT_MSG_EQ(interferenceHelper.IsDestroyedByInterference(event),
142 0,
143 "Packet did not survive interference as expected");
144 interferenceHelper.ClearAllEvents();
145
146 // Spreading factor imperfect orthogonality
147 // Different SFs are orthogonal only up to a point
148 event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequencyHz);
149 interferenceHelper.Add(Seconds(2), 14 + 17, 8, nullptr, frequencyHz);
150 NS_TEST_EXPECT_MSG_EQ(interferenceHelper.IsDestroyedByInterference(event),
151 8,
152 "Packet was not destroyed by interference as expected");
153 interferenceHelper.ClearAllEvents();
154
155 // If a more 'distant' spreading factor is used, isolation gets better
156 event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequencyHz);
157 interferenceHelper.Add(Seconds(2), 14 + 17, 10, nullptr, frequencyHz);
158 NS_TEST_EXPECT_MSG_EQ(interferenceHelper.IsDestroyedByInterference(event),
159 0,
160 "Packet was destroyed by interference while it should have survived");
161 interferenceHelper.ClearAllEvents();
162
163 // Cumulative interference
164 // Same spreading factor interference is cumulative
165 event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequencyHz);
166 interferenceHelper.Add(Seconds(2), 14 + 16, 8, nullptr, frequencyHz);
167 interferenceHelper.Add(Seconds(2), 14 + 16, 8, nullptr, frequencyHz);
168 interferenceHelper.Add(Seconds(2), 14 + 16, 8, nullptr, frequencyHz);
169 NS_TEST_EXPECT_MSG_EQ(interferenceHelper.IsDestroyedByInterference(event),
170 8,
171 "Packet was not destroyed by interference as expected");
172 interferenceHelper.ClearAllEvents();
173
174 // Cumulative interference
175 // Interference is not cumulative between different SFs
176 event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequencyHz);
177 interferenceHelper.Add(Seconds(2), 14 + 16, 8, nullptr, frequencyHz);
178 interferenceHelper.Add(Seconds(2), 14 + 16, 9, nullptr, frequencyHz);
179 interferenceHelper.Add(Seconds(2), 14 + 16, 10, nullptr, frequencyHz);
180 NS_TEST_EXPECT_MSG_EQ(interferenceHelper.IsDestroyedByInterference(event),
181 0,
182 "Packet did not survive interference as expected");
183 interferenceHelper.ClearAllEvents();
184}
185
186/**
187 * @ingroup lorawan
188 *
189 * It tests LoraDeviceAddress comparison operators overrides and generation of new addresses with
190 * LoraDeviceAddressGenerator
191 */
192class AddressTest : public TestCase
193{
194 public:
195 AddressTest(); //!< Default constructor
196 ~AddressTest() override; //!< Destructor
197
198 private:
199 void DoRun() override;
200};
201
202// Add some help text to this case to describe what it is intended to test
204 : TestCase("Verify that LoraDeviceAddress works as expected")
205{
206}
207
208// Reminder that the test case should clean up after itself
212
213// This method is the pure virtual method from class TestCase that every
214// TestCase must implement
215void
217{
218 NS_LOG_DEBUG("AddressTest");
219
220 //////////////////////////////////////
221 // Test the LoraDeviceAddress class //
222 //////////////////////////////////////
223
224 // Address equality
225 LoraDeviceAddress firstAddress(0xFFFFFFFF);
226 LoraDeviceAddress secondAddress(0xFFFFFFFF);
227 NS_TEST_EXPECT_MSG_EQ((firstAddress == secondAddress), true, "Addresses don't match");
228
229 // Address ordering
230 LoraDeviceAddress bigAddress(0xFFFFFF00);
231 LoraDeviceAddress smallAddress(0xFFF00000);
232 NS_TEST_EXPECT_MSG_EQ((bigAddress > smallAddress),
233 true,
234 "> function for addresses doesn't work correctly");
235
236 // Setting and getting
237 LoraDeviceAddress referenceAddress(0xFFFFFFFF);
238 LoraDeviceAddress address(0x00000000);
239 NS_TEST_EXPECT_MSG_EQ((address != referenceAddress), true, "Different addresses match!");
240 address.SetNwkAddr(0xFFFFFFF);
241 address.SetNwkID(0b1111111);
242 NS_TEST_EXPECT_MSG_EQ((address == referenceAddress),
243 true,
244 "Addresses set to be equal don't match");
245
246 // Serialization and deserialization
247 uint8_t buffer[4];
248 LoraDeviceAddress toSerialize(0x0F0F0F0F);
249 toSerialize.Serialize(buffer);
251 NS_TEST_EXPECT_MSG_EQ((toSerialize == deserialized),
252 true,
253 "Serialization + Deserialization doesn't yield an equal address");
254
255 ///////////////////////////////////
256 // Test the address generator class
257 ///////////////////////////////////
258
259 LoraDeviceAddressGenerator addressGenerator;
260 for (int i = 0; i < 200; i++)
261 {
262 addressGenerator.NextAddress();
263 }
264 // After 200 iterations, the address should be 0xC9
265 NS_TEST_EXPECT_MSG_EQ((addressGenerator.GetNextAddress() == LoraDeviceAddress(0xC9)),
266 true,
267 "LoraDeviceAddressGenerator doesn't increment as expected");
268}
269
270/**
271 * @ingroup lorawan
272 *
273 * It tests serialization/deserialization of LoRaWAN headers (the LorawanMacHeader and
274 * LoraFrameHeader classes) on packets
275 */
276class HeaderTest : public TestCase
277{
278 public:
279 HeaderTest(); //!< Default constructor
280 ~HeaderTest() override; //!< Destructor
281
282 private:
283 void DoRun() override;
284};
285
286// Add some help text to this case to describe what it is intended to test
288 : TestCase("Verify that LorawanMacHeader and LoraFrameHeader work as expected")
289{
290}
291
292// Reminder that the test case should clean up after itself
296
297// This method is the pure virtual method from class TestCase that every
298// TestCase must implement
299void
301{
302 NS_LOG_DEBUG("HeaderTest");
303
304 //////////////////////////////////
305 // Test the LorawanMacHeader class //
306 //////////////////////////////////
307 LorawanMacHeader macHdr;
309 macHdr.SetMajor(1);
310
311 Buffer macBuf;
312 macBuf.AddAtStart(100);
313 Buffer::Iterator macSerialized = macBuf.Begin();
314 macHdr.Serialize(macSerialized);
315
316 macHdr.Deserialize(macSerialized);
317
319 true,
320 "MType changes in the serialization/deserialization process");
321 NS_TEST_EXPECT_MSG_EQ((macHdr.GetMajor() == 1),
322 true,
323 "MType changes in the serialization/deserialization process");
324
325 ////////////////////////////////////
326 // Test the LoraFrameHeader class //
327 ////////////////////////////////////
328 LoraFrameHeader frameHdr;
329 frameHdr.SetAsDownlink();
330 frameHdr.SetAck(true);
331 frameHdr.SetAdr(false);
332 frameHdr.SetFCnt(1);
333 frameHdr.SetAddress(LoraDeviceAddress(56, 1864));
334 frameHdr.AddLinkCheckAns(10, 1);
335
336 // Serialization
337 Buffer buf;
338 buf.AddAtStart(100);
339 Buffer::Iterator serialized = buf.Begin();
340 frameHdr.Serialize(serialized);
341
342 // Deserialization
343 frameHdr.Deserialize(serialized);
344
345 Ptr<LinkCheckAns> command = DynamicCast<LinkCheckAns>(frameHdr.GetCommands().at(0));
346 uint8_t margin = command->GetMargin();
347 uint8_t gwCnt = command->GetGwCnt();
348
349 NS_TEST_EXPECT_MSG_EQ(frameHdr.GetAck(),
350 true,
351 "ACK bit changes in the serialization/deserialization process");
352 NS_TEST_EXPECT_MSG_EQ(frameHdr.GetAdr(),
353 false,
354 "ADR bit changes in the serialization/deserialization process");
356 1,
357 "FCnt changes in the serialization/deserialization process");
358 NS_TEST_EXPECT_MSG_EQ((frameHdr.GetAddress() == LoraDeviceAddress(56, 1864)),
359 true,
360 "Address changes in the serialization/deserialization process");
362 10,
363 "Margin changes in the serialization/deserialization process");
364 NS_TEST_EXPECT_MSG_EQ(gwCnt, 1, "GwCnt changes in the serialization/deserialization process");
365
366 /////////////////////////////////////////////////
367 // Test a combination of the two above classes //
368 /////////////////////////////////////////////////
369 Ptr<Packet> pkt = Create<Packet>(10);
370 pkt->AddHeader(frameHdr);
371 pkt->AddHeader(macHdr);
372
373 // Length = Payload + FrameHeader + MacHeader
374 // = 10 + (8+3) + 1 = 22
375 NS_TEST_EXPECT_MSG_EQ((pkt->GetSize()), 22, "Wrong size of packet + headers");
376
377 LorawanMacHeader macHdr1;
378
379 pkt->RemoveHeader(macHdr1);
380
381 NS_TEST_EXPECT_MSG_EQ((pkt->GetSize()), 21, "Wrong size of packet + headers - macHeader");
382
383 LoraFrameHeader frameHdr1;
384 frameHdr1.SetAsDownlink();
385
386 pkt->RemoveHeader(frameHdr1);
387 Ptr<LinkCheckAns> linkCheckAns = DynamicCast<LinkCheckAns>(frameHdr1.GetCommands().at(0));
388
389 NS_TEST_EXPECT_MSG_EQ((pkt->GetSize()),
390 10,
391 "Wrong size of packet + headers - macHeader - frameHeader");
392
393 // Verify contents of removed MAC header
395 macHdr.GetMType(),
396 "Removed header contents don't match");
398 macHdr.GetMajor(),
399 "Removed header contents don't match");
400
401 // Verify contents of removed frame header
402 NS_TEST_EXPECT_MSG_EQ(frameHdr1.GetAck(),
403 frameHdr.GetAck(),
404 "Removed header contents don't match");
405 NS_TEST_EXPECT_MSG_EQ(frameHdr1.GetAdr(),
406 frameHdr.GetAdr(),
407 "Removed header contents don't match");
408 NS_TEST_EXPECT_MSG_EQ(frameHdr1.GetFCnt(),
409 frameHdr.GetFCnt(),
410 "Removed header contents don't match");
411 NS_TEST_EXPECT_MSG_EQ((frameHdr1.GetAddress() == frameHdr.GetAddress()),
412 true,
413 "Removed header contents don't match");
414 NS_TEST_EXPECT_MSG_EQ(linkCheckAns->GetMargin(),
415 10,
416 "Removed header's MAC command contents don't match");
417 NS_TEST_EXPECT_MSG_EQ(linkCheckAns->GetGwCnt(),
418 1,
419 "Removed header's MAC command contents don't match");
420}
421
422/**
423 * @ingroup lorawan
424 *
425 * It tests a number of cases related to SimpleGatewayLoraPhy's parallel reception paths
426 *
427 * @todo The test is commented out. To be fixed.
428 */
430{
431 public:
432 ReceivePathTest(); //!< Default constructor
433 ~ReceivePathTest() override; //!< Destructor
434
435 private:
436 void DoRun() override;
437 /**
438 * Reset counters and gateway PHY for new sub test case.
439 */
440 void Reset();
441 /**
442 * Callback for tracing OccupiedReceptionPaths.
443 *
444 * @param oldValue The old value.
445 * @param newValue The new value.
446 */
447 void OccupiedReceptionPaths(int oldValue, int newValue);
448 /**
449 * Callback for tracing LostPacketBecauseNoMoreReceivers.
450 *
451 * @param packet The packet lost.
452 * @param node The receiver node id if any, 0 otherwise.
453 */
455 /**
456 * Callback for tracing LostPacketBecauseInterference.
457 *
458 * @param packet The packet lost.
459 * @param node The receiver node id if any, 0 otherwise.
460 */
461 void Interference(Ptr<const Packet> packet, uint32_t node);
462 /**
463 * Callback for tracing ReceivedPacket.
464 *
465 * @param packet The packet received.
466 * @param node The receiver node id if any, 0 otherwise.
467 */
468 void ReceivedPacket(Ptr<const Packet> packet, uint32_t node);
469
470 Ptr<SimpleGatewayLoraPhy> gatewayPhy; //!< PHY layer of a gateway to be tested
471
472 int m_noMoreDemodulatorsCalls = 0; //!< Counter for LostPacketBecauseNoMoreReceivers calls
473 int m_interferenceCalls = 0; //!< Counter for LostPacketBecauseInterference calls
474 int m_receivedPacketCalls = 0; //!< Counter for ReceivedPacket calls
475 int m_maxOccupiedReceptionPaths = 0; //!< Max number of concurrent OccupiedReceptionPaths
476};
477
478// Add some help text to this case to describe what it is intended to test
480 : TestCase("Verify that ReceivePaths work as expected")
481{
482}
483
484// Reminder that the test case should clean up after itself
488
489void
491{
492 // FIXME
493 // m_noMoreDemodulatorsCalls = 0;
494 // m_interferenceCalls = 0;
495 // m_receivedPacketCalls = 0;
496 // m_maxOccupiedReceptionPaths = 0;
497
498 // gatewayPhy = CreateObject<SimpleGatewayLoraPhy> ();
499 // gatewayPhy->TraceConnectWithoutContext (
500 // "LostPacketBecauseNoMoreReceivers",
501 // MakeCallback (&ReceivePathTest::NoMoreDemodulators, this));
502 // gatewayPhy->TraceConnectWithoutContext ("LostPacketBecauseInterference",
503 // MakeCallback (&ReceivePathTest::Interference, this));
504 // gatewayPhy->TraceConnectWithoutContext ("ReceivedPacket",
505 // MakeCallback (&ReceivePathTest::ReceivedPacket,
506 // this));
507 // gatewayPhy->TraceConnectWithoutContext (
508 // "OccupiedReceptionPaths", MakeCallback (&ReceivePathTest::OccupiedReceptionPaths, this));
509
510 // // Add receive paths
511 // gatewayPhy->AddReceptionPath ();
512 // gatewayPhy->AddReceptionPath ();
513 // gatewayPhy->AddReceptionPath ();
514 // gatewayPhy->AddReceptionPath ();
515 // gatewayPhy->AddReceptionPath ();
516 // gatewayPhy->AddReceptionPath ();
517}
518
519void
521{
522 NS_LOG_FUNCTION(oldValue << newValue);
523
524 if (m_maxOccupiedReceptionPaths < newValue)
525 {
527 }
528}
529
530void
537
538void
545
546void
553
554// This method is the pure virtual method from class TestCase that every
555// TestCase must implement
556void
558{
559 NS_LOG_DEBUG("ReceivePathTest");
560
561 Ptr<Packet> packet = Create<Packet>();
562
563 Reset();
564
565 // FIXME
566 // //////////////////////////////////////////////////////////////////////////////////
567 // // If no ReceptionPath is configured to listen on a frequency, no packet is received
568 // //////////////////////////////////////////////////////////////////////////////////
569
570 // Simulator::Schedule (Seconds (1), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
571 // 14, 7,
572 // Seconds (1), frequency4);
573
574 // Simulator::Stop (Hours (2));
575 // Simulator::Run ();
576 // Simulator::Destroy ();
577
578 // NS_TEST_EXPECT_MSG_EQ (m_noMoreDemodulatorsCalls, 1, "Unexpected value");
579
580 // Reset ();
581
582 // //////////////////////////////////////////////////////////////////////////////
583 // // A ReceptionPath can receive a packet of any spreading factor without any preconfiguration
584 // //////////////////////////////////////////////////////////////////////////////
585
586 // Simulator::Schedule (Seconds (1), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
587 // 14, 7,
588 // Seconds (1), frequency1);
589 // Simulator::Schedule (Seconds (3), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
590 // 14, 8,
591 // Seconds (1), frequency1);
592 // Simulator::Schedule (Seconds (5), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
593 // 14, 9,
594 // Seconds (1), frequency1);
595 // Simulator::Schedule (Seconds (7), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
596 // 14, 10,
597 // Seconds (1), frequency1);
598 // Simulator::Schedule (Seconds (9), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
599 // 14, 11,
600 // Seconds (1), frequency1);
601 // Simulator::Schedule (Seconds (11), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
602 // 14,
603 // 12, Seconds (1), frequency1);
604
605 // Simulator::Stop (Hours (2));
606 // Simulator::Run ();
607 // Simulator::Destroy ();
608
609 // NS_TEST_EXPECT_MSG_EQ (m_noMoreDemodulatorsCalls, 0, "Unexpected value");
610 // NS_TEST_EXPECT_MSG_EQ (m_receivedPacketCalls, 6, "Unexpected value");
611
612 // Reset ();
613
614 // ///////////////////////////////////////////////////////////////////////////
615 // // Schedule two reception events at the first frequency, where there are two
616 // // reception paths listening. Each packet should be received correctly.
617 // ///////////////////////////////////////////////////////////////////////////
618 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
619 // 14, 7,
620 // Seconds (4), frequency1);
621 // Simulator::Schedule (Seconds (3), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
622 // 14, 9,
623 // Seconds (4), frequency1);
624
625 // Simulator::Stop (Hours (2));
626 // Simulator::Run ();
627 // Simulator::Destroy ();
628
629 // NS_TEST_EXPECT_MSG_EQ (m_noMoreDemodulatorsCalls, 0, "Unexpected value");
630 // NS_TEST_EXPECT_MSG_EQ (m_receivedPacketCalls, 2, "Unexpected value");
631
632 // Reset ();
633
634 // ///////////////////////////////////////////////////////////////////////////
635 // // Interference between packets on the same frequency and different ReceptionPaths
636 // ///////////////////////////////////////////////////////////////////////////
637 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
638 // 14, 7,
639 // Seconds (4), frequency1);
640 // Simulator::Schedule (Seconds (3), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
641 // 14, 7,
642 // Seconds (4), frequency1);
643
644 // Simulator::Stop (Hours (2));
645 // Simulator::Run ();
646 // Simulator::Destroy ();
647
648 // NS_TEST_EXPECT_MSG_EQ (m_noMoreDemodulatorsCalls, 0, "Unexpected value");
649 // NS_TEST_EXPECT_MSG_EQ (m_interferenceCalls, 2, "Unexpected value");
650
651 // Reset ();
652
653 // ///////////////////////////////////////////////////////////////////////////
654 // // Three receptions where only two receivePaths are available
655 // ///////////////////////////////////////////////////////////////////////////
656 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
657 // 14, 7,
658 // Seconds (4), frequency1);
659 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
660 // 14, 7,
661 // Seconds (4), frequency1);
662 // Simulator::Schedule (Seconds (3), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
663 // 14, 7,
664 // Seconds (4), frequency1);
665
666 // Simulator::Stop (Hours (2));
667 // Simulator::Run ();
668 // Simulator::Destroy ();
669
670 // NS_TEST_EXPECT_MSG_EQ (m_noMoreDemodulatorsCalls, 1, "Unexpected value");
671
672 // Reset ();
673
674 // ///////////////////////////////////////////////////////////////////////////
675 // // Packets that are on different frequencys do not interfere
676 // ///////////////////////////////////////////////////////////////////////////
677 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
678 // 14, 7,
679 // Seconds (4), frequency1);
680 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
681 // 14, 7,
682 // Seconds (4), frequency2);
683
684 // Simulator::Stop (Hours (2));
685 // Simulator::Run ();
686 // Simulator::Destroy ();
687
688 // NS_TEST_EXPECT_MSG_EQ (m_interferenceCalls, 0, "Unexpected value");
689
690 // Reset ();
691
692 // ///////////////////////////////////////////////////////////////////////////
693 // // Full capacity
694 // ///////////////////////////////////////////////////////////////////////////
695 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
696 // 14, 7,
697 // Seconds (4), frequency1);
698 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
699 // 14, 8,
700 // Seconds (4), frequency1);
701 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
702 // 14, 9,
703 // Seconds (4), frequency2);
704 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
705 // 14, 10,
706 // Seconds (4), frequency2);
707 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
708 // 14, 11,
709 // Seconds (4), frequency3);
710 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
711 // 14, 12,
712 // Seconds (4), frequency3);
713
714 // Simulator::Stop (Hours (2));
715 // Simulator::Run ();
716 // Simulator::Destroy ();
717
718 // NS_TEST_EXPECT_MSG_EQ (m_noMoreDemodulatorsCalls, 0, "Unexpected value");
719 // NS_TEST_EXPECT_MSG_EQ (m_interferenceCalls, 0, "Unexpected value");
720 // NS_TEST_EXPECT_MSG_EQ (m_receivedPacketCalls, 6, "Unexpected value");
721
722 // Reset ();
723
724 // ///////////////////////////////////////////////////////////////////////////
725 // // Full capacity + 1
726 // ///////////////////////////////////////////////////////////////////////////
727 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
728 // 14, 7,
729 // Seconds (4), frequency1);
730 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
731 // 14, 8,
732 // Seconds (4), frequency1);
733 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
734 // 14, 9,
735 // Seconds (4), frequency2);
736 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
737 // 14, 10,
738 // Seconds (4), frequency2);
739 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
740 // 14, 11,
741 // Seconds (4), frequency3);
742 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
743 // 14, 12,
744 // Seconds (4), frequency3);
745 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
746 // 14, 10,
747 // Seconds (4), frequency3);
748
749 // Simulator::Stop (Hours (2));
750 // Simulator::Run ();
751 // Simulator::Destroy ();
752
753 // NS_TEST_EXPECT_MSG_EQ (m_noMoreDemodulatorsCalls, 1, "Unexpected value");
754 // NS_TEST_EXPECT_MSG_EQ (m_interferenceCalls, 0, "Unexpected value");
755 // NS_TEST_EXPECT_MSG_EQ (m_receivedPacketCalls, 6, "Unexpected value");
756
757 // Reset ();
758
759 // ///////////////////////////////////////////////////////////////////////////
760 // // Receive Paths are correctly freed
761 // ///////////////////////////////////////////////////////////////////////////
762 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
763 // 14, 7,
764 // Seconds (4), frequency1);
765 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
766 // 14, 8,
767 // Seconds (4), frequency1);
768 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
769 // 14, 9,
770 // Seconds (4), frequency2);
771 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
772 // 14, 10,
773 // Seconds (4), frequency2);
774 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
775 // 14, 11,
776 // Seconds (4), frequency3);
777 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
778 // 14, 12,
779 // Seconds (4), frequency3);
780
781 // Simulator::Schedule (Seconds (8), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
782 // 14, 7,
783 // Seconds (4), frequency1);
784 // Simulator::Schedule (Seconds (8), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
785 // 14, 8,
786 // Seconds (4), frequency1);
787 // Simulator::Schedule (Seconds (8), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
788 // 14, 9,
789 // Seconds (4), frequency2);
790 // Simulator::Schedule (Seconds (8), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
791 // 14, 10,
792 // Seconds (4), frequency2);
793 // Simulator::Schedule (Seconds (8), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
794 // 14, 11,
795 // Seconds (4), frequency3);
796 // Simulator::Schedule (Seconds (8), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
797 // 14, 12,
798 // Seconds (4), frequency3);
799
800 // Simulator::Stop (Hours (2));
801 // Simulator::Run ();
802 // Simulator::Destroy ();
803
804 // NS_TEST_EXPECT_MSG_EQ (m_noMoreDemodulatorsCalls, 0, "Unexpected value");
805 // NS_TEST_EXPECT_MSG_EQ (m_interferenceCalls, 0, "Unexpected value");
806 // NS_TEST_EXPECT_MSG_EQ (m_receivedPacketCalls, 12, "Unexpected value");
807
808 // Reset ();
809
810 // ///////////////////////////////////////////////////////////////////////////
811 // // Receive Paths stay occupied exactly for the necessary time
812 // // Occupy both ReceptionPaths centered at frequency1
813 // ///////////////////////////////////////////////////////////////////////////
814 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
815 // 14, 7,
816 // Seconds (4), frequency1);
817 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
818 // 14, 8,
819 // Seconds (4), frequency1);
820
821 // // This packet will find no free ReceptionPaths
822 // Simulator::Schedule (Seconds (2 + 4) - NanoSeconds (1), &SimpleGatewayLoraPhy::StartReceive,
823 // gatewayPhy, packet, 14, 9, Seconds (4), frequency1);
824
825 // // This packet will find a free ReceptionPath
826 // Simulator::Schedule (Seconds (2 + 4) + NanoSeconds (1), &SimpleGatewayLoraPhy::StartReceive,
827 // gatewayPhy, packet, 14, 10, Seconds (4), frequency1);
828
829 // Simulator::Stop (Hours (2));
830 // Simulator::Run ();
831 // Simulator::Destroy ();
832
833 // NS_TEST_EXPECT_MSG_EQ (m_noMoreDemodulatorsCalls, 1, "Unexpected value");
834 // NS_TEST_EXPECT_MSG_EQ (m_interferenceCalls, 0, "Unexpected value");
835 // NS_TEST_EXPECT_MSG_EQ (m_receivedPacketCalls, 3, "Unexpected value");
836
837 // Reset ();
838
839 // ///////////////////////////////////////////////////////////////////////////
840 // // Only one ReceivePath locks on the incoming packet
841 // ///////////////////////////////////////////////////////////////////////////
842 // Simulator::Schedule (Seconds (2), &SimpleGatewayLoraPhy::StartReceive, gatewayPhy, packet,
843 // 14, 7,
844 // Seconds (4), frequency1);
845
846 // Simulator::Stop (Hours (2));
847 // Simulator::Run ();
848 // Simulator::Destroy ();
849
850 // NS_TEST_EXPECT_MSG_EQ (m_noMoreDemodulatorsCalls, 0, "Unexpected value");
851 // NS_TEST_EXPECT_MSG_EQ (m_interferenceCalls, 0, "Unexpected value");
852 // NS_TEST_EXPECT_MSG_EQ (m_receivedPacketCalls, 1, "Unexpected value");
853 // NS_TEST_EXPECT_MSG_EQ (m_maxOccupiedReceptionPaths, 1, "Unexpected value");
854}
855
856/**
857 * @ingroup lorawan
858 *
859 * It tests functionality of the LogicalLoraChannel, SubBand and LogicalLoraChannelHelper classes
860 */
862{
863 public:
864 LogicalLoraChannelTest(); //!< Default constructor
865 ~LogicalLoraChannelTest() override; //!< Destructor
866
867 private:
868 void DoRun() override;
869};
870
871// Add some help text to this case to describe what it is intended to test
873 : TestCase("Verify that LogicalLoraChannel and LogicalLoraChannelHelper work as expected")
874{
875}
876
877// Reminder that the test case should clean up after itself
881
882// This method is the pure virtual method from class TestCase that every
883// TestCase must implement
884void
886{
887 NS_LOG_DEBUG("LogicalLoraChannelTest");
888
889 /////////////////////////////
890 // Test LogicalLoraChannel //
891 /////////////////////////////
892
893 // Setup
894 Ptr<LogicalLoraChannel> channel1 = Create<LogicalLoraChannel>(868000000, 0, 5);
895 Ptr<LogicalLoraChannel> channel2 = Create<LogicalLoraChannel>(868000000, 0, 5);
896 Ptr<LogicalLoraChannel> channel3 = Create<LogicalLoraChannel>(868100000, 0, 5);
897 Ptr<LogicalLoraChannel> channel4 = Create<LogicalLoraChannel>(868001000, 0, 5);
898
899 // Equality between channels
900 // Test the == and != operators
901 NS_TEST_EXPECT_MSG_EQ(channel1, channel2, "== operator doesn't work as expected");
902 NS_TEST_EXPECT_MSG_NE(channel1, channel3, "!= operator doesn't work as expected");
903 NS_TEST_EXPECT_MSG_NE(channel1, channel4, "!= operator doesn't work as expected");
904
905 //////////////////
906 // Test SubBand //
907 //////////////////
908
909 // Setup
910 auto subBand = Create<SubBand>(868000000, 868600000, 0.01, 14);
911 Ptr<LogicalLoraChannel> channel5 = Create<LogicalLoraChannel>(870000000, 0, 5);
912
913 // Test Contains
914 NS_TEST_EXPECT_MSG_EQ(subBand->Contains(channel3),
915 true,
916 "Contains does not behave as expected");
917 NS_TEST_EXPECT_MSG_EQ(subBand->Contains(channel3->GetFrequency()),
918 true,
919 "Contains does not behave as expected");
920 NS_TEST_EXPECT_MSG_EQ(subBand->Contains(channel5),
921 false,
922 "Contains does not behave as expected");
923
924 ///////////////////////////////////
925 // Test LogicalLoraChannelHelper //
926 ///////////////////////////////////
927
928 // Setup
929 auto channelHelper = Create<LogicalLoraChannelHelper>(16);
930 auto subBand1 = Create<SubBand>(869400000, 869650000, 0.10, 27);
931 channel1 = Create<LogicalLoraChannel>(868100000, 0, 5);
932 channel2 = Create<LogicalLoraChannel>(868300000, 0, 5);
933 channel3 = Create<LogicalLoraChannel>(869525000, 0, 5);
934
935 // Channel diagram
936 //
937 // Channels 1 2 3
938 // SubBands 868 ----- 1% ----- 868.6 869 ----- 10% ----- 869.4
939
940 // Add SubBands and LogicalLoraChannels to the helper
941 channelHelper->AddSubBand(subBand);
942 channelHelper->AddSubBand(subBand1);
943 channelHelper->SetChannel(0, channel1);
944 channelHelper->SetChannel(1, channel2);
945 channelHelper->SetChannel(2, channel3);
946
947 // Duty Cycle tests
948 // (high level duty cycle behavior)
949 ///////////////////////////////////
950
951 channelHelper->AddEvent(Seconds(2), channel1);
952 Time expectedTimeOff = Seconds(2 / 0.01);
953
954 // Wait time is computed correctly
955 NS_TEST_EXPECT_MSG_EQ(channelHelper->GetWaitTime(channel1),
956 expectedTimeOff,
957 "Wait time doesn't behave as expected");
958
959 // Duty Cycle involves the whole SubBand, not just a channel
960 NS_TEST_EXPECT_MSG_EQ(channelHelper->GetWaitTime(channel2),
961 expectedTimeOff,
962 "Wait time doesn't behave as expected");
963
964 // Other bands are not affected by this transmission
965 NS_TEST_EXPECT_MSG_EQ(channelHelper->GetWaitTime(channel3),
966 Time(0),
967 "Wait time affects other subbands");
968}
969
970/**
971 * @ingroup lorawan
972 *
973 * It tests the correctness of the LoraPhy::GetOnAirTime calculator against a number of pre-sourced
974 * time values of known scenarios
975 */
977{
978 public:
979 TimeOnAirTest(); //!< Default constructor
980 ~TimeOnAirTest() override; //!< Destructor
981
982 private:
983 void DoRun() override;
984};
985
986// Add some help text to this case to describe what it is intended to test
988 : TestCase(
989 "Verify that LoraPhy's function to compute the time on air of a packet works as expected")
990{
991}
992
993// Reminder that the test case should clean up after itself
997
998// This method is the pure virtual method from class TestCase that every
999// TestCase must implement
1000void
1002{
1003 NS_LOG_DEBUG("TimeOnAirTest");
1004
1005 Ptr<Packet> packet;
1006 Time duration;
1007
1008 // Available parameters:
1009 // PayloadSize, SF, HeaderDisabled, CodingRate, Bandwidth, nPreambleSyms, crcEnabled,
1010 // lowDROptimization
1011
1012 // Starting parameters
1013 packet = Create<Packet>(10);
1014 LoraTxParameters txParams;
1015 txParams.sf = 7;
1016 txParams.headerDisabled = false;
1017 txParams.codingRate = CodingRate::CR_4_5;
1018 txParams.bandwidthHz = 125000;
1019 txParams.nPreamble = 8;
1020 txParams.crcEnabled = true;
1021 txParams.lowDataRateOptimizationEnabled = false;
1022
1023 duration = LoraPhy::GetOnAirTime(packet, txParams);
1024 NS_TEST_EXPECT_MSG_EQ_TOL(duration.GetSeconds(), 0.041216, 0.0001, "Unexpected duration");
1025
1026 txParams.sf = 8;
1027 duration = LoraPhy::GetOnAirTime(packet, txParams);
1028 NS_TEST_EXPECT_MSG_EQ_TOL(duration.GetSeconds(), 0.072192, 0.0001, "Unexpected duration");
1029
1030 txParams.headerDisabled = true;
1031 duration = LoraPhy::GetOnAirTime(packet, txParams);
1032 NS_TEST_EXPECT_MSG_EQ_TOL(duration.GetSeconds(), 0.072192, 0.0001, "Unexpected duration");
1033
1034 txParams.codingRate = CodingRate::CR_4_6;
1035 duration = LoraPhy::GetOnAirTime(packet, txParams);
1036 NS_TEST_EXPECT_MSG_EQ_TOL(duration.GetSeconds(), 0.078336, 0.0001, "Unexpected duration");
1037
1038 txParams.nPreamble = 10;
1039 duration = LoraPhy::GetOnAirTime(packet, txParams);
1040 NS_TEST_EXPECT_MSG_EQ_TOL(duration.GetSeconds(), 0.082432, 0.0001, "Unexpected duration");
1041
1042 txParams.lowDataRateOptimizationEnabled = true;
1043 duration = LoraPhy::GetOnAirTime(packet, txParams);
1044 NS_TEST_EXPECT_MSG_EQ_TOL(duration.GetSeconds(), 0.082432, 0.0001, "Unexpected duration");
1045
1046 txParams.sf = 10;
1047 duration = LoraPhy::GetOnAirTime(packet, txParams);
1048 NS_TEST_EXPECT_MSG_EQ_TOL(duration.GetSeconds(), 0.280576, 0.0001, "Unexpected duration");
1049
1050 txParams.bandwidthHz = 250000;
1051 duration = LoraPhy::GetOnAirTime(packet, txParams);
1052 NS_TEST_EXPECT_MSG_EQ_TOL(duration.GetSeconds(), 0.14028, 0.0001, "Unexpected duration");
1053
1054 txParams.bandwidthHz = 500000;
1055 duration = LoraPhy::GetOnAirTime(packet, txParams);
1056 NS_TEST_EXPECT_MSG_EQ_TOL(duration.GetSeconds(), 0.070144, 0.0001, "Unexpected duration");
1057
1058 txParams.headerDisabled = false;
1059 duration = LoraPhy::GetOnAirTime(packet, txParams);
1060 NS_TEST_EXPECT_MSG_EQ_TOL(duration.GetSeconds(), 0.082432, 0.0001, "Unexpected duration");
1061
1062 txParams.nPreamble = 8;
1063 duration = LoraPhy::GetOnAirTime(packet, txParams);
1064 NS_TEST_EXPECT_MSG_EQ_TOL(duration.GetSeconds(), 0.078336, 0.0001, "Unexpected duration");
1065
1066 txParams.sf = 12;
1067 duration = LoraPhy::GetOnAirTime(packet, txParams);
1068 NS_TEST_EXPECT_MSG_EQ_TOL(duration.GetSeconds(), 0.264192, 0.0001, "Unexpected duration");
1069
1070 packet = Create<Packet>(50);
1071 duration = LoraPhy::GetOnAirTime(packet, txParams);
1072 NS_TEST_EXPECT_MSG_EQ_TOL(duration.GetSeconds(), 0.657408, 0.0001, "Unexpected duration");
1073
1074 txParams.bandwidthHz = 125000;
1075 duration = LoraPhy::GetOnAirTime(packet, txParams);
1076 NS_TEST_EXPECT_MSG_EQ_TOL(duration.GetSeconds(), 2.629632, 0.0001, "Unexpected duration");
1077
1078 txParams.codingRate = CodingRate::CR_4_5;
1079 duration = LoraPhy::GetOnAirTime(packet, txParams);
1080 NS_TEST_EXPECT_MSG_EQ_TOL(duration.GetSeconds(), 2.301952, 0.0001, "Unexpected duration");
1081}
1082
1083/**
1084 * @ingroup lorawan
1085 *
1086 * It tests sending packets over a LoRa physical channel between multiple devices and the resulting
1087 * possible outcomes
1088 */
1090{
1091 public:
1092 PhyConnectivityTest(); //!< Default constructor
1093 ~PhyConnectivityTest() override; //!< Destructor
1094
1095 /**
1096 * Reset counters and end devices' PHYs for new sub test case.
1097 */
1098 void Reset();
1099
1100 /**
1101 * Callback for tracing ReceivedPacket.
1102 *
1103 * @param packet The packet received.
1104 * @param node The receiver node id if any, 0 otherwise.
1105 */
1106 void ReceivedPacket(Ptr<const Packet> packet, uint32_t node);
1107
1108 /**
1109 * Callback for tracing LostPacketBecauseUnderSensitivity.
1110 *
1111 * @param packet The packet lost.
1112 * @param node The receiver node id if any, 0 otherwise.
1113 */
1114 void UnderSensitivity(Ptr<const Packet> packet, uint32_t node);
1115
1116 /**
1117 * Callback for tracing LostPacketBecauseInterference.
1118 *
1119 * @param packet The packet lost.
1120 * @param node The receiver node id if any, 0 otherwise.
1121 */
1122 void Interference(Ptr<const Packet> packet, uint32_t node);
1123
1124 /**
1125 * Callback for tracing LostPacketBecauseWrongFrequency.
1126 *
1127 * @param packet The packet lost.
1128 * @param node The receiver node id if any, 0 otherwise.
1129 */
1130 void WrongFrequency(Ptr<const Packet> packet, uint32_t node);
1131
1132 /**
1133 * Callback for tracing LostPacketBecauseWrongSpreadingFactor.
1134 *
1135 * @param packet The packet lost.
1136 * @param node The receiver node id if any, 0 otherwise.
1137 */
1138 void WrongSf(Ptr<const Packet> packet, uint32_t node);
1139
1140 /**
1141 * Compare two packets to check if they are equal.
1142 *
1143 * @param packet1 A first packet.
1144 * @param packet2 A second packet.
1145 * @return True if their unique identifiers are equal,
1146 * @return false otherwise.
1147 */
1148 bool IsSamePacket(Ptr<Packet> packet1, Ptr<Packet> packet2);
1149
1150 private:
1151 void DoRun() override;
1152
1153 Ptr<LoraChannel> channel; //!< The LoRa channel used for tests
1154 Ptr<SimpleEndDeviceLoraPhy> edPhy1; //!< The first end device's PHY layer used in tests
1155 Ptr<SimpleEndDeviceLoraPhy> edPhy2; //!< The second end device's PHY layer used in tests
1156 Ptr<SimpleEndDeviceLoraPhy> edPhy3; //!< The third end device's PHY layer used in tests
1157
1158 Ptr<Packet> m_latestReceivedPacket; //!< Pointer to track the last received packet
1159 int m_receivedPacketCalls = 0; //!< Counter for ReceivedPacket calls
1160 int m_underSensitivityCalls = 0; //!< Counter for LostPacketBecauseUnderSensitivity calls
1161 int m_interferenceCalls = 0; //!< Counter for LostPacketBecauseInterference calls
1162 int m_wrongSfCalls = 0; //!< Counter for LostPacketBecauseWrongSpreadingFactor calls
1163 int m_wrongFrequencyCalls = 0; //!< Counter for LostPacketBecauseWrongFrequency calls
1164};
1165
1166// Add some help text to this case to describe what it is intended to test
1168 : TestCase("Verify that PhyConnectivity works as expected")
1169{
1170}
1171
1172// Reminder that the test case should clean up after itself
1176
1177void
1179{
1180 NS_LOG_FUNCTION(packet << node);
1181
1183
1184 m_latestReceivedPacket = packet->Copy();
1185}
1186
1187void
1194
1195void
1197{
1198 NS_LOG_FUNCTION(packet << node);
1199
1201}
1202
1203void
1205{
1206 NS_LOG_FUNCTION(packet << node);
1207
1209}
1210
1211void
1218
1219bool
1221{
1222 return packet1->GetUid() == packet2->GetUid();
1223}
1224
1225void
1227{
1231 m_wrongSfCalls = 0;
1233
1235 loss->SetPathLossExponent(3.76);
1236 loss->SetReference(1, 7.7);
1237
1239
1240 // Create the channel
1241 channel = CreateObject<LoraChannel>(loss, delay);
1242
1243 // Connect PHYs
1247
1248 edPhy1->SetFrequency(868100000);
1249 edPhy2->SetFrequency(868100000);
1250 edPhy3->SetFrequency(868100000);
1251
1255
1256 mob1->SetPosition(Vector(0.0, 0.0, 0.0));
1257 mob2->SetPosition(Vector(10.0, 0.0, 0.0));
1258 mob3->SetPosition(Vector(20.0, 0.0, 0.0));
1259
1260 edPhy1->SetMobility(mob1);
1261 edPhy2->SetMobility(mob2);
1262 edPhy3->SetMobility(mob3);
1263
1264 edPhy1->SwitchToStandby();
1265 edPhy2->SwitchToStandby();
1266 edPhy3->SwitchToStandby();
1267
1268 channel->Add(edPhy1);
1269 channel->Add(edPhy2);
1270 channel->Add(edPhy3);
1271
1272 edPhy1->SetChannel(channel);
1273 edPhy2->SetChannel(channel);
1274 edPhy3->SetChannel(channel);
1275
1276 // Listen for a specific SpreadingFactor
1277 edPhy1->SetSpreadingFactor(12);
1278 edPhy2->SetSpreadingFactor(12);
1279 edPhy3->SetSpreadingFactor(12);
1280
1281 // Listen on a specific frequency
1282 edPhy1->SetFrequency(868100000);
1283 edPhy2->SetFrequency(868100000);
1284 edPhy3->SetFrequency(868100000);
1285
1286 edPhy1->TraceConnectWithoutContext("ReceivedPacket",
1288 edPhy2->TraceConnectWithoutContext("ReceivedPacket",
1290 edPhy3->TraceConnectWithoutContext("ReceivedPacket",
1292
1293 edPhy1->TraceConnectWithoutContext("LostPacketBecauseUnderSensitivity",
1295 edPhy2->TraceConnectWithoutContext("LostPacketBecauseUnderSensitivity",
1297 edPhy3->TraceConnectWithoutContext("LostPacketBecauseUnderSensitivity",
1299
1300 edPhy1->TraceConnectWithoutContext("LostPacketBecauseInterference",
1302 edPhy2->TraceConnectWithoutContext("LostPacketBecauseInterference",
1304 edPhy3->TraceConnectWithoutContext("LostPacketBecauseInterference",
1306
1307 edPhy1->TraceConnectWithoutContext("LostPacketBecauseWrongFrequency",
1309 edPhy2->TraceConnectWithoutContext("LostPacketBecauseWrongFrequency",
1311 edPhy3->TraceConnectWithoutContext("LostPacketBecauseWrongFrequency",
1313
1314 edPhy1->TraceConnectWithoutContext("LostPacketBecauseWrongSpreadingFactor",
1316 edPhy2->TraceConnectWithoutContext("LostPacketBecauseWrongSpreadingFactor",
1318 edPhy3->TraceConnectWithoutContext("LostPacketBecauseWrongSpreadingFactor",
1320}
1321
1322// This method is the pure virtual method from class TestCase that every
1323// TestCase must implement
1324void
1326{
1327 NS_LOG_DEBUG("PhyConnectivityTest");
1328
1329 // Setup
1330 ////////
1331
1332 Reset();
1333
1334 LoraTxParameters txParams;
1335 txParams.sf = 12;
1336
1337 uint8_t buffer[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
1338 Ptr<Packet> packet = Create<Packet>(buffer, 10);
1339
1340 // Testing
1341 //////////
1342
1343 // Basic packet delivery test
1344 /////////////////////////////
1345
1348 edPhy1,
1349 packet,
1350 txParams,
1351 868100000,
1352 14);
1353
1357
1360 2,
1361 "Channel skipped some PHYs when delivering a packet"); // All PHYs except the sender
1362
1363 Reset();
1364
1365 // Sleeping PHYs do not receive the packet
1366
1367 edPhy2->SwitchToSleep();
1368
1371 edPhy1,
1372 packet,
1373 txParams,
1374 868100000,
1375 14);
1376
1380
1383 1,
1384 "Packet was received by a PHY in SLEEP mode"); // All PHYs in Standby except the sender
1385
1386 Reset();
1387
1388 // Packet that arrives under sensitivity is received correctly if the spreading factor increases
1389
1390 txParams.sf = 7;
1391 edPhy2->SetSpreadingFactor(7);
1393 ->SetPosition(Vector(2990, 0, 0));
1394
1397 edPhy1,
1398 packet,
1399 txParams,
1400 868100000,
1401 14);
1402
1406
1409 1,
1410 "Packet that should have been lost because of low receive power was received");
1411
1412 Reset();
1413
1414 // Try again using a packet with higher spreading factor
1415 txParams.sf = 8;
1416 edPhy2->SetSpreadingFactor(8);
1418 ->SetPosition(Vector(2990, 0, 0));
1419
1422 edPhy1,
1423 packet,
1424 txParams,
1425 868100000,
1426 14);
1427
1431
1433 0,
1434 "Packets that should have arrived above sensitivity were under it");
1435
1436 Reset();
1437
1438 // Packets can be destroyed by interference
1439
1440 txParams.sf = 12;
1443 edPhy1,
1444 packet,
1445 txParams,
1446 868100000,
1447 14);
1450 edPhy3,
1451 packet,
1452 txParams,
1453 868100000,
1454 14);
1455
1459
1461 1,
1462 "Packets that should be destroyed by interference weren't");
1463
1464 Reset();
1465
1466 // Packets can be lost because the PHY is not listening on the right frequency
1467
1470 edPhy1,
1471 packet,
1472 txParams,
1473 868300000,
1474 14);
1475
1479
1481 2,
1482 "Packets were received even though PHY was on a different frequency");
1483
1484 Reset();
1485
1486 // Packets can be lost because the PHY is not listening for the right spreading factor
1487
1488 txParams.sf = 8; // Send with 8, listening for 12
1491 edPhy1,
1492 packet,
1493 txParams,
1494 868100000,
1495 14);
1496
1500
1503 2,
1504 "Packets were received even though PHY was listening for a different spreading factor.");
1505
1506 Reset();
1507
1508 // Sending of packets
1509 /////////////////////
1510
1511 // The very same packet arrives at the other PHY
1514 edPhy1,
1515 packet,
1516 txParams,
1517 868100000,
1518 14);
1519
1523
1525 true,
1526 "Packet changed contents when going through the channel");
1527
1528 Reset();
1529
1530 // Correct state transitions
1531 ////////////////////////////
1532
1533 // PHY switches to STANDBY after TX and RX
1534
1537 edPhy1,
1538 packet,
1539 txParams,
1540 868100000,
1541 14);
1542
1546
1547 NS_TEST_EXPECT_MSG_EQ(edPhy1->GetState(),
1549 "State didn't switch to STANDBY as expected");
1550 NS_TEST_EXPECT_MSG_EQ(edPhy2->GetState(),
1552 "State didn't switch to STANDBY as expected");
1553}
1554
1555/**
1556 * @ingroup lorawan
1557 *
1558 * It tests the functionalities of the MAC layer of LoRaWAN devices
1559 *
1560 * @todo Not implemented yet.
1561 */
1563{
1564 public:
1565 LorawanMacTest(); //!< Default constructor
1566 ~LorawanMacTest() override; //!< Destructor
1567
1568 private:
1569 void DoRun() override;
1570};
1571
1572// Add some help text to this case to describe what it is intended to test
1574 : TestCase("Verify that the MAC layer of end devices behaves as expected")
1575{
1576}
1577
1578// Reminder that the test case should clean up after itself
1582
1583// This method is the pure virtual method from class TestCase that every
1584// TestCase must implement
1585void
1587{
1588 NS_LOG_DEBUG("LorawanMacTest");
1589}
1590
1591/**
1592 * @ingroup lorawan
1593 *
1594 * It tests the functionalities of LoRaWAN MAC commands received by devices.
1595 *
1596 * This means testing that (i) settings in the downlink MAC commands are correctly applied/rejected
1597 * by the device, and that (ii) the correct answer (if expected) is produced by the device.
1598 */
1600{
1601 public:
1602 MacCommandTest(); //!< Default constructor
1603 ~MacCommandTest() override; //!< Destructor
1604
1605 private:
1606 /**
1607 * Have this class' MAC layer receive a downlink packet carrying the input MAC command. After,
1608 * trigger a new empty uplink packet send that can then be used to examine the MAC command
1609 * answers in the header.
1610 *
1611 * @tparam T \explicit The type of MAC command to create.
1612 * @tparam Ts \deduced Types of the constructor arguments.
1613 * @param [in] args MAC command constructor arguments.
1614 * @return The list of MAC commands produced by the device as an answer.
1615 */
1616 template <typename T, typename... Ts>
1617 std::vector<Ptr<MacCommand>> RunMacCommand(Ts&&... args);
1618
1619 /**
1620 * This function resets the state of the MAC layer used for tests. Use it before each call of
1621 * RunMacCommand. Otherwise, on consecutive calls the MAC layer will not send due to duty-cycle
1622 * limitations.
1623 */
1624 void Reset();
1625
1626 void DoRun() override;
1627
1628 Ptr<ClassAEndDeviceLorawanMac> m_mac; //!< The end device's MAC layer used in tests.
1629};
1630
1632 : TestCase("Test functionality of MAC commands when received by a device")
1633{
1634}
1635
1637{
1638 m_mac = nullptr;
1639}
1640
1641template <typename T, typename... Ts>
1642std::vector<Ptr<MacCommand>>
1644{
1645 Ptr<Packet> pkt;
1646 LoraFrameHeader fhdr;
1647 LorawanMacHeader mhdr;
1648 // Prepare DL packet with input command
1649 pkt = Create<Packet>(0);
1650 fhdr.SetAsDownlink();
1651 auto cmd = Create<T>(args...);
1652 fhdr.AddCommand(cmd);
1653 pkt->AddHeader(fhdr);
1655 pkt->AddHeader(mhdr);
1656 // Trigger MAC layer reception
1658 ->SwitchToStandby(); // usually done as we open Rx windows
1659 m_mac->Receive(pkt);
1660 // Trigger MAC layer send
1661 pkt = Create<Packet>(0);
1662 m_mac->Send(pkt);
1663 // Retrieve uplink MAC commands
1664 pkt->RemoveHeader(mhdr);
1665 fhdr.SetAsUplink();
1666 pkt->RemoveHeader(fhdr);
1667 return fhdr.GetCommands();
1668}
1669
1670void
1672{
1673 // Reset MAC state
1674 LorawanMacHelper macHelper;
1677 /// @todo Create should not require a node in input.
1678 m_mac = DynamicCast<ClassAEndDeviceLorawanMac>(macHelper.Install(nullptr, nullptr));
1679 NS_TEST_EXPECT_MSG_NE(m_mac, nullptr, "Failed to initialize MAC layer object.");
1681 phy->SetChannel(CreateObject<LoraChannel>());
1683 m_mac->SetPhy(phy);
1684}
1685
1686void
1688{
1689 NS_LOG_DEBUG("MacCommandTest");
1690
1691 Reset();
1692 // LinkCheckAns: get connectivity metrics of last uplink LinkCheckReq command
1693 {
1694 uint8_t margin = 20; // best reception margin [dB] from demodulation floor
1695 uint8_t gwCnt = 3; // number of gateways that received last uplink
1696 auto answers = RunMacCommand<LinkCheckAns>(margin, gwCnt);
1697 NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetLastKnownLinkMarginDb()),
1698 unsigned(margin),
1699 "m_lastKnownMarginDb differs from Margin field of LinkCheckAns");
1700 NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetLastKnownGatewayCount()),
1701 unsigned(gwCnt),
1702 "m_lastKnownGatewayCount differs GwCnt field of LinkCheckAns");
1703 NS_TEST_EXPECT_MSG_EQ(answers.size(),
1704 0,
1705 "Unexpected uplink MAC command answer(s) to LinkCheckAns");
1706 }
1707
1708 Reset();
1709 // LinkAdrReq: change data rate, TX power, redundancy, or channel mask
1710 {
1711 uint8_t dataRate = 5;
1712 uint8_t txPower = 2;
1713 uint16_t chMask = 0b101;
1714 uint8_t chMaskCntl = 0;
1715 uint8_t nbTrans = 13;
1716 auto answers = RunMacCommand<LinkAdrReq>(dataRate, txPower, chMask, chMaskCntl, nbTrans);
1717 NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetDataRate()),
1718 unsigned(dataRate),
1719 "m_dataRate does not match DataRate field of LinkAdrReq");
1720 NS_TEST_EXPECT_MSG_EQ(m_mac->GetTransmissionPowerDbm(),
1721 14 - txPower * 2,
1722 "m_txPowerDbm does not match txPower field of LinkAdrReq");
1723 NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetMaxNumberOfTransmissions()),
1724 unsigned(nbTrans),
1725 "m_nbTrans does not match nbTrans field of LinkAdrReq");
1726 auto channels = m_mac->GetLogicalLoraChannelHelper()->GetRawChannelArray();
1727 for (size_t i = 0; i < channels.size(); i++)
1728 {
1729 const auto& c = channels.at(i + 16 * chMaskCntl);
1730 bool actual = (c) ? c->IsEnabledForUplink() : false;
1731 bool expected = (chMask & 0b1 << i);
1732 NS_TEST_EXPECT_MSG_EQ(actual, expected, "Channel " << i << " state != chMask");
1733 }
1734 NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1");
1735 auto laa = DynamicCast<LinkAdrAns>(answers.at(0));
1736 NS_TEST_ASSERT_MSG_NE(laa, nullptr, "LinkAdrAns was expected, cmd type cast failed");
1737 NS_TEST_EXPECT_MSG_EQ(laa->GetChannelMaskAck(), true, "ChannelMaskAck expected to be true");
1738 NS_TEST_EXPECT_MSG_EQ(laa->GetDataRateAck(), true, "DataRateAck expected to be true");
1739 NS_TEST_EXPECT_MSG_EQ(laa->GetPowerAck(), true, "PowerAck expected to be true");
1740 }
1741
1742 Reset();
1743 // LinkAdrReq: ADR bit off, only change channel mask
1744 {
1745 uint8_t dataRate = 5;
1746 uint8_t txPower = 2;
1747 uint16_t chMask = 0b010;
1748 uint8_t chMaskCntl = 0;
1749 uint8_t nbTrans = 13;
1750 m_mac->SetUplinkAdrBit(false);
1751 auto answers = RunMacCommand<LinkAdrReq>(dataRate, txPower, chMask, chMaskCntl, nbTrans);
1752 NS_TEST_EXPECT_MSG_NE(unsigned(m_mac->GetDataRate()),
1753 unsigned(dataRate),
1754 "m_dataRate expected to differ from DataRate field of LinkAdrReq");
1755 NS_TEST_EXPECT_MSG_NE(m_mac->GetTransmissionPowerDbm(),
1756 14 - txPower * 2,
1757 "m_txPowerDbm expected to not match txPower field of LinkAdrReq");
1758 NS_TEST_EXPECT_MSG_NE(unsigned(m_mac->GetMaxNumberOfTransmissions()),
1759 unsigned(nbTrans),
1760 "m_nbTrans expected to differ from nbTrans field of LinkAdrReq");
1761 auto channels = m_mac->GetLogicalLoraChannelHelper()->GetRawChannelArray();
1762 for (size_t i = 0; i < channels.size(); i++)
1763 {
1764 const auto& c = channels.at(i + 16 * chMaskCntl);
1765 bool actual = (c) ? c->IsEnabledForUplink() : false;
1766 bool expected = (chMask & 0b1 << i);
1767 NS_TEST_EXPECT_MSG_EQ(actual, expected, "Channel " << i << " state != chMask");
1768 }
1769 NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1");
1770 auto laa = DynamicCast<LinkAdrAns>(answers.at(0));
1771 NS_TEST_ASSERT_MSG_NE(laa, nullptr, "LinkAdrAns was expected, cmd type cast failed");
1772 NS_TEST_EXPECT_MSG_EQ(laa->GetChannelMaskAck(), true, "ChannelMaskAck expected to be true");
1773 NS_TEST_EXPECT_MSG_EQ(laa->GetDataRateAck(), false, "DataRateAck expected to be false");
1774 NS_TEST_EXPECT_MSG_EQ(laa->GetPowerAck(), false, "PowerAck expected to be false");
1775 }
1776
1777 Reset();
1778 // LinkAdrReq: invalid chMask, data rate and power
1779 { // WARNING: default values are manually set here
1780 uint8_t dataRate = 12;
1781 uint8_t txPower = 8;
1782 uint16_t chMask = 0b0;
1783 uint8_t chMaskCntl = 0;
1784 uint8_t nbTrans = 6;
1785 auto answers = RunMacCommand<LinkAdrReq>(dataRate, txPower, chMask, chMaskCntl, nbTrans);
1786 NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetDataRate()),
1787 0,
1788 "m_dataRate expected to be default value");
1789 NS_TEST_EXPECT_MSG_EQ(m_mac->GetTransmissionPowerDbm(),
1790 14,
1791 "m_txPowerDbm expected to be default value");
1792 NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetMaxNumberOfTransmissions()),
1793 1,
1794 "m_nbTrans expected to be default value");
1795 auto channels = m_mac->GetLogicalLoraChannelHelper()->GetRawChannelArray();
1796 for (size_t i = 0; i < channels.size(); i++)
1797 {
1798 const auto& c = channels.at(i + 16 * chMaskCntl);
1799 bool actual = (c) ? c->IsEnabledForUplink() : false;
1800 bool expected = (uint16_t(0b111) & 0b1 << i);
1801 NS_TEST_EXPECT_MSG_EQ(actual, expected, "Channel " << i << " state != default");
1802 }
1803 NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1");
1804 auto laa = DynamicCast<LinkAdrAns>(answers.at(0));
1805 NS_TEST_ASSERT_MSG_NE(laa, nullptr, "LinkAdrAns was expected, cmd type cast failed");
1806 NS_TEST_EXPECT_MSG_EQ(laa->GetChannelMaskAck(), false, "ChannelMaskAck != false");
1807 NS_TEST_EXPECT_MSG_EQ(laa->GetDataRateAck(), false, "DataRateAck expected to be false");
1808 NS_TEST_EXPECT_MSG_EQ(laa->GetPowerAck(), false, "PowerAck expected to be false");
1809 }
1810
1811 Reset();
1812 // LinkAdrReq: invalid chMask, valid data rate and power
1813 { // WARNING: default values are manually set here
1814 uint8_t dataRate = 1;
1815 uint8_t txPower = 7;
1816 uint16_t chMask = 0b1000; // enable only non-exisitng channel
1817 uint8_t chMaskCntl = 0;
1818 uint8_t nbTrans = 3;
1819 auto answers = RunMacCommand<LinkAdrReq>(dataRate, txPower, chMask, chMaskCntl, nbTrans);
1820 NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetDataRate()),
1821 0,
1822 "m_dataRate expected to be default value");
1823 NS_TEST_EXPECT_MSG_EQ(m_mac->GetTransmissionPowerDbm(),
1824 14,
1825 "m_txPowerDbm expected to be default value");
1826 NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetMaxNumberOfTransmissions()),
1827 1,
1828 "m_nbTrans expected to be default value");
1829 auto channels = m_mac->GetLogicalLoraChannelHelper()->GetRawChannelArray();
1830 for (size_t i = 0; i < channels.size(); i++)
1831 {
1832 const auto& c = channels.at(i + 16 * chMaskCntl);
1833 bool actual = (c) ? c->IsEnabledForUplink() : false;
1834 bool expected = (uint16_t(0b111) & 0b1 << i);
1835 NS_TEST_EXPECT_MSG_EQ(actual, expected, "Channel " << i << " state != default");
1836 }
1837 NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1");
1838 auto laa = DynamicCast<LinkAdrAns>(answers.at(0));
1839 NS_TEST_ASSERT_MSG_NE(laa, nullptr, "LinkAdrAns was expected, cmd type cast failed");
1840 NS_TEST_EXPECT_MSG_EQ(laa->GetChannelMaskAck(), false, "ChannelMaskAck != false");
1841 NS_TEST_EXPECT_MSG_EQ(laa->GetDataRateAck(), true, "DataRateAck expected to be true");
1842 NS_TEST_EXPECT_MSG_EQ(laa->GetPowerAck(), true, "PowerAck expected to be true");
1843 }
1844
1845 Reset();
1846 // LinkAdrReq: fringe parameter values
1847 { // WARNING: default values are manually set here
1848 uint8_t dataRate = 0xF;
1849 uint8_t txPower = 0xF; // 0x0F ignores config
1850 uint16_t chMask = 0b0; // should be ignored because chMaskCntl is 6
1851 uint8_t chMaskCntl = 6; // all channels on
1852 uint8_t nbTrans = 0; // restore default 1
1853 // Set device params to values different from default
1854 m_mac->SetDataRate(3);
1855 m_mac->SetTransmissionPowerDbm(12);
1856 m_mac->SetMaxNumberOfTransmissions(15);
1857 auto channels = m_mac->GetLogicalLoraChannelHelper()->GetRawChannelArray();
1858 channels.at(0)->DisableForUplink();
1859 auto answers = RunMacCommand<LinkAdrReq>(dataRate, txPower, chMask, chMaskCntl, nbTrans);
1860 NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetDataRate()),
1861 3,
1862 "m_dataRate expected to be default value");
1863 NS_TEST_EXPECT_MSG_EQ(m_mac->GetTransmissionPowerDbm(),
1864 12,
1865 "m_txPowerDbm expected to be default value");
1866 NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetMaxNumberOfTransmissions()),
1867 1,
1868 "m_nbTrans expected to be default value");
1869 for (size_t i = 0; i < channels.size(); i++)
1870 {
1871 const auto& c = channels.at(i);
1872 bool actual = (c) ? c->IsEnabledForUplink() : false;
1873 bool expected = (uint16_t(0b111) & 0b1 << i);
1874 NS_TEST_EXPECT_MSG_EQ(actual, expected, "Channel " << i << " state != default");
1875 }
1876 NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1");
1877 auto laa = DynamicCast<LinkAdrAns>(answers.at(0));
1878 NS_TEST_ASSERT_MSG_NE(laa, nullptr, "LinkAdrAns was expected, cmd type cast failed");
1879 NS_TEST_EXPECT_MSG_EQ(laa->GetChannelMaskAck(), true, "ChannelMaskAck != true");
1880 NS_TEST_EXPECT_MSG_EQ(laa->GetDataRateAck(), true, "DataRateAck expected to be true");
1881 NS_TEST_EXPECT_MSG_EQ(laa->GetPowerAck(), true, "PowerAck expected to be true");
1882 }
1883
1884 Reset();
1885 // DutyCycleReq: duty cycle to 100%
1886 {
1887 uint8_t maxDutyCycle = 0;
1888 auto answers = RunMacCommand<DutyCycleReq>(maxDutyCycle);
1889 NS_TEST_EXPECT_MSG_EQ(m_mac->GetAggregatedDutyCycle(),
1890 1 / std::pow(2, maxDutyCycle),
1891 "m_aggregatedDutyCycle != 1");
1892 NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1");
1893 auto dca = DynamicCast<DutyCycleAns>(answers.at(0));
1894 NS_TEST_EXPECT_MSG_NE(dca, nullptr, "DutyCycleAns was expected, cmd type cast failed");
1895 }
1896
1897 Reset();
1898 // DutyCycleReq: duty cycle to 12.5%
1899 {
1900 uint8_t maxDutyCycle = 3;
1901 auto answers = RunMacCommand<DutyCycleReq>(maxDutyCycle);
1902 NS_TEST_EXPECT_MSG_EQ(m_mac->GetAggregatedDutyCycle(),
1903 1 / std::pow(2, maxDutyCycle),
1904 "m_aggregatedDutyCycle != 1");
1905 NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1");
1906 auto dca = DynamicCast<DutyCycleAns>(answers.at(0));
1907 NS_TEST_EXPECT_MSG_NE(dca, nullptr, "DutyCycleAns was expected, cmd type cast failed");
1908 }
1909
1910 Reset();
1911 // RxParamSetupReq: set rx1Dr, rx2Dr, frequency
1912 {
1913 uint8_t rx1DrOffset = 5;
1914 uint8_t rx2DataRate = 5;
1915 double frequencyHz = 863500000;
1916 m_mac->SetDataRate(5);
1917 auto answers = RunMacCommand<RxParamSetupReq>(rx1DrOffset, rx2DataRate, frequencyHz);
1918 NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetFirstReceiveWindowDataRate()),
1919 unsigned(5 - rx1DrOffset),
1920 "Rx1DataRate does not match rx1DrOffset from RxParamSetupReq");
1921 NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetSecondReceiveWindowDataRate()),
1922 unsigned(rx2DataRate),
1923 "Rx2DataRate does not match rx2DataRate from RxParamSetupReq");
1924 NS_TEST_EXPECT_MSG_EQ(m_mac->GetSecondReceiveWindowFrequency(),
1925 frequencyHz,
1926 "Rx2 frequency does not match frequency from RxParamSetupReq");
1927 NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1");
1928 auto rpsa = DynamicCast<RxParamSetupAns>(answers.at(0));
1929 NS_TEST_ASSERT_MSG_NE(rpsa, nullptr, "RxParamSetupAns was expected, cmd type cast failed");
1930 NS_TEST_EXPECT_MSG_EQ(rpsa->GetRx1DrOffsetAck(), true, "Rx1DrOffsetAck != true");
1931 NS_TEST_EXPECT_MSG_EQ(rpsa->GetRx2DataRateAck(), true, "Rx2DataRateAck != true");
1932 NS_TEST_EXPECT_MSG_EQ(rpsa->GetChannelAck(), true, "ChannelAck expected to be true");
1933 }
1934
1935 Reset();
1936 // RxParamSetupReq: invalid rx1Dr, rx2Dr, frequency
1937 { // WARNING: default values are manually set here
1938 uint8_t rx1DrOffset = 6;
1939 uint8_t rx2DataRate = 12;
1940 double frequencyHz = 871000000;
1941 m_mac->SetDataRate(5);
1942 auto answers = RunMacCommand<RxParamSetupReq>(rx1DrOffset, rx2DataRate, frequencyHz);
1943 NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetFirstReceiveWindowDataRate()),
1944 5,
1945 "Rx1DataRate expected to be default value");
1946 NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetSecondReceiveWindowDataRate()),
1947 0,
1948 "Rx2DataRate expected to be default value");
1949 NS_TEST_EXPECT_MSG_EQ(m_mac->GetSecondReceiveWindowFrequency(),
1950 869525000,
1951 "Rx2 frequency expected to be default value");
1952 NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1");
1953 auto rpsa = DynamicCast<RxParamSetupAns>(answers.at(0));
1954 NS_TEST_ASSERT_MSG_NE(rpsa, nullptr, "RxParamSetupAns was expected, cmd type cast failed");
1955 NS_TEST_EXPECT_MSG_EQ(rpsa->GetRx1DrOffsetAck(), false, "Rx1DrOffsetAck != false");
1956 NS_TEST_EXPECT_MSG_EQ(rpsa->GetRx2DataRateAck(), false, "Rx2DataRateAck != false");
1957 NS_TEST_EXPECT_MSG_EQ(rpsa->GetChannelAck(), false, "ChannelAck expected to be false");
1958 }
1959
1960 Reset();
1961 // DevStatusReq: get default values
1962 { // WARNING: default values are manually set here
1963 auto answers = RunMacCommand<DevStatusReq>();
1964 NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1");
1965 auto dsa = DynamicCast<DevStatusAns>(answers.at(0));
1966 NS_TEST_ASSERT_MSG_NE(dsa, nullptr, "DevStatusAns was expected, cmd type cast failed");
1967 NS_TEST_EXPECT_MSG_EQ(unsigned(dsa->GetBattery()), 0, "Battery expected == 0 (ext power)");
1968 NS_TEST_EXPECT_MSG_EQ(unsigned(dsa->GetMargin()), 31, "Margin expected to be 31 (default)");
1969 }
1970
1971 Reset();
1972 // NewChannelReq: add a new channel
1973 {
1974 uint8_t chIndex = 4;
1975 double frequencyHz = 865100000;
1976 uint8_t minDataRate = 1;
1977 uint8_t maxDataRate = 4;
1978 auto answers = RunMacCommand<NewChannelReq>(chIndex, frequencyHz, minDataRate, maxDataRate);
1979 NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1");
1980 auto c = m_mac->GetLogicalLoraChannelHelper()->GetRawChannelArray().at(chIndex);
1981 NS_TEST_ASSERT_MSG_NE(c, nullptr, "Channel at chIndex slot expected not to be nullptr");
1982 NS_TEST_EXPECT_MSG_EQ(c->GetFrequency(),
1983 frequencyHz,
1984 "Channel frequency expected to equal NewChannelReq frequency");
1985 NS_TEST_EXPECT_MSG_EQ(c->GetMinimumDataRate(),
1986 unsigned(minDataRate),
1987 "Channel minDataRate expected to equal NewChannelReq minDataRate");
1988 NS_TEST_EXPECT_MSG_EQ(c->GetMaximumDataRate(),
1989 unsigned(maxDataRate),
1990 "Channel maxDataRate expected to equal NewChannelReq maxDataRate");
1991 auto nca = DynamicCast<NewChannelAns>(answers.at(0));
1992 NS_TEST_ASSERT_MSG_NE(nca, nullptr, "NewChannelAns was expected, cmd type cast failed");
1993 NS_TEST_EXPECT_MSG_EQ(nca->GetDataRateRangeOk(), true, "DataRateRangeOk != true");
1994 NS_TEST_EXPECT_MSG_EQ(nca->GetChannelFrequencyOk(), true, "ChannelFrequencyOk != true");
1995 }
1996
1997 Reset();
1998 // NewChannelReq: invalid new channel
1999 { // WARNING: default values are manually set here
2000 uint8_t chIndex = 1;
2001 double frequencyHz = 862000000;
2002 uint8_t minDataRate = 14;
2003 uint8_t maxDataRate = 13;
2004 auto answers = RunMacCommand<NewChannelReq>(chIndex, frequencyHz, minDataRate, maxDataRate);
2005 NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1");
2006 double defaultFrequenciesHz[3] = {868100000, 868300000, 868500000};
2007 auto channels = m_mac->GetLogicalLoraChannelHelper()->GetRawChannelArray();
2008 for (size_t i = 0; i < channels.size(); i++)
2009 {
2010 const auto& c = channels.at(i);
2011 if (i > 2)
2012 {
2013 NS_TEST_ASSERT_MSG_EQ(c, nullptr, "Channel " << i << "expected to be nullptr");
2014 continue;
2015 }
2016 NS_TEST_EXPECT_MSG_EQ(c->GetFrequency(),
2017 defaultFrequenciesHz[i],
2018 "Channel frequency expected to equal NewChannelReq frequency");
2019 NS_TEST_EXPECT_MSG_EQ(unsigned(c->GetMinimumDataRate()),
2020 0,
2021 "Channel " << i << " minDataRate expected to be default");
2022 NS_TEST_EXPECT_MSG_EQ(unsigned(c->GetMaximumDataRate()),
2023 5,
2024 "Channel " << i << " maxDataRate expected to be default");
2025 NS_TEST_EXPECT_MSG_EQ(c->IsEnabledForUplink(),
2026 true,
2027 "Channel " << i << " state expected to be active by default");
2028 }
2029 auto nca = DynamicCast<NewChannelAns>(answers.at(0));
2030 NS_TEST_ASSERT_MSG_NE(nca, nullptr, "NewChannelAns was expected, cmd type cast failed");
2031 NS_TEST_EXPECT_MSG_EQ(nca->GetDataRateRangeOk(), false, "DataRateRangeOk != false");
2032 NS_TEST_EXPECT_MSG_EQ(nca->GetChannelFrequencyOk(), false, "ChannelFrequencyOk != false");
2033 }
2034}
2035
2036/**
2037 * @ingroup lorawan
2038 *
2039 * It tests the correct execution of the ADR backoff procedure of LoRaWAN devices.
2040 * (See, LoRaWAN L2 1.0.4 Specifications (2020), Section 4.3.1.1)
2041 */
2043{
2044 public:
2045 AdrBackoffTest(); //!< Default constructor
2046 ~AdrBackoffTest() override; //!< Destructor
2047
2048 private:
2049 /**
2050 * Create and send an empty app payload unconfirmed frame through the MAC layer to increment
2051 * of the FCnt and ADRACKCnt and eventually activate the ADR backoff procedure configurations of
2052 * the MAC layer. The packet is sent after a delay (simulated time is fast-forwarded to the
2053 * event) such that the device does not incur any duty-cycle limitation. The sent packet FHDR is
2054 * returned as argument for validation purposes.
2055 *
2056 * @param after Delay to schedule the packet after to avoid duty-cycle limitations
2057 * @param fhdr [out] FHDR of the constructed frame passed to PHY by the MAC
2058 */
2059 void SendUplink(Time after, LoraFrameHeader& fhdr);
2060
2061 /**
2062 * Create and receive an empty payload downlink destined for the LoRaWAN MAC. This is used to
2063 * test resetting the ADR backoff procedure.
2064 */
2065 void ReceiveDownlink();
2066
2067 /**
2068 * This function resets the simulation and device MAC layer, use before test sub-cases.
2069 */
2070 void Reset();
2071
2072 void DoRun() override;
2073
2074 Ptr<ClassAEndDeviceLorawanMac> m_mac; //!< The end device's MAC layer used in tests.
2075};
2076
2078 : TestCase("Test the ADR backoff procedure of the LoRaWAN MAC protocol")
2079{
2080}
2081
2083{
2084 m_mac = nullptr;
2085}
2086
2087void
2089{
2090 Ptr<Packet> pkt;
2091 LorawanMacHeader mhdr;
2092 // Send packet through the MAC layer
2093 pkt = Create<Packet>(0);
2096 // Retrieve uplink FHDR
2097 pkt->RemoveHeader(mhdr);
2098 fhdr.SetAsUplink();
2099 pkt->RemoveHeader(fhdr);
2100 NS_LOG_LOGIC("FHDR: " << fhdr);
2101}
2102
2103void
2105{
2106 Ptr<Packet> pkt;
2107 LoraFrameHeader fhdr;
2108 LorawanMacHeader mhdr;
2109 // Prepare DL packet
2110 pkt = Create<Packet>(0);
2111 fhdr.SetAsDownlink();
2112 pkt->AddHeader(fhdr);
2114 pkt->AddHeader(mhdr);
2115 // Trigger MAC layer reception
2117 ->SwitchToStandby(); // usually done as we open Rx windows
2118 m_mac->Receive(pkt);
2119}
2120
2121void
2123{
2125 // Reset MAC state
2126 LorawanMacHelper macHelper;
2129 /// @todo Install should not require a node in input.
2130 m_mac = DynamicCast<ClassAEndDeviceLorawanMac>(macHelper.Install(nullptr, nullptr));
2131 NS_TEST_EXPECT_MSG_NE(m_mac, nullptr, "Failed to initialize MAC layer object.");
2133 phy->SetChannel(CreateObject<LoraChannel>());
2135 m_mac->SetPhy(phy);
2136}
2137
2138void
2140{
2141 NS_LOG_DEBUG("AdrBackoffTest");
2142
2143 Reset();
2144 // Full ADR Backoff procedure
2145 {
2146 LoraFrameHeader fhdr;
2147 auto llch = m_mac->GetLogicalLoraChannelHelper();
2148 auto ADR_ACK_LIMIT = EndDeviceLorawanMac::ADR_ACK_LIMIT;
2149 auto ADR_ACK_DELAY = EndDeviceLorawanMac::ADR_ACK_DELAY;
2150 // Custom config to force full ADR backoff
2151 {
2152 // Tx parameters to furthest settings from default
2153 m_mac->SetDataRate(5);
2154 m_mac->SetTransmissionPowerDbm(0);
2155 m_mac->SetMaxNumberOfTransmissions(8);
2156 auto chVec = llch->GetRawChannelArray();
2157 chVec.at(0)->DisableForUplink();
2158 chVec.at(1)->DisableForUplink();
2159 chVec.at(2)->DisableForUplink();
2160 // Provide additional non-default channel for uplinks
2161 auto nonDefaultChannel = Create<LogicalLoraChannel>(869850000, 0, 5);
2162 llch->SetChannel(3, nonDefaultChannel);
2163 }
2164 // 7 total backoff steps: 1 tx power + 5 data rate + 1 nbtrans & channels
2165 for (uint32_t fCnt = 0; fCnt <= ADR_ACK_LIMIT + ADR_ACK_DELAY * 7U; ++fCnt)
2166 {
2167 SendUplink(Minutes(20), fhdr);
2168 NS_TEST_EXPECT_MSG_EQ(fhdr.GetFCnt(), fCnt, "Unexpected FCnt value in uplink FHDR");
2170 fCnt >= ADR_ACK_LIMIT,
2171 "Unexpected ADRACKReq value in FHDR of uplink fCnt=" << fCnt);
2172 uint8_t step = (fCnt >= ADR_ACK_LIMIT) ? (fCnt - ADR_ACK_LIMIT) / ADR_ACK_DELAY : 0;
2173 NS_TEST_EXPECT_MSG_EQ(m_mac->GetTransmissionPowerDbm(),
2174 (step > 0) ? 14 : 0,
2175 "Unexpected tx power on uplink fCnt=" << fCnt);
2176 uint8_t expectedDr = (step == 0) ? 5 : (step < 7) ? 5 - (step - 1) : 0;
2177 NS_TEST_EXPECT_MSG_EQ(m_mac->GetDataRate(),
2178 expectedDr,
2179 "Unexpected data rate on uplink fCnt=" << fCnt);
2180 auto chVec = llch->GetRawChannelArray();
2181 for (uint8_t i = 0; i < 3; ++i)
2182 {
2183 NS_TEST_EXPECT_MSG_EQ(chVec.at(i)->IsEnabledForUplink(),
2184 step >= 7,
2185 "Unexpected activation state of channel "
2186 << unsigned(i) << " on uplink fCnt=" << fCnt);
2187 }
2189 chVec.at(3)->IsEnabledForUplink(),
2190 true,
2191 "Unexpected activation state of channel 3 on uplink fCnt=" << fCnt);
2192 }
2193 }
2194
2195 Reset();
2196 // ADRACKReq back to false after downlink
2197 {
2198 LoraFrameHeader fhdr;
2199 auto ADR_ACK_LIMIT = EndDeviceLorawanMac::ADR_ACK_LIMIT;
2200 // Trigger ADRACKReq
2201 for (uint16_t fCnt = 0; fCnt <= ADR_ACK_LIMIT; ++fCnt)
2202 {
2203 SendUplink(Minutes(20), fhdr);
2204 NS_TEST_EXPECT_MSG_EQ(fhdr.GetFCnt(), fCnt, "Unexpected FCnt value in uplink FHDR");
2206 fCnt >= ADR_ACK_LIMIT,
2207 "Unexpected ADRACKReq value in FHDR of uplink fCnt=" << fCnt);
2208 }
2210 SendUplink(Minutes(20), fhdr);
2212 ADR_ACK_LIMIT + 1,
2213 "Unexpected FCnt value in uplink FHDR");
2215 fhdr.GetAdrAckReq(),
2216 false,
2217 "Unexpected ADRACKReq value in FHDR of uplink fCnt=" << fhdr.GetFCnt());
2218 }
2219}
2220
2221/**
2222 * @ingroup lorawan
2223 *
2224 * The TestSuite class names the TestSuite, identifies what type of TestSuite, and enables the
2225 * TestCases to be run. Typically, only the constructor for this class must be defined
2226 */
2228{
2229 public:
2230 LorawanTestSuite(); //!< Default constructor
2231};
2232
2234 : TestSuite("lorawan", Type::UNIT)
2235{
2236 // LogComponentEnable("LorawanTestSuite", LOG_LEVEL_DEBUG);
2237 // LogComponentEnable("LorawanMac", LOG_LEVEL_DEBUG);
2238 // LogComponentEnable("EndDeviceLorawanMac", LOG_LEVEL_DEBUG);
2239 // LogComponentEnable("ClassAEndDeviceLorawanMac", LOG_LEVEL_DEBUG);
2240 // LogComponentEnable("SimpleEndDeviceLoraPhy", LOG_LEVEL_DEBUG);
2241 // LogComponentEnable("EndDeviceLoraPhy", LOG_LEVEL_DEBUG);
2242 // LogComponentEnable("LoraPhy", LOG_LEVEL_DEBUG);
2243 // LogComponentEnable("LoraChannel", LOG_LEVEL_DEBUG);
2244 // LogComponentEnable("LoraFrameHeader", LOG_LEVEL_DEBUG);
2245 // LogComponentEnableAll(LOG_PREFIX_FUNC);
2246 // LogComponentEnableAll(LOG_PREFIX_NODE);
2247 // LogComponentEnableAll(LOG_PREFIX_TIME);
2248
2258}
2259
2260// 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 the correct execution of the ADR backoff procedure of LoRaWAN devices.
AdrBackoffTest()
Default constructor.
void DoRun() override
Implementation to actually run this TestCase.
Ptr< ClassAEndDeviceLorawanMac > m_mac
The end device's MAC layer used in tests.
~AdrBackoffTest() override
Destructor.
void ReceiveDownlink()
Create and receive an empty payload downlink destined for the LoRaWAN MAC.
void Reset()
This function resets the simulation and device MAC layer, use before test sub-cases.
void SendUplink(Time after, LoraFrameHeader &fhdr)
Create and send an empty app payload unconfirmed frame through the MAC layer to increment of the FCnt...
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.
~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 the functionalities of LoRaWAN MAC commands received by devices.
~MacCommandTest() override
Destructor.
MacCommandTest()
Default constructor.
void Reset()
This function resets the state of the MAC layer used for tests.
void DoRun() override
Implementation to actually run this TestCase.
Ptr< ClassAEndDeviceLorawanMac > m_mac
The end device's MAC layer used in tests.
std::vector< Ptr< MacCommand > > RunMacCommand(Ts &&... args)
Have this class' MAC layer receive a downlink packet carrying the input MAC command.
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:1075
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:70
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:580
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition simulator.cc:125
static void Run()
Run the simulation.
Definition simulator.cc:161
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Definition simulator.cc:169
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition test.cc:296
@ QUICK
Fast test.
Definition test.h:1057
TestCase(const TestCase &)=delete
Caller graph was not generated because of its size.
Type
Type of test.
Definition test.h:1271
TestSuite(std::string name, Type type=Type::UNIT)
Construct a new test suite.
Definition test.cc:494
Simulation virtual time values and global simulation resolution.
Definition nstime.h:95
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition nstime.h:398
@ STANDBY
The PHY layer is in STANDBY.
static constexpr uint16_t ADR_ACK_DELAY
ADRACKCnt threshold for ADR backoff action.
void Send(Ptr< Packet > packet) override
Send a packet.
static constexpr uint16_t ADR_ACK_LIMIT
ADRACKCnt threshold for setting ADRACKReq.
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.
std::vector< Ptr< MacCommand > > GetCommands()
Return a vector of pointers to all the MAC commands saved in this header.
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 AddCommand(Ptr< MacCommand > macCommand)
Add a predefined command to the vector in this frame header.
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.
bool GetAdrAckReq() const
Get the value of the ADRACKReq bit field.
void SetAsUplink()
State that this is an uplink message.
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.
void SetAsDownlink()
State that this is a downlink message.
Helper for LoraPhy that manages interference calculations.
Time GetOverlapTime(Ptr< LoraInterferenceHelper::Event > event1, Ptr< LoraInterferenceHelper::Event > event2)
Compute the time duration in which two given events are overlapping.
Ptr< LoraInterferenceHelper::Event > Add(Time duration, double rxPower, uint8_t spreadingFactor, Ptr< Packet > packet, uint32_t frequencyHz)
Add an event to the InterferenceHelper.
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:155
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.
Helper class for configuring and installing the LorawanMac class on devices and gateways.
void SetDeviceType(enum DeviceType dt)
Set the kind of MAC this helper will create.
void SetRegion(enum Regions region)
Set the region in which the device is to operate.
Ptr< LorawanMac > Install(Ptr< Node > node, Ptr< NetDevice > device) const
Create the LorawanMac instance and connect it to a device.
void Send(Ptr< Packet > packet, LoraTxParameters txParams, uint32_t frequencyHz, double txPowerDbm) override
Instruct the PHY to send a packet according to some parameters.
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:690
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:194
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:260
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition log.h:274
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
@ CR_4_5
Coding rate 4/5.
Definition lora-phy.h:31
@ CR_4_6
Coding rate 4/6.
Definition lora-phy.h:32
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:627
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:454
#define NS_TEST_ASSERT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report and abort if not.
Definition test.h:133
#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:655
#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:240
#define NS_TEST_ASSERT_MSG_NE(actual, limit, msg)
Test that an actual and expected (limit) value are not equal and report and abort if not.
Definition test.h:553
#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:499
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1273
Time Hours(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1244
Time Minutes(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1256
static LorawanTestSuite lorawanTestSuite
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:605
Structure to collect all parameters that are used to compute the duration of a packet (excluding payl...
Definition lora-phy.h:54
uint32_t nPreamble
Number of preamble symbols.
Definition lora-phy.h:59
CodingRate codingRate
Code rate (obtained as 4/(codingRate+4)).
Definition lora-phy.h:57
uint32_t bandwidthHz
Bandwidth in Hz.
Definition lora-phy.h:58
bool headerDisabled
Whether to use implicit header mode.
Definition lora-phy.h:56
bool lowDataRateOptimizationEnabled
Whether low data rate optimization is enabled.
Definition lora-phy.h:61
bool crcEnabled
Whether Cyclic Redundancy Check (CRC) is enabled.
Definition lora-phy.h:60
uint8_t sf
Spreading Factor.
Definition lora-phy.h:55