From 2b7e8dbf629fc484568484b05831e042d47c2075 Mon Sep 17 00:00:00 2001 From: Alessandro Aimi Date: Fri, 8 Nov 2024 15:02:05 +0100 Subject: [PATCH 01/34] Comment out logging in tests --- test/lorawan-test-suite.cc | 4 ++-- test/network-scheduler-test-suite.cc | 4 ++-- test/network-server-test-suite.cc | 28 ++++++++++++++-------------- test/network-status-test-suite.cc | 4 ++-- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/test/lorawan-test-suite.cc b/test/lorawan-test-suite.cc index c3e3d1d7e5..bf16f22c55 100644 --- a/test/lorawan-test-suite.cc +++ b/test/lorawan-test-suite.cc @@ -1617,8 +1617,8 @@ class LorawanTestSuite : public TestSuite LorawanTestSuite::LorawanTestSuite() : TestSuite("lorawan", Type::UNIT) { - LogComponentEnable("LorawanTestSuite", LOG_LEVEL_DEBUG); - // TestDuration for TestCase can be QUICK, EXTENSIVE or TAKES_FOREVER + // LogComponentEnable("LorawanTestSuite", LOG_LEVEL_DEBUG); + AddTestCase(new InterferenceTest, Duration::QUICK); AddTestCase(new AddressTest, Duration::QUICK); AddTestCase(new HeaderTest, Duration::QUICK); diff --git a/test/network-scheduler-test-suite.cc b/test/network-scheduler-test-suite.cc index 2fc69d7972..06e42d30bb 100644 --- a/test/network-scheduler-test-suite.cc +++ b/test/network-scheduler-test-suite.cc @@ -70,8 +70,8 @@ class NetworkSchedulerTestSuite : public TestSuite NetworkSchedulerTestSuite::NetworkSchedulerTestSuite() : TestSuite("network-scheduler", Type::UNIT) { - LogComponentEnable("NetworkSchedulerTestSuite", LOG_LEVEL_DEBUG); - // TestDuration for TestCase can be QUICK, EXTENSIVE or TAKES_FOREVER + // LogComponentEnable("NetworkSchedulerTestSuite", LOG_LEVEL_DEBUG); + AddTestCase(new NetworkSchedulerTest, Duration::QUICK); } diff --git a/test/network-server-test-suite.cc b/test/network-server-test-suite.cc index 46f19ddf45..94b9ed8886 100644 --- a/test/network-server-test-suite.cc +++ b/test/network-server-test-suite.cc @@ -344,20 +344,20 @@ NetworkServerTestSuite::NetworkServerTestSuite() { LogComponentEnable("NetworkServerTestSuite", LOG_LEVEL_DEBUG); - LogComponentEnable("NetworkServer", LOG_LEVEL_ALL); - LogComponentEnable("NetworkStatus", LOG_LEVEL_ALL); - LogComponentEnable("NetworkScheduler", LOG_LEVEL_ALL); - LogComponentEnable("NetworkController", LOG_LEVEL_ALL); - LogComponentEnable("NetworkControllerComponent", LOG_LEVEL_ALL); - LogComponentEnable("LoraNetDevice", LOG_LEVEL_ALL); - LogComponentEnable("GatewayLorawanMac", LOG_LEVEL_ALL); - LogComponentEnable("EndDeviceLorawanMac", LOG_LEVEL_ALL); - LogComponentEnable("EndDeviceLoraPhy", LOG_LEVEL_ALL); - LogComponentEnable("EndDeviceStatus", LOG_LEVEL_ALL); - - LogComponentEnableAll(LOG_PREFIX_FUNC); - LogComponentEnableAll(LOG_PREFIX_NODE); - LogComponentEnableAll(LOG_PREFIX_TIME); + // Activate only at need, as these can create problems among test suites when running ./test.py + // LogComponentEnable("NetworkServer", LOG_LEVEL_ALL); + // LogComponentEnable("NetworkStatus", LOG_LEVEL_ALL); + // LogComponentEnable("NetworkScheduler", LOG_LEVEL_ALL); + // LogComponentEnable("NetworkController", LOG_LEVEL_ALL); + // LogComponentEnable("NetworkControllerComponent", LOG_LEVEL_ALL); + // LogComponentEnable("LoraNetDevice", LOG_LEVEL_ALL); + // LogComponentEnable("GatewayLorawanMac", LOG_LEVEL_ALL); + // LogComponentEnable("EndDeviceLorawanMac", LOG_LEVEL_ALL); + // LogComponentEnable("EndDeviceLoraPhy", LOG_LEVEL_ALL); + // LogComponentEnable("EndDeviceStatus", LOG_LEVEL_ALL); + // LogComponentEnableAll(LOG_PREFIX_FUNC); + // LogComponentEnableAll(LOG_PREFIX_NODE); + // LogComponentEnableAll(LOG_PREFIX_TIME); // TestDuration for TestCase can be QUICK, EXTENSIVE or TAKES_FOREVER AddTestCase(new UplinkPacketTest, Duration::QUICK); diff --git a/test/network-status-test-suite.cc b/test/network-status-test-suite.cc index ac0058af7b..a24bce89f8 100644 --- a/test/network-status-test-suite.cc +++ b/test/network-status-test-suite.cc @@ -126,8 +126,8 @@ class NetworkStatusTestSuite : public TestSuite NetworkStatusTestSuite::NetworkStatusTestSuite() : TestSuite("network-status", Type::UNIT) { - LogComponentEnable("NetworkStatusTestSuite", LOG_LEVEL_DEBUG); - // TestDuration for TestCase can be QUICK, EXTENSIVE or TAKES_FOREVER + // LogComponentEnable("NetworkStatusTestSuite", LOG_LEVEL_DEBUG); + AddTestCase(new EndDeviceStatusTest, Duration::QUICK); AddTestCase(new NetworkStatusTest, Duration::QUICK); } From fd2721cca808966e56c8355af22770c09f364cd9 Mon Sep 17 00:00:00 2001 From: Alessandro Aimi Date: Fri, 8 Nov 2024 19:28:11 +0100 Subject: [PATCH 02/34] Refactor DB to Db for consistency --- examples/adr-example.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/adr-example.cc b/examples/adr-example.cc index 2e4167cf58..1b1d1c2d0d 100644 --- a/examples/adr-example.cc +++ b/examples/adr-example.cc @@ -73,7 +73,7 @@ main(int argc, char* argv[]) double mobileNodeProbability = 0; double sideLengthMeters = 10000; int gatewayDistanceMeters = 5000; - double maxRandomLossDB = 10; + double maxRandomLossDb = 10; double minSpeedMetersPerSecond = 2; double maxSpeedMetersPerSecond = 16; std::string adrType = "ns3::AdrComponent"; @@ -98,7 +98,7 @@ main(int argc, char* argv[]) sideLengthMeters); cmd.AddValue("maxRandomLoss", "Maximum amount (dB) of the random loss component", - maxRandomLossDB); + maxRandomLossDb); cmd.AddValue("gatewayDistance", "Distance (m) between gateways", gatewayDistanceMeters); cmd.AddValue("initializeSF", "Whether to initialize the SFs", initializeSF); cmd.AddValue("MinSpeed", "Minimum speed (m/s) for mobile devices", minSpeedMetersPerSecond); @@ -143,7 +143,7 @@ main(int argc, char* argv[]) Ptr x = CreateObject(); x->SetAttribute("Min", DoubleValue(0.0)); - x->SetAttribute("Max", DoubleValue(maxRandomLossDB)); + x->SetAttribute("Max", DoubleValue(maxRandomLossDb)); Ptr randomLoss = CreateObject(); randomLoss->SetAttribute("Variable", PointerValue(x)); From d541034cc2978603f133e926e663afae5131f57a Mon Sep 17 00:00:00 2001 From: Alessandro Aimi Date: Sat, 9 Nov 2024 12:29:39 +0100 Subject: [PATCH 03/34] Refactor m_controlDataRate/DataRateAdaptation to ADR bit as in LoRaWAN specifications --- examples/adr-example.cc | 2 +- model/end-device-lorawan-mac.cc | 25 +++++++++++++------------ model/end-device-lorawan-mac.h | 25 +++++++++++++++---------- 3 files changed, 29 insertions(+), 23 deletions(-) diff --git a/examples/adr-example.cc b/examples/adr-example.cc index 1b1d1c2d0d..6d99a02299 100644 --- a/examples/adr-example.cc +++ b/examples/adr-example.cc @@ -132,7 +132,7 @@ main(int argc, char* argv[]) // Set the end devices to allow data rate control (i.e. adaptive data rate) from the network // server - Config::SetDefault("ns3::EndDeviceLorawanMac::DRControl", BooleanValue(true)); + Config::SetDefault("ns3::EndDeviceLorawanMac::ADR", BooleanValue(true)); // Create a simple wireless channel /////////////////////////////////// diff --git a/model/end-device-lorawan-mac.cc b/model/end-device-lorawan-mac.cc index 449730ac1f..ae126b679d 100644 --- a/model/end-device-lorawan-mac.cc +++ b/model/end-device-lorawan-mac.cc @@ -49,10 +49,11 @@ EndDeviceLorawanMac::GetTypeId() MakeTraceSourceAccessor(&EndDeviceLorawanMac::m_dataRate), "ns3::TracedValueCallback::uint8_t") .AddAttribute( - "DRControl", - "Whether to request the network server to control this device's data rate", - BooleanValue(), - MakeBooleanAccessor(&EndDeviceLorawanMac::m_controlDataRate), + "ADR", + "Ensure to the network server that this device will accept data rate, transmission " + "power and number of retransmissions configurations received via LinkADRReq.", + BooleanValue(true), + MakeBooleanAccessor(&EndDeviceLorawanMac::m_adr), MakeBooleanChecker()) .AddTraceSource("TxPower", "Transmission power currently employed by this end device", @@ -109,8 +110,7 @@ EndDeviceLorawanMac::EndDeviceLorawanMac() m_address(LoraDeviceAddress(0)), // LoraWAN default m_receiveWindowDurationInSymbols(8), - // LoraWAN default - m_controlDataRate(false), + m_adr(true), m_lastKnownLinkMargin(0), m_lastKnownGatewayCount(0), m_aggregatedDutyCycle(1), @@ -453,7 +453,7 @@ EndDeviceLorawanMac::ApplyNecessaryOptions(LoraFrameHeader& frameHeader) frameHeader.SetAsUplink(); frameHeader.SetFPort(1); // TODO Use an appropriate frame port based on the application frameHeader.SetAddress(m_address); - frameHeader.SetAdr(m_controlDataRate); + frameHeader.SetAdr(m_adr); frameHeader.SetAdrAckReq(false); // TODO Set ADRACKREQ if a member variable is true // FPending does not exist in uplink messages @@ -612,16 +612,17 @@ EndDeviceLorawanMac::resetRetransmissionParameters() } void -EndDeviceLorawanMac::SetDataRateAdaptation(bool adapt) +EndDeviceLorawanMac::SetUplinkAdrBit(bool adr) { - NS_LOG_FUNCTION(this << adapt); - m_enableDRAdapt = adapt; + NS_LOG_FUNCTION(this << adr); + m_adr = adr; } bool -EndDeviceLorawanMac::GetDataRateAdaptation() const +EndDeviceLorawanMac::GetUplinkAdrBit() const { - return m_enableDRAdapt; + NS_LOG_FUNCTION(this); + return m_adr; } void diff --git a/model/end-device-lorawan-mac.h b/model/end-device-lorawan-mac.h index 5f588f68d9..9693f7cdb9 100644 --- a/model/end-device-lorawan-mac.h +++ b/model/end-device-lorawan-mac.h @@ -114,18 +114,22 @@ class EndDeviceLorawanMac : public LorawanMac virtual void resetRetransmissionParameters(); /** - * Enable data rate adaptation in the retransmitting procedure. + * Signals to the network server that this device will or may not comply with LinkADRReq + * settings (data rate, transmission power and number of retransmissions) received in downlink. * - * \param adapt If the data rate adaptation is enabled or not. + * \param adr The ADR bit. */ - void SetDataRateAdaptation(bool adapt); + void SetUplinkAdrBit(bool adr); /** - * Get if data rate adaptation is enabled or not. + * Get the current value of the device's uplink ADR bit of the LoRaWAN FHDR. * - * \return True if the data rate adaptation is enabled, false if disabled. + * \return true The device will comply with data rate, transmission power and number of + * retransmissions settings received from the network server via LikADRReq. + * \return false Signals to the network server that the device may not comply with the data + * rate, transmission power and number of retransmissions settings received via LikADRReq. */ - bool GetDataRateAdaptation() const; + bool GetUplinkAdrBit() const; /** * Set the max number of unacknowledged redundant transmissions of each packet. If, @@ -441,10 +445,11 @@ class EndDeviceLorawanMac : public LorawanMac */ Time GetNextTransmissionDelay(); - /** - * Whether this device's data rate should be controlled by the network server. - */ - bool m_controlDataRate; + bool m_adr; //!< Uplink ADR bit contained in the FCtrl field of the LoRaWAN FHDR. + //!< Controlled by the device, if set to false signals the network server + //!< that the device may not accept attempts to control the number of + //!< retransmissions, the data rate, or the TX power with downlink + //!< LinkADRReq commands. /** * The event of retransmitting a packet in a consecutive moment if an ACK is not received. From 56062ee5dd9a4d39272df2bbef87ae2c6dd8a7df Mon Sep 17 00:00:00 2001 From: Alessandro Aimi Date: Mon, 11 Nov 2024 15:10:48 +0100 Subject: [PATCH 04/34] Add Margin unit of measure & getters for Margin and GwCnt --- model/end-device-lorawan-mac.cc | 22 +++++++++++++++++----- model/end-device-lorawan-mac.h | 26 +++++++++++++++++++++++--- test/network-server-test-suite.cc | 6 +++--- 3 files changed, 43 insertions(+), 11 deletions(-) diff --git a/model/end-device-lorawan-mac.cc b/model/end-device-lorawan-mac.cc index ae126b679d..afa972b2cf 100644 --- a/model/end-device-lorawan-mac.cc +++ b/model/end-device-lorawan-mac.cc @@ -63,13 +63,13 @@ EndDeviceLorawanMac::GetTypeId() "Last known demodulation margin in " "communications between this end device " "and a gateway", - MakeTraceSourceAccessor(&EndDeviceLorawanMac::m_lastKnownLinkMargin), - "ns3::TracedValueCallback::Double") + MakeTraceSourceAccessor(&EndDeviceLorawanMac::m_lastKnownLinkMarginDb), + "ns3::TracedValueCallback::uint8_t") .AddTraceSource("LastKnownGatewayCount", "Last known number of gateways able to " "listen to this end device", MakeTraceSourceAccessor(&EndDeviceLorawanMac::m_lastKnownGatewayCount), - "ns3::TracedValueCallback::Int") + "ns3::TracedValueCallback::uint8_t") .AddTraceSource("AggregatedDutyCycle", "Aggregate duty cycle, in fraction form, " "this end device must respect", @@ -111,7 +111,7 @@ EndDeviceLorawanMac::EndDeviceLorawanMac() // LoraWAN default m_receiveWindowDurationInSymbols(8), m_adr(true), - m_lastKnownLinkMargin(0), + m_lastKnownLinkMarginDb(0), m_lastKnownGatewayCount(0), m_aggregatedDutyCycle(1), m_mType(LorawanMacHeader::CONFIRMED_DATA_UP), @@ -677,7 +677,7 @@ EndDeviceLorawanMac::OnLinkCheckAns(uint8_t margin, uint8_t gwCnt) { NS_LOG_FUNCTION(this << unsigned(margin) << unsigned(gwCnt)); - m_lastKnownLinkMargin = margin; + m_lastKnownLinkMarginDb = margin; m_lastKnownGatewayCount = gwCnt; } @@ -897,6 +897,18 @@ EndDeviceLorawanMac::AddSubBand(double startFrequency, m_channelHelper->AddSubBand(startFrequency, endFrequency, dutyCycle, maxTxPowerDbm); } +uint8_t +EndDeviceLorawanMac::GetLastKnownLinkMarginDb() const +{ + return m_lastKnownLinkMarginDb; +} + +uint8_t +EndDeviceLorawanMac::GetLastKnownGatewayCount() const +{ + return m_lastKnownGatewayCount; +} + double EndDeviceLorawanMac::GetAggregatedDutyCycle() { diff --git a/model/end-device-lorawan-mac.h b/model/end-device-lorawan-mac.h index 9693f7cdb9..c9ce0beb85 100644 --- a/model/end-device-lorawan-mac.h +++ b/model/end-device-lorawan-mac.h @@ -188,6 +188,26 @@ class EndDeviceLorawanMac : public LorawanMac // uint8_t GetRx1DrOffset (); + /** + * Get the last known link margin from the demodulation floor. + * + * This is intended for asynchronous polling by the Application layer of the device. For + * synchronous behavior provide a callback using the trace system. + * + * \return The last known link margin [dB] + */ + uint8_t GetLastKnownLinkMarginDb() const; + + /** + * Get the last known number of gateways concurrently receiving transmissions from the device. + * + * This is intended for asynchronous polling by the Application layer of the device. For + * synchronous behavior provide a callback using the trace system. + * + * \return The last known number of receiver gateways. + */ + uint8_t GetLastKnownGatewayCount() const; + /** * Get the aggregated duty cycle. * @@ -469,12 +489,12 @@ class EndDeviceLorawanMac : public LorawanMac EventId m_nextRetx; /** - * The last known link margin. + * The last known link margin in dB from the demodulation floor. * * This value is obtained (and updated) when a LinkCheckAns Mac command is * received. */ - TracedValue m_lastKnownLinkMargin; + TracedValue m_lastKnownLinkMarginDb; /** * The last known gateway count (i.e., gateways that are in communication @@ -483,7 +503,7 @@ class EndDeviceLorawanMac : public LorawanMac * This value is obtained (and updated) when a LinkCheckAns Mac command is * received. */ - TracedValue m_lastKnownGatewayCount; + TracedValue m_lastKnownGatewayCount; /** * The aggregated duty cycle this device needs to respect across all sub-bands. diff --git a/test/network-server-test-suite.cc b/test/network-server-test-suite.cc index 94b9ed8886..bf34b6aaae 100644 --- a/test/network-server-test-suite.cc +++ b/test/network-server-test-suite.cc @@ -240,7 +240,7 @@ class LinkCheckTest : public TestCase * \param newValue The updated value. * \param oldValue The previous value. */ - void LastKnownGatewayCount(int newValue, int oldValue); + void LastKnownGatewayCount(uint8_t newValue, uint8_t oldValue); /** * Send a packet containing a LinkCheckReq MAC command from the input end device. @@ -254,7 +254,7 @@ class LinkCheckTest : public TestCase void DoRun() override; bool m_receivedPacketAtEd = false; //!< Set to true if a packet containing a LinkCheckAns MAC //!< command is received by the end device - int m_numberOfGatewaysThatReceivedPacket = + uint8_t m_numberOfGatewaysThatReceivedPacket = 0; //!< Stores the number of gateways that received the last packet carrying a //!< LinkCheckReq MAC command }; @@ -272,7 +272,7 @@ LinkCheckTest::~LinkCheckTest() } void -LinkCheckTest::LastKnownGatewayCount(int newValue, int oldValue) +LinkCheckTest::LastKnownGatewayCount(uint8_t newValue, uint8_t oldValue) { NS_LOG_DEBUG("Updated gateway count"); m_receivedPacketAtEd = true; From 913c6a062a4cc55cba883fb2eeeec7e1dc38b606 Mon Sep 17 00:00:00 2001 From: Alessandro Aimi Date: Sat, 9 Nov 2024 16:09:39 +0100 Subject: [PATCH 05/34] Fit LinkAdrReq MAC command to specifications and remove regional dependencies --- model/mac-command.cc | 50 ++++++++++++++++++++------------------------ model/mac-command.h | 48 ++++++++++++++++++++++++------------------ 2 files changed, 51 insertions(+), 47 deletions(-) diff --git a/model/mac-command.cc b/model/mac-command.cc index 7696dd9a22..bfd630d083 100644 --- a/model/mac-command.cc +++ b/model/mac-command.cc @@ -264,14 +264,14 @@ LinkAdrReq::LinkAdrReq() LinkAdrReq::LinkAdrReq(uint8_t dataRate, uint8_t txPower, - uint16_t channelMask, + uint16_t chMask, uint8_t chMaskCntl, - uint8_t nbRep) + uint8_t nbTrans) : m_dataRate(dataRate), m_txPower(txPower), - m_channelMask(channelMask), + m_chMask(chMask), m_chMaskCntl(chMaskCntl), - m_nbRep(nbRep) + m_nbTrans(nbTrans) { NS_LOG_FUNCTION(this); @@ -287,8 +287,8 @@ LinkAdrReq::Serialize(Buffer::Iterator& start) const // Write the CID start.WriteU8(GetCIDFromMacCommand(m_commandType)); start.WriteU8(m_dataRate << 4 | (m_txPower & 0b1111)); - start.WriteU16(m_channelMask); - start.WriteU8(m_chMaskCntl << 4 | (m_nbRep & 0b1111)); + start.WriteU16(m_chMask); + start.WriteU8(m_chMaskCntl << 4 | (m_nbTrans & 0b1111)); } uint8_t @@ -301,10 +301,10 @@ LinkAdrReq::Deserialize(Buffer::Iterator& start) uint8_t firstByte = start.ReadU8(); m_dataRate = firstByte >> 4; m_txPower = firstByte & 0b1111; - m_channelMask = start.ReadU16(); + m_chMask = start.ReadU16(); uint8_t fourthByte = start.ReadU8(); m_chMaskCntl = fourthByte >> 4; - m_nbRep = fourthByte & 0b1111; + m_nbTrans = fourthByte & 0b1111; return m_serializedSize; } @@ -317,13 +317,13 @@ LinkAdrReq::Print(std::ostream& os) const os << "LinkAdrReq" << std::endl; os << "dataRate: " << unsigned(m_dataRate) << std::endl; os << "txPower: " << unsigned(m_txPower) << std::endl; - os << "channelMask: " << std::bitset<16>(m_channelMask) << std::endl; + os << "chMask: " << std::bitset<16>(m_chMask) << std::endl; os << "chMaskCntl: " << unsigned(m_chMaskCntl) << std::endl; - os << "nbRep: " << unsigned(m_nbRep) << std::endl; + os << "nbTrans: " << unsigned(m_nbTrans) << std::endl; } uint8_t -LinkAdrReq::GetDataRate() +LinkAdrReq::GetDataRate() const { NS_LOG_FUNCTION(this); @@ -331,37 +331,33 @@ LinkAdrReq::GetDataRate() } uint8_t -LinkAdrReq::GetTxPower() +LinkAdrReq::GetTxPower() const { NS_LOG_FUNCTION(this); return m_txPower; } -std::list -LinkAdrReq::GetEnabledChannelsList() +uint16_t +LinkAdrReq::GetChMask() const { NS_LOG_FUNCTION(this); - std::list channelIndices; - for (int i = 0; i < 16; i++) - { - if (m_channelMask & (0b1 << i)) // Take channel mask's i-th bit - { - NS_LOG_DEBUG("Adding channel index " << i); - channelIndices.push_back(i); - } - } + return m_chMask; +} - return channelIndices; +uint8_t +LinkAdrReq::GetChMaskCtrl() const +{ + return m_chMaskCntl; } -int -LinkAdrReq::GetRepetitions() +uint8_t +LinkAdrReq::GetNbTrans() const { NS_LOG_FUNCTION(this); - return m_nbRep; + return m_nbTrans; } //////////////// diff --git a/model/mac-command.h b/model/mac-command.h index 08a7359e5f..23ec9b6643 100644 --- a/model/mac-command.h +++ b/model/mac-command.h @@ -219,15 +219,15 @@ class LinkAdrReq : public MacCommand * * \param dataRate The DataRate field to set. * \param txPower The TXPower field to set. - * \param channelMask The ChMask field to set. + * \param chMask The ChMask field to set. * \param chMaskCntl The ChMaskCntl field to set. - * \param nbRep The NbTrans field to set. + * \param nbTrans The NbTrans field to set. */ LinkAdrReq(uint8_t dataRate, uint8_t txPower, - uint16_t channelMask, + uint16_t chMask, uint8_t chMaskCntl, - uint8_t nbRep); + uint8_t nbTrans); void Serialize(Buffer::Iterator& start) const override; uint8_t Deserialize(Buffer::Iterator& start) override; @@ -238,7 +238,7 @@ class LinkAdrReq : public MacCommand * * \return An unsigned 8-bit integer containing the data rate. */ - uint8_t GetDataRate(); + uint8_t GetDataRate() const; /** * Get the transmission power prescribed by this MAC command. @@ -249,31 +249,39 @@ class LinkAdrReq : public MacCommand * * \return The TX power, encoded as an unsigned 8-bit integer. */ - uint8_t GetTxPower(); + uint8_t GetTxPower() const; /** - * Get the list of enabled channels. This method takes the 16-bit channel mask - * and translates it to a list of integers that can be more easily parsed. + * Get the 16 bit mask of enabled channels. * - * \return The list of enabled channels. + * \return The 16 bit channel mask. */ - std::list GetEnabledChannelsList(); + uint16_t GetChMask() const; /** - * Get the number of repetitions prescribed by this MAC command. + * Get the ChMaskCtrl field, used as an indicator of the 16-channel bank to apply the ChMask to. * - * \return The number of repetitions. + * The interpretation of this field is region-dependent. + * + * \return The ChMaskCtrl field. + */ + uint8_t GetChMaskCtrl() const; + + /** + * Get the number of repeated transmissions prescribed by this MAC command. + * + * \return The number of repeated transmissions. */ - int GetRepetitions(); + uint8_t GetNbTrans() const; private: - uint8_t m_dataRate; //!< The DataRate field, a serializable parameter for setting the - //!< spreading factor and bandwidth of end devices - uint8_t m_txPower; //!< The TXPower field, a serializable parameter for setting the - //!< transmission power of end devices - uint16_t m_channelMask; //!< The ChMask field - uint8_t m_chMaskCntl; //!< The ChMaskCntl field - uint8_t m_nbRep; //!< The NbTrans field + uint8_t m_dataRate; //!< The DataRate field, a serializable parameter for setting the + //!< spreading factor and bandwidth of end devices + uint8_t m_txPower; //!< The TXPower field, a serializable parameter for setting the + //!< transmission power of end devices + uint16_t m_chMask; //!< The ChMask field + uint8_t m_chMaskCntl; //!< The ChMaskCntl field + uint8_t m_nbTrans; //!< The NbTrans field }; /** From ae19631e085589c1ed618425a3ed8fb967c103f3 Mon Sep 17 00:00:00 2001 From: Alessandro Aimi Date: Mon, 11 Nov 2024 11:55:03 +0100 Subject: [PATCH 06/34] Refactor MaxNumbTx to NbTrans as in LoRaWAN specifications + correct default value --- model/class-a-end-device-lorawan-mac.cc | 12 +++++----- model/end-device-lorawan-mac.cc | 30 ++++++++++++------------- model/end-device-lorawan-mac.h | 7 +++--- 3 files changed, 24 insertions(+), 25 deletions(-) diff --git a/model/class-a-end-device-lorawan-mac.cc b/model/class-a-end-device-lorawan-mac.cc index e85c9db4c8..de6eb43823 100644 --- a/model/class-a-end-device-lorawan-mac.cc +++ b/model/class-a-end-device-lorawan-mac.cc @@ -75,7 +75,7 @@ ClassAEndDeviceLorawanMac::SendToPhy(Ptr packetToSend) NS_LOG_DEBUG("PacketToSend: " << packetToSend); // Data rate adaptation as in LoRaWAN specification, V1.0.2 (2016) - if (m_enableDRAdapt && (m_dataRate > 0) && (m_retxParams.retxLeft < m_maxNumbTx) && + if (m_enableDRAdapt && (m_dataRate > 0) && (m_retxParams.retxLeft < m_nbTrans) && (m_retxParams.retxLeft % 2 == 0)) { m_txPower = 14; // Reset transmission power @@ -187,7 +187,7 @@ ClassAEndDeviceLorawanMac::Receive(Ptr packet) { if (m_retxParams.retxLeft == 0) { - uint8_t txs = m_maxNumbTx - (m_retxParams.retxLeft); + uint8_t txs = m_nbTrans - (m_retxParams.retxLeft); m_requiredTxCallback(txs, false, m_retxParams.firstAttempt, @@ -218,7 +218,7 @@ ClassAEndDeviceLorawanMac::Receive(Ptr packet) } else { - uint8_t txs = m_maxNumbTx - (m_retxParams.retxLeft); + uint8_t txs = m_nbTrans - (m_retxParams.retxLeft); m_requiredTxCallback(txs, false, m_retxParams.firstAttempt, m_retxParams.packet); NS_LOG_DEBUG("Failure: no more retransmissions left. Used " << unsigned(txs) << " transmissions."); @@ -249,7 +249,7 @@ ClassAEndDeviceLorawanMac::FailedReception(Ptr packet) } else { - uint8_t txs = m_maxNumbTx - (m_retxParams.retxLeft); + uint8_t txs = m_nbTrans - (m_retxParams.retxLeft); m_requiredTxCallback(txs, false, m_retxParams.firstAttempt, m_retxParams.packet); NS_LOG_DEBUG("Failure: no more retransmissions left. Used " << unsigned(txs) << " transmissions."); @@ -412,7 +412,7 @@ ClassAEndDeviceLorawanMac::CloseSecondReceiveWindow() else if (m_retxParams.retxLeft == 0 && DynamicCast(m_phy)->GetState() != EndDeviceLoraPhy::RX) { - uint8_t txs = m_maxNumbTx - (m_retxParams.retxLeft); + uint8_t txs = m_nbTrans - (m_retxParams.retxLeft); m_requiredTxCallback(txs, false, m_retxParams.firstAttempt, m_retxParams.packet); NS_LOG_DEBUG("Failure: no more retransmissions left. Used " << unsigned(txs) << " transmissions."); @@ -428,7 +428,7 @@ ClassAEndDeviceLorawanMac::CloseSecondReceiveWindow() } else { - uint8_t txs = m_maxNumbTx - (m_retxParams.retxLeft); + uint8_t txs = m_nbTrans - (m_retxParams.retxLeft); m_requiredTxCallback(txs, true, m_retxParams.firstAttempt, m_retxParams.packet); NS_LOG_INFO( "We have " << unsigned(m_retxParams.retxLeft) diff --git a/model/end-device-lorawan-mac.cc b/model/end-device-lorawan-mac.cc index afa972b2cf..3da759c835 100644 --- a/model/end-device-lorawan-mac.cc +++ b/model/end-device-lorawan-mac.cc @@ -76,9 +76,9 @@ EndDeviceLorawanMac::GetTypeId() MakeTraceSourceAccessor(&EndDeviceLorawanMac::m_aggregatedDutyCycle), "ns3::TracedValueCallback::Double") .AddAttribute("MaxTransmissions", - "Maximum number of transmissions for a packet", - IntegerValue(8), - MakeIntegerAccessor(&EndDeviceLorawanMac::m_maxNumbTx), + "Maximum number of transmissions for a packet (NbTrans)", + IntegerValue(1), + MakeIntegerAccessor(&EndDeviceLorawanMac::m_nbTrans), MakeIntegerChecker()) .AddAttribute("EnableEDDataRateAdaptation", "Whether the end device should up its data rate " @@ -100,7 +100,7 @@ EndDeviceLorawanMac::GetTypeId() EndDeviceLorawanMac::EndDeviceLorawanMac() : m_enableDRAdapt(false), - m_maxNumbTx(8), + m_nbTrans(1), m_dataRate(0), m_txPower(14), m_codingRate(1), @@ -129,7 +129,7 @@ EndDeviceLorawanMac::EndDeviceLorawanMac() // Initialize structure for retransmission parameters m_retxParams = EndDeviceLorawanMac::LoraRetxParameters(); - m_retxParams.retxLeft = m_maxNumbTx; + m_retxParams.retxLeft = m_nbTrans; } EndDeviceLorawanMac::~EndDeviceLorawanMac() @@ -232,12 +232,12 @@ EndDeviceLorawanMac::DoSend(Ptr packet) if (m_retxParams.waitingAck) { // Call the callback to notify about the failure - uint8_t txs = m_maxNumbTx - (m_retxParams.retxLeft); + uint8_t txs = m_nbTrans - (m_retxParams.retxLeft); m_requiredTxCallback(txs, false, m_retxParams.firstAttempt, m_retxParams.packet); NS_LOG_DEBUG(" Received new packet from the application layer: stopping retransmission " "procedure. Used " << unsigned(txs) << " transmissions out of a maximum of " - << unsigned(m_maxNumbTx) << "."); + << unsigned(m_nbTrans) << "."); } // Reset retransmission parameters @@ -248,7 +248,7 @@ EndDeviceLorawanMac::DoSend(Ptr packet) if (m_mType == LorawanMacHeader::CONFIRMED_DATA_UP) { m_retxParams.packet = packet->Copy(); - m_retxParams.retxLeft = m_maxNumbTx; + m_retxParams.retxLeft = m_nbTrans; m_retxParams.waitingAck = true; m_retxParams.firstAttempt = Simulator::Now(); m_retxParams.retxLeft = @@ -339,7 +339,7 @@ EndDeviceLorawanMac::ParseCommands(LoraFrameHeader frameHeader) NS_LOG_DEBUG("Reset retransmission variables to default values and cancel " "retransmission if already scheduled."); - uint8_t txs = m_maxNumbTx - (m_retxParams.retxLeft); + uint8_t txs = m_nbTrans - (m_retxParams.retxLeft); m_requiredTxCallback(txs, true, m_retxParams.firstAttempt, m_retxParams.packet); NS_LOG_DEBUG("Received ACK packet after " << unsigned(txs) << " transmissions: stopping retransmission procedure. "); @@ -603,7 +603,7 @@ void EndDeviceLorawanMac::resetRetransmissionParameters() { m_retxParams.waitingAck = false; - m_retxParams.retxLeft = m_maxNumbTx; + m_retxParams.retxLeft = m_nbTrans; m_retxParams.packet = nullptr; m_retxParams.firstAttempt = Seconds(0); @@ -626,18 +626,18 @@ EndDeviceLorawanMac::GetUplinkAdrBit() const } void -EndDeviceLorawanMac::SetMaxNumberOfTransmissions(uint8_t maxNumbTx) +EndDeviceLorawanMac::SetMaxNumberOfTransmissions(uint8_t nbTrans) { - NS_LOG_FUNCTION(this << unsigned(maxNumbTx)); - m_maxNumbTx = maxNumbTx; - m_retxParams.retxLeft = maxNumbTx; + NS_LOG_FUNCTION(this << unsigned(nbTrans)); + m_nbTrans = nbTrans; + m_retxParams.retxLeft = nbTrans; } uint8_t EndDeviceLorawanMac::GetMaxNumberOfTransmissions() { NS_LOG_FUNCTION(this); - return m_maxNumbTx; + return m_nbTrans; } void diff --git a/model/end-device-lorawan-mac.h b/model/end-device-lorawan-mac.h index c9ce0beb85..1d1f85cf2d 100644 --- a/model/end-device-lorawan-mac.h +++ b/model/end-device-lorawan-mac.h @@ -135,9 +135,9 @@ class EndDeviceLorawanMac : public LorawanMac * Set the max number of unacknowledged redundant transmissions of each packet. If, * after a transmission, any acknowledgement is received, no more are sent for that packet. * - * \param maxNumbTx The number of transmissions. + * \param nbTrans The number of transmissions. */ - void SetMaxNumberOfTransmissions(uint8_t maxNumbTx); + void SetMaxNumberOfTransmissions(uint8_t nbTrans); /** * Get the max number of unacknowledged redundant transmissions of each packet. If, @@ -383,8 +383,7 @@ class EndDeviceLorawanMac : public LorawanMac bool m_enableDRAdapt; //!< Enable data rate adaptation (ADR) during the retransmission procedure. - uint8_t - m_maxNumbTx; //!< Default number of unacknowledged redundant transmissions of each packet. + uint8_t m_nbTrans; //!< Default number of unacknowledged redundant transmissions of each packet. TracedValue m_dataRate; //!< The data rate this device is using to transmit. TracedValue m_txPower; //!< The transmission power this device is using to transmit. uint8_t m_codingRate; //!< The coding rate used by this device. From 10a9d309cc71189b7493956b28dfa623b9cefed1 Mon Sep 17 00:00:00 2001 From: Alessandro Aimi Date: Mon, 11 Nov 2024 12:04:37 +0100 Subject: [PATCH 07/34] Tx power should be converted to dBm ERP, not EIRP --- helper/lorawan-mac-helper.cc | 24 ++++++++++++------------ model/lorawan-mac.cc | 4 ++-- model/lorawan-mac.h | 2 +- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/helper/lorawan-mac-helper.cc b/helper/lorawan-mac-helper.cc index 4dbdf57d4e..523bf04c5f 100644 --- a/helper/lorawan-mac-helper.cc +++ b/helper/lorawan-mac-helper.cc @@ -132,10 +132,10 @@ LorawanMacHelper::ConfigureForAlohaRegion(Ptr edMac) ApplyCommonAlohaConfigurations(edMac); - ///////////////////////////////////////////////////// - // TxPower -> Transmission power in dBm conversion // - ///////////////////////////////////////////////////// - edMac->SetTxDbmForTxPower(std::vector{16, 14, 12, 10, 8, 6, 4, 2}); + ///////////////////////////////////////////////////////// + // TxPower -> Transmission power in dBm ERP conversion // + ///////////////////////////////////////////////////////// + edMac->SetTxDbmForTxPower(std::vector{14, 12, 10, 8, 6, 4, 2, 0}); //////////////////////////////////////////////////////////// // Matrix to know which data rate the gateway will respond with // @@ -229,10 +229,10 @@ LorawanMacHelper::ConfigureForEuRegion(Ptr edMac) con ApplyCommonEuConfigurations(edMac); - ///////////////////////////////////////////////////// - // TxPower -> Transmission power in dBm conversion // - ///////////////////////////////////////////////////// - edMac->SetTxDbmForTxPower(std::vector{16, 14, 12, 10, 8, 6, 4, 2}); + ///////////////////////////////////////////////////////// + // TxPower -> Transmission power in dBm ERP conversion // + ///////////////////////////////////////////////////////// + edMac->SetTxDbmForTxPower(std::vector{14, 12, 10, 8, 6, 4, 2, 0}); //////////////////////////////////////////////////////////// // Matrix to know which data rate the gateway will respond with // @@ -343,10 +343,10 @@ LorawanMacHelper::ConfigureForSingleChannelRegion(Ptr ApplyCommonSingleChannelConfigurations(edMac); - ///////////////////////////////////////////////////// - // TxPower -> Transmission power in dBm conversion // - ///////////////////////////////////////////////////// - edMac->SetTxDbmForTxPower(std::vector{16, 14, 12, 10, 8, 6, 4, 2}); + ///////////////////////////////////////////////////////// + // TxPower -> Transmission power in dBm ERP conversion // + ///////////////////////////////////////////////////////// + edMac->SetTxDbmForTxPower(std::vector{14, 12, 10, 8, 6, 4, 2, 0}); //////////////////////////////////////////////////////////// // Matrix to know which DataRate the gateway will respond with // diff --git a/model/lorawan-mac.cc b/model/lorawan-mac.cc index 829f6aa1b2..8fdc13c58a 100644 --- a/model/lorawan-mac.cc +++ b/model/lorawan-mac.cc @@ -129,9 +129,9 @@ LorawanMac::GetDbmForTxPower(uint8_t txPower) { NS_LOG_FUNCTION(this << unsigned(txPower)); - if (txPower > m_txDbmForTxPower.size()) + if (txPower > m_txDbmForTxPower.size() - 1) { - return 0; + return -1; } return m_txDbmForTxPower.at(txPower); diff --git a/model/lorawan-mac.h b/model/lorawan-mac.h index 6cb51abe6e..6eb273fa43 100644 --- a/model/lorawan-mac.h +++ b/model/lorawan-mac.h @@ -148,7 +148,7 @@ class LorawanMac : public Object * * \param txPower The 8-bit encoded txPower to convert. * - * \return The corresponding transmission power in dBm, or 0 if the encoded + * \return The corresponding transmission power in dBm ERP, or -1 if the encoded * power was not recognized as valid. */ double GetDbmForTxPower(uint8_t txPower); From 4820c0744f28ea7f5ce77098343a1a778f771d14 Mon Sep 17 00:00:00 2001 From: Alessandro Aimi Date: Mon, 11 Nov 2024 12:19:28 +0100 Subject: [PATCH 08/34] Avoid Object initialization for MAC commands (CreateObject -> Create) --- model/class-a-end-device-lorawan-mac.cc | 2 +- model/end-device-lorawan-mac.cc | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/model/class-a-end-device-lorawan-mac.cc b/model/class-a-end-device-lorawan-mac.cc index de6eb43823..f84cf8dda9 100644 --- a/model/class-a-end-device-lorawan-mac.cc +++ b/model/class-a-end-device-lorawan-mac.cc @@ -554,7 +554,7 @@ ClassAEndDeviceLorawanMac::OnRxClassParamSetupReq(Ptr rxParamSe // Craft a RxParamSetupAns as response NS_LOG_INFO("Adding RxParamSetupAns reply"); - m_macCommandList.emplace_back(CreateObject(offsetOk, dataRateOk, true)); + m_macCommandList.emplace_back(Create(offsetOk, dataRateOk, true)); } } /* namespace lorawan */ diff --git a/model/end-device-lorawan-mac.cc b/model/end-device-lorawan-mac.cc index 3da759c835..87c182997d 100644 --- a/model/end-device-lorawan-mac.cc +++ b/model/end-device-lorawan-mac.cc @@ -790,7 +790,7 @@ EndDeviceLorawanMac::OnLinkAdrReq(uint8_t dataRate, // Craft a LinkAdrAns MAC command as a response /////////////////////////////////////////////// - m_macCommandList.emplace_back(CreateObject(txPowerOk, dataRateOk, channelMaskOk)); + m_macCommandList.emplace_back(Create(txPowerOk, dataRateOk, channelMaskOk)); } void @@ -806,7 +806,7 @@ EndDeviceLorawanMac::OnDutyCycleReq(double dutyCycle) // Craft a DutyCycleAns as response NS_LOG_INFO("Adding DutyCycleAns reply"); - m_macCommandList.emplace_back(CreateObject()); + m_macCommandList.emplace_back(Create()); } void @@ -833,7 +833,7 @@ EndDeviceLorawanMac::OnDevStatusReq() // Craft a RxParamSetupAns as response NS_LOG_INFO("Adding DevStatusAns reply"); - m_macCommandList.emplace_back(CreateObject(battery, margin)); + m_macCommandList.emplace_back(Create(battery, margin)); } void @@ -853,7 +853,7 @@ EndDeviceLorawanMac::OnNewChannelReq(uint8_t chIndex, SetLogicalChannel(chIndex, frequency, minDataRate, maxDataRate); NS_LOG_INFO("Adding NewChannelAns reply"); - m_macCommandList.emplace_back(CreateObject(dataRateRangeOk, channelFrequencyOk)); + m_macCommandList.emplace_back(Create(dataRateRangeOk, channelFrequencyOk)); } void From 8b3571920c3455d6a27612ffbe5ef232843dee0c Mon Sep 17 00:00:00 2001 From: Alessandro Aimi Date: Mon, 11 Nov 2024 12:21:45 +0100 Subject: [PATCH 09/34] Rewrite OnLinkAdrReq from reputable source --- model/end-device-lorawan-mac.cc | 206 ++++++++++++++++++++------------ model/end-device-lorawan-mac.h | 10 +- 2 files changed, 137 insertions(+), 79 deletions(-) diff --git a/model/end-device-lorawan-mac.cc b/model/end-device-lorawan-mac.cc index 87c182997d..98048c9f55 100644 --- a/model/end-device-lorawan-mac.cc +++ b/model/end-device-lorawan-mac.cc @@ -18,6 +18,7 @@ #include "ns3/simulator.h" #include +#include namespace ns3 { @@ -382,8 +383,9 @@ EndDeviceLorawanMac::ParseCommands(LoraFrameHeader frameHeader) // Call the appropriate function to take action OnLinkAdrReq(linkAdrReq->GetDataRate(), linkAdrReq->GetTxPower(), - linkAdrReq->GetEnabledChannelsList(), - linkAdrReq->GetRepetitions()); + linkAdrReq->GetChMask(), + linkAdrReq->GetChMaskCtrl(), + linkAdrReq->GetNbTrans()); break; } @@ -684,113 +686,167 @@ EndDeviceLorawanMac::OnLinkCheckAns(uint8_t margin, uint8_t gwCnt) void EndDeviceLorawanMac::OnLinkAdrReq(uint8_t dataRate, uint8_t txPower, - std::list enabledChannels, - int repetitions) + uint16_t chMask, + uint8_t chMaskCtrl, + uint8_t nbTrans) { - NS_LOG_FUNCTION(this << unsigned(dataRate) << unsigned(txPower) << repetitions); + NS_LOG_FUNCTION(this << unsigned(dataRate) << unsigned(txPower) << std::bitset<16>(chMask) + << unsigned(chMaskCtrl) << unsigned(nbTrans)); - // Three bools for three requirements before setting things up - bool channelMaskOk = true; - bool dataRateOk = true; - bool txPowerOk = true; + // Adapted from: github.com/Lora-net/SWL2001.git v4.3.1 + // For the time being, this implementation is valid for the EU868 region + + NS_ASSERT_MSG(!(dataRate & 0xF0), "dataRate field > 4 bits"); + NS_ASSERT_MSG(!(txPower & 0xF0), "txPower field > 4 bits"); + NS_ASSERT_MSG(!(chMaskCtrl & 0xF8), "chMaskCtrl field > 3 bits"); + NS_ASSERT_MSG(!(nbTrans & 0xF0), "nbTrans field > 4 bits"); - // Check the channel mask - ///////////////////////// - // Check whether all specified channels exist on this device auto channelList = m_channelHelper->GetChannelList(); - int channelListSize = channelList.size(); - for (auto it = enabledChannels.begin(); it != enabledChannels.end(); it++) + bool channelMaskAck = true; + bool dataRateAck = true; + bool powerAck = true; + + NS_LOG_DEBUG("Channel mask = " << std::bitset<16>(chMask) + << ", ChMaskCtrl = " << unsigned(chMaskCtrl)); + + // Check channel mask + switch (chMaskCtrl) { - if ((*it) > channelListSize) + // Channels 0 to 15 + case 0: + // Check if all enabled channels have a valid frequency + for (uint8_t i = 0; i < 16; ++i) { - channelMaskOk = false; - break; + if ((chMask & 0b1 << i) && i >= channelList.size()) + { + NS_LOG_WARN("Invalid channel mask"); + channelMaskAck = false; + break; // break for loop + } + } + break; + // All channels ON independently of the ChMask field value + case 6: + chMask = 0b0; + for (uint8_t i = 0; i < 16; ++i) + { + if (i < channelList.size()) + { + chMask |= 0b1 << i; + } } + break; + default: + NS_LOG_WARN("Invalid channel mask ctrl field"); + channelMaskAck = false; + break; } - // Check the dataRate - ///////////////////// - // We need to know we can use it at all - // To assess this, we try and convert it to a spreading factor / bandwidth combination and check - // if those values are valid. Since GetSfFromDataRate and GetBandwidthFromDataRate return 0 if - // the dataRate is not recognized, we can check against this. - uint8_t sf = GetSfFromDataRate(dataRate); - double bw = GetBandwidthFromDataRate(dataRate); - NS_LOG_DEBUG("SF: " << unsigned(sf) << ", BW: " << bw); - if (sf == 0 || bw == 0) + // check if all channels are disabled + if (chMask == 0) { - dataRateOk = false; - NS_LOG_DEBUG("Data rate non valid"); + NS_LOG_WARN("Invalid channel mask"); + channelMaskAck = false; } - // We need to know we can use it in at least one of the enabled channels - // Cycle through available channels, stop when at least one is enabled for the - // specified dataRate. - if (dataRateOk && channelMaskOk) // If false, skip the check + // Temporary channel mask is built and validated + if (!m_adr) // ADR disabled, only consider channel mask conf. { - bool foundAvailableChannel = false; - for (auto it = enabledChannels.begin(); it != enabledChannels.end(); it++) + if (channelMaskAck) // valid channel mask { - NS_LOG_DEBUG("MinDR: " << unsigned(channelList.at(*it)->GetMinimumDataRate())); - NS_LOG_DEBUG("MaxDR: " << unsigned(channelList.at(*it)->GetMaximumDataRate())); - if (channelList.at(*it)->GetMinimumDataRate() <= dataRate && - channelList.at(*it)->GetMaximumDataRate() >= dataRate) + bool compatible = false; + // Look for enabled channel that supports current data rate. + // Note: Original code checks for DR0 because this is considered mobile-mode + for (uint8_t i = 0; i < 16; ++i) + { + if ((chMask & 0b1 << i) && m_dataRate >= channelList[i]->GetMinimumDataRate() && + m_dataRate <= channelList[i]->GetMaximumDataRate()) + { // Found compatible channel, break loop + compatible = true; + break; + } + } + if (!compatible) { - foundAvailableChannel = true; - break; + NS_LOG_WARN("Invalid channel mask for current device data rate (ADR off)"); + channelMaskAck = dataRateAck = powerAck = false; // reject all configurations + } + else // apply channel mask configuration + { + for (size_t i = 0; i < channelList.size(); ++i) + { + (chMask & 0b1 << i) ? channelList[i]->SetEnabledForUplink() + : channelList[i]->DisableForUplink(); + } + dataRateAck = powerAck = false; // only ack channel mask } } - - if (!foundAvailableChannel) + else // reject { - dataRateOk = false; - NS_LOG_DEBUG("Available channel not found"); + NS_LOG_WARN("Invalid channel mask"); + dataRateAck = powerAck = false; // reject all configurations } } - - // Check the txPower - //////////////////// - // Check whether we can use this transmission power - if (GetDbmForTxPower(txPower) == 0) - { - txPowerOk = false; - } - - NS_LOG_DEBUG("Finished checking. ChannelMaskOk: " << channelMaskOk << ", " - << "DataRateOk: " << dataRateOk << ", " - << "txPowerOk: " << txPowerOk); - - // If all checks are successful, set parameters up - ////////////////////////////////////////////////// - if (channelMaskOk && dataRateOk && txPowerOk) + else // Server-side ADR is enabled { - // Cycle over all channels in the list - for (uint32_t i = 0; i < m_channelHelper->GetChannelList().size(); i++) + if (dataRate != 0xF) // If value is 0xF, ignore config. { - if (std::find(enabledChannels.begin(), enabledChannels.end(), i) != - enabledChannels.end()) + bool compatible = false; + // Look for enabled channel that supports config. data rate. + for (uint8_t i = 0; i < channelList.size() && i < 16; ++i) { - m_channelHelper->GetChannelList().at(i)->SetEnabledForUplink(); - NS_LOG_DEBUG("Channel " << i << " enabled"); + if ((chMask & 0b1 << i) && dataRate >= channelList[i]->GetMinimumDataRate() && + dataRate <= channelList[i]->GetMaximumDataRate()) + { // Found compatible channel, break loop + compatible = true; + break; + } } - else + // Check if it is acceptable + if (!compatible || !GetSfFromDataRate(dataRate) || !GetBandwidthFromDataRate(dataRate)) { - m_channelHelper->GetChannelList().at(i)->DisableForUplink(); - NS_LOG_DEBUG("Channel " << i << " disabled"); + NS_LOG_WARN("Invalid data rate"); + dataRateAck = false; } } - // Set the data rate - m_dataRate = dataRate; + if (txPower != 0xF) // If value is 0xF, ignore config. + { + // Check if it is acceptable + if (GetDbmForTxPower(txPower) < 0) + { + NS_LOG_WARN("Invalid tx power"); + powerAck = false; + } + } - // Set the transmission power - m_txPower = GetDbmForTxPower(txPower); + // If no error, apply configurations + if (channelMaskAck && dataRateAck && powerAck) + { + for (size_t i = 0; i < channelList.size(); ++i) + { + (chMask & 0b1 << i) ? channelList[i]->SetEnabledForUplink() + : channelList[i]->DisableForUplink(); + } + if (txPower != 0xF) // If value is 0xF, ignore config. + { + m_txPower = GetDbmForTxPower(txPower); + } + m_nbTrans = (nbTrans == 0) ? 1 : nbTrans; + if (dataRate != 0xF) // If value is 0xF, ignore config. + { + m_dataRate = dataRate; + } + NS_LOG_DEBUG("MacTxDataRateAdr = " << unsigned(m_dataRate)); + NS_LOG_DEBUG("MacTxPower = " << unsigned(m_txPower) << "dBm"); + NS_LOG_DEBUG("MacNbTrans = " << unsigned(m_nbTrans)); + } } // Craft a LinkAdrAns MAC command as a response /////////////////////////////////////////////// - m_macCommandList.emplace_back(Create(txPowerOk, dataRateOk, channelMaskOk)); + m_macCommandList.emplace_back(Create(powerAck, dataRateAck, channelMaskAck)); } void diff --git a/model/end-device-lorawan-mac.h b/model/end-device-lorawan-mac.h index 1d1f85cf2d..5664735576 100644 --- a/model/end-device-lorawan-mac.h +++ b/model/end-device-lorawan-mac.h @@ -267,13 +267,15 @@ class EndDeviceLorawanMac : public LorawanMac * * \param dataRate The data rate value of the command. * \param txPower The transmission power value of the command. - * \param enabledChannels A list of the enabled channels. - * \param repetitions The number of repetitions prescribed by the command. + * \param chMask Mask of enabled channels of the command. + * \param chMaskCtrl Indicator of the 16 channel bank to apply the chMask to. + * \param nbTrans The number of repetitions prescribed by the command. */ void OnLinkAdrReq(uint8_t dataRate, uint8_t txPower, - std::list enabledChannels, - int repetitions); + uint16_t chMask, + uint8_t chMaskCtrl, + uint8_t nbTrans); /** * Perform the actions that need to be taken when receiving a DutyCycleReq command. From fa9c56d2b379208903a60edac597cab68c92ec93 Mon Sep 17 00:00:00 2001 From: Alessandro Aimi Date: Mon, 11 Nov 2024 13:51:28 +0100 Subject: [PATCH 10/34] Tx power dBm values to double + more robust GetTxPowerIndex impl --- helper/lora-helper.cc | 2 +- model/adr-component.cc | 60 +++++++------------------ model/adr-component.h | 13 +++--- model/class-a-end-device-lorawan-mac.cc | 4 +- model/end-device-lorawan-mac.cc | 19 ++++---- model/end-device-lorawan-mac.h | 9 ++-- 6 files changed, 39 insertions(+), 68 deletions(-) diff --git a/helper/lora-helper.cc b/helper/lora-helper.cc index ba691ed76b..96b916fef7 100644 --- a/helper/lora-helper.cc +++ b/helper/lora-helper.cc @@ -204,7 +204,7 @@ LoraHelper::DoPrintDeviceStatus(NodeContainer endDevices, Ptr mac = DynamicCast(loraNetDevice->GetMac()); int dr = int(mac->GetDataRate()); - double txPower = mac->GetTransmissionPower(); + double txPower = mac->GetTransmissionPowerDbm(); Vector pos = position->GetPosition(); outputFile << currentTime.GetSeconds() << " " << object->GetId() << " " << pos.x << " " << pos.y << " " << dr << " " << unsigned(txPower) << std::endl; diff --git a/model/adr-component.cc b/model/adr-component.cc index 7d2a86f2f3..157c05ebee 100644 --- a/model/adr-component.cc +++ b/model/adr-component.cc @@ -110,22 +110,22 @@ AdrComponent::BeforeSendingReply(Ptr status, Ptr uint8_t spreadingFactor = status->GetFirstReceiveWindowSpreadingFactor(); // Get the device transmission power (dBm) - uint8_t transmissionPower = status->GetMac()->GetTransmissionPower(); + double transmissionPowerDbm = status->GetMac()->GetTransmissionPowerDbm(); // New parameters for the end-device uint8_t newDataRate; - uint8_t newTxPower; + double newTxPowerDbm; // Adaptive Data Rate (ADR) Algorithm - AdrImplementation(&newDataRate, &newTxPower, status); + AdrImplementation(&newDataRate, &newTxPowerDbm, status); // Change the power back to the default if we don't want to change it if (!m_toggleTxPower) { - newTxPower = transmissionPower; + newTxPowerDbm = transmissionPowerDbm; } - if (newDataRate != SfToDr(spreadingFactor) || newTxPower != transmissionPower) + if (newDataRate != SfToDr(spreadingFactor) || newTxPowerDbm != transmissionPowerDbm) { // Create a list with mandatory channel indexes int channels[] = {0, 1, 2}; @@ -134,12 +134,11 @@ AdrComponent::BeforeSendingReply(Ptr status, Ptr // Repetitions Setting const int rep = 1; - NS_LOG_DEBUG("Sending LinkAdrReq with DR = " << (unsigned)newDataRate - << " and TP = " << (unsigned)newTxPower - << " dBm"); + NS_LOG_DEBUG("Sending LinkAdrReq with DR = " + << (unsigned)newDataRate << " and TP = " << newTxPowerDbm << "dBm"); status->m_reply.frameHeader.AddLinkAdrReq(newDataRate, - GetTxPowerIndex(newTxPower), + GetTxPowerIndex(newTxPowerDbm), enabledChannels, rep); status->m_reply.frameHeader.SetAsDownlink(); @@ -167,7 +166,7 @@ AdrComponent::OnFailedReply(Ptr status, Ptr netw void AdrComponent::AdrImplementation(uint8_t* newDataRate, - uint8_t* newTxPower, + double* newTxPower, Ptr status) { // Compute the maximum or median SNR, based on the boolean value historyAveraging @@ -197,7 +196,7 @@ AdrComponent::AdrImplementation(uint8_t* newDataRate, NS_LOG_DEBUG("Required SNR = " << req_SNR); // Get the device transmission power (dBm) - double transmissionPower = status->GetMac()->GetTransmissionPower(); + double transmissionPower = status->GetMac()->GetTransmissionPowerDbm(); NS_LOG_DEBUG("Transmission Power = " << transmissionPower); @@ -429,41 +428,12 @@ AdrComponent::GetAverageSNR(EndDeviceStatus::ReceivedPacketList packetList, int return average; } -int -AdrComponent::GetTxPowerIndex(int txPower) +uint8_t +AdrComponent::GetTxPowerIndex(double txPower) { - if (txPower >= 16) - { - return 0; - } - else if (txPower >= 14) - { - return 1; - } - else if (txPower >= 12) - { - return 2; - } - else if (txPower >= 10) - { - return 3; - } - else if (txPower >= 8) - { - return 4; - } - else if (txPower >= 6) - { - return 5; - } - else if (txPower >= 4) - { - return 6; - } - else - { - return 7; - } + NS_ASSERT_MSG(txPower <= 14 || txPower >= 0, "TxPower dBm value out of supported range"); + NS_ASSERT_MSG(fmod(txPower, 2) == 0, "Invalid TxPower value"); + return 7 - txPower / 2; } } // namespace lorawan } // namespace ns3 diff --git a/model/adr-component.h b/model/adr-component.h index 7f59b4c4c7..7bf256df69 100644 --- a/model/adr-component.h +++ b/model/adr-component.h @@ -65,10 +65,10 @@ class AdrComponent : public NetworkControllerComponent * https://doi.org/10.1109/NOMS.2018.8406255 . * * \param newDataRate [out] new data rate value selected for the end device. - * \param newTxPower [out] new tx power value selected for the end device. + * \param newTxPower [out] new tx power [dBm] value selected for the end device. * \param status State representation of the current end device. */ - void AdrImplementation(uint8_t* newDataRate, uint8_t* newTxPower, Ptr status); + void AdrImplementation(uint8_t* newDataRate, double* newTxPower, Ptr status); /** * Convert spreading factor values [7:12] to respective data rate values [0:5]. @@ -147,13 +147,12 @@ class AdrComponent : public NetworkControllerComponent double GetAverageSNR(EndDeviceStatus::ReceivedPacketList packetList, int historyRange); /** - * Get the LoRaWAN protocol TXPower configuration index from the Equivalent Isotropically - * Radiated Power (EIRP) in dBm. + * Get the LoRaWAN protocol TxPower parameter from the Equivalent Radiated Power (ERP) in dBm. * - * \param txPower Transission EIRP configuration. - * \return TXPower index as int. + * \param txPower Transission ERP configuration [dBm]. + * \return TxPower parameter value as uint8_t. */ - int GetTxPowerIndex(int txPower); + uint8_t GetTxPowerIndex(double txPower); enum CombiningMethod tpAveraging; //!< TX power from gateways policy int historyRange; //!< Number of previous packets to consider diff --git a/model/class-a-end-device-lorawan-mac.cc b/model/class-a-end-device-lorawan-mac.cc index f84cf8dda9..222680b3d6 100644 --- a/model/class-a-end-device-lorawan-mac.cc +++ b/model/class-a-end-device-lorawan-mac.cc @@ -78,7 +78,7 @@ ClassAEndDeviceLorawanMac::SendToPhy(Ptr packetToSend) if (m_enableDRAdapt && (m_dataRate > 0) && (m_retxParams.retxLeft < m_nbTrans) && (m_retxParams.retxLeft % 2 == 0)) { - m_txPower = 14; // Reset transmission power + m_txPowerDbm = 14; // Reset transmission power m_dataRate = m_dataRate - 1; } @@ -97,7 +97,7 @@ ClassAEndDeviceLorawanMac::SendToPhy(Ptr packetToSend) Ptr txChannel = GetChannelForTx(); NS_LOG_DEBUG("PacketToSend: " << packetToSend); - m_phy->Send(packetToSend, params, txChannel->GetFrequency(), m_txPower); + m_phy->Send(packetToSend, params, txChannel->GetFrequency(), m_txPowerDbm); ////////////////////////////////////////////// // Register packet transmission for duty cycle diff --git a/model/end-device-lorawan-mac.cc b/model/end-device-lorawan-mac.cc index 98048c9f55..fcb140fee8 100644 --- a/model/end-device-lorawan-mac.cc +++ b/model/end-device-lorawan-mac.cc @@ -57,8 +57,8 @@ EndDeviceLorawanMac::GetTypeId() MakeBooleanAccessor(&EndDeviceLorawanMac::m_adr), MakeBooleanChecker()) .AddTraceSource("TxPower", - "Transmission power currently employed by this end device", - MakeTraceSourceAccessor(&EndDeviceLorawanMac::m_txPower), + "Transmission ERP [dBm] currently employed by this end device", + MakeTraceSourceAccessor(&EndDeviceLorawanMac::m_txPowerDbm), "ns3::TracedValueCallback::Double") .AddTraceSource("LastKnownLinkMargin", "Last known demodulation margin in " @@ -103,7 +103,7 @@ EndDeviceLorawanMac::EndDeviceLorawanMac() : m_enableDRAdapt(false), m_nbTrans(1), m_dataRate(0), - m_txPower(14), + m_txPowerDbm(14), m_codingRate(1), // LoraWAN default m_headerDisabled(false), @@ -176,7 +176,7 @@ EndDeviceLorawanMac::Send(Ptr packet) // retransmissions { // Make sure we can transmit at the current power on this channel - NS_ASSERT_MSG(m_txPower <= m_channelHelper->GetTxPowerForChannel(txChannel), + NS_ASSERT_MSG(m_txPowerDbm <= m_channelHelper->GetTxPowerForChannel(txChannel), " The selected power is too high to be supported by this channel."); DoSend(packet); } @@ -831,7 +831,7 @@ EndDeviceLorawanMac::OnLinkAdrReq(uint8_t dataRate, } if (txPower != 0xF) // If value is 0xF, ignore config. { - m_txPower = GetDbmForTxPower(txPower); + m_txPowerDbm = GetDbmForTxPower(txPower); } m_nbTrans = (nbTrans == 0) ? 1 : nbTrans; if (dataRate != 0xF) // If value is 0xF, ignore config. @@ -839,7 +839,7 @@ EndDeviceLorawanMac::OnLinkAdrReq(uint8_t dataRate, m_dataRate = dataRate; } NS_LOG_DEBUG("MacTxDataRateAdr = " << unsigned(m_dataRate)); - NS_LOG_DEBUG("MacTxPower = " << unsigned(m_txPower) << "dBm"); + NS_LOG_DEBUG("MacTxPower = " << unsigned(m_txPowerDbm) << "dBm"); NS_LOG_DEBUG("MacNbTrans = " << unsigned(m_nbTrans)); } } @@ -981,10 +981,11 @@ EndDeviceLorawanMac::AddMacCommand(Ptr macCommand) m_macCommandList.push_back(macCommand); } -uint8_t -EndDeviceLorawanMac::GetTransmissionPower() +double +EndDeviceLorawanMac::GetTransmissionPowerDbm() { - return m_txPower; + return m_txPowerDbm; } + } // namespace lorawan } // namespace ns3 diff --git a/model/end-device-lorawan-mac.h b/model/end-device-lorawan-mac.h index 5664735576..b2ffe12ba5 100644 --- a/model/end-device-lorawan-mac.h +++ b/model/end-device-lorawan-mac.h @@ -166,9 +166,9 @@ class EndDeviceLorawanMac : public LorawanMac /** * Get the transmission power this end device is set to use. * - * \return The transmission power this device uses when transmitting. + * \return The transmission ERP [dBm] this device uses when transmitting. */ - virtual uint8_t GetTransmissionPower(); + double GetTransmissionPowerDbm(); /** * Set the network address of this device. @@ -387,8 +387,9 @@ class EndDeviceLorawanMac : public LorawanMac m_enableDRAdapt; //!< Enable data rate adaptation (ADR) during the retransmission procedure. uint8_t m_nbTrans; //!< Default number of unacknowledged redundant transmissions of each packet. TracedValue m_dataRate; //!< The data rate this device is using to transmit. - TracedValue m_txPower; //!< The transmission power this device is using to transmit. - uint8_t m_codingRate; //!< The coding rate used by this device. + TracedValue + m_txPowerDbm; //!< The transmission ERP [dBm] this device is currently using. + uint8_t m_codingRate; //!< The coding rate used by this device. bool m_headerDisabled; //!< Whether or not the LoRa PHY header is disabled for communications by //!< this device. LoraDeviceAddress m_address; //!< The address of this device. From 0b1c56ab2ad7f667acf8212615dc2e7d086f9e50 Mon Sep 17 00:00:00 2001 From: Alessandro Aimi Date: Tue, 12 Nov 2024 10:46:55 +0100 Subject: [PATCH 11/34] LoRaWAN Headers: store MAC commands to vector instead of list, clean-up and modernize c++, fix printing output --- model/end-device-lorawan-mac.cc | 57 ++------- model/lora-frame-header.cc | 220 +++++++++----------------------- model/lora-frame-header.h | 22 ++-- model/lorawan-mac-header.cc | 4 +- model/mac-command.cc | 83 ++++++------ 5 files changed, 134 insertions(+), 252 deletions(-) diff --git a/model/end-device-lorawan-mac.cc b/model/end-device-lorawan-mac.cc index fcb140fee8..27a5ab76a3 100644 --- a/model/end-device-lorawan-mac.cc +++ b/model/end-device-lorawan-mac.cc @@ -211,7 +211,8 @@ EndDeviceLorawanMac::DoSend(Ptr packet) ApplyNecessaryOptions(frameHdr); packet->AddHeader(frameHdr); - NS_LOG_INFO("Added frame header of size " << frameHdr.GetSerializedSize() << " bytes."); + auto fhdrSize = frameHdr.GetSerializedSize(); + NS_LOG_INFO("Added frame header of size " << fhdrSize << " bytes."); // Check that MACPayload length is below the allowed maximum if (packet->GetSize() > m_maxAppPayloadForDataRate.at(m_dataRate)) @@ -259,7 +260,8 @@ EndDeviceLorawanMac::DoSend(Ptr packet) NS_LOG_DEBUG("It is a confirmed packet. Setting retransmission parameters and " "decreasing the number of transmissions left."); - NS_LOG_INFO("Added MAC header of size " << macHdr.GetSerializedSize() << " bytes."); + auto mhdrSize = macHdr.GetSerializedSize(); + NS_LOG_INFO("Added MAC header of size " << mhdrSize << " bytes."); // Sent a new packet NS_LOG_DEBUG("Copied packet: " << m_retxParams.packet); @@ -291,7 +293,8 @@ EndDeviceLorawanMac::DoSend(Ptr packet) ApplyNecessaryOptions(frameHdr); packet->AddHeader(frameHdr); - NS_LOG_INFO("Added frame header of size " << frameHdr.GetSerializedSize() << " bytes."); + auto fhdrSize = frameHdr.GetSerializedSize(); + NS_LOG_INFO("Added frame header of size " << fhdrSize << " bytes."); // Add the Lorawan Mac header to the packet macHdr = LorawanMacHeader(); @@ -355,85 +358,53 @@ EndDeviceLorawanMac::ParseCommands(LoraFrameHeader frameHeader) } } - std::list> commands = frameHeader.GetCommands(); - std::list>::iterator it; - for (it = commands.begin(); it != commands.end(); it++) + for (const auto& c : frameHeader.GetCommands()) { NS_LOG_DEBUG("Iterating over the MAC commands..."); - enum MacCommandType type = (*it)->GetCommandType(); + enum MacCommandType type = (c)->GetCommandType(); switch (type) { case (LINK_CHECK_ANS): { NS_LOG_DEBUG("Detected a LinkCheckAns command."); - - // Cast the command - Ptr linkCheckAns = DynamicCast(*it); - - // Call the appropriate function to take action + auto linkCheckAns = DynamicCast(c); OnLinkCheckAns(linkCheckAns->GetMargin(), linkCheckAns->GetGwCnt()); - break; } case (LINK_ADR_REQ): { NS_LOG_DEBUG("Detected a LinkAdrReq command."); - - // Cast the command - Ptr linkAdrReq = DynamicCast(*it); - - // Call the appropriate function to take action + auto linkAdrReq = DynamicCast(c); OnLinkAdrReq(linkAdrReq->GetDataRate(), linkAdrReq->GetTxPower(), linkAdrReq->GetChMask(), linkAdrReq->GetChMaskCtrl(), linkAdrReq->GetNbTrans()); - break; } case (DUTY_CYCLE_REQ): { NS_LOG_DEBUG("Detected a DutyCycleReq command."); - - // Cast the command - Ptr dutyCycleReq = DynamicCast(*it); - - // Call the appropriate function to take action + auto dutyCycleReq = DynamicCast(c); OnDutyCycleReq(dutyCycleReq->GetMaximumAllowedDutyCycle()); - break; } case (RX_PARAM_SETUP_REQ): { NS_LOG_DEBUG("Detected a RxParamSetupReq command."); - - // Cast the command - Ptr rxParamSetupReq = DynamicCast(*it); - - // Call the appropriate function to take action + auto rxParamSetupReq = DynamicCast(c); OnRxParamSetupReq(rxParamSetupReq); - break; } case (DEV_STATUS_REQ): { NS_LOG_DEBUG("Detected a DevStatusReq command."); - - // Cast the command - Ptr devStatusReq = DynamicCast(*it); - - // Call the appropriate function to take action + auto devStatusReq = DynamicCast(c); OnDevStatusReq(); - break; } case (NEW_CHANNEL_REQ): { NS_LOG_DEBUG("Detected a NewChannelReq command."); - - // Cast the command - Ptr newChannelReq = DynamicCast(*it); - - // Call the appropriate function to take action + auto newChannelReq = DynamicCast(c); OnNewChannelReq(newChannelReq->GetChannelIndex(), newChannelReq->GetFrequency(), newChannelReq->GetMinDataRate(), newChannelReq->GetMaxDataRate()); - break; } case (RX_TIMING_SETUP_REQ): diff --git a/model/lora-frame-header.cc b/model/lora-frame-header.cc index f6d8c4a3ce..b668ea6aff 100644 --- a/model/lora-frame-header.cc +++ b/model/lora-frame-header.cc @@ -53,21 +53,17 @@ LoraFrameHeader::GetInstanceTypeId() const uint32_t LoraFrameHeader::GetSerializedSize() const { - NS_LOG_FUNCTION_NOARGS(); - - // Sizes in bytes: + NS_LOG_FUNCTION(this); // 4 for DevAddr + 1 for FCtrl + 2 for FCnt + 1 for FPort + 0-15 for FOpts uint32_t size = 8 + m_fOptsLen; - NS_LOG_INFO("LoraFrameHeader serialized size: " << size); - return size; } void LoraFrameHeader::Serialize(Buffer::Iterator start) const { - NS_LOG_FUNCTION_NOARGS(); + NS_LOG_FUNCTION(this); // Device Address field start.WriteU32(m_address.Get()); @@ -88,29 +84,20 @@ LoraFrameHeader::Serialize(Buffer::Iterator start) const start.WriteU16(m_fCnt); // FOpts field - for (auto it = m_macCommands.begin(); it != m_macCommands.end(); it++) + for (const auto& c : m_macCommands) { NS_LOG_DEBUG("Serializing a MAC command"); - (*it)->Serialize(start); + c->Serialize(start); } // FPort start.WriteU8(m_fPort); - - NS_LOG_DEBUG("Serializing the following data: "); - NS_LOG_DEBUG("Address: " << m_address.Print()); - NS_LOG_DEBUG("ADR: " << unsigned(m_adr)); - NS_LOG_DEBUG("ADRAckReq: " << unsigned(m_adrAckReq)); - NS_LOG_DEBUG("Ack: " << unsigned(m_ack)); - NS_LOG_DEBUG("fPending: " << unsigned(m_fPending)); - NS_LOG_DEBUG("fOptsLen: " << unsigned(m_fOptsLen)); - NS_LOG_DEBUG("fCnt: " << unsigned(m_fCnt)); } uint32_t LoraFrameHeader::Deserialize(Buffer::Iterator start) { - NS_LOG_FUNCTION_NOARGS(); + NS_LOG_FUNCTION(this); // Empty the list of MAC commands m_macCommands.clear(); @@ -127,15 +114,6 @@ LoraFrameHeader::Deserialize(Buffer::Iterator start) m_fOptsLen = fCtrl & 0b1111; m_fCnt = start.ReadU16(); - NS_LOG_DEBUG("Deserialized data: "); - NS_LOG_DEBUG("Address: " << m_address.Print()); - NS_LOG_DEBUG("ADR: " << unsigned(m_adr)); - NS_LOG_DEBUG("ADRAckReq: " << unsigned(m_adrAckReq)); - NS_LOG_DEBUG("Ack: " << unsigned(m_ack)); - NS_LOG_DEBUG("fPending: " << unsigned(m_fPending)); - NS_LOG_DEBUG("fOptsLen: " << unsigned(m_fOptsLen)); - NS_LOG_DEBUG("fCnt: " << unsigned(m_fCnt)); - // Deserialize MAC commands NS_LOG_DEBUG("Starting deserialization of MAC commands"); for (uint8_t byteNumber = 0; byteNumber < m_fOptsLen;) @@ -147,6 +125,7 @@ LoraFrameHeader::Deserialize(Buffer::Iterator start) // This needs to be done because they have the same CID, and the context // about where this message will be Serialized/Deserialized (i.e., at the // end device or at the network server) is umportant. + Ptr command; if (m_isUplink) { switch (cid) @@ -155,65 +134,47 @@ LoraFrameHeader::Deserialize(Buffer::Iterator start) // request for a link check case (0x02): { NS_LOG_DEBUG("Creating a LinkCheckReq command"); - Ptr command = Create(); - byteNumber += command->Deserialize(start); - m_macCommands.emplace_back(command); + command = Create(); break; } case (0x03): { NS_LOG_DEBUG("Creating a LinkAdrAns command"); - Ptr command = Create(); - byteNumber += command->Deserialize(start); - m_macCommands.emplace_back(command); + command = Create(); break; } case (0x04): { NS_LOG_DEBUG("Creating a DutyCycleAns command"); - Ptr command = Create(); - byteNumber += command->Deserialize(start); - m_macCommands.emplace_back(command); + command = Create(); break; } case (0x05): { NS_LOG_DEBUG("Creating a RxParamSetupAns command"); - Ptr command = Create(); - byteNumber += command->Deserialize(start); - m_macCommands.emplace_back(command); + command = Create(); break; } case (0x06): { NS_LOG_DEBUG("Creating a DevStatusAns command"); - Ptr command = Create(); - byteNumber += command->Deserialize(start); - m_macCommands.emplace_back(command); + command = Create(); break; } case (0x07): { NS_LOG_DEBUG("Creating a NewChannelAns command"); - Ptr command = Create(); - byteNumber += command->Deserialize(start); - m_macCommands.emplace_back(command); + command = Create(); break; } case (0x08): { NS_LOG_DEBUG("Creating a RxTimingSetupAns command"); - Ptr command = Create(); - byteNumber += command->Deserialize(start); - m_macCommands.emplace_back(command); + command = Create(); break; } case (0x09): { NS_LOG_DEBUG("Creating a TxParamSetupAns command"); - Ptr command = Create(); - byteNumber += command->Deserialize(start); - m_macCommands.emplace_back(command); + command = Create(); break; } case (0x0A): { NS_LOG_DEBUG("Creating a DlChannelAns command"); - Ptr command = Create(); - byteNumber += command->Deserialize(start); - m_macCommands.emplace_back(command); + command = Create(); break; } default: { @@ -229,58 +190,42 @@ LoraFrameHeader::Deserialize(Buffer::Iterator start) // answer to a link check case (0x02): { NS_LOG_DEBUG("Creating a LinkCheckAns command"); - Ptr command = Create(); - byteNumber += command->Deserialize(start); - m_macCommands.emplace_back(command); + command = Create(); break; } case (0x03): { NS_LOG_DEBUG("Creating a LinkAdrReq command"); - Ptr command = Create(); - byteNumber += command->Deserialize(start); - m_macCommands.emplace_back(command); + command = Create(); break; } case (0x04): { NS_LOG_DEBUG("Creating a DutyCycleReq command"); - Ptr command = Create(); - byteNumber += command->Deserialize(start); - m_macCommands.emplace_back(command); + command = Create(); break; } case (0x05): { NS_LOG_DEBUG("Creating a RxParamSetupReq command"); - Ptr command = Create(); - byteNumber += command->Deserialize(start); - m_macCommands.emplace_back(command); + command = Create(); break; } case (0x06): { NS_LOG_DEBUG("Creating a DevStatusReq command"); - Ptr command = Create(); - byteNumber += command->Deserialize(start); - m_macCommands.emplace_back(command); + command = Create(); break; } case (0x07): { NS_LOG_DEBUG("Creating a NewChannelReq command"); - Ptr command = Create(); - byteNumber += command->Deserialize(start); - m_macCommands.emplace_back(command); + command = Create(); break; } case (0x08): { NS_LOG_DEBUG("Creating a RxTimingSetupReq command"); - Ptr command = Create(); - byteNumber += command->Deserialize(start); - m_macCommands.emplace_back(command); + command = Create(); break; } case (0x09): { NS_LOG_DEBUG("Creating a TxParamSetupReq command"); - Ptr command = Create(); - byteNumber += command->Deserialize(start); - m_macCommands.emplace_back(command); + command = Create(); break; } default: { @@ -288,47 +233,42 @@ LoraFrameHeader::Deserialize(Buffer::Iterator start) } } } + byteNumber += command->Deserialize(start); + m_macCommands.emplace_back(command); } - - m_fPort = uint8_t(start.ReadU8()); - + m_fPort = start.ReadU8(); return 8 + m_fOptsLen; // the number of bytes consumed. } void LoraFrameHeader::Print(std::ostream& os) const { - NS_LOG_FUNCTION_NOARGS(); - - os << "Address=" << m_address.Print() << std::endl; - os << "ADR=" << m_adr << std::endl; - os << "ADRAckReq=" << m_adrAckReq << std::endl; - os << "ACK=" << m_ack << std::endl; - os << "FPending=" << m_fPending << std::endl; - os << "FOptsLen=" << unsigned(m_fOptsLen) << std::endl; - os << "FCnt=" << unsigned(m_fCnt) << std::endl; - - for (auto it = m_macCommands.begin(); it != m_macCommands.end(); it++) + os << "Address=" << m_address.Print(); + os << ", ADR=" << m_adr; + os << ", ADRAckReq=" << m_adrAckReq; + os << ", ACK=" << m_ack; + os << ", FPending=" << m_fPending; + os << ", FOptsLen=" << unsigned(m_fOptsLen); + os << ", FCnt=" << unsigned(m_fCnt); + for (const auto& c : m_macCommands) { - (*it)->Print(os); + os << ", "; + c->Print(os); } - - os << "FPort=" << unsigned(m_fPort) << std::endl; + os << ", FPort=" << unsigned(m_fPort); } void LoraFrameHeader::SetAsUplink() { - NS_LOG_FUNCTION_NOARGS(); - + NS_LOG_FUNCTION(this); m_isUplink = true; } void LoraFrameHeader::SetAsDownlink() { - NS_LOG_FUNCTION_NOARGS(); - + NS_LOG_FUNCTION(this); m_isUplink = false; } @@ -409,12 +349,10 @@ LoraFrameHeader::GetFPending() const uint8_t LoraFrameHeader::GetFOptsLen() const { - // Sum the serialized length of all commands in the list uint8_t fOptsLen = 0; - std::list>::const_iterator it; - for (it = m_macCommands.begin(); it != m_macCommands.end(); it++) + for (const auto& c : m_macCommands) { - fOptsLen = fOptsLen + (*it)->GetSerializedSize(); + fOptsLen += c->GetSerializedSize(); } return fOptsLen; } @@ -434,12 +372,9 @@ LoraFrameHeader::GetFCnt() const void LoraFrameHeader::AddLinkCheckReq() { - NS_LOG_FUNCTION_NOARGS(); - - Ptr command = Create(); + NS_LOG_FUNCTION(this); + auto command = Create(); m_macCommands.emplace_back(command); - - NS_LOG_DEBUG("Command SerializedSize: " << unsigned(command->GetSerializedSize())); m_fOptsLen += command->GetSerializedSize(); } @@ -447,10 +382,8 @@ void LoraFrameHeader::AddLinkCheckAns(uint8_t margin, uint8_t gwCnt) { NS_LOG_FUNCTION(this << unsigned(margin) << unsigned(gwCnt)); - - Ptr command = Create(margin, gwCnt); + auto command = Create(margin, gwCnt); m_macCommands.emplace_back(command); - m_fOptsLen += command->GetSerializedSize(); } @@ -461,23 +394,15 @@ LoraFrameHeader::AddLinkAdrReq(uint8_t dataRate, int repetitions) { NS_LOG_FUNCTION(this << unsigned(dataRate) << txPower << repetitions); - uint16_t channelMask = 0; - for (auto it = enabledChannels.begin(); it != enabledChannels.end(); it++) + for (const auto chId : enabledChannels) { - NS_ASSERT((*it) < 16 && (*it) > -1); - - channelMask |= 0b1 << (*it); + NS_ASSERT(chId < 16 && chId > -1); + channelMask |= 0b1 << chId; } - - // TODO Implement chMaskCntl field - - NS_LOG_DEBUG("Creating LinkAdrReq with: DR = " << unsigned(dataRate) - << " and txPower = " << unsigned(txPower)); - - Ptr command = Create(dataRate, txPower, channelMask, 0, repetitions); + /// \todo Implement chMaskCntl field + auto command = Create(dataRate, txPower, channelMask, 0, repetitions); m_macCommands.emplace_back(command); - m_fOptsLen += command->GetSerializedSize(); } @@ -485,10 +410,8 @@ void LoraFrameHeader::AddLinkAdrAns(bool powerAck, bool dataRateAck, bool channelMaskAck) { NS_LOG_FUNCTION(this << powerAck << dataRateAck << channelMaskAck); - - Ptr command = Create(powerAck, dataRateAck, channelMaskAck); + auto command = Create(powerAck, dataRateAck, channelMaskAck); m_macCommands.emplace_back(command); - m_fOptsLen += command->GetSerializedSize(); } @@ -496,11 +419,8 @@ void LoraFrameHeader::AddDutyCycleReq(uint8_t dutyCycle) { NS_LOG_FUNCTION(this << unsigned(dutyCycle)); - - Ptr command = Create(dutyCycle); - + auto command = Create(dutyCycle); m_macCommands.emplace_back(command); - m_fOptsLen += command->GetSerializedSize(); } @@ -508,11 +428,8 @@ void LoraFrameHeader::AddDutyCycleAns() { NS_LOG_FUNCTION(this); - - Ptr command = Create(); - + auto command = Create(); m_macCommands.emplace_back(command); - m_fOptsLen += command->GetSerializedSize(); } @@ -520,14 +437,10 @@ void LoraFrameHeader::AddRxParamSetupReq(uint8_t rx1DrOffset, uint8_t rx2DataRate, double frequency) { NS_LOG_FUNCTION(this << unsigned(rx1DrOffset) << unsigned(rx2DataRate) << frequency); - // Evaluate whether to eliminate this assert in case new offsets can be defined. NS_ASSERT(0 <= rx1DrOffset && rx1DrOffset <= 5); - - Ptr command = Create(rx1DrOffset, rx2DataRate, frequency); - + auto command = Create(rx1DrOffset, rx2DataRate, frequency); m_macCommands.emplace_back(command); - m_fOptsLen += command->GetSerializedSize(); } @@ -535,11 +448,8 @@ void LoraFrameHeader::AddRxParamSetupAns() { NS_LOG_FUNCTION(this); - - Ptr command = Create(); - + auto command = Create(); m_macCommands.emplace_back(command); - m_fOptsLen += command->GetSerializedSize(); } @@ -547,11 +457,8 @@ void LoraFrameHeader::AddDevStatusReq() { NS_LOG_FUNCTION(this); - - Ptr command = Create(); - + auto command = Create(); m_macCommands.emplace_back(command); - m_fOptsLen += command->GetSerializedSize(); } @@ -561,21 +468,17 @@ LoraFrameHeader::AddNewChannelReq(uint8_t chIndex, uint8_t minDataRate, uint8_t maxDataRate) { - NS_LOG_FUNCTION(this); - - Ptr command = - Create(chIndex, frequency, minDataRate, maxDataRate); - + NS_LOG_FUNCTION(this << unsigned(chIndex) << frequency << unsigned(minDataRate) + << unsigned(maxDataRate)); + auto command = Create(chIndex, frequency, minDataRate, maxDataRate); m_macCommands.emplace_back(command); - m_fOptsLen += command->GetSerializedSize(); } -std::list> +std::vector> LoraFrameHeader::GetCommands() { - NS_LOG_FUNCTION_NOARGS(); - + NS_LOG_FUNCTION(this); return m_macCommands; } @@ -583,8 +486,7 @@ void LoraFrameHeader::AddCommand(Ptr macCommand) { NS_LOG_FUNCTION(this << macCommand); - - m_macCommands.push_back(macCommand); + m_macCommands.emplace_back(macCommand); m_fOptsLen += macCommand->GetSerializedSize(); } diff --git a/model/lora-frame-header.h b/model/lora-frame-header.h index 8d32f1de1c..56688a0133 100644 --- a/model/lora-frame-header.h +++ b/model/lora-frame-header.h @@ -298,14 +298,14 @@ class LoraFrameHeader : public Header uint8_t maxDataRate); /** - * Return a list of pointers to all the MAC commands saved in this header. + * Return a vector of pointers to all the MAC commands saved in this header. * - * \return The list of pointers to MacCommand objects. + * \return The vector of pointers to MacCommand objects. */ - std::list> GetCommands(); + std::vector> GetCommands(); /** - * Add a predefined command to the list in this frame header. + * Add a predefined command to the vector in this frame header. * * \param macCommand A pointer to the MacCommand object to add. */ @@ -324,9 +324,9 @@ class LoraFrameHeader : public Header uint16_t m_fCnt; //!< The FCnt field - Buffer m_fOpts; //!< The FOpts field - std::list> m_macCommands; //!< List containing all the MacCommand instances that - //!< are contained in this LoraFrameHeader + Buffer m_fOpts; //!< The FOpts field + std::vector> m_macCommands; //!< Vector containing all the MacCommand instances + //!< that are contained in this LoraFrameHeader bool m_isUplink; //!< Whether this frame header is uplink or not }; @@ -336,15 +336,13 @@ Ptr LoraFrameHeader::GetMacCommand() { // Iterate on MAC commands and try casting - std::list>::const_iterator it; - for (it = m_macCommands.begin(); it != m_macCommands.end(); ++it) + for (const auto& cmd : m_macCommands) { - if (DynamicCast(*it)) + if (auto c = DynamicCast(cmd); c) { - return DynamicCast(*it); + return c; } } - // If no command was found, return 0 return nullptr; } diff --git a/model/lorawan-mac-header.cc b/model/lorawan-mac-header.cc index b323b1ffdf..6f403d3834 100644 --- a/model/lorawan-mac-header.cc +++ b/model/lorawan-mac-header.cc @@ -94,8 +94,8 @@ LorawanMacHeader::Deserialize(Buffer::Iterator start) void LorawanMacHeader::Print(std::ostream& os) const { - os << "MessageType=" << unsigned(m_mtype) << std::endl; - os << "Major=" << unsigned(m_major) << std::endl; + os << "MessageType=" << unsigned(m_mtype); + os << ", Major=" << unsigned(m_major); } void diff --git a/model/mac-command.cc b/model/mac-command.cc index bfd630d083..9a995e100e 100644 --- a/model/mac-command.cc +++ b/model/mac-command.cc @@ -148,7 +148,7 @@ LinkCheckReq::Print(std::ostream& os) const { NS_LOG_FUNCTION_NOARGS(); - os << "LinkCheckReq" << std::endl; + os << "LinkCheckReq()"; } ////////////////// @@ -205,9 +205,10 @@ LinkCheckAns::Print(std::ostream& os) const { NS_LOG_FUNCTION_NOARGS(); - os << "LinkCheckAns" << std::endl; - os << "margin: " << unsigned(m_margin) << std::endl; - os << "gwCnt: " << unsigned(m_gwCnt) << std::endl; + os << "LinkCheckAns("; + os << "margin=" << unsigned(m_margin); + os << ", gwCnt=" << unsigned(m_gwCnt); + os << ")"; } void @@ -314,12 +315,13 @@ LinkAdrReq::Print(std::ostream& os) const { NS_LOG_FUNCTION_NOARGS(); - os << "LinkAdrReq" << std::endl; - os << "dataRate: " << unsigned(m_dataRate) << std::endl; - os << "txPower: " << unsigned(m_txPower) << std::endl; - os << "chMask: " << std::bitset<16>(m_chMask) << std::endl; - os << "chMaskCntl: " << unsigned(m_chMaskCntl) << std::endl; - os << "nbTrans: " << unsigned(m_nbTrans) << std::endl; + os << "LinkAdrReq("; + os << "dataRate=" << unsigned(m_dataRate); + os << ", txPower=" << unsigned(m_txPower); + os << ", chMask=" << std::bitset<16>(m_chMask); + os << ", chMaskCntl=" << unsigned(m_chMaskCntl); + os << ", nbTrans=" << unsigned(m_nbTrans); + os << ")"; } uint8_t @@ -418,7 +420,11 @@ LinkAdrAns::Print(std::ostream& os) const { NS_LOG_FUNCTION_NOARGS(); - os << "LinkAdrAns" << std::endl; + os << "LinkAdrAns("; + os << "powerAck=" << m_powerAck; + os << ", dataRateAck=" << m_dataRateAck; + os << ", channelMaskAck=" << m_channelMaskAck; + os << ")"; } ////////////////// @@ -469,9 +475,10 @@ DutyCycleReq::Print(std::ostream& os) const { NS_LOG_FUNCTION_NOARGS(); - os << "DutyCycleReq" << std::endl; - os << "maxDCycle: " << unsigned(m_maxDCycle) << std::endl; - os << "maxDCycle (fraction): " << GetMaximumAllowedDutyCycle() << std::endl; + os << "DutyCycleReq("; + os << "maxDCycle=" << unsigned(m_maxDCycle); + os << ", fraction=" << GetMaximumAllowedDutyCycle(); + os << ")"; } double @@ -529,7 +536,7 @@ DutyCycleAns::Print(std::ostream& os) const { NS_LOG_FUNCTION_NOARGS(); - os << "DutyCycleAns" << std::endl; + os << "DutyCycleAns()"; } ////////////////// @@ -609,10 +616,11 @@ RxParamSetupReq::Print(std::ostream& os) const { NS_LOG_FUNCTION_NOARGS(); - os << "RxParamSetupReq" << std::endl; - os << "rx1DrOffset: " << unsigned(m_rx1DrOffset) << std::endl; - os << "rx2DataRate: " << unsigned(m_rx2DataRate) << std::endl; - os << "frequency: " << m_frequency << std::endl; + os << "RxParamSetupReq("; + os << "rx1DrOffset=" << unsigned(m_rx1DrOffset); + os << ", rx2DataRate=" << unsigned(m_rx2DataRate); + os << ", frequency=" << m_frequency; + os << ")"; } uint8_t @@ -696,10 +704,11 @@ RxParamSetupAns::Print(std::ostream& os) const { NS_LOG_FUNCTION_NOARGS(); - os << "RxParamSetupAns" << std::endl; - os << "m_rx1DrOffsetAck: " << m_rx1DrOffsetAck << std::endl; - os << "m_rx2DataRateAck: " << m_rx2DataRateAck << std::endl; - os << "m_channelAck: " << m_channelAck << std::endl; + os << "RxParamSetupAns("; + os << "m_rx1DrOffsetAck=" << m_rx1DrOffsetAck; + os << ", m_rx2DataRateAck=" << m_rx2DataRateAck; + os << ", m_channelAck=" << m_channelAck; + os << ")"; } ////////////////// @@ -739,7 +748,7 @@ DevStatusReq::Print(std::ostream& os) const { NS_LOG_FUNCTION_NOARGS(); - os << "DevStatusReq" << std::endl; + os << "DevStatusReq()"; } ////////////////// @@ -793,9 +802,10 @@ DevStatusAns::Print(std::ostream& os) const { NS_LOG_FUNCTION_NOARGS(); - os << "DevStatusAns" << std::endl; - os << "Battery: " << unsigned(m_battery) << std::endl; - os << "Margin: " << unsigned(m_margin) << std::endl; + os << "DevStatusAns("; + os << "Battery=" << unsigned(m_battery); + os << ", Margin=" << unsigned(m_margin); + os << ")"; } uint8_t @@ -882,7 +892,7 @@ NewChannelReq::Print(std::ostream& os) const { NS_LOG_FUNCTION_NOARGS(); - os << "NewChannelReq" << std::endl; + os << "NewChannelReq()"; } uint8_t @@ -970,9 +980,10 @@ NewChannelAns::Print(std::ostream& os) const { NS_LOG_FUNCTION_NOARGS(); - os << "NewChannelAns" << std::endl; - os << "DataRateRangeOk: " << m_dataRateRangeOk << std::endl; - os << "ChannelFrequencyOk: " << m_channelFrequencyOk << std::endl; + os << "NewChannelAns("; + os << "DataRateRangeOk=" << m_dataRateRangeOk; + os << ", ChannelFrequencyOk=" << m_channelFrequencyOk; + os << ")"; } ////////////////////// @@ -1025,7 +1036,7 @@ RxTimingSetupReq::Print(std::ostream& os) const { NS_LOG_FUNCTION_NOARGS(); - os << "RxTimingSetupReq" << std::endl; + os << "RxTimingSetupReq()"; } Time @@ -1077,7 +1088,7 @@ RxTimingSetupAns::Print(std::ostream& os) const { NS_LOG_FUNCTION_NOARGS(); - os << "RxTimingSetupAns" << std::endl; + os << "RxTimingSetupAns()"; } ////////////////// @@ -1117,7 +1128,7 @@ DlChannelAns::Print(std::ostream& os) const { NS_LOG_FUNCTION_NOARGS(); - os << "DlChannelAns" << std::endl; + os << "DlChannelAns()"; } ////////////////// @@ -1157,7 +1168,7 @@ TxParamSetupReq::Print(std::ostream& os) const { NS_LOG_FUNCTION_NOARGS(); - os << "TxParamSetupReq" << std::endl; + os << "TxParamSetupReq()"; } ////////////////// @@ -1197,7 +1208,7 @@ TxParamSetupAns::Print(std::ostream& os) const { NS_LOG_FUNCTION_NOARGS(); - os << "TxParamSetupAns" << std::endl; + os << "TxParamSetupAns()"; } } // namespace lorawan From 4c8bf626b26f5ee54727386883ff095952737c73 Mon Sep 17 00:00:00 2001 From: Alessandro Aimi Date: Tue, 12 Nov 2024 11:22:05 +0100 Subject: [PATCH 12/34] Add getters to LinkAdrAns MAC command --- model/mac-command.cc | 18 ++++++++++++++++++ model/mac-command.h | 30 ++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/model/mac-command.cc b/model/mac-command.cc index 9a995e100e..65171eac01 100644 --- a/model/mac-command.cc +++ b/model/mac-command.cc @@ -427,6 +427,24 @@ LinkAdrAns::Print(std::ostream& os) const os << ")"; } +bool +LinkAdrAns::GetPowerAck() const +{ + return m_powerAck; +} + +bool +LinkAdrAns::GetDataRateAck() const +{ + return m_dataRateAck; +} + +bool +LinkAdrAns::GetChannelMaskAck() const +{ + return m_channelMaskAck; +} + ////////////////// // DutyCycleReq // ////////////////// diff --git a/model/mac-command.h b/model/mac-command.h index 23ec9b6643..1fbee85541 100644 --- a/model/mac-command.h +++ b/model/mac-command.h @@ -309,6 +309,36 @@ class LinkAdrAns : public MacCommand uint8_t Deserialize(Buffer::Iterator& start) override; void Print(std::ostream& os) const override; + /** + * Get the PowerAck field value of the LinkAdrAns command. + * + * \return true The power level was successfully set. + * \return false The end-device is unable to operate at or below the requested power level. The + * command was discarded and the end-device state was not changed. + */ + bool GetPowerAck() const; + + /** + * Get the DataRateAck field value of the LinkAdrAns command. + * + * \return true The data rate was successfully set. + * \return false The data rate requested is unknown to the end-device or is not possible, given + * the channel mask provided (not supported by any of the enabled channels). The command was + * discarded, and the end-device state was not changed. + */ + bool GetDataRateAck() const; + + /** + * Get the ChannelMaskAck field value of the LinkAdrAns command. + * + * \return true The channel mask sent was successfully interpreted. All currently defined + * channel states were set according to the mask. + * \return false The channel mask enables a yet undefined channel or the channel mask required + * all channels to be disabled or the channel mask is incompatible with the resulting data rate + * or TX power. The command was discarded, and the end-device state was not changed. + */ + bool GetChannelMaskAck() const; + private: bool m_powerAck; //!< The PowerACK field bool m_dataRateAck; //!< The DataRateACK field From f682b991960c5534cbac00dc3d72cd3d630564f1 Mon Sep 17 00:00:00 2001 From: Alessandro Aimi Date: Tue, 12 Nov 2024 15:15:07 +0100 Subject: [PATCH 13/34] LinkCheckAns and LinkAdrReq tests --- test/lorawan-test-suite.cc | 220 ++++++++++++++++++++++++++++++++++++- 1 file changed, 218 insertions(+), 2 deletions(-) diff --git a/test/lorawan-test-suite.cc b/test/lorawan-test-suite.cc index bf16f22c55..3c1d731ca4 100644 --- a/test/lorawan-test-suite.cc +++ b/test/lorawan-test-suite.cc @@ -346,7 +346,7 @@ HeaderTest::DoRun() // Deserialization frameHdr.Deserialize(serialized); - Ptr command = DynamicCast(*frameHdr.GetCommands().begin()); + Ptr command = DynamicCast(frameHdr.GetCommands().at(0)); uint8_t margin = command->GetMargin(); uint8_t gwCnt = command->GetGwCnt(); @@ -388,7 +388,7 @@ HeaderTest::DoRun() frameHdr1.SetAsDownlink(); pkt->RemoveHeader(frameHdr1); - Ptr linkCheckAns = DynamicCast(*frameHdr1.GetCommands().begin()); + Ptr linkCheckAns = DynamicCast(frameHdr1.GetCommands().at(0)); NS_TEST_EXPECT_MSG_EQ((pkt->GetSize()), 10, @@ -1602,6 +1602,210 @@ LorawanMacTest::DoRun() NS_LOG_DEBUG("LorawanMacTest"); } +/** + * \ingroup lorawan + * + * It tests the functionalities of LoRaWAN MAC commands received by devices. + * + * This means testing that (i) settings in the downlink MAC commands are correctly applied/rejected + * by the device, and that (ii) the correct answer (if expected) is produced by the device. + */ +class MacCommandTest : public TestCase +{ + public: + MacCommandTest(); //!< Default constructor + ~MacCommandTest() override; //!< Destructor + + private: + /** + * Have this class' MAC layer receive a downlink packet carrying the input MAC command. After, + * trigger a new empty uplink packet send that can then be used to examine the MAC command + * answers in the header. + * + * \tparam T \explicit The type of MAC command to create. + * \tparam Ts \deduced Types of the constructor arguments. + * \param [in] args MAC command constructor arguments. + * \return The list of MAC commands produced by the device as an answer. + */ + template + std::vector> RunMacCommand(Ts&&... args); + + /** + * This function resets the state of the MAC layer used for tests. Use it before each call of + * RunMacCommand. Otherwise, on consecutive calls the MAC layer will not send due to duty-cycle + * limitations. + */ + void Reset(); + + void DoRun() override; + + Ptr m_mac; //!< The end device's MAC layer used in tests. +}; + +MacCommandTest::MacCommandTest() + : TestCase("Test functionality of MAC commands when received by a device") +{ +} + +MacCommandTest::~MacCommandTest() +{ + m_mac = nullptr; +} + +template +std::vector> +MacCommandTest::RunMacCommand(Ts&&... args) +{ + Ptr pkt; + LoraFrameHeader fhdr; + LorawanMacHeader mhdr; + // Prepare DL packet with input command + pkt = Create(0); + fhdr.SetAsDownlink(); + auto cmd = Create(args...); + fhdr.AddCommand(cmd); + pkt->AddHeader(fhdr); + mhdr.SetMType(LorawanMacHeader::UNCONFIRMED_DATA_DOWN); + pkt->AddHeader(mhdr); + // Trigger MAC layer reception + DynamicCast(m_mac->GetPhy()) + ->SwitchToStandby(); // usually done as we open Rx windows + m_mac->Receive(pkt); + // Trigger MAC layer send + pkt = Create(0); + m_mac->Send(pkt); + // Retrieve uplink MAC commands + pkt->RemoveHeader(mhdr); + fhdr.SetAsUplink(); + pkt->RemoveHeader(fhdr); + return fhdr.GetCommands(); +} + +void +MacCommandTest::Reset() +{ + // Reset MAC state + LorawanMacHelper macHelper; + macHelper.SetRegion(LorawanMacHelper::EU); + macHelper.SetDeviceType(LorawanMacHelper::ED_A); + /// \todo Create should not require a node in input. + m_mac = DynamicCast(macHelper.Create(nullptr, nullptr)); + NS_TEST_EXPECT_MSG_NE(m_mac, nullptr, "Failed to initialize MAC layer object."); + auto phy = CreateObject(); + phy->SetChannel(CreateObject()); + phy->SetMobility(CreateObject()); + m_mac->SetPhy(phy); +} + +void +MacCommandTest::DoRun() +{ + NS_LOG_DEBUG("MacCommandTest"); + + Reset(); + // LinkCheckAns: get connectivity metrics of last uplink LinkCheckReq command + uint8_t margin = 20; // best reception margin [dB] from demodulation floor + uint8_t gwCnt = 3; // number of gateways that received last uplink + auto answers = RunMacCommand(margin, gwCnt); + NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetLastKnownLinkMarginDb()), + unsigned(margin), + "m_lastKnownMarginDb differs from Margin field of LinkCheckAns"); + NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetLastKnownGatewayCount()), + unsigned(gwCnt), + "m_lastKnownGatewayCount differs GwCnt field of LinkCheckAns"); + NS_TEST_EXPECT_MSG_EQ(answers.size(), + 0, + "Unexpected uplink MAC command answer(s) to LinkCheckAns"); + + Reset(); + // LinkAdrReq: change data rate, TX power, redundancy, or channel mask + uint8_t dataRate = 5; + uint8_t txPower = 2; + uint16_t chMask = 0b101; + uint8_t chMaskCntl = 0; + uint8_t nbTrans = 13; + answers = RunMacCommand(dataRate, txPower, chMask, chMaskCntl, nbTrans); + NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetDataRate()), + unsigned(dataRate), + "m_dataRate does not match DataRate field of LinkAdrReq"); + NS_TEST_EXPECT_MSG_EQ(m_mac->GetTransmissionPowerDbm(), + 10, + "m_txPowerDbm does not match txPower field of LinkAdrReq"); + NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetMaxNumberOfTransmissions()), + 13, + "m_nbTrans does not match nbTrans field of LinkAdrReq"); + auto channels = m_mac->GetLogicalLoraChannelHelper()->GetChannelList(); + for (size_t i = 0; i < channels.size() && i < 16; i++) + { + bool actual = channels.at(i + 16 * chMaskCntl)->IsEnabledForUplink(); + bool expected = (chMask & 0b1 << i); + NS_TEST_EXPECT_MSG_EQ(actual, expected, "Channel " << i << " state does not match chMask"); + } + NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1"); + auto laa = DynamicCast(answers.at(0)); + NS_TEST_ASSERT_MSG_NE(laa, nullptr, "LinkAdrAns was expected, cmd type cast failed"); + NS_TEST_ASSERT_MSG_EQ(laa->GetChannelMaskAck(), true, "ChannelMaskAck expected to be true"); + NS_TEST_ASSERT_MSG_EQ(laa->GetDataRateAck(), true, "DataRateAck expected to be true"); + NS_TEST_ASSERT_MSG_EQ(laa->GetPowerAck(), true, "PowerAck expected to be true"); + + Reset(); + // LinkAdrReq: ADR bit off, only change channel mask + chMask = 0b011; + m_mac->SetUplinkAdrBit(false); + answers = RunMacCommand(dataRate, txPower, chMask, chMaskCntl, nbTrans); + NS_TEST_EXPECT_MSG_NE(unsigned(m_mac->GetDataRate()), + unsigned(dataRate), + "m_dataRate expected to differ from DataRate field of LinkAdrReq"); + NS_TEST_EXPECT_MSG_NE(m_mac->GetTransmissionPowerDbm(), + 10, + "m_txPowerDbm expected to not match txPower field of LinkAdrReq"); + NS_TEST_EXPECT_MSG_NE(unsigned(m_mac->GetMaxNumberOfTransmissions()), + 13, + "m_nbTrans expected to differ from nbTrans field of LinkAdrReq"); + channels = m_mac->GetLogicalLoraChannelHelper()->GetChannelList(); + for (size_t i = 0; i < channels.size() && i < 16; i++) + { + bool actual = channels.at(i + 16 * chMaskCntl)->IsEnabledForUplink(); + bool expected = (chMask & 0b1 << i); + NS_TEST_EXPECT_MSG_EQ(actual, expected, "Channel " << i << " state does not match chMask"); + } + NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1"); + laa = DynamicCast(answers.at(0)); + NS_TEST_ASSERT_MSG_NE(laa, nullptr, "LinkAdrAns was expected, cmd type cast failed"); + NS_TEST_ASSERT_MSG_EQ(laa->GetChannelMaskAck(), true, "ChannelMaskAck expected to be true"); + NS_TEST_ASSERT_MSG_EQ(laa->GetDataRateAck(), false, "DataRateAck expected to be false"); + NS_TEST_ASSERT_MSG_EQ(laa->GetPowerAck(), false, "PowerAck expected to be false"); + + Reset(); + // LinkAdrReq: invalid chMask, data rate and power + // WARNING: default values are manually set here + dataRate = 12; + txPower = 8; + chMask = 0b1100; + answers = RunMacCommand(dataRate, txPower, chMask, chMaskCntl, nbTrans); + NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetDataRate()), + 0, + "m_dataRate expected to be left to default value"); + NS_TEST_EXPECT_MSG_EQ(m_mac->GetTransmissionPowerDbm(), + 14, + "m_txPowerDbm expected to be left to default value"); + NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetMaxNumberOfTransmissions()), + 1, + "m_nbTrans expected to be left to default value"); + channels = m_mac->GetLogicalLoraChannelHelper()->GetChannelList(); + for (size_t i = 0; i < channels.size() && i < 16; i++) + { + bool actual = channels.at(i + 16 * chMaskCntl)->IsEnabledForUplink(); + NS_TEST_EXPECT_MSG_EQ(actual, true, "Channel " << i << " differs from default"); + } + NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1"); + laa = DynamicCast(answers.at(0)); + NS_TEST_ASSERT_MSG_NE(laa, nullptr, "LinkAdrAns was expected, cmd type cast failed"); + NS_TEST_ASSERT_MSG_EQ(laa->GetChannelMaskAck(), false, "ChannelMaskAck expected to be false"); + NS_TEST_ASSERT_MSG_EQ(laa->GetDataRateAck(), false, "DataRateAck expected to be false"); + NS_TEST_ASSERT_MSG_EQ(laa->GetPowerAck(), false, "PowerAck expected to be false"); +} + /** * \ingroup lorawan * @@ -1618,6 +1822,17 @@ LorawanTestSuite::LorawanTestSuite() : TestSuite("lorawan", Type::UNIT) { // LogComponentEnable("LorawanTestSuite", LOG_LEVEL_DEBUG); + // LogComponentEnable("LorawanMac", LOG_LEVEL_DEBUG); + // LogComponentEnable("EndDeviceLorawanMac", LOG_LEVEL_DEBUG); + // LogComponentEnable("ClassAEndDeviceLorawanMac", LOG_LEVEL_DEBUG); + // LogComponentEnable("SimpleEndDeviceLoraPhy", LOG_LEVEL_DEBUG); + // LogComponentEnable("EndDeviceLoraPhy", LOG_LEVEL_DEBUG); + // LogComponentEnable("LoraPhy", LOG_LEVEL_DEBUG); + // LogComponentEnable("LoraChannel", LOG_LEVEL_DEBUG); + // LogComponentEnable("LoraFrameHeader", LOG_LEVEL_DEBUG); + // LogComponentEnableAll(LOG_PREFIX_FUNC); + // LogComponentEnableAll(LOG_PREFIX_NODE); + // LogComponentEnableAll(LOG_PREFIX_TIME); AddTestCase(new InterferenceTest, Duration::QUICK); AddTestCase(new AddressTest, Duration::QUICK); @@ -1626,6 +1841,7 @@ LorawanTestSuite::LorawanTestSuite() AddTestCase(new LogicalLoraChannelTest, Duration::QUICK); AddTestCase(new TimeOnAirTest, Duration::QUICK); AddTestCase(new PhyConnectivityTest, Duration::QUICK); + AddTestCase(new MacCommandTest, Duration::QUICK); } // Do not forget to allocate an instance of this TestSuite From 20c554adbcf2ad123d633a5b9ffacf11ccfc37bc Mon Sep 17 00:00:00 2001 From: Alessandro Aimi Date: Tue, 12 Nov 2024 16:01:19 +0100 Subject: [PATCH 14/34] DutyCycleReq: align terminology with specs, move logic from header to end-device, tests --- model/end-device-lorawan-mac.cc | 16 +++++----------- model/end-device-lorawan-mac.h | 5 ++--- model/mac-command.cc | 32 ++++++++++---------------------- model/mac-command.h | 12 ++++++------ test/lorawan-test-suite.cc | 24 +++++++++++++++++++++--- 5 files changed, 44 insertions(+), 45 deletions(-) diff --git a/model/end-device-lorawan-mac.cc b/model/end-device-lorawan-mac.cc index 27a5ab76a3..9a73f32efc 100644 --- a/model/end-device-lorawan-mac.cc +++ b/model/end-device-lorawan-mac.cc @@ -383,7 +383,7 @@ EndDeviceLorawanMac::ParseCommands(LoraFrameHeader frameHeader) case (DUTY_CYCLE_REQ): { NS_LOG_DEBUG("Detected a DutyCycleReq command."); auto dutyCycleReq = DynamicCast(c); - OnDutyCycleReq(dutyCycleReq->GetMaximumAllowedDutyCycle()); + OnDutyCycleReq(dutyCycleReq->GetMaxDutyCycle()); break; } case (RX_PARAM_SETUP_REQ): { @@ -821,17 +821,11 @@ EndDeviceLorawanMac::OnLinkAdrReq(uint8_t dataRate, } void -EndDeviceLorawanMac::OnDutyCycleReq(double dutyCycle) +EndDeviceLorawanMac::OnDutyCycleReq(uint8_t maxDutyCycle) { - NS_LOG_FUNCTION(this << dutyCycle); - - // Make sure we get a value that makes sense - NS_ASSERT(0 <= dutyCycle && dutyCycle < 1); - - // Set the new duty cycle value - m_aggregatedDutyCycle = dutyCycle; - - // Craft a DutyCycleAns as response + NS_LOG_FUNCTION(this << unsigned(maxDutyCycle)); + NS_ASSERT_MSG(!(maxDutyCycle & 0xF0), "maxDutyCycle > 4 bits"); + m_aggregatedDutyCycle = 1 / std::pow(2, maxDutyCycle); NS_LOG_INFO("Adding DutyCycleAns reply"); m_macCommandList.emplace_back(Create()); } diff --git a/model/end-device-lorawan-mac.h b/model/end-device-lorawan-mac.h index b2ffe12ba5..5dde99d872 100644 --- a/model/end-device-lorawan-mac.h +++ b/model/end-device-lorawan-mac.h @@ -280,10 +280,9 @@ class EndDeviceLorawanMac : public LorawanMac /** * Perform the actions that need to be taken when receiving a DutyCycleReq command. * - * \param dutyCycle The aggregate duty cycle prescribed by the command, in - * fraction form. + * \param maxDutyCycle The aggregate duty cycle encoded by the command. */ - void OnDutyCycleReq(double dutyCycle); + void OnDutyCycleReq(uint8_t maxDutyCycle); /** * Perform the actions that need to be taken when receiving a RxParamSetupReq command. diff --git a/model/mac-command.cc b/model/mac-command.cc index 65171eac01..c5855ac726 100644 --- a/model/mac-command.cc +++ b/model/mac-command.cc @@ -457,11 +457,12 @@ DutyCycleReq::DutyCycleReq() m_serializedSize = 2; } -DutyCycleReq::DutyCycleReq(uint8_t dutyCycle) - : m_maxDCycle(dutyCycle) +DutyCycleReq::DutyCycleReq(uint8_t maxDutyCycle) { - NS_LOG_FUNCTION(this); + NS_LOG_FUNCTION(this << unsigned(maxDutyCycle)); + NS_ASSERT_MSG(!(maxDutyCycle & 0xF0), "maxDutyCycle > 4 bits"); + m_maxDutyCycle = maxDutyCycle; m_commandType = DUTY_CYCLE_REQ; m_serializedSize = 2; } @@ -473,7 +474,7 @@ DutyCycleReq::Serialize(Buffer::Iterator& start) const // Write the CID start.WriteU8(GetCIDFromMacCommand(m_commandType)); - start.WriteU8(m_maxDCycle); + start.WriteU8(m_maxDutyCycle); } uint8_t @@ -483,7 +484,7 @@ DutyCycleReq::Deserialize(Buffer::Iterator& start) // Consume the CID start.ReadU8(); - m_maxDCycle = start.ReadU8(); + m_maxDutyCycle = start.ReadU8(); return m_serializedSize; } @@ -494,28 +495,15 @@ DutyCycleReq::Print(std::ostream& os) const NS_LOG_FUNCTION_NOARGS(); os << "DutyCycleReq("; - os << "maxDCycle=" << unsigned(m_maxDCycle); - os << ", fraction=" << GetMaximumAllowedDutyCycle(); + os << "maxDutyCycle=" << unsigned(m_maxDutyCycle); os << ")"; } -double -DutyCycleReq::GetMaximumAllowedDutyCycle() const +uint8_t +DutyCycleReq::GetMaxDutyCycle() const { NS_LOG_FUNCTION(this); - - // Check if we need to turn off completely - if (m_maxDCycle == 255) - { - return 0; - } - - if (m_maxDCycle == 0) - { - return 1; - } - - return 1 / std::pow(2, double(m_maxDCycle)); + return m_maxDutyCycle; } ////////////////// diff --git a/model/mac-command.h b/model/mac-command.h index 1fbee85541..55b49d5709 100644 --- a/model/mac-command.h +++ b/model/mac-command.h @@ -361,23 +361,23 @@ class DutyCycleReq : public MacCommand /** * Constructor providing initialization of all parameters. * - * \param dutyCycle The duty cycle as a 8-bit unsigned integer. + * \param maxDutyCycle The MaxDutyCycle field as a 8-bit unsigned integer. */ - DutyCycleReq(uint8_t dutyCycle); + DutyCycleReq(uint8_t maxDutyCycle); void Serialize(Buffer::Iterator& start) const override; uint8_t Deserialize(Buffer::Iterator& start) override; void Print(std::ostream& os) const override; /** - * Get the maximum duty cycle prescribed by this Mac command, in fraction form. + * Get the maximum duty cycle prescribed by this Mac command, encoded in 4 bits. * - * \return The maximum duty cycle. + * \return The MaxDutyCycle field value. */ - double GetMaximumAllowedDutyCycle() const; + uint8_t GetMaxDutyCycle() const; private: - uint8_t m_maxDCycle; //!< The MaxDutyCycle field + uint8_t m_maxDutyCycle; //!< The MaxDutyCycle field }; /** diff --git a/test/lorawan-test-suite.cc b/test/lorawan-test-suite.cc index 3c1d731ca4..19cb62a643 100644 --- a/test/lorawan-test-suite.cc +++ b/test/lorawan-test-suite.cc @@ -1801,9 +1801,27 @@ MacCommandTest::DoRun() NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1"); laa = DynamicCast(answers.at(0)); NS_TEST_ASSERT_MSG_NE(laa, nullptr, "LinkAdrAns was expected, cmd type cast failed"); - NS_TEST_ASSERT_MSG_EQ(laa->GetChannelMaskAck(), false, "ChannelMaskAck expected to be false"); - NS_TEST_ASSERT_MSG_EQ(laa->GetDataRateAck(), false, "DataRateAck expected to be false"); - NS_TEST_ASSERT_MSG_EQ(laa->GetPowerAck(), false, "PowerAck expected to be false"); + NS_TEST_EXPECT_MSG_EQ(laa->GetChannelMaskAck(), false, "ChannelMaskAck expected to be false"); + NS_TEST_EXPECT_MSG_EQ(laa->GetDataRateAck(), false, "DataRateAck expected to be false"); + NS_TEST_EXPECT_MSG_EQ(laa->GetPowerAck(), false, "PowerAck expected to be false"); + + Reset(); + // DutyCycleReq: duty cycle to 100% + uint8_t maxDutyCycle = 0; + answers = RunMacCommand(maxDutyCycle); + NS_TEST_EXPECT_MSG_EQ(m_mac->GetAggregatedDutyCycle(), 1, "m_aggregatedDutyCycle != 1"); + NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1"); + auto dca = DynamicCast(answers.at(0)); + NS_TEST_ASSERT_MSG_NE(dca, nullptr, "DutyCycleAns was expected, cmd type cast failed"); + + Reset(); + // DutyCycleReq: duty cycle to 12.5% + maxDutyCycle = 3; + answers = RunMacCommand(maxDutyCycle); + NS_TEST_EXPECT_MSG_EQ(m_mac->GetAggregatedDutyCycle(), 0.125, "m_aggregatedDutyCycle != 1"); + NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1"); + dca = DynamicCast(answers.at(0)); + NS_TEST_ASSERT_MSG_NE(dca, nullptr, "DutyCycleAns was expected, cmd type cast failed"); } /** From 941bbc3d49dd6a2cfe6a684d31b4df1dd4f04c2c Mon Sep 17 00:00:00 2001 From: Alessandro Aimi Date: Tue, 12 Nov 2024 16:04:41 +0100 Subject: [PATCH 15/34] NS_TEST_ASSERT_MSG_EQ where needed --- test/lorawan-test-suite.cc | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/lorawan-test-suite.cc b/test/lorawan-test-suite.cc index 19cb62a643..33a0b6c209 100644 --- a/test/lorawan-test-suite.cc +++ b/test/lorawan-test-suite.cc @@ -1744,9 +1744,9 @@ MacCommandTest::DoRun() NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1"); auto laa = DynamicCast(answers.at(0)); NS_TEST_ASSERT_MSG_NE(laa, nullptr, "LinkAdrAns was expected, cmd type cast failed"); - NS_TEST_ASSERT_MSG_EQ(laa->GetChannelMaskAck(), true, "ChannelMaskAck expected to be true"); - NS_TEST_ASSERT_MSG_EQ(laa->GetDataRateAck(), true, "DataRateAck expected to be true"); - NS_TEST_ASSERT_MSG_EQ(laa->GetPowerAck(), true, "PowerAck expected to be true"); + NS_TEST_EXPECT_MSG_EQ(laa->GetChannelMaskAck(), true, "ChannelMaskAck expected to be true"); + NS_TEST_EXPECT_MSG_EQ(laa->GetDataRateAck(), true, "DataRateAck expected to be true"); + NS_TEST_EXPECT_MSG_EQ(laa->GetPowerAck(), true, "PowerAck expected to be true"); Reset(); // LinkAdrReq: ADR bit off, only change channel mask @@ -1772,9 +1772,9 @@ MacCommandTest::DoRun() NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1"); laa = DynamicCast(answers.at(0)); NS_TEST_ASSERT_MSG_NE(laa, nullptr, "LinkAdrAns was expected, cmd type cast failed"); - NS_TEST_ASSERT_MSG_EQ(laa->GetChannelMaskAck(), true, "ChannelMaskAck expected to be true"); - NS_TEST_ASSERT_MSG_EQ(laa->GetDataRateAck(), false, "DataRateAck expected to be false"); - NS_TEST_ASSERT_MSG_EQ(laa->GetPowerAck(), false, "PowerAck expected to be false"); + NS_TEST_EXPECT_MSG_EQ(laa->GetChannelMaskAck(), true, "ChannelMaskAck expected to be true"); + NS_TEST_EXPECT_MSG_EQ(laa->GetDataRateAck(), false, "DataRateAck expected to be false"); + NS_TEST_EXPECT_MSG_EQ(laa->GetPowerAck(), false, "PowerAck expected to be false"); Reset(); // LinkAdrReq: invalid chMask, data rate and power @@ -1812,7 +1812,7 @@ MacCommandTest::DoRun() NS_TEST_EXPECT_MSG_EQ(m_mac->GetAggregatedDutyCycle(), 1, "m_aggregatedDutyCycle != 1"); NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1"); auto dca = DynamicCast(answers.at(0)); - NS_TEST_ASSERT_MSG_NE(dca, nullptr, "DutyCycleAns was expected, cmd type cast failed"); + NS_TEST_EXPECT_MSG_NE(dca, nullptr, "DutyCycleAns was expected, cmd type cast failed"); Reset(); // DutyCycleReq: duty cycle to 12.5% @@ -1821,7 +1821,7 @@ MacCommandTest::DoRun() NS_TEST_EXPECT_MSG_EQ(m_mac->GetAggregatedDutyCycle(), 0.125, "m_aggregatedDutyCycle != 1"); NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1"); dca = DynamicCast(answers.at(0)); - NS_TEST_ASSERT_MSG_NE(dca, nullptr, "DutyCycleAns was expected, cmd type cast failed"); + NS_TEST_EXPECT_MSG_NE(dca, nullptr, "DutyCycleAns was expected, cmd type cast failed"); } /** From c23c76bf986ae700d18a37b6a06cddc735155735 Mon Sep 17 00:00:00 2001 From: Alessandro Aimi Date: Tue, 12 Nov 2024 17:07:39 +0100 Subject: [PATCH 16/34] Fix MAC command frequency encoding endianness --- model/mac-command.cc | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/model/mac-command.cc b/model/mac-command.cc index c5855ac726..acb22f4f15 100644 --- a/model/mac-command.cc +++ b/model/mac-command.cc @@ -591,9 +591,10 @@ RxParamSetupReq::Serialize(Buffer::Iterator& start) const uint32_t encodedFrequency = m_frequency / 100; NS_LOG_DEBUG(unsigned(encodedFrequency)); NS_LOG_DEBUG(std::bitset<32>(encodedFrequency)); - start.WriteU8((encodedFrequency & 0xff0000) >> 16); // Most significant byte - start.WriteU8((encodedFrequency & 0xff00) >> 8); // Middle byte + // Frequency is in little endian (lsb -> msb) start.WriteU8(encodedFrequency & 0xff); // Least significant byte + start.WriteU8((encodedFrequency & 0xff00) >> 8); // Middle byte + start.WriteU8((encodedFrequency & 0xff0000) >> 16); // Most significant byte } uint8_t @@ -607,10 +608,11 @@ RxParamSetupReq::Deserialize(Buffer::Iterator& start) uint8_t firstByte = start.ReadU8(); m_rx1DrOffset = (firstByte & 0b1110000) >> 4; m_rx2DataRate = firstByte & 0b1111; - uint32_t secondByte = start.ReadU8(); - uint32_t thirdByte = start.ReadU8(); - uint32_t fourthByte = start.ReadU8(); - uint32_t encodedFrequency = (secondByte << 16) | (thirdByte << 8) | fourthByte; + uint32_t encodedFrequency = 0; + // Frequency is in little endian (lsb -> msb) + encodedFrequency += start.ReadU8(); // Least significant byte + encodedFrequency += start.ReadU8() << 8; // Middle byte + encodedFrequency += start.ReadU8() << 16; // Most significant byte NS_LOG_DEBUG(std::bitset<32>(encodedFrequency)); m_frequency = double(encodedFrequency) * 100; @@ -867,9 +869,10 @@ NewChannelReq::Serialize(Buffer::Iterator& start) const start.WriteU8(m_chIndex); uint32_t encodedFrequency = m_frequency / 100; - start.WriteU8((encodedFrequency & 0xff0000) >> 16); - start.WriteU8((encodedFrequency & 0xff00) >> 8); - start.WriteU8(encodedFrequency & 0xff); + // Frequency is in little endian (lsb -> msb) + start.WriteU8(encodedFrequency & 0xff); // Least significant byte + start.WriteU8((encodedFrequency & 0xff00) >> 8); // Middle byte + start.WriteU8((encodedFrequency & 0xff0000) >> 16); // Most significant byte start.WriteU8((m_maxDataRate << 4) | (m_minDataRate & 0xf)); } @@ -883,8 +886,10 @@ NewChannelReq::Deserialize(Buffer::Iterator& start) // Read the data m_chIndex = start.ReadU8(); uint32_t encodedFrequency = 0; - encodedFrequency |= uint32_t(start.ReadU16()) << 8; - encodedFrequency |= uint32_t(start.ReadU8()); + // Frequency is in little endian (lsb -> msb) + encodedFrequency += start.ReadU8(); // Least significant byte + encodedFrequency += start.ReadU8() << 8; // Middle byte + encodedFrequency += start.ReadU8() << 16; // Most significant byte m_frequency = double(encodedFrequency) * 100; uint8_t dataRateByte = start.ReadU8(); m_maxDataRate = dataRateByte >> 4; From 71b940325c92b95a7956a997af75dbcdce48219b Mon Sep 17 00:00:00 2001 From: Alessandro Aimi Date: Tue, 12 Nov 2024 18:12:56 +0100 Subject: [PATCH 17/34] RxParamSetupReq: add RxParamSetupAns getters, clean-up, fix frequency unit of measure, add tests --- model/class-a-end-device-lorawan-mac.cc | 57 +++++++++++++---------- model/class-a-end-device-lorawan-mac.h | 15 ++---- model/end-device-lorawan-mac.cc | 21 ++------- model/end-device-lorawan-mac.h | 13 ++---- model/mac-command.cc | 32 ++++++++----- model/mac-command.h | 25 ++++++++++ test/lorawan-test-suite.cc | 61 +++++++++++++++++++++++-- 7 files changed, 144 insertions(+), 80 deletions(-) diff --git a/model/class-a-end-device-lorawan-mac.cc b/model/class-a-end-device-lorawan-mac.cc index 222680b3d6..d7a8ad1053 100644 --- a/model/class-a-end-device-lorawan-mac.cc +++ b/model/class-a-end-device-lorawan-mac.cc @@ -352,10 +352,10 @@ ClassAEndDeviceLorawanMac::OpenSecondReceiveWindow() DynamicCast(m_phy)->SwitchToStandby(); // Switch to appropriate channel and data rate - NS_LOG_INFO("Using parameters: " << m_secondReceiveWindowFrequency << "Hz, DR" + NS_LOG_INFO("Using parameters: " << m_secondReceiveWindowFrequencyMHz << "MHz, DR" << unsigned(m_secondReceiveWindowDataRate)); - DynamicCast(m_phy)->SetFrequency(m_secondReceiveWindowFrequency); + DynamicCast(m_phy)->SetFrequency(m_secondReceiveWindowFrequencyMHz); DynamicCast(m_phy)->SetSpreadingFactor( GetSfFromDataRate(m_secondReceiveWindowDataRate)); @@ -508,13 +508,13 @@ ClassAEndDeviceLorawanMac::GetSecondReceiveWindowDataRate() const void ClassAEndDeviceLorawanMac::SetSecondReceiveWindowFrequency(double frequencyMHz) { - m_secondReceiveWindowFrequency = frequencyMHz; + m_secondReceiveWindowFrequencyMHz = frequencyMHz; } double ClassAEndDeviceLorawanMac::GetSecondReceiveWindowFrequency() const { - return m_secondReceiveWindowFrequency; + return m_secondReceiveWindowFrequencyMHz; } ///////////////////////// @@ -522,39 +522,46 @@ ClassAEndDeviceLorawanMac::GetSecondReceiveWindowFrequency() const ///////////////////////// void -ClassAEndDeviceLorawanMac::OnRxClassParamSetupReq(Ptr rxParamSetupReq) +ClassAEndDeviceLorawanMac::OnRxParamSetupReq(uint8_t rx1DrOffset, + uint8_t rx2DataRate, + double frequency) { - NS_LOG_FUNCTION(this << rxParamSetupReq); + NS_LOG_FUNCTION(this << unsigned(rx1DrOffset) << unsigned(rx2DataRate) << frequency); - bool offsetOk = true; - bool dataRateOk = true; + // Adapted from: github.com/Lora-net/SWL2001.git v4.3.1 + // For the time being, this implementation is valid for the EU868 region - uint8_t rx1DrOffset = rxParamSetupReq->GetRx1DrOffset(); - uint8_t rx2DataRate = rxParamSetupReq->GetRx2DataRate(); - double frequency = rxParamSetupReq->GetFrequency(); + bool rx1DrOffsetAck = true; + bool rx2DataRateAck = true; + bool channelAck = true; - NS_LOG_FUNCTION(this << unsigned(rx1DrOffset) << unsigned(rx2DataRate) << frequency); + if (rx1DrOffset >= 6) + { + NS_LOG_WARN("Invalid rx1DrOffset"); + rx1DrOffsetAck = false; + } - // Check that the desired offset is valid - if (!(0 <= rx1DrOffset && rx1DrOffset <= 5)) + if (!GetSfFromDataRate(rx2DataRate) || !GetBandwidthFromDataRate(rx2DataRate)) { - offsetOk = false; + NS_LOG_WARN("Invalid rx2DataRate"); + rx2DataRateAck = false; } - // Check that the desired data rate is valid - if (GetSfFromDataRate(rx2DataRate) == 0 || GetBandwidthFromDataRate(rx2DataRate) == 0) + if (frequency > 870000000 || frequency < 863000000) { - dataRateOk = false; + NS_LOG_WARN("Invalid rx2 frequency"); + channelAck = false; } - // For now, don't check for validity of frequency - m_secondReceiveWindowDataRate = rx2DataRate; - m_rx1DrOffset = rx1DrOffset; - m_secondReceiveWindowFrequency = frequency; + if (rx1DrOffsetAck && rx2DataRateAck && channelAck) + { + m_rx1DrOffset = rx1DrOffset; + m_secondReceiveWindowDataRate = rx2DataRate; + m_secondReceiveWindowFrequencyMHz = frequency / 1e6; + } - // Craft a RxParamSetupAns as response - NS_LOG_INFO("Adding RxParamSetupAns reply"); - m_macCommandList.emplace_back(Create(offsetOk, dataRateOk, true)); + m_macCommandList.emplace_back( + Create(rx1DrOffsetAck, rx2DataRateAck, channelAck)); } } /* namespace lorawan */ diff --git a/model/class-a-end-device-lorawan-mac.h b/model/class-a-end-device-lorawan-mac.h index d85c6422e8..ffd18db90b 100644 --- a/model/class-a-end-device-lorawan-mac.h +++ b/model/class-a-end-device-lorawan-mac.h @@ -144,16 +144,7 @@ class ClassAEndDeviceLorawanMac : public EndDeviceLorawanMac // MAC command methods // ///////////////////////// - /** - * Perform the actions that need to be taken when receiving a RxParamSetupReq - * command based on the Device's Class Type. - * - * \param rxParamSetupReq The Parameter Setup Request, which contains: - * - The offset to set. - * - The data rate to use for the second receive window. - * - The frequency to use for the second receive window. - */ - void OnRxClassParamSetupReq(Ptr rxParamSetupReq) override; + void OnRxParamSetupReq(uint8_t rx1DrOffset, uint8_t rx2DataRate, double frequency) override; private: Time m_receiveDelay1; //!< The interval between when a packet is done sending and when the first @@ -188,9 +179,9 @@ class ClassAEndDeviceLorawanMac : public EndDeviceLorawanMac EventId m_secondReceiveWindow; /** - * The frequency to listen on for the second receive window. + * The frequency [MHz] to listen on for the second receive window. */ - double m_secondReceiveWindowFrequency; + double m_secondReceiveWindowFrequencyMHz; /** * The data rate to listen for during the second downlink transmission. diff --git a/model/end-device-lorawan-mac.cc b/model/end-device-lorawan-mac.cc index 9a73f32efc..2f827c6f3d 100644 --- a/model/end-device-lorawan-mac.cc +++ b/model/end-device-lorawan-mac.cc @@ -94,8 +94,7 @@ EndDeviceLorawanMac::GetTypeId() MakeEnumChecker(LorawanMacHeader::UNCONFIRMED_DATA_UP, "Unconfirmed", LorawanMacHeader::CONFIRMED_DATA_UP, - "Confirmed")) - .AddConstructor(); + "Confirmed")); return tid; } @@ -389,7 +388,9 @@ EndDeviceLorawanMac::ParseCommands(LoraFrameHeader frameHeader) case (RX_PARAM_SETUP_REQ): { NS_LOG_DEBUG("Detected a RxParamSetupReq command."); auto rxParamSetupReq = DynamicCast(c); - OnRxParamSetupReq(rxParamSetupReq); + OnRxParamSetupReq(rxParamSetupReq->GetRx1DrOffset(), + rxParamSetupReq->GetRx2DataRate(), + rxParamSetupReq->GetFrequency()); break; } case (DEV_STATUS_REQ): { @@ -830,20 +831,6 @@ EndDeviceLorawanMac::OnDutyCycleReq(uint8_t maxDutyCycle) m_macCommandList.emplace_back(Create()); } -void -EndDeviceLorawanMac::OnRxClassParamSetupReq(Ptr rxParamSetupReq) -{ -} - -void -EndDeviceLorawanMac::OnRxParamSetupReq(Ptr rxParamSetupReq) -{ - NS_LOG_FUNCTION(this << rxParamSetupReq); - - // static_cast(this)->OnRxClassParamSetupReq (rxParamSetupReq); - OnRxClassParamSetupReq(rxParamSetupReq); -} - void EndDeviceLorawanMac::OnDevStatusReq() { diff --git a/model/end-device-lorawan-mac.h b/model/end-device-lorawan-mac.h index 5dde99d872..bdf2e03888 100644 --- a/model/end-device-lorawan-mac.h +++ b/model/end-device-lorawan-mac.h @@ -284,20 +284,15 @@ class EndDeviceLorawanMac : public LorawanMac */ void OnDutyCycleReq(uint8_t maxDutyCycle); - /** - * Perform the actions that need to be taken when receiving a RxParamSetupReq command. - * - * \param rxParamSetupReq The Parameter Setup Request. - */ - void OnRxParamSetupReq(Ptr rxParamSetupReq); - /** * Perform the actions that need to be taken when receiving a RxParamSetupReq * command based on the Device's Class Type. * - * \param rxParamSetupReq The Parameter Setup Request. + * \param rx1DrOffset The first reception window data rate offset to set. + * \param rx2DataRate The data rate to use for the second receive window. + * \param frequency The frequency [Hz] to use for the second receive window. */ - virtual void OnRxClassParamSetupReq(Ptr rxParamSetupReq); + virtual void OnRxParamSetupReq(uint8_t rx1DrOffset, uint8_t rx2DataRate, double frequency) = 0; /** * Perform the actions that need to be taken when receiving a DevStatusReq command. diff --git a/model/mac-command.cc b/model/mac-command.cc index acb22f4f15..54a74558a6 100644 --- a/model/mac-command.cc +++ b/model/mac-command.cc @@ -563,18 +563,8 @@ RxParamSetupReq::RxParamSetupReq(uint8_t rx1DrOffset, uint8_t rx2DataRate, doubl m_frequency(frequency) { NS_LOG_FUNCTION(this << unsigned(rx1DrOffset) << unsigned(rx2DataRate) << frequency); - - if ((rx1DrOffset & 0b11111000) != 0) - { - NS_LOG_WARN( - "Warning: received an rx1DrOffset greater than 7. Actual value will be different."); - } - if ((rx2DataRate & 0b11110000) != 0) - { - NS_LOG_WARN( - "Warning: received a rx2DataRate greater than 15. Actual value will be different."); - } - + NS_ASSERT_MSG(!(rx1DrOffset & 0xF8), "rx1DrOffset > 3 bits"); + NS_ASSERT_MSG(!(rx2DataRate & 0xF0), "rx2DataRate > 4 bits"); m_commandType = RX_PARAM_SETUP_REQ; m_serializedSize = 5; } @@ -719,6 +709,24 @@ RxParamSetupAns::Print(std::ostream& os) const os << ")"; } +bool +RxParamSetupAns::GetRx1DrOffsetAck() const +{ + return m_rx1DrOffsetAck; +} + +bool +RxParamSetupAns::GetRx2DataRateAck() const +{ + return m_rx2DataRateAck; +} + +bool +RxParamSetupAns::GetChannelAck() const +{ + return m_channelAck; +} + ////////////////// // DevStatusReq // ////////////////// diff --git a/model/mac-command.h b/model/mac-command.h index 55b49d5709..29e8004ac0 100644 --- a/model/mac-command.h +++ b/model/mac-command.h @@ -472,6 +472,31 @@ class RxParamSetupAns : public MacCommand uint8_t Deserialize(Buffer::Iterator& start) override; void Print(std::ostream& os) const override; + /** + * Get the Rx1DrOffsetAck field value of the RxParamSetupAns command. + * + * \return true RX1 data-rate offset was successfully set. + * \return false The uplink/downlink data rate offset for RX1 slot is not within the allowed + * range. + */ + bool GetRx1DrOffsetAck() const; + + /** + * Get the Rx2DataRateAck field value of the RxParamSetupAns command. + * + * \return true RX2 slot data rate was successfully set. + * \return false The data rate requested is unknown to the end-device. + */ + bool GetRx2DataRateAck() const; + + /** + * Get the ChannelAck field value of the RxParamSetupAns command. + * + * \return true RX2 slot channel was successfully set. + * \return false The frequency requested is not usable by the end-device. + */ + bool GetChannelAck() const; + private: bool m_rx1DrOffsetAck; //!< The RX1DROffsetACK field bool m_rx2DataRateAck; //!< The RX2DataRateACK field diff --git a/test/lorawan-test-suite.cc b/test/lorawan-test-suite.cc index 33a0b6c209..507342faa4 100644 --- a/test/lorawan-test-suite.cc +++ b/test/lorawan-test-suite.cc @@ -1785,13 +1785,13 @@ MacCommandTest::DoRun() answers = RunMacCommand(dataRate, txPower, chMask, chMaskCntl, nbTrans); NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetDataRate()), 0, - "m_dataRate expected to be left to default value"); + "m_dataRate expected to be default value"); NS_TEST_EXPECT_MSG_EQ(m_mac->GetTransmissionPowerDbm(), 14, - "m_txPowerDbm expected to be left to default value"); + "m_txPowerDbm expected to be default value"); NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetMaxNumberOfTransmissions()), 1, - "m_nbTrans expected to be left to default value"); + "m_nbTrans expected to be default value"); channels = m_mac->GetLogicalLoraChannelHelper()->GetChannelList(); for (size_t i = 0; i < channels.size() && i < 16; i++) { @@ -1809,7 +1809,9 @@ MacCommandTest::DoRun() // DutyCycleReq: duty cycle to 100% uint8_t maxDutyCycle = 0; answers = RunMacCommand(maxDutyCycle); - NS_TEST_EXPECT_MSG_EQ(m_mac->GetAggregatedDutyCycle(), 1, "m_aggregatedDutyCycle != 1"); + NS_TEST_EXPECT_MSG_EQ(m_mac->GetAggregatedDutyCycle(), + 1 / std::pow(2, maxDutyCycle), + "m_aggregatedDutyCycle != 1"); NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1"); auto dca = DynamicCast(answers.at(0)); NS_TEST_EXPECT_MSG_NE(dca, nullptr, "DutyCycleAns was expected, cmd type cast failed"); @@ -1818,10 +1820,59 @@ MacCommandTest::DoRun() // DutyCycleReq: duty cycle to 12.5% maxDutyCycle = 3; answers = RunMacCommand(maxDutyCycle); - NS_TEST_EXPECT_MSG_EQ(m_mac->GetAggregatedDutyCycle(), 0.125, "m_aggregatedDutyCycle != 1"); + NS_TEST_EXPECT_MSG_EQ(m_mac->GetAggregatedDutyCycle(), + 1 / std::pow(2, maxDutyCycle), + "m_aggregatedDutyCycle != 1"); NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1"); dca = DynamicCast(answers.at(0)); NS_TEST_EXPECT_MSG_NE(dca, nullptr, "DutyCycleAns was expected, cmd type cast failed"); + + Reset(); + // RxParamSetupReq: set rx1Dr, rx2Dr, frequency + uint8_t rx1DrOffset = 5; + uint8_t rx2DataRate = 5; + double frequency = 863500000; + m_mac->SetDataRate(5); + answers = RunMacCommand(rx1DrOffset, rx2DataRate, frequency); + NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetFirstReceiveWindowDataRate()), + 0, + "Rx1DataRate does not match rx1DrOffset from RxParamSetupReq"); + NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetSecondReceiveWindowDataRate()), + rx2DataRate, + "Rx2DataRate does not match rx2DataRate from RxParamSetupReq"); + NS_TEST_EXPECT_MSG_EQ(m_mac->GetSecondReceiveWindowFrequency(), + frequency / 1e6, + "Rx2 frequency does not match frequency from RxParamSetupReq"); + NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1"); + auto rpsa = DynamicCast(answers.at(0)); + NS_TEST_ASSERT_MSG_NE(rpsa, nullptr, "RxParamSetupAns was expected, cmd type cast failed"); + NS_TEST_EXPECT_MSG_EQ(rpsa->GetRx1DrOffsetAck(), true, "Rx1DrOffsetAck expected to be true"); + NS_TEST_EXPECT_MSG_EQ(rpsa->GetRx2DataRateAck(), true, "Rx2DataRateAck expected to be true"); + NS_TEST_EXPECT_MSG_EQ(rpsa->GetChannelAck(), true, "ChannelAck expected to be true"); + + Reset(); + // RxParamSetupReq: invalid rx1Dr, rx2Dr, frequency + // WARNING: default values are manually set here + rx1DrOffset = 7; + rx2DataRate = 12; + frequency = 871000000; + m_mac->SetDataRate(5); + answers = RunMacCommand(rx1DrOffset, rx2DataRate, frequency); + NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetFirstReceiveWindowDataRate()), + 5, + "Rx1DataRate expected to be default value"); + NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetSecondReceiveWindowDataRate()), + 0, + "Rx2DataRate expected to be default value"); + NS_TEST_EXPECT_MSG_EQ(m_mac->GetSecondReceiveWindowFrequency(), + 869.525, + "Rx2 frequency expected to be default value"); + NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1"); + rpsa = DynamicCast(answers.at(0)); + NS_TEST_ASSERT_MSG_NE(rpsa, nullptr, "RxParamSetupAns was expected, cmd type cast failed"); + NS_TEST_EXPECT_MSG_EQ(rpsa->GetRx1DrOffsetAck(), false, "Rx1DrOffsetAck expected to be false"); + NS_TEST_EXPECT_MSG_EQ(rpsa->GetRx2DataRateAck(), false, "Rx2DataRateAck expected to be false"); + NS_TEST_EXPECT_MSG_EQ(rpsa->GetChannelAck(), false, "ChannelAck expected to be false"); } /** From fb624808d4dc4fa6cbb25a9ac00d05827b9b3459 Mon Sep 17 00:00:00 2001 From: Alessandro Aimi Date: Tue, 12 Nov 2024 19:34:36 +0100 Subject: [PATCH 18/34] DevStatusReq: implementation and tests --- model/class-a-end-device-lorawan-mac.cc | 6 ++++++ model/end-device-lorawan-mac.cc | 23 +++++++++++++++++++++-- model/end-device-lorawan-mac.h | 5 +++++ model/simple-end-device-lora-phy.cc | 5 +++++ test/lorawan-test-suite.cc | 9 +++++++++ 5 files changed, 46 insertions(+), 2 deletions(-) diff --git a/model/class-a-end-device-lorawan-mac.cc b/model/class-a-end-device-lorawan-mac.cc index d7a8ad1053..316aec10b4 100644 --- a/model/class-a-end-device-lorawan-mac.cc +++ b/model/class-a-end-device-lorawan-mac.cc @@ -14,6 +14,7 @@ #include "end-device-lora-phy.h" #include "end-device-lorawan-mac.h" +#include "lora-tag.h" #include "ns3/log.h" @@ -166,6 +167,11 @@ ClassAEndDeviceLorawanMac::Receive(Ptr packet) // THIS WILL BE GetReceiveWindow() Simulator::Cancel(m_secondReceiveWindow); + LoraTag tag; + packet->PeekPacketTag(tag); + /// \see ns3::lorawan::AdrComponent::RxPowerToSNR + m_lastRxSnr = tag.GetReceivePower() + 174 - 10 * log10(125000) - 6; + // Parse the MAC commands ParseCommands(fHdr); diff --git a/model/end-device-lorawan-mac.cc b/model/end-device-lorawan-mac.cc index 2f827c6f3d..854d4b8975 100644 --- a/model/end-device-lorawan-mac.cc +++ b/model/end-device-lorawan-mac.cc @@ -14,6 +14,7 @@ #include "class-a-end-device-lorawan-mac.h" #include "end-device-lora-phy.h" +#include "ns3/energy-source-container.h" #include "ns3/log.h" #include "ns3/simulator.h" @@ -110,6 +111,8 @@ EndDeviceLorawanMac::EndDeviceLorawanMac() m_address(LoraDeviceAddress(0)), // LoraWAN default m_receiveWindowDurationInSymbols(8), + // Max initial value + m_lastRxSnr(32), m_adr(true), m_lastKnownLinkMarginDb(0), m_lastKnownGatewayCount(0), @@ -836,8 +839,24 @@ EndDeviceLorawanMac::OnDevStatusReq() { NS_LOG_FUNCTION(this); - uint8_t battery = 10; // XXX Fake battery level - uint8_t margin = 10; // XXX Fake margin + uint8_t battery = 255; // could not measure + if (m_device && m_device->GetNode()) + { + if (auto sc = m_device->GetNode()->GetObject(); + sc && sc->GetN() == 1) + { + battery = sc->Get(0)->GetEnergyFraction() * 253 + 1.5; // range 1-254 + } + } + else + { + battery = 0; // external power source + } + + int8_t snr = (m_lastRxSnr < 0) ? m_lastRxSnr - .5 : m_lastRxSnr + .5; + snr = (snr > 31) ? 31 : snr; + snr = (snr < -32) ? -32 : snr; + uint8_t margin = std::bitset<6>(snr).to_ulong(); // Craft a RxParamSetupAns as response NS_LOG_INFO("Adding DevStatusAns reply"); diff --git a/model/end-device-lorawan-mac.h b/model/end-device-lorawan-mac.h index bdf2e03888..4a07f97285 100644 --- a/model/end-device-lorawan-mac.h +++ b/model/end-device-lorawan-mac.h @@ -434,6 +434,11 @@ class EndDeviceLorawanMac : public LorawanMac */ Ptr m_uniformRV; + /** + * Used to record the last reception SNR measurement to be included in the DevStatusAns. + */ + double m_lastRxSnr; + ///////////////// // Callbacks // ///////////////// diff --git a/model/simple-end-device-lora-phy.cc b/model/simple-end-device-lora-phy.cc index 8ed3c11f4d..c19ad15ec4 100644 --- a/model/simple-end-device-lora-phy.cc +++ b/model/simple-end-device-lora-phy.cc @@ -280,6 +280,11 @@ SimpleEndDeviceLoraPhy::EndReceive(Ptr packet, PtrRemovePacketTag(tag); + tag.SetReceivePower(event->GetRxPowerdBm()); + tag.SetFrequency(event->GetFrequency()); + packet->AddPacketTag(tag); m_rxOkCallback(packet); } } diff --git a/test/lorawan-test-suite.cc b/test/lorawan-test-suite.cc index 507342faa4..cb34107fb4 100644 --- a/test/lorawan-test-suite.cc +++ b/test/lorawan-test-suite.cc @@ -1873,6 +1873,15 @@ MacCommandTest::DoRun() NS_TEST_EXPECT_MSG_EQ(rpsa->GetRx1DrOffsetAck(), false, "Rx1DrOffsetAck expected to be false"); NS_TEST_EXPECT_MSG_EQ(rpsa->GetRx2DataRateAck(), false, "Rx2DataRateAck expected to be false"); NS_TEST_EXPECT_MSG_EQ(rpsa->GetChannelAck(), false, "ChannelAck expected to be false"); + + Reset(); + // DevStatusReq: get default values + answers = RunMacCommand(); + NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1"); + auto dsa = DynamicCast(answers.at(0)); + NS_TEST_ASSERT_MSG_NE(dsa, nullptr, "DevStatusAns was expected, cmd type cast failed"); + NS_TEST_EXPECT_MSG_EQ(unsigned(dsa->GetBattery()), 0, "Battery expected to be 0 (ext power)"); + NS_TEST_EXPECT_MSG_EQ(unsigned(dsa->GetMargin()), 31, "Margin expected to be 31 (default)"); } /** From 2ef7c230fe2a346fb979f2361614a6b5c12e134a Mon Sep 17 00:00:00 2001 From: Alessandro Aimi Date: Wed, 13 Nov 2024 15:00:52 +0100 Subject: [PATCH 19/34] (hopefully) annotate all frequency variables with MHz/Hz --- model/class-a-end-device-lorawan-mac.cc | 9 ++-- model/class-a-end-device-lorawan-mac.h | 2 +- model/end-device-lora-phy.cc | 6 +-- model/end-device-lora-phy.h | 2 +- model/end-device-lorawan-mac.cc | 30 +++++------ model/end-device-lorawan-mac.h | 26 +++++----- model/end-device-status.cc | 10 ++-- model/end-device-status.h | 10 ++-- model/gateway-lorawan-mac.cc | 16 +++--- model/gateway-lorawan-mac.h | 4 +- model/gateway-status.cc | 4 +- model/gateway-status.h | 5 +- model/logical-lora-channel-helper.cc | 21 ++++---- model/logical-lora-channel-helper.h | 16 +++--- model/logical-lora-channel.cc | 14 ++--- model/logical-lora-channel.h | 10 ++-- model/lora-frame-header.cc | 13 ++--- model/lora-frame-header.h | 8 +-- model/lora-interference-helper.cc | 4 +- model/lora-interference-helper.h | 2 +- model/lora-phy.h | 4 +- model/lora-tag.cc | 12 ++--- model/lora-tag.h | 6 +-- model/mac-command.cc | 25 ++++----- model/mac-command.h | 12 ++--- model/simple-end-device-lora-phy.cc | 2 +- model/sub-band.cc | 20 ++++---- model/sub-band.h | 17 ++++--- test/lorawan-test-suite.cc | 68 ++++++++++++------------- 29 files changed, 195 insertions(+), 183 deletions(-) diff --git a/model/class-a-end-device-lorawan-mac.cc b/model/class-a-end-device-lorawan-mac.cc index 316aec10b4..47d5e460f5 100644 --- a/model/class-a-end-device-lorawan-mac.cc +++ b/model/class-a-end-device-lorawan-mac.cc @@ -530,9 +530,10 @@ ClassAEndDeviceLorawanMac::GetSecondReceiveWindowFrequency() const void ClassAEndDeviceLorawanMac::OnRxParamSetupReq(uint8_t rx1DrOffset, uint8_t rx2DataRate, - double frequency) + double frequencyHz) { - NS_LOG_FUNCTION(this << unsigned(rx1DrOffset) << unsigned(rx2DataRate) << frequency); + NS_LOG_FUNCTION(this << unsigned(rx1DrOffset) << unsigned(rx2DataRate) + << uint32_t(frequencyHz)); // Adapted from: github.com/Lora-net/SWL2001.git v4.3.1 // For the time being, this implementation is valid for the EU868 region @@ -553,7 +554,7 @@ ClassAEndDeviceLorawanMac::OnRxParamSetupReq(uint8_t rx1DrOffset, rx2DataRateAck = false; } - if (frequency > 870000000 || frequency < 863000000) + if (frequencyHz > 870000000 || frequencyHz < 863000000) { NS_LOG_WARN("Invalid rx2 frequency"); channelAck = false; @@ -563,7 +564,7 @@ ClassAEndDeviceLorawanMac::OnRxParamSetupReq(uint8_t rx1DrOffset, { m_rx1DrOffset = rx1DrOffset; m_secondReceiveWindowDataRate = rx2DataRate; - m_secondReceiveWindowFrequencyMHz = frequency / 1e6; + m_secondReceiveWindowFrequencyMHz = frequencyHz / 1e6; } m_macCommandList.emplace_back( diff --git a/model/class-a-end-device-lorawan-mac.h b/model/class-a-end-device-lorawan-mac.h index ffd18db90b..93ad5e2d12 100644 --- a/model/class-a-end-device-lorawan-mac.h +++ b/model/class-a-end-device-lorawan-mac.h @@ -144,7 +144,7 @@ class ClassAEndDeviceLorawanMac : public EndDeviceLorawanMac // MAC command methods // ///////////////////////// - void OnRxParamSetupReq(uint8_t rx1DrOffset, uint8_t rx2DataRate, double frequency) override; + void OnRxParamSetupReq(uint8_t rx1DrOffset, uint8_t rx2DataRate, double frequencyHz) override; private: Time m_receiveDelay1; //!< The interval between when a packet is done sending and when the first diff --git a/model/end-device-lora-phy.cc b/model/end-device-lora-phy.cc index fcc8c1d868..f54e0c286b 100644 --- a/model/end-device-lora-phy.cc +++ b/model/end-device-lora-phy.cc @@ -62,7 +62,7 @@ EndDeviceLoraPhy::GetTypeId() // These will then be changed by helpers. EndDeviceLoraPhy::EndDeviceLoraPhy() : m_state(SLEEP), - m_frequency(868.1), + m_frequencyMHz(868.1), m_sf(7) { } @@ -97,13 +97,13 @@ EndDeviceLoraPhy::IsTransmitting() bool EndDeviceLoraPhy::IsOnFrequency(double frequencyMHz) { - return m_frequency == frequencyMHz; + return m_frequencyMHz == frequencyMHz; } void EndDeviceLoraPhy::SetFrequency(double frequencyMHz) { - m_frequency = frequencyMHz; + m_frequencyMHz = frequencyMHz; } void diff --git a/model/end-device-lora-phy.h b/model/end-device-lora-phy.h index c55d460e58..65cbdf3524 100644 --- a/model/end-device-lora-phy.h +++ b/model/end-device-lora-phy.h @@ -263,7 +263,7 @@ class EndDeviceLoraPhy : public LoraPhy // static const double sensitivity[6]; //!< The sensitivity vector of this device to different // SFs - double m_frequency; //!< The frequency this device is listening on + double m_frequencyMHz; //!< The frequency [MHz] this device is listening on uint8_t m_sf; //!< The Spreading Factor this device is listening for diff --git a/model/end-device-lorawan-mac.cc b/model/end-device-lorawan-mac.cc index 854d4b8975..a9ed6aca56 100644 --- a/model/end-device-lorawan-mac.cc +++ b/model/end-device-lorawan-mac.cc @@ -501,12 +501,12 @@ EndDeviceLorawanMac::GetNextTransmissionDelay() { // Pointer to the current channel Ptr logicalChannel = *it; - double frequency = logicalChannel->GetFrequency(); + double frequencyMHz = logicalChannel->GetFrequency(); waitingTime = std::min(waitingTime, m_channelHelper->GetWaitingTime(logicalChannel)); NS_LOG_DEBUG("Waiting time before the next transmission in channel with frequency " - << frequency << " is = " << waitingTime.GetSeconds() << "."); + << frequencyMHz << " is = " << waitingTime.GetSeconds() << "."); } waitingTime = GetNextClassTransmissionDelay(waitingTime); @@ -531,9 +531,9 @@ EndDeviceLorawanMac::GetChannelForTx() { // Pointer to the current channel Ptr logicalChannel = *it; - double frequency = logicalChannel->GetFrequency(); + double frequencyMHz = logicalChannel->GetFrequency(); - NS_LOG_DEBUG("Frequency of the current channel: " << frequency); + NS_LOG_DEBUG("Frequency of the current channel: " << frequencyMHz); // Verify that we can send the packet Time waitingTime = m_channelHelper->GetWaitingTime(logicalChannel); @@ -865,7 +865,7 @@ EndDeviceLorawanMac::OnDevStatusReq() void EndDeviceLorawanMac::OnNewChannelReq(uint8_t chIndex, - double frequency, + double frequencyHz, uint8_t minDataRate, uint8_t maxDataRate) { @@ -877,18 +877,18 @@ EndDeviceLorawanMac::OnNewChannelReq(uint8_t chIndex, // TODO Return false if one of the checks above failed // TODO Create new channel in the LogicalLoraChannelHelper - SetLogicalChannel(chIndex, frequency, minDataRate, maxDataRate); + SetLogicalChannel(chIndex, frequencyHz, minDataRate, maxDataRate); NS_LOG_INFO("Adding NewChannelAns reply"); m_macCommandList.emplace_back(Create(dataRateRangeOk, channelFrequencyOk)); } void -EndDeviceLorawanMac::AddLogicalChannel(double frequency) +EndDeviceLorawanMac::AddLogicalChannel(double frequencyMHz) { - NS_LOG_FUNCTION(this << frequency); + NS_LOG_FUNCTION(this << frequencyMHz); - m_channelHelper->AddChannel(frequency); + m_channelHelper->AddChannel(frequencyMHz); } void @@ -901,27 +901,27 @@ EndDeviceLorawanMac::AddLogicalChannel(Ptr logicalChannel) void EndDeviceLorawanMac::SetLogicalChannel(uint8_t chIndex, - double frequency, + double frequencyMHz, uint8_t minDataRate, uint8_t maxDataRate) { - NS_LOG_FUNCTION(this << unsigned(chIndex) << frequency << unsigned(minDataRate) + NS_LOG_FUNCTION(this << unsigned(chIndex) << frequencyMHz << unsigned(minDataRate) << unsigned(maxDataRate)); m_channelHelper->SetChannel( chIndex, - CreateObject(frequency, minDataRate, maxDataRate)); + CreateObject(frequencyMHz, minDataRate, maxDataRate)); } void -EndDeviceLorawanMac::AddSubBand(double startFrequency, - double endFrequency, +EndDeviceLorawanMac::AddSubBand(double startFrequencyMHz, + double endFrequencyMHz, double dutyCycle, double maxTxPowerDbm) { NS_LOG_FUNCTION_NOARGS(); - m_channelHelper->AddSubBand(startFrequency, endFrequency, dutyCycle, maxTxPowerDbm); + m_channelHelper->AddSubBand(startFrequencyMHz, endFrequencyMHz, dutyCycle, maxTxPowerDbm); } uint8_t diff --git a/model/end-device-lorawan-mac.h b/model/end-device-lorawan-mac.h index 4a07f97285..a3a363db48 100644 --- a/model/end-device-lorawan-mac.h +++ b/model/end-device-lorawan-mac.h @@ -290,9 +290,11 @@ class EndDeviceLorawanMac : public LorawanMac * * \param rx1DrOffset The first reception window data rate offset to set. * \param rx2DataRate The data rate to use for the second receive window. - * \param frequency The frequency [Hz] to use for the second receive window. + * \param frequencyHz The frequency [Hz] to use for the second receive window. */ - virtual void OnRxParamSetupReq(uint8_t rx1DrOffset, uint8_t rx2DataRate, double frequency) = 0; + virtual void OnRxParamSetupReq(uint8_t rx1DrOffset, + uint8_t rx2DataRate, + double frequencyHz) = 0; /** * Perform the actions that need to be taken when receiving a DevStatusReq command. @@ -303,12 +305,12 @@ class EndDeviceLorawanMac : public LorawanMac * Perform the actions that need to be taken when receiving a NewChannelReq command. * * \param chIndex The ChIndex field of the received NewChannelReq command. - * \param frequency The Frequency field of the received NewChannelReq command. + * \param frequencyHz The Frequency [Hz] field of the received NewChannelReq command. * \param minDataRate The MinDR field of the received NewChannelReq command. * \param maxDataRate The MaxDR field of the received NewChannelReq command. */ void OnNewChannelReq(uint8_t chIndex, - double frequency, + double frequencyHz, uint8_t minDataRate, uint8_t maxDataRate); @@ -319,20 +321,20 @@ class EndDeviceLorawanMac : public LorawanMac /** * Add a logical channel to the helper. * - * \param frequency The channel's center frequency. + * \param frequencyMHz The channel's center frequency [MHz]. */ - void AddLogicalChannel(double frequency); + void AddLogicalChannel(double frequencyMHz); /** * Set a new logical channel in the helper. * * \param chIndex The channel's new index. - * \param frequency The channel's center frequency. + * \param frequencyMHz The channel's center frequency [MHz]. * \param minDataRate The minimum data rate allowed on the channel. * \param maxDataRate The maximum data rate allowed on the channel. */ void SetLogicalChannel(uint8_t chIndex, - double frequency, + double frequencyMHz, uint8_t minDataRate, uint8_t maxDataRate); @@ -346,13 +348,13 @@ class EndDeviceLorawanMac : public LorawanMac /** * Add a subband to the logical channel helper. * - * \param startFrequency The SubBand's lowest frequency. - * \param endFrequency The SubBand's highest frequency. + * \param startFrequencyMHz The SubBand's lowest frequency [MHz]. + * \param endFrequencyMHz The SubBand's highest frequency [MHz]. * \param dutyCycle The SubBand's duty cycle, in fraction form. * \param maxTxPowerDbm The maximum transmission power allowed on the SubBand. */ - void AddSubBand(double startFrequency, - double endFrequency, + void AddSubBand(double startFrequencyMHz, + double endFrequencyMHz, double dutyCycle, double maxTxPowerDbm); diff --git a/model/end-device-status.cc b/model/end-device-status.cc index e0a327e838..a1a4bed1ad 100644 --- a/model/end-device-status.cc +++ b/model/end-device-status.cc @@ -184,10 +184,10 @@ EndDeviceStatus::SetFirstReceiveWindowSpreadingFactor(uint8_t sf) } void -EndDeviceStatus::SetFirstReceiveWindowFrequency(double frequency) +EndDeviceStatus::SetFirstReceiveWindowFrequency(double frequencyMHz) { NS_LOG_FUNCTION_NOARGS(); - m_firstReceiveWindowFrequency = frequency; + m_firstReceiveWindowFrequency = frequencyMHz; } void @@ -198,10 +198,10 @@ EndDeviceStatus::SetSecondReceiveWindowSpreadingFactor(uint8_t sf) } void -EndDeviceStatus::SetSecondReceiveWindowFrequency(double frequency) +EndDeviceStatus::SetSecondReceiveWindowFrequency(double frequencyMHz) { NS_LOG_FUNCTION_NOARGS(); - m_secondReceiveWindowFrequency = frequency; + m_secondReceiveWindowFrequency = frequencyMHz; } void @@ -254,7 +254,7 @@ EndDeviceStatus::InsertReceivedPacket(Ptr receivedPacket, const Ad // Update Information on the received packet ReceivedPacketInfo info; info.sf = tag.GetSpreadingFactor(); - info.frequency = tag.GetFrequency(); + info.frequencyMHz = tag.GetFrequency(); info.packet = receivedPacket; double rcvPower = tag.GetReceivePower(); diff --git a/model/end-device-status.h b/model/end-device-status.h index d7b6f93e02..c5450ddba8 100644 --- a/model/end-device-status.h +++ b/model/end-device-status.h @@ -154,7 +154,7 @@ class EndDeviceStatus : public Object Ptr packet = nullptr; //!< The received packet GatewayList gwList; //!< List of gateways that received this packet uint8_t sf; //!< Spreading factor used to send this packet - double frequency; //!< Carrier frequency [MHz] used to send this packet + double frequencyMHz; //!< Carrier frequency [MHz] used to send this packet }; /** @@ -230,9 +230,9 @@ class EndDeviceStatus : public Object /** * Set the first window frequency of this device. * - * \param frequency The frequency [MHz]. + * \param frequencyMHz The frequency [MHz]. */ - void SetFirstReceiveWindowFrequency(double frequency); + void SetFirstReceiveWindowFrequency(double frequencyMHz); /** * Set the spreading factor this device is using in the second receive window. @@ -244,9 +244,9 @@ class EndDeviceStatus : public Object /** * Set the second window frequency of this device. * - * \param frequency The frequency [MHz]. + * \param frequencyMHz The frequency [MHz]. */ - void SetSecondReceiveWindowFrequency(double frequency); + void SetSecondReceiveWindowFrequency(double frequencyMHz); /** * Set the reply packet mac header. diff --git a/model/gateway-lorawan-mac.cc b/model/gateway-lorawan-mac.cc index 7dae8e43bc..a91fbb3f0c 100644 --- a/model/gateway-lorawan-mac.cc +++ b/model/gateway-lorawan-mac.cc @@ -52,15 +52,15 @@ GatewayLorawanMac::Send(Ptr packet) LoraTag tag; packet->RemovePacketTag(tag); uint8_t dataRate = tag.GetDataRate(); - double frequency = tag.GetFrequency(); + double frequencyMHz = tag.GetFrequency(); NS_LOG_DEBUG("DR: " << unsigned(dataRate)); NS_LOG_DEBUG("SF: " << unsigned(GetSfFromDataRate(dataRate))); NS_LOG_DEBUG("BW: " << GetBandwidthFromDataRate(dataRate)); - NS_LOG_DEBUG("Freq: " << frequency << " MHz"); + NS_LOG_DEBUG("Freq: " << frequencyMHz << " MHz"); packet->AddPacketTag(tag); // Make sure we can transmit this packet - if (m_channelHelper->GetWaitingTime(CreateObject(frequency)) > Time(0)) + if (m_channelHelper->GetWaitingTime(CreateObject(frequencyMHz)) > Time(0)) { // We cannot send now! NS_LOG_WARN("Trying to send a packet but Duty Cycle won't allow it. Aborting."); @@ -83,13 +83,13 @@ GatewayLorawanMac::Send(Ptr packet) // Find the channel with the desired frequency double sendingPower = - m_channelHelper->GetTxPowerForChannel(CreateObject(frequency)); + m_channelHelper->GetTxPowerForChannel(CreateObject(frequencyMHz)); // Add the event to the channelHelper to keep track of duty cycle - m_channelHelper->AddEvent(duration, CreateObject(frequency)); + m_channelHelper->AddEvent(duration, CreateObject(frequencyMHz)); // Send the packet to the PHY layer to send it on the channel - m_phy->Send(packet, params, frequency, sendingPower); + m_phy->Send(packet, params, frequencyMHz, sendingPower); m_sentNewPacket(packet); } @@ -139,11 +139,11 @@ GatewayLorawanMac::TxFinished(Ptr packet) } Time -GatewayLorawanMac::GetWaitingTime(double frequency) +GatewayLorawanMac::GetWaitingTime(double frequencyMHz) { NS_LOG_FUNCTION_NOARGS(); - return m_channelHelper->GetWaitingTime(CreateObject(frequency)); + return m_channelHelper->GetWaitingTime(CreateObject(frequencyMHz)); } } // namespace lorawan } // namespace ns3 diff --git a/model/gateway-lorawan-mac.h b/model/gateway-lorawan-mac.h index 30fcc29d47..936d5bcc90 100644 --- a/model/gateway-lorawan-mac.h +++ b/model/gateway-lorawan-mac.h @@ -56,10 +56,10 @@ class GatewayLorawanMac : public LorawanMac /** * Return the next time at which we will be able to transmit on the specified frequency. * - * \param frequency The frequency value [MHz]. + * \param frequencyMHz The frequency value [MHz]. * \return The next transmission time. */ - Time GetWaitingTime(double frequency); + Time GetWaitingTime(double frequencyMHz); private: protected: diff --git a/model/gateway-status.cc b/model/gateway-status.cc index ebbc69dfae..fafc9df581 100644 --- a/model/gateway-status.cc +++ b/model/gateway-status.cc @@ -81,7 +81,7 @@ GatewayStatus::GetGatewayMac() } bool -GatewayStatus::IsAvailableForTransmission(double frequency) +GatewayStatus::IsAvailableForTransmission(double frequencyMHz) { // We can't send multiple packets at once, see SX1301 V2.01 page 29 @@ -100,7 +100,7 @@ GatewayStatus::IsAvailableForTransmission(double frequency) } // Check that the gateway is not constrained by the duty cycle - Time waitingTime = m_gatewayMac->GetWaitingTime(frequency); + Time waitingTime = m_gatewayMac->GetWaitingTime(frequencyMHz); if (waitingTime > Seconds(0)) { NS_LOG_INFO("Gateway cannot be used because of duty cycle"); diff --git a/model/gateway-status.h b/model/gateway-status.h index fa79d3decb..b8bfb543df 100644 --- a/model/gateway-status.h +++ b/model/gateway-status.h @@ -97,10 +97,11 @@ class GatewayStatus : public Object * Query whether or not this gateway is available for immediate transmission * on this frequency. * - * \param frequency The frequency at which the gateway's availability should be queried. + * \param frequencyMHz The frequency [MHz] at which the gateway's availability should be + * queried. * \return True if the gateway's available, false otherwise. */ - bool IsAvailableForTransmission(double frequency); + bool IsAvailableForTransmission(double frequencyMHz); /** * Set the time of the next scheduled transmission for the gateway. diff --git a/model/logical-lora-channel-helper.cc b/model/logical-lora-channel-helper.cc index a43f87be5e..93c983ee87 100644 --- a/model/logical-lora-channel-helper.cc +++ b/model/logical-lora-channel-helper.cc @@ -85,31 +85,31 @@ LogicalLoraChannelHelper::GetSubBandFromChannel(Ptr channel) } Ptr -LogicalLoraChannelHelper::GetSubBandFromFrequency(double frequency) +LogicalLoraChannelHelper::GetSubBandFromFrequency(double frequencyMHz) { // Get the SubBand this frequency belongs to std::list>::iterator it; for (it = m_subBandList.begin(); it != m_subBandList.end(); it++) { - if ((*it)->BelongsToSubBand(frequency)) + if ((*it)->BelongsToSubBand(frequencyMHz)) { return *it; } } - NS_LOG_ERROR("Requested frequency: " << frequency); + NS_LOG_ERROR("Requested frequency: " << frequencyMHz); NS_ABORT_MSG("Warning: frequency is outside any known SubBand."); return nullptr; // If no SubBand is found, return 0 } void -LogicalLoraChannelHelper::AddChannel(double frequency) +LogicalLoraChannelHelper::AddChannel(double frequencyMHz) { - NS_LOG_FUNCTION(this << frequency); + NS_LOG_FUNCTION(this << frequencyMHz); // Create the new channel and increment the counter - Ptr channel = Create(frequency); + Ptr channel = Create(frequencyMHz); // Add it to the list m_channelList.push_back(channel); @@ -136,14 +136,15 @@ LogicalLoraChannelHelper::SetChannel(uint8_t chIndex, Ptr lo } void -LogicalLoraChannelHelper::AddSubBand(double firstFrequency, - double lastFrequency, +LogicalLoraChannelHelper::AddSubBand(double firstFrequencyMHz, + double lastFrequencyMHz, double dutyCycle, double maxTxPowerDbm) { - NS_LOG_FUNCTION(this << firstFrequency << lastFrequency); + NS_LOG_FUNCTION(this << firstFrequencyMHz << lastFrequencyMHz); - Ptr subBand = Create(firstFrequency, lastFrequency, dutyCycle, maxTxPowerDbm); + Ptr subBand = + Create(firstFrequencyMHz, lastFrequencyMHz, dutyCycle, maxTxPowerDbm); m_subBandList.push_back(subBand); } diff --git a/model/logical-lora-channel-helper.h b/model/logical-lora-channel-helper.h index 25dfbb5444..dfabaa2a74 100644 --- a/model/logical-lora-channel-helper.h +++ b/model/logical-lora-channel-helper.h @@ -96,9 +96,9 @@ class LogicalLoraChannelHelper : public Object /** * Add a new channel to the list. * - * \param frequency The frequency of the channel to create. + * \param frequencyMHz The frequency [MHz] of the channel to create. */ - void AddChannel(double frequency); + void AddChannel(double frequencyMHz); /** * Add a new channel to the list. @@ -118,14 +118,14 @@ class LogicalLoraChannelHelper : public Object /** * Add a new SubBand to this helper. * - * \param firstFrequency The first frequency of the subband, in MHz. - * \param lastFrequency The last frequency of the subband, in MHz. + * \param firstFrequencyMHz The first frequency of the subband, in MHz. + * \param lastFrequencyMHz The last frequency of the subband, in MHz. * \param dutyCycle The duty cycle that needs to be enforced on this subband. * \param maxTxPowerDbm The maximum transmission power [dBm] that can be used. * on this SubBand. */ - void AddSubBand(double firstFrequency, - double lastFrequency, + void AddSubBand(double firstFrequencyMHz, + double lastFrequencyMHz, double dutyCycle, double maxTxPowerDbm); @@ -163,10 +163,10 @@ class LogicalLoraChannelHelper : public Object /** * Get the SubBand a frequency belongs to. * - * \param frequency The frequency we want to check. + * \param frequencyMHz The frequency [MHz] we want to check. * \return The SubBand the frequency belongs to. */ - Ptr GetSubBandFromFrequency(double frequency); + Ptr GetSubBandFromFrequency(double frequencyMHz); /** * Disable the channel at a specified index. diff --git a/model/logical-lora-channel.cc b/model/logical-lora-channel.cc index f0ee4ada46..e20d004c85 100644 --- a/model/logical-lora-channel.cc +++ b/model/logical-lora-channel.cc @@ -28,7 +28,7 @@ LogicalLoraChannel::GetTypeId() } LogicalLoraChannel::LogicalLoraChannel() - : m_frequency(0), + : m_frequencyMHz(0), m_minDataRate(0), m_maxDataRate(5), m_enabledForUplink(true) @@ -41,15 +41,17 @@ LogicalLoraChannel::~LogicalLoraChannel() NS_LOG_FUNCTION(this); } -LogicalLoraChannel::LogicalLoraChannel(double frequency) - : m_frequency(frequency), +LogicalLoraChannel::LogicalLoraChannel(double frequencyMHz) + : m_frequencyMHz(frequencyMHz), m_enabledForUplink(true) { NS_LOG_FUNCTION(this); } -LogicalLoraChannel::LogicalLoraChannel(double frequency, uint8_t minDataRate, uint8_t maxDataRate) - : m_frequency(frequency), +LogicalLoraChannel::LogicalLoraChannel(double frequencyMHz, + uint8_t minDataRate, + uint8_t maxDataRate) + : m_frequencyMHz(frequencyMHz), m_minDataRate(minDataRate), m_maxDataRate(maxDataRate), m_enabledForUplink(true) @@ -60,7 +62,7 @@ LogicalLoraChannel::LogicalLoraChannel(double frequency, uint8_t minDataRate, ui double LogicalLoraChannel::GetFrequency() const { - return m_frequency; + return m_frequencyMHz; } void diff --git a/model/logical-lora-channel.h b/model/logical-lora-channel.h index 6f75e8629d..af3c82bfac 100644 --- a/model/logical-lora-channel.h +++ b/model/logical-lora-channel.h @@ -46,18 +46,18 @@ class LogicalLoraChannel : public Object /** * Construct a new LogicalLoraChannel object initializing the carrier frequency. * - * \param frequency The carrier frequency [MHz]. + * \param frequencyMHz The carrier frequency [MHz]. */ - LogicalLoraChannel(double frequency); + LogicalLoraChannel(double frequencyMHz); /** * Constructor providing initialization of frequency and data rate limits. * - * \param frequency This channel's frequency [MHz]. + * \param frequencyMHz This channel's frequency [MHz]. * \param minDataRate This channel's minimum data rate. * \param maxDataRate This channel's maximum data rate. */ - LogicalLoraChannel(double frequency, uint8_t minDataRate, uint8_t maxDataRate); + LogicalLoraChannel(double frequencyMHz, uint8_t minDataRate, uint8_t maxDataRate); /** * Get the frequency (MHz). @@ -114,7 +114,7 @@ class LogicalLoraChannel : public Object bool IsEnabledForUplink() const; private: - double m_frequency; //!< The central frequency of this channel, in MHz. + double m_frequencyMHz; //!< The central frequency of this channel, in MHz. uint8_t m_minDataRate; //!< The minimum data rate that is allowed on this channel. uint8_t m_maxDataRate; //!< The maximum data rate that is allowed on this channel. bool m_enabledForUplink; //!< Whether this channel can be used for uplink or not. diff --git a/model/lora-frame-header.cc b/model/lora-frame-header.cc index b668ea6aff..449007c9e3 100644 --- a/model/lora-frame-header.cc +++ b/model/lora-frame-header.cc @@ -434,12 +434,13 @@ LoraFrameHeader::AddDutyCycleAns() } void -LoraFrameHeader::AddRxParamSetupReq(uint8_t rx1DrOffset, uint8_t rx2DataRate, double frequency) +LoraFrameHeader::AddRxParamSetupReq(uint8_t rx1DrOffset, uint8_t rx2DataRate, double frequencyHz) { - NS_LOG_FUNCTION(this << unsigned(rx1DrOffset) << unsigned(rx2DataRate) << frequency); + NS_LOG_FUNCTION(this << unsigned(rx1DrOffset) << unsigned(rx2DataRate) + << uint32_t(frequencyHz)); // Evaluate whether to eliminate this assert in case new offsets can be defined. NS_ASSERT(0 <= rx1DrOffset && rx1DrOffset <= 5); - auto command = Create(rx1DrOffset, rx2DataRate, frequency); + auto command = Create(rx1DrOffset, rx2DataRate, frequencyHz); m_macCommands.emplace_back(command); m_fOptsLen += command->GetSerializedSize(); } @@ -464,13 +465,13 @@ LoraFrameHeader::AddDevStatusReq() void LoraFrameHeader::AddNewChannelReq(uint8_t chIndex, - double frequency, + double frequencyHz, uint8_t minDataRate, uint8_t maxDataRate) { - NS_LOG_FUNCTION(this << unsigned(chIndex) << frequency << unsigned(minDataRate) + NS_LOG_FUNCTION(this << unsigned(chIndex) << uint32_t(frequencyHz) << unsigned(minDataRate) << unsigned(maxDataRate)); - auto command = Create(chIndex, frequency, minDataRate, maxDataRate); + auto command = Create(chIndex, frequencyHz, minDataRate, maxDataRate); m_macCommands.emplace_back(command); m_fOptsLen += command->GetSerializedSize(); } diff --git a/model/lora-frame-header.h b/model/lora-frame-header.h index 56688a0133..701d2ef92c 100644 --- a/model/lora-frame-header.h +++ b/model/lora-frame-header.h @@ -270,9 +270,9 @@ class LoraFrameHeader : public Header * * \param rx1DrOffset The requested data rate offset for the first receive window. * \param rx2DataRate The requested data rate for the second receive window. - * \param frequency The frequency at which to listen for the second receive window. + * \param frequencyHz The frequency [Hz] at which to listen for the second receive window. */ - void AddRxParamSetupReq(uint8_t rx1DrOffset, uint8_t rx2DataRate, double frequency); + void AddRxParamSetupReq(uint8_t rx1DrOffset, uint8_t rx2DataRate, double frequencyHz); /** * Add a RxParamSetupAns command. @@ -288,12 +288,12 @@ class LoraFrameHeader : public Header * Add a NewChannelReq command with provided fields. * * \param chIndex The ChIndex field. - * \param frequency The Frequency field. + * \param frequencyHz The Frequency field in Hz. * \param minDataRate The MinDR field. * \param maxDataRate The MaxDR field. */ void AddNewChannelReq(uint8_t chIndex, - double frequency, + double frequencyHz, uint8_t minDataRate, uint8_t maxDataRate); diff --git a/model/lora-interference-helper.cc b/model/lora-interference-helper.cc index 647ade1b1a..bb03a5cc1a 100644 --- a/model/lora-interference-helper.cc +++ b/model/lora-interference-helper.cc @@ -263,7 +263,7 @@ LoraInterferenceHelper::IsDestroyedByInterference(PtrGetRxPowerdBm(); uint8_t sf = event->GetSpreadingFactor(); - double frequency = event->GetFrequency(); + double frequencyMHz = event->GetFrequency(); // Handy information about the time frame when the packet was received Time now = Simulator::Now(); @@ -285,7 +285,7 @@ LoraInterferenceHelper::IsDestroyedByInterference(PtrGetFrequency() == frequency) || interferer == event) + if (!(interferer->GetFrequency() == frequencyMHz) || interferer == event) { NS_LOG_DEBUG("Different channel or same event"); it++; diff --git a/model/lora-interference-helper.h b/model/lora-interference-helper.h index 6889a9a765..a050be7e7c 100644 --- a/model/lora-interference-helper.h +++ b/model/lora-interference-helper.h @@ -108,7 +108,7 @@ class LoraInterferenceHelper /** * Get the frequency this event was on. * - * \return The carrier frequency as a double. + * \return The carrier frequency [MHz] as a double. */ double GetFrequency() const; diff --git a/model/lora-phy.h b/model/lora-phy.h index 952d89db30..b56e242f2e 100644 --- a/model/lora-phy.h +++ b/model/lora-phy.h @@ -153,11 +153,11 @@ class LoraPhy : public Object /** * Whether this device is listening on the specified frequency or not. * - * \param frequency The frequency to query. + * \param frequencyMHz The frequency [MHz] to query. * \return True if the device is listening on that frequency, false * otherwise. */ - virtual bool IsOnFrequency(double frequency) = 0; + virtual bool IsOnFrequency(double frequencyMHz) = 0; /** * Set the callback to call upon successful reception of a packet. diff --git a/model/lora-tag.cc b/model/lora-tag.cc index b676b7a8aa..7ab330430d 100644 --- a/model/lora-tag.cc +++ b/model/lora-tag.cc @@ -37,7 +37,7 @@ LoraTag::LoraTag(uint8_t sf, uint8_t destroyedBy) m_destroyedBy(destroyedBy), m_receivePower(0), m_dataRate(0), - m_frequency(0) + m_frequencyMHz(0) { } @@ -60,7 +60,7 @@ LoraTag::Serialize(TagBuffer i) const i.WriteU8(m_destroyedBy); i.WriteDouble(m_receivePower); i.WriteU8(m_dataRate); - i.WriteDouble(m_frequency); + i.WriteDouble(m_frequencyMHz); } void @@ -70,7 +70,7 @@ LoraTag::Deserialize(TagBuffer i) m_destroyedBy = i.ReadU8(); m_receivePower = i.ReadDouble(); m_dataRate = i.ReadU8(); - m_frequency = i.ReadDouble(); + m_frequencyMHz = i.ReadDouble(); } void @@ -116,15 +116,15 @@ LoraTag::SetReceivePower(double receivePower) } void -LoraTag::SetFrequency(double frequency) +LoraTag::SetFrequency(double frequencyMHz) { - m_frequency = frequency; + m_frequencyMHz = frequencyMHz; } double LoraTag::GetFrequency() const { - return m_frequency; + return m_frequencyMHz; } uint8_t diff --git a/model/lora-tag.h b/model/lora-tag.h index d46b5d1e0d..5d6ad9d75b 100644 --- a/model/lora-tag.h +++ b/model/lora-tag.h @@ -98,9 +98,9 @@ class LoraTag : public Tag * - It is used by the network server to signal to the gateway the frequency of a downlink * packet. * - * \param frequency The frequency value [MHz]. + * \param frequencyMHz The frequency value [MHz]. */ - void SetFrequency(double frequency); + void SetFrequency(double frequencyMHz); /** * Get the frequency of the packet. @@ -134,7 +134,7 @@ class LoraTag : public Tag uint8_t m_destroyedBy; //!< The Spreading Factor that destroyed the packet. double m_receivePower; //!< The reception power of this packet. uint8_t m_dataRate; //!< The data rate that needs to be used to send this packet. - double m_frequency; //!< The frequency of this packet + double m_frequencyMHz; //!< The frequency [MHz] of this packet }; } // namespace lorawan } // namespace ns3 diff --git a/model/mac-command.cc b/model/mac-command.cc index 54a74558a6..fa665ee223 100644 --- a/model/mac-command.cc +++ b/model/mac-command.cc @@ -557,12 +557,13 @@ RxParamSetupReq::RxParamSetupReq() m_serializedSize = 5; } -RxParamSetupReq::RxParamSetupReq(uint8_t rx1DrOffset, uint8_t rx2DataRate, double frequency) +RxParamSetupReq::RxParamSetupReq(uint8_t rx1DrOffset, uint8_t rx2DataRate, double frequencyHz) : m_rx1DrOffset(rx1DrOffset), m_rx2DataRate(rx2DataRate), - m_frequency(frequency) + m_frequencyHz(frequencyHz) { - NS_LOG_FUNCTION(this << unsigned(rx1DrOffset) << unsigned(rx2DataRate) << frequency); + NS_LOG_FUNCTION(this << unsigned(rx1DrOffset) << unsigned(rx2DataRate) + << uint32_t(frequencyHz)); NS_ASSERT_MSG(!(rx1DrOffset & 0xF8), "rx1DrOffset > 3 bits"); NS_ASSERT_MSG(!(rx2DataRate & 0xF0), "rx2DataRate > 4 bits"); m_commandType = RX_PARAM_SETUP_REQ; @@ -578,7 +579,7 @@ RxParamSetupReq::Serialize(Buffer::Iterator& start) const start.WriteU8(GetCIDFromMacCommand(m_commandType)); // Data serialization start.WriteU8((m_rx1DrOffset & 0b111) << 4 | (m_rx2DataRate & 0b1111)); - uint32_t encodedFrequency = m_frequency / 100; + uint32_t encodedFrequency = m_frequencyHz / 100; NS_LOG_DEBUG(unsigned(encodedFrequency)); NS_LOG_DEBUG(std::bitset<32>(encodedFrequency)); // Frequency is in little endian (lsb -> msb) @@ -604,7 +605,7 @@ RxParamSetupReq::Deserialize(Buffer::Iterator& start) encodedFrequency += start.ReadU8() << 8; // Middle byte encodedFrequency += start.ReadU8() << 16; // Most significant byte NS_LOG_DEBUG(std::bitset<32>(encodedFrequency)); - m_frequency = double(encodedFrequency) * 100; + m_frequencyHz = double(encodedFrequency) * 100; return m_serializedSize; } @@ -617,7 +618,7 @@ RxParamSetupReq::Print(std::ostream& os) const os << "RxParamSetupReq("; os << "rx1DrOffset=" << unsigned(m_rx1DrOffset); os << ", rx2DataRate=" << unsigned(m_rx2DataRate); - os << ", frequency=" << m_frequency; + os << ", frequency=" << m_frequencyHz; os << ")"; } @@ -642,7 +643,7 @@ RxParamSetupReq::GetFrequency() { NS_LOG_FUNCTION(this); - return m_frequency; + return m_frequencyHz; } ///////////////////// @@ -853,11 +854,11 @@ NewChannelReq::NewChannelReq() } NewChannelReq::NewChannelReq(uint8_t chIndex, - double frequency, + double frequencyHz, uint8_t minDataRate, uint8_t maxDataRate) : m_chIndex(chIndex), - m_frequency(frequency), + m_frequencyHz(frequencyHz), m_minDataRate(minDataRate), m_maxDataRate(maxDataRate) { @@ -876,7 +877,7 @@ NewChannelReq::Serialize(Buffer::Iterator& start) const start.WriteU8(GetCIDFromMacCommand(m_commandType)); start.WriteU8(m_chIndex); - uint32_t encodedFrequency = m_frequency / 100; + uint32_t encodedFrequency = m_frequencyHz / 100; // Frequency is in little endian (lsb -> msb) start.WriteU8(encodedFrequency & 0xff); // Least significant byte start.WriteU8((encodedFrequency & 0xff00) >> 8); // Middle byte @@ -898,7 +899,7 @@ NewChannelReq::Deserialize(Buffer::Iterator& start) encodedFrequency += start.ReadU8(); // Least significant byte encodedFrequency += start.ReadU8() << 8; // Middle byte encodedFrequency += start.ReadU8() << 16; // Most significant byte - m_frequency = double(encodedFrequency) * 100; + m_frequencyHz = double(encodedFrequency) * 100; uint8_t dataRateByte = start.ReadU8(); m_maxDataRate = dataRateByte >> 4; m_minDataRate = dataRateByte & 0xf; @@ -927,7 +928,7 @@ NewChannelReq::GetFrequency() const { NS_LOG_FUNCTION_NOARGS(); - return m_frequency; + return m_frequencyHz; } uint8_t diff --git a/model/mac-command.h b/model/mac-command.h index 29e8004ac0..200e54b905 100644 --- a/model/mac-command.h +++ b/model/mac-command.h @@ -415,9 +415,9 @@ class RxParamSetupReq : public MacCommand * * \param rx1DrOffset The data rate offset to use for the first receive window. * \param rx2DataRate The data rate to use for the second receive window. - * \param frequency The frequency in Hz to use for the second receive window. + * \param frequencyHz The frequency in Hz to use for the second receive window. */ - RxParamSetupReq(uint8_t rx1DrOffset, uint8_t rx2DataRate, double frequency); + RxParamSetupReq(uint8_t rx1DrOffset, uint8_t rx2DataRate, double frequencyHz); void Serialize(Buffer::Iterator& start) const override; uint8_t Deserialize(Buffer::Iterator& start) override; @@ -447,7 +447,7 @@ class RxParamSetupReq : public MacCommand private: uint8_t m_rx1DrOffset; //!< The RX1DROffset field uint8_t m_rx2DataRate; //!< The RX2DataRate field - double m_frequency; //!< The Frequency field, _in Hz_ + double m_frequencyHz; //!< The Frequency field, _in Hz_ }; /** @@ -576,11 +576,11 @@ class NewChannelReq : public MacCommand * Constructor providing initialization of all parameters. * * \param chIndex The index of the channel this command wants to operate on. - * \param frequency The new frequency for this channel in Hz. + * \param frequencyHz The new frequency for this channel in Hz. * \param minDataRate The minimum data rate allowed on this channel. * \param maxDataRate The maximum data rate allowed on this channel. */ - NewChannelReq(uint8_t chIndex, double frequency, uint8_t minDataRate, uint8_t maxDataRate); + NewChannelReq(uint8_t chIndex, double frequencyHz, uint8_t minDataRate, uint8_t maxDataRate); void Serialize(Buffer::Iterator& start) const override; uint8_t Deserialize(Buffer::Iterator& start) override; @@ -613,7 +613,7 @@ class NewChannelReq : public MacCommand private: uint8_t m_chIndex; //!< The ChIndex field - double m_frequency; //!< The Frequency field, in Hz + double m_frequencyHz; //!< The Frequency field, in Hz uint8_t m_minDataRate; //!< The MinDR field uint8_t m_maxDataRate; //!< The MaxDR field }; diff --git a/model/simple-end-device-lora-phy.cc b/model/simple-end-device-lora-phy.cc index c19ad15ec4..6f452115cc 100644 --- a/model/simple-end-device-lora-phy.cc +++ b/model/simple-end-device-lora-phy.cc @@ -150,7 +150,7 @@ SimpleEndDeviceLoraPhy::StartReceive(Ptr packet, if (!IsOnFrequency(frequencyMHz)) { NS_LOG_INFO("Packet lost because it's on frequency " - << frequencyMHz << " MHz and we are listening at " << m_frequency + << frequencyMHz << " MHz and we are listening at " << m_frequencyMHz << " MHz"); // Fire the trace source for this event. diff --git a/model/sub-band.cc b/model/sub-band.cc index 7602c4a6ad..606e01d834 100644 --- a/model/sub-band.cc +++ b/model/sub-band.cc @@ -31,17 +31,17 @@ SubBand::SubBand() NS_LOG_FUNCTION(this); } -SubBand::SubBand(double firstFrequency, - double lastFrequency, +SubBand::SubBand(double firstFrequencyMHz, + double lastFrequencyMHz, double dutyCycle, double maxTxPowerDbm) - : m_firstFrequency(firstFrequency), - m_lastFrequency(lastFrequency), + : m_firstFrequencyMHz(firstFrequencyMHz), + m_lastFrequencyMHz(lastFrequencyMHz), m_dutyCycle(dutyCycle), m_nextTransmissionTime(Seconds(0)), m_maxTxPowerDbm(maxTxPowerDbm) { - NS_LOG_FUNCTION(this << firstFrequency << lastFrequency << dutyCycle << maxTxPowerDbm); + NS_LOG_FUNCTION(this << firstFrequencyMHz << lastFrequencyMHz << dutyCycle << maxTxPowerDbm); } SubBand::~SubBand() @@ -52,7 +52,7 @@ SubBand::~SubBand() double SubBand::GetFirstFrequency() const { - return m_firstFrequency; + return m_firstFrequencyMHz; } double @@ -62,16 +62,16 @@ SubBand::GetDutyCycle() const } bool -SubBand::BelongsToSubBand(double frequency) const +SubBand::BelongsToSubBand(double frequencyMHz) const { - return (frequency > m_firstFrequency) && (frequency < m_lastFrequency); + return (frequencyMHz > m_firstFrequencyMHz) && (frequencyMHz < m_lastFrequencyMHz); } bool SubBand::BelongsToSubBand(Ptr logicalChannel) const { - double frequency = logicalChannel->GetFrequency(); - return BelongsToSubBand(frequency); + double frequencyMHz = logicalChannel->GetFrequency(); + return BelongsToSubBand(frequencyMHz); } void diff --git a/model/sub-band.h b/model/sub-band.h index 02512101ba..ea9b171767 100644 --- a/model/sub-band.h +++ b/model/sub-band.h @@ -42,12 +42,15 @@ class SubBand : public Object /** * Create a new SubBand by specifying all of its properties. * - * \param firstFrequency The SubBand's lowest frequency [MHz]. - * \param lastFrequency The SubBand's highest frequency [MHz]. + * \param firstFrequencyMHz The SubBand's lowest frequency [MHz]. + * \param lastFrequencyMHz The SubBand's highest frequency [MHz]. * \param dutyCycle The duty cycle (as a fraction) allowed on this SubBand. * \param maxTxPowerDbm The maximum transmission power [dBm] allowed on this SubBand. */ - SubBand(double firstFrequency, double lastFrequency, double dutyCycle, double maxTxPowerDbm); + SubBand(double firstFrequencyMHz, + double lastFrequencyMHz, + double dutyCycle, + double maxTxPowerDbm); /** * Get the lowest frequency of the SubBand. @@ -94,11 +97,11 @@ class SubBand : public Object /** * Return whether or not a frequency belongs to this SubBand. * - * \param frequency The frequency [MHz] we want to test against the current subband. + * \param frequencyMHz The frequency [MHz] we want to test against the current subband. * \return True if the frequency is between firstFrequency and lastFrequency, * false otherwise. */ - bool BelongsToSubBand(double frequency) const; + bool BelongsToSubBand(double frequencyMHz) const; /** * Return whether or not a channel belongs to this SubBand. @@ -124,8 +127,8 @@ class SubBand : public Object double GetMaxTxPowerDbm() const; private: - double m_firstFrequency; //!< Starting frequency of the subband, in MHz - double m_lastFrequency; //!< Ending frequency of the subband, in MHz + double m_firstFrequencyMHz; //!< Starting frequency of the subband, in MHz + double m_lastFrequencyMHz; //!< Ending frequency of the subband, in MHz double m_dutyCycle; //!< The duty cycle that needs to be enforced on this subband Time m_nextTransmissionTime; //!< The next time a transmission will be allowed in this subband double m_maxTxPowerDbm; //!< The maximum transmission power that is admitted on this subband diff --git a/test/lorawan-test-suite.cc b/test/lorawan-test-suite.cc index cb34107fb4..75c171e248 100644 --- a/test/lorawan-test-suite.cc +++ b/test/lorawan-test-suite.cc @@ -59,36 +59,36 @@ InterferenceTest::DoRun() LoraInterferenceHelper interferenceHelper; - double frequency = 868.1; - double differentFrequency = 868.3; + double frequencyMHz = 868.1; + double differentFrequencyMHz = 868.3; Ptr event; Ptr event1; // Test overlap duration - event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequency); - event1 = interferenceHelper.Add(Seconds(1), 14, 12, nullptr, frequency); + event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequencyMHz); + event1 = interferenceHelper.Add(Seconds(1), 14, 12, nullptr, frequencyMHz); NS_TEST_EXPECT_MSG_EQ(interferenceHelper.GetOverlapTime(event, event1), Seconds(1), "Overlap computation didn't give the expected result"); interferenceHelper.ClearAllEvents(); - event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequency); - event1 = interferenceHelper.Add(Seconds(1.5), 14, 12, nullptr, frequency); + event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequencyMHz); + event1 = interferenceHelper.Add(Seconds(1.5), 14, 12, nullptr, frequencyMHz); NS_TEST_EXPECT_MSG_EQ(interferenceHelper.GetOverlapTime(event, event1), Seconds(1.5), "Overlap computation didn't give the expected result"); interferenceHelper.ClearAllEvents(); - event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequency); - event1 = interferenceHelper.Add(Seconds(3), 14, 12, nullptr, frequency); + event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequencyMHz); + event1 = interferenceHelper.Add(Seconds(3), 14, 12, nullptr, frequencyMHz); NS_TEST_EXPECT_MSG_EQ(interferenceHelper.GetOverlapTime(event, event1), Seconds(2), "Overlap computation didn't give the expected result"); interferenceHelper.ClearAllEvents(); - event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequency); - event1 = interferenceHelper.Add(Seconds(2), 14, 12, nullptr, frequency); + event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequencyMHz); + event1 = interferenceHelper.Add(Seconds(2), 14, 12, nullptr, frequencyMHz); // Because of some strange behavior, this test would get stuck if we used the same syntax of the // previous ones. This works instead. bool retval = interferenceHelper.GetOverlapTime(event, event1) == Seconds(2); @@ -96,32 +96,32 @@ InterferenceTest::DoRun() interferenceHelper.ClearAllEvents(); // Perfect overlap, packet survives - event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequency); - interferenceHelper.Add(Seconds(2), 14, 12, nullptr, frequency); + event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequencyMHz); + interferenceHelper.Add(Seconds(2), 14, 12, nullptr, frequencyMHz); NS_TEST_EXPECT_MSG_EQ(interferenceHelper.IsDestroyedByInterference(event), 0, "Packet did not survive interference as expected"); interferenceHelper.ClearAllEvents(); // Perfect overlap, packet survives - event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequency); - interferenceHelper.Add(Seconds(2), 14 - 7, 7, nullptr, frequency); + event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequencyMHz); + interferenceHelper.Add(Seconds(2), 14 - 7, 7, nullptr, frequencyMHz); NS_TEST_EXPECT_MSG_EQ(interferenceHelper.IsDestroyedByInterference(event), 0, "Packet did not survive interference as expected"); interferenceHelper.ClearAllEvents(); // Perfect overlap, packet destroyed - event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequency); - interferenceHelper.Add(Seconds(2), 14 - 6, 7, nullptr, frequency); + event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequencyMHz); + interferenceHelper.Add(Seconds(2), 14 - 6, 7, nullptr, frequencyMHz); NS_TEST_EXPECT_MSG_EQ(interferenceHelper.IsDestroyedByInterference(event), 7, "Packet was not destroyed by interference as expected"); interferenceHelper.ClearAllEvents(); // Partial overlap, packet survives - event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequency); - interferenceHelper.Add(Seconds(1), 14 - 6, 7, nullptr, frequency); + event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequencyMHz); + interferenceHelper.Add(Seconds(1), 14 - 6, 7, nullptr, frequencyMHz); NS_TEST_EXPECT_MSG_EQ(interferenceHelper.IsDestroyedByInterference(event), 0, "Packet did not survive interference as expected"); @@ -130,8 +130,8 @@ InterferenceTest::DoRun() // Different frequencys // Packet would be destroyed if they were on the same frequency, but survives // since they are on different frequencies - event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequency); - interferenceHelper.Add(Seconds(2), 14, 7, nullptr, differentFrequency); + event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequencyMHz); + interferenceHelper.Add(Seconds(2), 14, 7, nullptr, differentFrequencyMHz); NS_TEST_EXPECT_MSG_EQ(interferenceHelper.IsDestroyedByInterference(event), 0, "Packet did not survive interference as expected"); @@ -140,8 +140,8 @@ InterferenceTest::DoRun() // Different SFs // Packet would be destroyed if they both were SF7, but survives thanks to spreading factor // semi-orthogonality - event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequency); - interferenceHelper.Add(Seconds(2), 14 + 16, 8, nullptr, frequency); + event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequencyMHz); + interferenceHelper.Add(Seconds(2), 14 + 16, 8, nullptr, frequencyMHz); NS_TEST_EXPECT_MSG_EQ(interferenceHelper.IsDestroyedByInterference(event), 0, "Packet did not survive interference as expected"); @@ -149,16 +149,16 @@ InterferenceTest::DoRun() // Spreading factor imperfect orthogonality // Different SFs are orthogonal only up to a point - event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequency); - interferenceHelper.Add(Seconds(2), 14 + 17, 8, nullptr, frequency); + event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequencyMHz); + interferenceHelper.Add(Seconds(2), 14 + 17, 8, nullptr, frequencyMHz); NS_TEST_EXPECT_MSG_EQ(interferenceHelper.IsDestroyedByInterference(event), 8, "Packet was not destroyed by interference as expected"); interferenceHelper.ClearAllEvents(); // If a more 'distant' spreading factor is used, isolation gets better - event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequency); - interferenceHelper.Add(Seconds(2), 14 + 17, 10, nullptr, frequency); + event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequencyMHz); + interferenceHelper.Add(Seconds(2), 14 + 17, 10, nullptr, frequencyMHz); NS_TEST_EXPECT_MSG_EQ(interferenceHelper.IsDestroyedByInterference(event), 0, "Packet was destroyed by interference while it should have survived"); @@ -166,10 +166,10 @@ InterferenceTest::DoRun() // Cumulative interference // Same spreading factor interference is cumulative - event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequency); - interferenceHelper.Add(Seconds(2), 14 + 16, 8, nullptr, frequency); - interferenceHelper.Add(Seconds(2), 14 + 16, 8, nullptr, frequency); - interferenceHelper.Add(Seconds(2), 14 + 16, 8, nullptr, frequency); + event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequencyMHz); + interferenceHelper.Add(Seconds(2), 14 + 16, 8, nullptr, frequencyMHz); + interferenceHelper.Add(Seconds(2), 14 + 16, 8, nullptr, frequencyMHz); + interferenceHelper.Add(Seconds(2), 14 + 16, 8, nullptr, frequencyMHz); NS_TEST_EXPECT_MSG_EQ(interferenceHelper.IsDestroyedByInterference(event), 8, "Packet was not destroyed by interference as expected"); @@ -177,10 +177,10 @@ InterferenceTest::DoRun() // Cumulative interference // Interference is not cumulative between different SFs - event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequency); - interferenceHelper.Add(Seconds(2), 14 + 16, 8, nullptr, frequency); - interferenceHelper.Add(Seconds(2), 14 + 16, 9, nullptr, frequency); - interferenceHelper.Add(Seconds(2), 14 + 16, 10, nullptr, frequency); + event = interferenceHelper.Add(Seconds(2), 14, 7, nullptr, frequencyMHz); + interferenceHelper.Add(Seconds(2), 14 + 16, 8, nullptr, frequencyMHz); + interferenceHelper.Add(Seconds(2), 14 + 16, 9, nullptr, frequencyMHz); + interferenceHelper.Add(Seconds(2), 14 + 16, 10, nullptr, frequencyMHz); NS_TEST_EXPECT_MSG_EQ(interferenceHelper.IsDestroyedByInterference(event), 0, "Packet did not survive interference as expected"); From f5bdabc8567f778d882af52d7baf42f5f44a094c Mon Sep 17 00:00:00 2001 From: Alessandro Aimi Date: Wed, 13 Nov 2024 15:04:05 +0100 Subject: [PATCH 20/34] Isolate unit test scope, add LinkAdrAns/RxParamSetupAns creation printing, clarify margin code --- model/class-a-end-device-lorawan-mac.cc | 1 + model/end-device-lorawan-mac.cc | 12 +- test/lorawan-test-suite.cc | 320 +++++++++++++----------- 3 files changed, 178 insertions(+), 155 deletions(-) diff --git a/model/class-a-end-device-lorawan-mac.cc b/model/class-a-end-device-lorawan-mac.cc index 47d5e460f5..4cb9c18f12 100644 --- a/model/class-a-end-device-lorawan-mac.cc +++ b/model/class-a-end-device-lorawan-mac.cc @@ -567,6 +567,7 @@ ClassAEndDeviceLorawanMac::OnRxParamSetupReq(uint8_t rx1DrOffset, m_secondReceiveWindowFrequencyMHz = frequencyHz / 1e6; } + NS_LOG_INFO("Adding RxParamSetupAns reply"); m_macCommandList.emplace_back( Create(rx1DrOffsetAck, rx2DataRateAck, channelAck)); } diff --git a/model/end-device-lorawan-mac.cc b/model/end-device-lorawan-mac.cc index a9ed6aca56..9be53f3217 100644 --- a/model/end-device-lorawan-mac.cc +++ b/model/end-device-lorawan-mac.cc @@ -819,8 +819,7 @@ EndDeviceLorawanMac::OnLinkAdrReq(uint8_t dataRate, } } - // Craft a LinkAdrAns MAC command as a response - /////////////////////////////////////////////// + NS_LOG_INFO("Adding LinkAdrAns reply"); m_macCommandList.emplace_back(Create(powerAck, dataRateAck, channelMaskAck)); } @@ -853,12 +852,13 @@ EndDeviceLorawanMac::OnDevStatusReq() battery = 0; // external power source } - int8_t snr = (m_lastRxSnr < 0) ? m_lastRxSnr - .5 : m_lastRxSnr + .5; - snr = (snr > 31) ? 31 : snr; - snr = (snr < -32) ? -32 : snr; + // approximate to nearest integer + double snr = round(m_lastRxSnr); + // clamp value to boundaries + snr = snr < -32 ? -32 : snr > 31 ? 31 : snr; + // cast to 6-bit signed int and store in uint8_t uint8_t margin = std::bitset<6>(snr).to_ulong(); - // Craft a RxParamSetupAns as response NS_LOG_INFO("Adding DevStatusAns reply"); m_macCommandList.emplace_back(Create(battery, margin)); } diff --git a/test/lorawan-test-suite.cc b/test/lorawan-test-suite.cc index 75c171e248..37cf0ae3ad 100644 --- a/test/lorawan-test-suite.cc +++ b/test/lorawan-test-suite.cc @@ -1704,184 +1704,206 @@ MacCommandTest::DoRun() Reset(); // LinkCheckAns: get connectivity metrics of last uplink LinkCheckReq command - uint8_t margin = 20; // best reception margin [dB] from demodulation floor - uint8_t gwCnt = 3; // number of gateways that received last uplink - auto answers = RunMacCommand(margin, gwCnt); - NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetLastKnownLinkMarginDb()), - unsigned(margin), - "m_lastKnownMarginDb differs from Margin field of LinkCheckAns"); - NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetLastKnownGatewayCount()), - unsigned(gwCnt), - "m_lastKnownGatewayCount differs GwCnt field of LinkCheckAns"); - NS_TEST_EXPECT_MSG_EQ(answers.size(), - 0, - "Unexpected uplink MAC command answer(s) to LinkCheckAns"); + { + uint8_t margin = 20; // best reception margin [dB] from demodulation floor + uint8_t gwCnt = 3; // number of gateways that received last uplink + auto answers = RunMacCommand(margin, gwCnt); + NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetLastKnownLinkMarginDb()), + unsigned(margin), + "m_lastKnownMarginDb differs from Margin field of LinkCheckAns"); + NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetLastKnownGatewayCount()), + unsigned(gwCnt), + "m_lastKnownGatewayCount differs GwCnt field of LinkCheckAns"); + NS_TEST_EXPECT_MSG_EQ(answers.size(), + 0, + "Unexpected uplink MAC command answer(s) to LinkCheckAns"); + } Reset(); // LinkAdrReq: change data rate, TX power, redundancy, or channel mask - uint8_t dataRate = 5; - uint8_t txPower = 2; - uint16_t chMask = 0b101; - uint8_t chMaskCntl = 0; - uint8_t nbTrans = 13; - answers = RunMacCommand(dataRate, txPower, chMask, chMaskCntl, nbTrans); - NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetDataRate()), - unsigned(dataRate), - "m_dataRate does not match DataRate field of LinkAdrReq"); - NS_TEST_EXPECT_MSG_EQ(m_mac->GetTransmissionPowerDbm(), - 10, - "m_txPowerDbm does not match txPower field of LinkAdrReq"); - NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetMaxNumberOfTransmissions()), - 13, - "m_nbTrans does not match nbTrans field of LinkAdrReq"); - auto channels = m_mac->GetLogicalLoraChannelHelper()->GetChannelList(); - for (size_t i = 0; i < channels.size() && i < 16; i++) { - bool actual = channels.at(i + 16 * chMaskCntl)->IsEnabledForUplink(); - bool expected = (chMask & 0b1 << i); - NS_TEST_EXPECT_MSG_EQ(actual, expected, "Channel " << i << " state does not match chMask"); + uint8_t dataRate = 5; + uint8_t txPower = 2; + uint16_t chMask = 0b101; + uint8_t chMaskCntl = 0; + uint8_t nbTrans = 13; + auto answers = RunMacCommand(dataRate, txPower, chMask, chMaskCntl, nbTrans); + NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetDataRate()), + unsigned(dataRate), + "m_dataRate does not match DataRate field of LinkAdrReq"); + NS_TEST_EXPECT_MSG_EQ(m_mac->GetTransmissionPowerDbm(), + 14 - txPower * 2, + "m_txPowerDbm does not match txPower field of LinkAdrReq"); + NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetMaxNumberOfTransmissions()), + unsigned(nbTrans), + "m_nbTrans does not match nbTrans field of LinkAdrReq"); + auto channels = m_mac->GetLogicalLoraChannelHelper()->GetChannelList(); + for (size_t i = 0; i < channels.size() && i < 16; i++) + { + bool actual = channels.at(i + 16 * chMaskCntl)->IsEnabledForUplink(); + bool expected = (chMask & 0b1 << i); + NS_TEST_EXPECT_MSG_EQ(actual, expected, "Channel " << i << " state != chMask"); + } + NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1"); + auto laa = DynamicCast(answers.at(0)); + NS_TEST_ASSERT_MSG_NE(laa, nullptr, "LinkAdrAns was expected, cmd type cast failed"); + NS_TEST_EXPECT_MSG_EQ(laa->GetChannelMaskAck(), true, "ChannelMaskAck expected to be true"); + NS_TEST_EXPECT_MSG_EQ(laa->GetDataRateAck(), true, "DataRateAck expected to be true"); + NS_TEST_EXPECT_MSG_EQ(laa->GetPowerAck(), true, "PowerAck expected to be true"); } - NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1"); - auto laa = DynamicCast(answers.at(0)); - NS_TEST_ASSERT_MSG_NE(laa, nullptr, "LinkAdrAns was expected, cmd type cast failed"); - NS_TEST_EXPECT_MSG_EQ(laa->GetChannelMaskAck(), true, "ChannelMaskAck expected to be true"); - NS_TEST_EXPECT_MSG_EQ(laa->GetDataRateAck(), true, "DataRateAck expected to be true"); - NS_TEST_EXPECT_MSG_EQ(laa->GetPowerAck(), true, "PowerAck expected to be true"); Reset(); // LinkAdrReq: ADR bit off, only change channel mask - chMask = 0b011; - m_mac->SetUplinkAdrBit(false); - answers = RunMacCommand(dataRate, txPower, chMask, chMaskCntl, nbTrans); - NS_TEST_EXPECT_MSG_NE(unsigned(m_mac->GetDataRate()), - unsigned(dataRate), - "m_dataRate expected to differ from DataRate field of LinkAdrReq"); - NS_TEST_EXPECT_MSG_NE(m_mac->GetTransmissionPowerDbm(), - 10, - "m_txPowerDbm expected to not match txPower field of LinkAdrReq"); - NS_TEST_EXPECT_MSG_NE(unsigned(m_mac->GetMaxNumberOfTransmissions()), - 13, - "m_nbTrans expected to differ from nbTrans field of LinkAdrReq"); - channels = m_mac->GetLogicalLoraChannelHelper()->GetChannelList(); - for (size_t i = 0; i < channels.size() && i < 16; i++) { - bool actual = channels.at(i + 16 * chMaskCntl)->IsEnabledForUplink(); - bool expected = (chMask & 0b1 << i); - NS_TEST_EXPECT_MSG_EQ(actual, expected, "Channel " << i << " state does not match chMask"); + uint8_t dataRate = 5; + uint8_t txPower = 2; + uint16_t chMask = 0b010; + uint8_t chMaskCntl = 0; + uint8_t nbTrans = 13; + m_mac->SetUplinkAdrBit(false); + auto answers = RunMacCommand(dataRate, txPower, chMask, chMaskCntl, nbTrans); + NS_TEST_EXPECT_MSG_NE(unsigned(m_mac->GetDataRate()), + unsigned(dataRate), + "m_dataRate expected to differ from DataRate field of LinkAdrReq"); + NS_TEST_EXPECT_MSG_NE(m_mac->GetTransmissionPowerDbm(), + 14 - txPower * 2, + "m_txPowerDbm expected to not match txPower field of LinkAdrReq"); + NS_TEST_EXPECT_MSG_NE(unsigned(m_mac->GetMaxNumberOfTransmissions()), + unsigned(nbTrans), + "m_nbTrans expected to differ from nbTrans field of LinkAdrReq"); + auto channels = m_mac->GetLogicalLoraChannelHelper()->GetChannelList(); + for (size_t i = 0; i < channels.size() && i < 16; i++) + { + bool actual = channels.at(i + 16 * chMaskCntl)->IsEnabledForUplink(); + bool expected = (chMask & 0b1 << i); + NS_TEST_EXPECT_MSG_EQ(actual, expected, "Channel " << i << " state != chMask"); + } + NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1"); + auto laa = DynamicCast(answers.at(0)); + NS_TEST_ASSERT_MSG_NE(laa, nullptr, "LinkAdrAns was expected, cmd type cast failed"); + NS_TEST_EXPECT_MSG_EQ(laa->GetChannelMaskAck(), true, "ChannelMaskAck expected to be true"); + NS_TEST_EXPECT_MSG_EQ(laa->GetDataRateAck(), false, "DataRateAck expected to be false"); + NS_TEST_EXPECT_MSG_EQ(laa->GetPowerAck(), false, "PowerAck expected to be false"); } - NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1"); - laa = DynamicCast(answers.at(0)); - NS_TEST_ASSERT_MSG_NE(laa, nullptr, "LinkAdrAns was expected, cmd type cast failed"); - NS_TEST_EXPECT_MSG_EQ(laa->GetChannelMaskAck(), true, "ChannelMaskAck expected to be true"); - NS_TEST_EXPECT_MSG_EQ(laa->GetDataRateAck(), false, "DataRateAck expected to be false"); - NS_TEST_EXPECT_MSG_EQ(laa->GetPowerAck(), false, "PowerAck expected to be false"); Reset(); // LinkAdrReq: invalid chMask, data rate and power - // WARNING: default values are manually set here - dataRate = 12; - txPower = 8; - chMask = 0b1100; - answers = RunMacCommand(dataRate, txPower, chMask, chMaskCntl, nbTrans); - NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetDataRate()), - 0, - "m_dataRate expected to be default value"); - NS_TEST_EXPECT_MSG_EQ(m_mac->GetTransmissionPowerDbm(), - 14, - "m_txPowerDbm expected to be default value"); - NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetMaxNumberOfTransmissions()), - 1, - "m_nbTrans expected to be default value"); - channels = m_mac->GetLogicalLoraChannelHelper()->GetChannelList(); - for (size_t i = 0; i < channels.size() && i < 16; i++) - { - bool actual = channels.at(i + 16 * chMaskCntl)->IsEnabledForUplink(); - NS_TEST_EXPECT_MSG_EQ(actual, true, "Channel " << i << " differs from default"); + { // WARNING: default values are manually set here + uint8_t dataRate = 12; + uint8_t txPower = 8; + uint16_t chMask = 0b1100; + uint8_t chMaskCntl = 0; + uint8_t nbTrans = 0; + auto answers = RunMacCommand(dataRate, txPower, chMask, chMaskCntl, nbTrans); + NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetDataRate()), + 0, + "m_dataRate expected to be default value"); + NS_TEST_EXPECT_MSG_EQ(m_mac->GetTransmissionPowerDbm(), + 14, + "m_txPowerDbm expected to be default value"); + NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetMaxNumberOfTransmissions()), + 1, + "m_nbTrans expected to be default value"); + auto channels = m_mac->GetLogicalLoraChannelHelper()->GetChannelList(); + for (size_t i = 0; i < channels.size() && i < 16; i++) + { + bool actual = channels.at(i + 16 * chMaskCntl)->IsEnabledForUplink(); + NS_TEST_EXPECT_MSG_EQ(actual, true, "Channel " << i << " state != default true"); + } + NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1"); + auto laa = DynamicCast(answers.at(0)); + NS_TEST_ASSERT_MSG_NE(laa, nullptr, "LinkAdrAns was expected, cmd type cast failed"); + NS_TEST_EXPECT_MSG_EQ(laa->GetChannelMaskAck(), false, "ChannelMaskAck != false"); + NS_TEST_EXPECT_MSG_EQ(laa->GetDataRateAck(), false, "DataRateAck expected to be false"); + NS_TEST_EXPECT_MSG_EQ(laa->GetPowerAck(), false, "PowerAck expected to be false"); } - NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1"); - laa = DynamicCast(answers.at(0)); - NS_TEST_ASSERT_MSG_NE(laa, nullptr, "LinkAdrAns was expected, cmd type cast failed"); - NS_TEST_EXPECT_MSG_EQ(laa->GetChannelMaskAck(), false, "ChannelMaskAck expected to be false"); - NS_TEST_EXPECT_MSG_EQ(laa->GetDataRateAck(), false, "DataRateAck expected to be false"); - NS_TEST_EXPECT_MSG_EQ(laa->GetPowerAck(), false, "PowerAck expected to be false"); Reset(); // DutyCycleReq: duty cycle to 100% - uint8_t maxDutyCycle = 0; - answers = RunMacCommand(maxDutyCycle); - NS_TEST_EXPECT_MSG_EQ(m_mac->GetAggregatedDutyCycle(), - 1 / std::pow(2, maxDutyCycle), - "m_aggregatedDutyCycle != 1"); - NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1"); - auto dca = DynamicCast(answers.at(0)); - NS_TEST_EXPECT_MSG_NE(dca, nullptr, "DutyCycleAns was expected, cmd type cast failed"); + { + uint8_t maxDutyCycle = 0; + auto answers = RunMacCommand(maxDutyCycle); + NS_TEST_EXPECT_MSG_EQ(m_mac->GetAggregatedDutyCycle(), + 1 / std::pow(2, maxDutyCycle), + "m_aggregatedDutyCycle != 1"); + NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1"); + auto dca = DynamicCast(answers.at(0)); + NS_TEST_EXPECT_MSG_NE(dca, nullptr, "DutyCycleAns was expected, cmd type cast failed"); + } Reset(); // DutyCycleReq: duty cycle to 12.5% - maxDutyCycle = 3; - answers = RunMacCommand(maxDutyCycle); - NS_TEST_EXPECT_MSG_EQ(m_mac->GetAggregatedDutyCycle(), - 1 / std::pow(2, maxDutyCycle), - "m_aggregatedDutyCycle != 1"); - NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1"); - dca = DynamicCast(answers.at(0)); - NS_TEST_EXPECT_MSG_NE(dca, nullptr, "DutyCycleAns was expected, cmd type cast failed"); + { + uint8_t maxDutyCycle = 3; + auto answers = RunMacCommand(maxDutyCycle); + NS_TEST_EXPECT_MSG_EQ(m_mac->GetAggregatedDutyCycle(), + 1 / std::pow(2, maxDutyCycle), + "m_aggregatedDutyCycle != 1"); + NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1"); + auto dca = DynamicCast(answers.at(0)); + NS_TEST_EXPECT_MSG_NE(dca, nullptr, "DutyCycleAns was expected, cmd type cast failed"); + } Reset(); // RxParamSetupReq: set rx1Dr, rx2Dr, frequency - uint8_t rx1DrOffset = 5; - uint8_t rx2DataRate = 5; - double frequency = 863500000; - m_mac->SetDataRate(5); - answers = RunMacCommand(rx1DrOffset, rx2DataRate, frequency); - NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetFirstReceiveWindowDataRate()), - 0, - "Rx1DataRate does not match rx1DrOffset from RxParamSetupReq"); - NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetSecondReceiveWindowDataRate()), - rx2DataRate, - "Rx2DataRate does not match rx2DataRate from RxParamSetupReq"); - NS_TEST_EXPECT_MSG_EQ(m_mac->GetSecondReceiveWindowFrequency(), - frequency / 1e6, - "Rx2 frequency does not match frequency from RxParamSetupReq"); - NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1"); - auto rpsa = DynamicCast(answers.at(0)); - NS_TEST_ASSERT_MSG_NE(rpsa, nullptr, "RxParamSetupAns was expected, cmd type cast failed"); - NS_TEST_EXPECT_MSG_EQ(rpsa->GetRx1DrOffsetAck(), true, "Rx1DrOffsetAck expected to be true"); - NS_TEST_EXPECT_MSG_EQ(rpsa->GetRx2DataRateAck(), true, "Rx2DataRateAck expected to be true"); - NS_TEST_EXPECT_MSG_EQ(rpsa->GetChannelAck(), true, "ChannelAck expected to be true"); + { + uint8_t rx1DrOffset = 5; + uint8_t rx2DataRate = 5; + double frequencyHz = 863500000; + m_mac->SetDataRate(5); + auto answers = RunMacCommand(rx1DrOffset, rx2DataRate, frequencyHz); + NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetFirstReceiveWindowDataRate()), + 5 - rx1DrOffset, + "Rx1DataRate does not match rx1DrOffset from RxParamSetupReq"); + NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetSecondReceiveWindowDataRate()), + rx2DataRate, + "Rx2DataRate does not match rx2DataRate from RxParamSetupReq"); + NS_TEST_EXPECT_MSG_EQ(m_mac->GetSecondReceiveWindowFrequency(), + frequencyHz / 1e6, + "Rx2 frequency does not match frequency from RxParamSetupReq"); + NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1"); + auto rpsa = DynamicCast(answers.at(0)); + NS_TEST_ASSERT_MSG_NE(rpsa, nullptr, "RxParamSetupAns was expected, cmd type cast failed"); + NS_TEST_EXPECT_MSG_EQ(rpsa->GetRx1DrOffsetAck(), true, "Rx1DrOffsetAck != true"); + NS_TEST_EXPECT_MSG_EQ(rpsa->GetRx2DataRateAck(), true, "Rx2DataRateAck != true"); + NS_TEST_EXPECT_MSG_EQ(rpsa->GetChannelAck(), true, "ChannelAck expected to be true"); + } Reset(); // RxParamSetupReq: invalid rx1Dr, rx2Dr, frequency - // WARNING: default values are manually set here - rx1DrOffset = 7; - rx2DataRate = 12; - frequency = 871000000; - m_mac->SetDataRate(5); - answers = RunMacCommand(rx1DrOffset, rx2DataRate, frequency); - NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetFirstReceiveWindowDataRate()), - 5, - "Rx1DataRate expected to be default value"); - NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetSecondReceiveWindowDataRate()), - 0, - "Rx2DataRate expected to be default value"); - NS_TEST_EXPECT_MSG_EQ(m_mac->GetSecondReceiveWindowFrequency(), - 869.525, - "Rx2 frequency expected to be default value"); - NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1"); - rpsa = DynamicCast(answers.at(0)); - NS_TEST_ASSERT_MSG_NE(rpsa, nullptr, "RxParamSetupAns was expected, cmd type cast failed"); - NS_TEST_EXPECT_MSG_EQ(rpsa->GetRx1DrOffsetAck(), false, "Rx1DrOffsetAck expected to be false"); - NS_TEST_EXPECT_MSG_EQ(rpsa->GetRx2DataRateAck(), false, "Rx2DataRateAck expected to be false"); - NS_TEST_EXPECT_MSG_EQ(rpsa->GetChannelAck(), false, "ChannelAck expected to be false"); + { // WARNING: default values are manually set here + uint8_t rx1DrOffset = 7; + uint8_t rx2DataRate = 12; + double frequencyHz = 871000000; + m_mac->SetDataRate(5); + auto answers = RunMacCommand(rx1DrOffset, rx2DataRate, frequencyHz); + NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetFirstReceiveWindowDataRate()), + 5, + "Rx1DataRate expected to be default value"); + NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetSecondReceiveWindowDataRate()), + 0, + "Rx2DataRate expected to be default value"); + NS_TEST_EXPECT_MSG_EQ(m_mac->GetSecondReceiveWindowFrequency(), + 869.525, + "Rx2 frequency expected to be default value"); + NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1"); + auto rpsa = DynamicCast(answers.at(0)); + NS_TEST_ASSERT_MSG_NE(rpsa, nullptr, "RxParamSetupAns was expected, cmd type cast failed"); + NS_TEST_EXPECT_MSG_EQ(rpsa->GetRx1DrOffsetAck(), false, "Rx1DrOffsetAck != false"); + NS_TEST_EXPECT_MSG_EQ(rpsa->GetRx2DataRateAck(), false, "Rx2DataRateAck != false"); + NS_TEST_EXPECT_MSG_EQ(rpsa->GetChannelAck(), false, "ChannelAck expected to be false"); + } Reset(); // DevStatusReq: get default values - answers = RunMacCommand(); - NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1"); - auto dsa = DynamicCast(answers.at(0)); - NS_TEST_ASSERT_MSG_NE(dsa, nullptr, "DevStatusAns was expected, cmd type cast failed"); - NS_TEST_EXPECT_MSG_EQ(unsigned(dsa->GetBattery()), 0, "Battery expected to be 0 (ext power)"); - NS_TEST_EXPECT_MSG_EQ(unsigned(dsa->GetMargin()), 31, "Margin expected to be 31 (default)"); + { // WARNING: default values are manually set here + auto answers = RunMacCommand(); + NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1"); + auto dsa = DynamicCast(answers.at(0)); + NS_TEST_ASSERT_MSG_NE(dsa, nullptr, "DevStatusAns was expected, cmd type cast failed"); + NS_TEST_EXPECT_MSG_EQ(unsigned(dsa->GetBattery()), 0, "Battery != 0 (external power)"); + NS_TEST_EXPECT_MSG_EQ(unsigned(dsa->GetMargin()), 31, "Margin expected to be 31 (default)"); + } } /** From ed4389f8f4be7ea2f87045def3c909beeeaa3598 Mon Sep 17 00:00:00 2001 From: Alessandro Aimi Date: Wed, 13 Nov 2024 17:06:45 +0100 Subject: [PATCH 21/34] Refactor Create to Install in LoraPhyHelper and LorawanMacHelper to avoid name collision with ns3::Create --- helper/lora-helper.cc | 4 ++-- helper/lora-phy-helper.cc | 2 +- helper/lora-phy-helper.h | 2 +- helper/lorawan-mac-helper.cc | 2 +- helper/lorawan-mac-helper.h | 2 +- test/lorawan-test-suite.cc | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/helper/lora-helper.cc b/helper/lora-helper.cc index 96b916fef7..62ebe5c8f7 100644 --- a/helper/lora-helper.cc +++ b/helper/lora-helper.cc @@ -47,7 +47,7 @@ LoraHelper::Install(const LoraPhyHelper& phyHelper, Ptr device = CreateObject(); // Create the PHY - Ptr phy = phyHelper.Create(node, device); + Ptr phy = phyHelper.Install(node, device); NS_ASSERT(phy); device->SetPhy(phy); NS_LOG_DEBUG("Done creating the PHY"); @@ -85,7 +85,7 @@ LoraHelper::Install(const LoraPhyHelper& phyHelper, } // Create the MAC - Ptr mac = macHelper.Create(node, device); + Ptr mac = macHelper.Install(node, device); NS_ASSERT(mac); mac->SetPhy(phy); NS_LOG_DEBUG("Done creating the MAC"); diff --git a/helper/lora-phy-helper.cc b/helper/lora-phy-helper.cc index 51ff87bd3d..86f81514ac 100644 --- a/helper/lora-phy-helper.cc +++ b/helper/lora-phy-helper.cc @@ -60,7 +60,7 @@ LoraPhyHelper::Set(std::string name, const AttributeValue& v) } Ptr -LoraPhyHelper::Create(Ptr node, Ptr device) const +LoraPhyHelper::Install(Ptr node, Ptr device) const { NS_LOG_FUNCTION(this << node->GetId() << device); diff --git a/helper/lora-phy-helper.h b/helper/lora-phy-helper.h index 249f32f5ab..845e9cbd5e 100644 --- a/helper/lora-phy-helper.h +++ b/helper/lora-phy-helper.h @@ -80,7 +80,7 @@ class LoraPhyHelper * \param device The device within which this PHY will be created. * \return A newly-created PHY object. */ - Ptr Create(Ptr node, Ptr device) const; + Ptr Install(Ptr node, Ptr device) const; /** * Set the maximum number of gateway receive paths. diff --git a/helper/lorawan-mac-helper.cc b/helper/lorawan-mac-helper.cc index 523bf04c5f..1fa3227d47 100644 --- a/helper/lorawan-mac-helper.cc +++ b/helper/lorawan-mac-helper.cc @@ -63,7 +63,7 @@ LorawanMacHelper::SetRegion(enum LorawanMacHelper::Regions region) } Ptr -LorawanMacHelper::Create(Ptr node, Ptr device) const +LorawanMacHelper::Install(Ptr node, Ptr device) const { Ptr mac = m_mac.Create(); mac->SetDevice(device); diff --git a/helper/lorawan-mac-helper.h b/helper/lorawan-mac-helper.h index 44e5ac7d9b..9fe88d5e85 100644 --- a/helper/lorawan-mac-helper.h +++ b/helper/lorawan-mac-helper.h @@ -97,7 +97,7 @@ class LorawanMacHelper * \param device The device within which this MAC will be created. * \return A newly-created LorawanMac object. */ - Ptr Create(Ptr node, Ptr device) const; + Ptr Install(Ptr node, Ptr device) const; /** * Initialize the end devices' data rate parameter. diff --git a/test/lorawan-test-suite.cc b/test/lorawan-test-suite.cc index 37cf0ae3ad..76c50f5e38 100644 --- a/test/lorawan-test-suite.cc +++ b/test/lorawan-test-suite.cc @@ -1689,7 +1689,7 @@ MacCommandTest::Reset() macHelper.SetRegion(LorawanMacHelper::EU); macHelper.SetDeviceType(LorawanMacHelper::ED_A); /// \todo Create should not require a node in input. - m_mac = DynamicCast(macHelper.Create(nullptr, nullptr)); + m_mac = DynamicCast(macHelper.Install(nullptr, nullptr)); NS_TEST_EXPECT_MSG_NE(m_mac, nullptr, "Failed to initialize MAC layer object."); auto phy = CreateObject(); phy->SetChannel(CreateObject()); From 76e9f6f8688aecd4406cb93cdc7d2ef420ff9d2b Mon Sep 17 00:00:00 2001 From: Alessandro Aimi Date: Thu, 14 Nov 2024 17:14:47 +0100 Subject: [PATCH 22/34] Evaluate null Ptr in return statements as indicated by the Ptr class documentation --- model/lora-net-device.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/model/lora-net-device.cc b/model/lora-net-device.cc index 44f92794d1..866ed67840 100644 --- a/model/lora-net-device.cc +++ b/model/lora-net-device.cc @@ -188,7 +188,7 @@ LoraNetDevice::IsLinkUp() const { NS_LOG_FUNCTION(this); - return m_phy != nullptr; + return (bool)(m_phy); } void From 4e5ea770f2fbfc6dfbeee6824518c457d0d3bfde Mon Sep 17 00:00:00 2001 From: Alessandro Aimi Date: Sat, 16 Nov 2024 18:59:24 +0100 Subject: [PATCH 23/34] Rework the SubBand class - add missing EU868 radio sub-bands and fix tests - downgrade SubBand from Object to SimpleRefCount - remove unused default constructor/destructor - refactor BelongsToSubBand to Contains for clarity - re-add last frequency getter --- helper/lorawan-mac-helper.cc | 15 ++++++----- model/logical-lora-channel-helper.cc | 2 +- model/sub-band.cc | 34 +++++++---------------- model/sub-band.h | 35 +++++++++--------------- test/lorawan-test-suite.cc | 40 +++++++++++----------------- 5 files changed, 45 insertions(+), 81 deletions(-) diff --git a/helper/lorawan-mac-helper.cc b/helper/lorawan-mac-helper.cc index 1fa3227d47..73b1728c94 100644 --- a/helper/lorawan-mac-helper.cc +++ b/helper/lorawan-mac-helper.cc @@ -201,7 +201,7 @@ LorawanMacHelper::ApplyCommonAlohaConfigurations(Ptr lorawanMac) con ////////////// Ptr channelHelper = CreateObject(); - channelHelper->AddSubBand(868, 868.6, 1, 14); + channelHelper->AddSubBand(Create(868, 868.6, 1, 14)); ////////////////////// // Default channels // @@ -307,9 +307,12 @@ LorawanMacHelper::ApplyCommonEuConfigurations(Ptr lorawanMac) const ////////////// Ptr channelHelper = CreateObject(); - channelHelper->AddSubBand(868, 868.6, 0.01, 14); - channelHelper->AddSubBand(868.7, 869.2, 0.001, 14); - channelHelper->AddSubBand(869.4, 869.65, 0.1, 27); + channelHelper->AddSubBand(Create(863, 865, 0.001, 14)); + channelHelper->AddSubBand(Create(865, 868, 0.01, 14)); + channelHelper->AddSubBand(Create(868, 868.6, 0.01, 14)); + channelHelper->AddSubBand(Create(868.7, 869.2, 0.001, 14)); + channelHelper->AddSubBand(Create(869.4, 869.65, 0.1, 27)); + channelHelper->AddSubBand(Create(869.7, 870, 0.01, 14)); ////////////////////// // Default channels // @@ -419,9 +422,7 @@ LorawanMacHelper::ApplyCommonSingleChannelConfigurations(Ptr lorawan ////////////// Ptr channelHelper = CreateObject(); - channelHelper->AddSubBand(868, 868.6, 0.01, 14); - channelHelper->AddSubBand(868.7, 869.2, 0.001, 14); - channelHelper->AddSubBand(869.4, 869.65, 0.1, 27); + channelHelper->AddSubBand(Create(868, 868.6, 0.01, 14)); ////////////////////// // Default channels // diff --git a/model/logical-lora-channel-helper.cc b/model/logical-lora-channel-helper.cc index 93c983ee87..5f72b3893c 100644 --- a/model/logical-lora-channel-helper.cc +++ b/model/logical-lora-channel-helper.cc @@ -91,7 +91,7 @@ LogicalLoraChannelHelper::GetSubBandFromFrequency(double frequencyMHz) std::list>::iterator it; for (it = m_subBandList.begin(); it != m_subBandList.end(); it++) { - if ((*it)->BelongsToSubBand(frequencyMHz)) + if (sb->Contains(frequencyMHz)) { return *it; } diff --git a/model/sub-band.cc b/model/sub-band.cc index 606e01d834..b997fd929c 100644 --- a/model/sub-band.cc +++ b/model/sub-band.cc @@ -8,8 +8,6 @@ #include "sub-band.h" -#include "ns3/log.h" - namespace ns3 { namespace lorawan @@ -17,20 +15,6 @@ namespace lorawan NS_LOG_COMPONENT_DEFINE("SubBand"); -NS_OBJECT_ENSURE_REGISTERED(SubBand); - -TypeId -SubBand::GetTypeId() -{ - static TypeId tid = TypeId("ns3::SubBand").SetParent().SetGroupName("lorawan"); - return tid; -} - -SubBand::SubBand() -{ - NS_LOG_FUNCTION(this); -} - SubBand::SubBand(double firstFrequencyMHz, double lastFrequencyMHz, double dutyCycle, @@ -38,21 +22,22 @@ SubBand::SubBand(double firstFrequencyMHz, : m_firstFrequencyMHz(firstFrequencyMHz), m_lastFrequencyMHz(lastFrequencyMHz), m_dutyCycle(dutyCycle), - m_nextTransmissionTime(Seconds(0)), + m_nextTransmissionTime(Time(0)), m_maxTxPowerDbm(maxTxPowerDbm) { NS_LOG_FUNCTION(this << firstFrequencyMHz << lastFrequencyMHz << dutyCycle << maxTxPowerDbm); } -SubBand::~SubBand() +double +SubBand::GetFirstFrequency() const { - NS_LOG_FUNCTION(this); + return m_firstFrequencyMHz; } double -SubBand::GetFirstFrequency() const +SubBand::GetLastFrequency() const { - return m_firstFrequencyMHz; + return m_lastFrequencyMHz; } double @@ -62,16 +47,15 @@ SubBand::GetDutyCycle() const } bool -SubBand::BelongsToSubBand(double frequencyMHz) const +SubBand::Contains(double frequencyMHz) const { return (frequencyMHz > m_firstFrequencyMHz) && (frequencyMHz < m_lastFrequencyMHz); } bool -SubBand::BelongsToSubBand(Ptr logicalChannel) const +SubBand::Contains(Ptr logicalChannel) const { - double frequencyMHz = logicalChannel->GetFrequency(); - return BelongsToSubBand(frequencyMHz); + return Contains(logicalChannel->GetFrequency()); } void diff --git a/model/sub-band.h b/model/sub-band.h index ea9b171767..cf2101c493 100644 --- a/model/sub-band.h +++ b/model/sub-band.h @@ -12,33 +12,22 @@ #include "logical-lora-channel.h" #include "ns3/nstime.h" -#include "ns3/object.h" +#include "ns3/simple-ref-count.h" namespace ns3 { namespace lorawan { -class LogicalLoraChannel; - /** * \ingroup lorawan * * Class representing a SubBand, i.e., a frequency band subject to some * regulations on duty cycle and transmission power. */ -class SubBand : public Object +class SubBand : public SimpleRefCount { public: - /** - * Register this type. - * \return The object TypeId. - */ - static TypeId GetTypeId(); - - SubBand(); //!< Default constructor - ~SubBand() override; //!< Destructor - /** * Create a new SubBand by specifying all of its properties. * @@ -59,12 +48,12 @@ class SubBand : public Object */ double GetFirstFrequency() const; - ///** - // * Get the last frequency of the subband. - // * - // * \return The lowest frequency [MHz] of the SubBand. - // */ - // double GetLastFrequency (); + /** + * Get the highest frequency of the SubBand. + * + * \return The highest frequency [MHz] of the SubBand. + */ + double GetLastFrequency() const; /** * Get the duty cycle of the subband. @@ -101,16 +90,16 @@ class SubBand : public Object * \return True if the frequency is between firstFrequency and lastFrequency, * false otherwise. */ - bool BelongsToSubBand(double frequencyMHz) const; + bool Contains(double frequencyMHz) const; /** * Return whether or not a channel belongs to this SubBand. * * \param channel The channel we want to test against the current subband. - * \return True if the channel's center frequency is between firstFrequency - * and lastFrequency, false otherwise. + * \return Whether the channel's center frequency is between the first and last frequency of the + * sub-band, margins excluded. */ - bool BelongsToSubBand(Ptr channel) const; + bool Contains(Ptr channel) const; /** * Set the maximum transmission power that is allowed on this SubBand. diff --git a/test/lorawan-test-suite.cc b/test/lorawan-test-suite.cc index 76c50f5e38..8c91f505e8 100644 --- a/test/lorawan-test-suite.cc +++ b/test/lorawan-test-suite.cc @@ -911,19 +911,19 @@ LogicalLoraChannelTest::DoRun() ////////////////// // Setup - SubBand subBand(868, 868.7, 0.01, 14); + auto subBand = Create(868, 868.6, 0.01, 14); Ptr channel5 = CreateObject(870); - // Test BelongsToSubBand - NS_TEST_EXPECT_MSG_EQ(subBand.BelongsToSubBand(channel3), + // Test Contains + NS_TEST_EXPECT_MSG_EQ(subBand->Contains(channel3), true, - "BelongsToSubBand does not behave as expected"); - NS_TEST_EXPECT_MSG_EQ(subBand.BelongsToSubBand(channel3->GetFrequency()), + "Contains does not behave as expected"); + NS_TEST_EXPECT_MSG_EQ(subBand->Contains(channel3->GetFrequency()), true, - "BelongsToSubBand does not behave as expected"); - NS_TEST_EXPECT_MSG_EQ(subBand.BelongsToSubBand(channel5), + "Contains does not behave as expected"); + NS_TEST_EXPECT_MSG_EQ(subBand->Contains(channel5), false, - "BelongsToSubBand does not behave as expected"); + "Contains does not behave as expected"); /////////////////////////////////// // Test LogicalLoraChannelHelper // @@ -931,26 +931,22 @@ LogicalLoraChannelTest::DoRun() // Setup Ptr channelHelper = CreateObject(); - SubBand subBand1(869, 869.4, 0.1, 27); + auto subBand1 = Create(869.4, 869.65, 0.10, 27); channel1 = CreateObject(868.1); channel2 = CreateObject(868.3); - channel3 = CreateObject(868.5); - channel4 = CreateObject(869.1); - channel5 = CreateObject(869.3); + channel3 = CreateObject(869.525); // Channel diagram // - // Channels 1 2 3 4 5 - // SubBands 868 ----- 0.1% ----- 868.7 869 ----- 1% ----- 869.4 + // Channels 1 2 3 + // SubBands 868 ----- 1% ----- 868.6 869 ----- 10% ----- 869.4 // Add SubBands and LogicalLoraChannels to the helper - channelHelper->AddSubBand(&subBand); - channelHelper->AddSubBand(&subBand1); + channelHelper->AddSubBand(subBand); + channelHelper->AddSubBand(subBand1); channelHelper->AddChannel(channel1); channelHelper->AddChannel(channel2); channelHelper->AddChannel(channel3); - channelHelper->AddChannel(channel4); - channelHelper->AddChannel(channel5); // Duty Cycle tests // (high level duty cycle behavior) @@ -968,15 +964,9 @@ LogicalLoraChannelTest::DoRun() NS_TEST_EXPECT_MSG_EQ(channelHelper->GetWaitingTime(channel2), expectedTimeOff, "Waiting time doesn't behave as expected"); - NS_TEST_EXPECT_MSG_EQ(channelHelper->GetWaitingTime(channel3), - expectedTimeOff, - "Waiting time doesn't behave as expected"); // Other bands are not affected by this transmission - NS_TEST_EXPECT_MSG_EQ(channelHelper->GetWaitingTime(channel4), - Time(0), - "Waiting time affects other subbands"); - NS_TEST_EXPECT_MSG_EQ(channelHelper->GetWaitingTime(channel5), + NS_TEST_EXPECT_MSG_EQ(channelHelper->GetWaitingTime(channel3), Time(0), "Waiting time affects other subbands"); } From 2f15be89bc1332912ecc1b1b83014fb689829fd9 Mon Sep 17 00:00:00 2001 From: Alessandro Aimi Date: Sun, 17 Nov 2024 14:42:21 +0100 Subject: [PATCH 24/34] Rework the LogicalLoraChannel class - downgrade LogicalLoraChannel from Object to SimpleRefCount - remove unused default constructor/destructor and incomplete initializer constructor - remove setters (constructor initialization only) - refactor SetEnabledForUplink to EnableForUplink (align with DisableForUplink) --- helper/lorawan-mac-helper.cc | 10 +++--- model/end-device-lorawan-mac.cc | 9 +++--- model/logical-lora-channel-helper.cc | 2 +- model/logical-lora-channel.cc | 48 +++------------------------- model/logical-lora-channel.h | 43 +++---------------------- test/lorawan-test-suite.cc | 16 +++++----- 6 files changed, 26 insertions(+), 102 deletions(-) diff --git a/helper/lorawan-mac-helper.cc b/helper/lorawan-mac-helper.cc index 73b1728c94..6267ad37b3 100644 --- a/helper/lorawan-mac-helper.cc +++ b/helper/lorawan-mac-helper.cc @@ -206,7 +206,7 @@ LorawanMacHelper::ApplyCommonAlohaConfigurations(Ptr lorawanMac) con ////////////////////// // Default channels // ////////////////////// - Ptr lc1 = CreateObject(868.1, 0, 5); + Ptr lc1 = Create(868.1, 0, 5); channelHelper->AddChannel(lc1); lorawanMac->SetLogicalLoraChannelHelper(channelHelper); @@ -317,9 +317,9 @@ LorawanMacHelper::ApplyCommonEuConfigurations(Ptr lorawanMac) const ////////////////////// // Default channels // ////////////////////// - Ptr lc1 = CreateObject(868.1, 0, 5); - Ptr lc2 = CreateObject(868.3, 0, 5); - Ptr lc3 = CreateObject(868.5, 0, 5); + Ptr lc1 = Create(868.1, 0, 5); + Ptr lc2 = Create(868.3, 0, 5); + Ptr lc3 = Create(868.5, 0, 5); channelHelper->AddChannel(lc1); channelHelper->AddChannel(lc2); channelHelper->AddChannel(lc3); @@ -427,7 +427,7 @@ LorawanMacHelper::ApplyCommonSingleChannelConfigurations(Ptr lorawan ////////////////////// // Default channels // ////////////////////// - Ptr lc1 = CreateObject(868.1, 0, 5); + Ptr lc1 = Create(868.1, 0, 5); channelHelper->AddChannel(lc1); lorawanMac->SetLogicalLoraChannelHelper(channelHelper); diff --git a/model/end-device-lorawan-mac.cc b/model/end-device-lorawan-mac.cc index 9be53f3217..c5aee92732 100644 --- a/model/end-device-lorawan-mac.cc +++ b/model/end-device-lorawan-mac.cc @@ -751,7 +751,7 @@ EndDeviceLorawanMac::OnLinkAdrReq(uint8_t dataRate, { for (size_t i = 0; i < channelList.size(); ++i) { - (chMask & 0b1 << i) ? channelList[i]->SetEnabledForUplink() + (chMask & 0b1 << i) ? channelList[i]->EnableForUplink() : channelList[i]->DisableForUplink(); } dataRateAck = powerAck = false; // only ack channel mask @@ -801,7 +801,7 @@ EndDeviceLorawanMac::OnLinkAdrReq(uint8_t dataRate, { for (size_t i = 0; i < channelList.size(); ++i) { - (chMask & 0b1 << i) ? channelList[i]->SetEnabledForUplink() + (chMask & 0b1 << i) ? channelList[i]->EnableForUplink() : channelList[i]->DisableForUplink(); } if (txPower != 0xF) // If value is 0xF, ignore config. @@ -908,9 +908,8 @@ EndDeviceLorawanMac::SetLogicalChannel(uint8_t chIndex, NS_LOG_FUNCTION(this << unsigned(chIndex) << frequencyMHz << unsigned(minDataRate) << unsigned(maxDataRate)); - m_channelHelper->SetChannel( - chIndex, - CreateObject(frequencyMHz, minDataRate, maxDataRate)); + m_channelHelper->SetChannel(chIndex, + Create(frequencyMHz, minDataRate, maxDataRate)); } void diff --git a/model/logical-lora-channel-helper.cc b/model/logical-lora-channel-helper.cc index 5f72b3893c..4bda6d0229 100644 --- a/model/logical-lora-channel-helper.cc +++ b/model/logical-lora-channel-helper.cc @@ -109,7 +109,7 @@ LogicalLoraChannelHelper::AddChannel(double frequencyMHz) NS_LOG_FUNCTION(this << frequencyMHz); // Create the new channel and increment the counter - Ptr channel = Create(frequencyMHz); + Ptr channel = Create(frequencyMHz, 0, 5); // Add it to the list m_channelList.push_back(channel); diff --git a/model/logical-lora-channel.cc b/model/logical-lora-channel.cc index e20d004c85..f4e9367680 100644 --- a/model/logical-lora-channel.cc +++ b/model/logical-lora-channel.cc @@ -8,6 +8,8 @@ #include "logical-lora-channel.h" +#include "sub-band.h" + #include "ns3/log.h" namespace ns3 @@ -17,37 +19,6 @@ namespace lorawan NS_LOG_COMPONENT_DEFINE("LogicalLoraChannel"); -NS_OBJECT_ENSURE_REGISTERED(LogicalLoraChannel); - -TypeId -LogicalLoraChannel::GetTypeId() -{ - static TypeId tid = - TypeId("ns3::LogicalLoraChannel").SetParent().SetGroupName("lorawan"); - return tid; -} - -LogicalLoraChannel::LogicalLoraChannel() - : m_frequencyMHz(0), - m_minDataRate(0), - m_maxDataRate(5), - m_enabledForUplink(true) -{ - NS_LOG_FUNCTION(this); -} - -LogicalLoraChannel::~LogicalLoraChannel() -{ - NS_LOG_FUNCTION(this); -} - -LogicalLoraChannel::LogicalLoraChannel(double frequencyMHz) - : m_frequencyMHz(frequencyMHz), - m_enabledForUplink(true) -{ - NS_LOG_FUNCTION(this); -} - LogicalLoraChannel::LogicalLoraChannel(double frequencyMHz, uint8_t minDataRate, uint8_t maxDataRate) @@ -65,18 +36,6 @@ LogicalLoraChannel::GetFrequency() const return m_frequencyMHz; } -void -LogicalLoraChannel::SetMinimumDataRate(uint8_t minDataRate) -{ - m_minDataRate = minDataRate; -} - -void -LogicalLoraChannel::SetMaximumDataRate(uint8_t maxDataRate) -{ - m_maxDataRate = maxDataRate; -} - uint8_t LogicalLoraChannel::GetMinimumDataRate() const { @@ -90,7 +49,7 @@ LogicalLoraChannel::GetMaximumDataRate() const } void -LogicalLoraChannel::SetEnabledForUplink() +LogicalLoraChannel::EnableForUplink() { m_enabledForUplink = true; } @@ -125,5 +84,6 @@ operator!=(const Ptr& first, const Ptr& { return !(first == second); } + } // namespace lorawan } // namespace ns3 diff --git a/model/logical-lora-channel.h b/model/logical-lora-channel.h index af3c82bfac..f95cb49c8c 100644 --- a/model/logical-lora-channel.h +++ b/model/logical-lora-channel.h @@ -9,17 +9,14 @@ #ifndef LOGICAL_LORA_CHANNEL_H #define LOGICAL_LORA_CHANNEL_H -#include "sub-band.h" - -#include "ns3/object.h" +#include "ns3/ptr.h" +#include "ns3/simple-ref-count.h" namespace ns3 { namespace lorawan { -class SubBand; - /** * \ingroup lorawan * @@ -31,25 +28,9 @@ class SubBand; * Furthermore, a LogicalLoraChannel can be marked as enabled or disabled for * uplink transmission. */ -class LogicalLoraChannel : public Object +class LogicalLoraChannel : public SimpleRefCount { public: - /** - * Register this type. - * \return The object TypeId. - */ - static TypeId GetTypeId(); - - LogicalLoraChannel(); //!< Default constructor - ~LogicalLoraChannel() override; //!< Destructor - - /** - * Construct a new LogicalLoraChannel object initializing the carrier frequency. - * - * \param frequencyMHz The carrier frequency [MHz]. - */ - LogicalLoraChannel(double frequencyMHz); - /** * Constructor providing initialization of frequency and data rate limits. * @@ -66,22 +47,6 @@ class LogicalLoraChannel : public Object */ double GetFrequency() const; - // void SetFrequency (double frequencyMHz); - - /** - * Set the minimum data rate that is allowed on this channel. - * - * \param minDataRate The minimum data rate value. - */ - void SetMinimumDataRate(uint8_t minDataRate); - - /** - * Set the maximum data rate that is allowed on this channel. - * - * \param maxDataRate The maximum data rate value. - */ - void SetMaximumDataRate(uint8_t maxDataRate); - /** * Get the minimum data rate that is allowed on this channel. * @@ -99,7 +64,7 @@ class LogicalLoraChannel : public Object /** * Set this channel as enabled for uplink. */ - void SetEnabledForUplink(); + void EnableForUplink(); /** * Set this channel as disabled for uplink. diff --git a/test/lorawan-test-suite.cc b/test/lorawan-test-suite.cc index 8c91f505e8..51fd80aa1e 100644 --- a/test/lorawan-test-suite.cc +++ b/test/lorawan-test-suite.cc @@ -895,10 +895,10 @@ LogicalLoraChannelTest::DoRun() ///////////////////////////// // Setup - Ptr channel1 = CreateObject(868); - Ptr channel2 = CreateObject(868); - Ptr channel3 = CreateObject(868.1); - Ptr channel4 = CreateObject(868.001); + Ptr channel1 = Create(868, 0, 5); + Ptr channel2 = Create(868, 0, 5); + Ptr channel3 = Create(868.1, 0, 5); + Ptr channel4 = Create(868.001, 0, 5); // Equality between channels // Test the == and != operators @@ -912,7 +912,7 @@ LogicalLoraChannelTest::DoRun() // Setup auto subBand = Create(868, 868.6, 0.01, 14); - Ptr channel5 = CreateObject(870); + Ptr channel5 = Create(870, 0, 5); // Test Contains NS_TEST_EXPECT_MSG_EQ(subBand->Contains(channel3), @@ -932,9 +932,9 @@ LogicalLoraChannelTest::DoRun() // Setup Ptr channelHelper = CreateObject(); auto subBand1 = Create(869.4, 869.65, 0.10, 27); - channel1 = CreateObject(868.1); - channel2 = CreateObject(868.3); - channel3 = CreateObject(869.525); + channel1 = Create(868.1, 0, 5); + channel2 = Create(868.3, 0, 5); + channel3 = Create(869.525, 0, 5); // Channel diagram // From 62b394281caa2011ca3ef156b7d627b4b79ec09c Mon Sep 17 00:00:00 2001 From: Alessandro Aimi Date: Mon, 18 Nov 2024 09:04:03 +0100 Subject: [PATCH 25/34] LinkCheckAns: Fill margin field with meaningful values --- model/network-controller-components.cc | 30 ++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/model/network-controller-components.cc b/model/network-controller-components.cc index 066f9fe213..0237052324 100644 --- a/model/network-controller-components.cc +++ b/model/network-controller-components.cc @@ -163,12 +163,30 @@ LinkCheckComponent::BeforeSendingReply(Ptr status, { status->m_reply.needsReply = true; - // Get the number of gateways that received the packet and the best - // margin - uint8_t gwCount = status->GetLastReceivedPacketInfo().gwList.size(); - - Ptr replyCommand = Create(); - replyCommand->SetGwCnt(gwCount); + auto info = status->GetLastReceivedPacketInfo(); + + // Adapted from: github.com/chirpstack/chirpstack v4.9.0 + + // Get the best demodulation margin of the most recent LinkCheckReq command + double maxRssi = -1e3; + for (const auto& [_, gwRxData] : info.gwList) + { + if (gwRxData.rxPower > maxRssi) + { + maxRssi = gwRxData.rxPower; + } + } + /// \see ns3::lorawan::AdrComponent::RxPowerToSNR + double maxSnr = maxRssi + 174 - 10 * log10(125000) - 6; + /// \todo make this a global PHY constant, manage unknown sf values + double requiredSnr[] = {-20.0, -17.5, -15.0, -12.5, -10.0, -7.5, -5}; + double diff = maxSnr - requiredSnr[12 - info.sf]; + uint8_t margin = (diff < 0) ? 0 : (diff > 254) ? 254 : diff; + + // Get the number of gateways that received the most recent LinkCheckReq command + uint8_t gwCount = info.gwList.size(); + + auto replyCommand = Create(margin, gwCount); status->m_reply.frameHeader.SetAsDownlink(); status->m_reply.frameHeader.AddCommand(replyCommand); status->m_reply.macHeader.SetMType(LorawanMacHeader::UNCONFIRMED_DATA_DOWN); From 0f49026a567715d2e9d082b51c6f9202f44ea954 Mon Sep 17 00:00:00 2001 From: Alessandro Aimi Date: Mon, 18 Nov 2024 09:10:57 +0100 Subject: [PATCH 26/34] Rework LogicalLoraChannelHelper class - redo the channel storage model to be aligned with LoRaWAN specifications: a fixed size array of channels accessed by index - GetRawChannelArray replaces GetChannelList and GetEnabledChannelList as the only way to get channels: the MAC layer now performs its channel-related tasks (get wait time, get TX channel, change channel mask) outside of this class with just one sweep through of the array - AddChannel becomes just SetChannel at index, in line with the channel storage structure found in the LoRaWAN specifications - Similarly, discard RemoveChannel function: channels can be overwritten in the internal array with SetChannel as in specifications - downgrade LogicalLoraChannelHelper from Object to SimpleRefCount - add size initialization to constructor, remove default constructor - remove aggregated duty-cycle management (already managed by external MAC layer) - FIX duty-cycle next transmission time calculation in AddEvent - add channel validity check - add GetWaitingTime overload by frequency (that's what it is needed to get the wait time, no need to create an ad-hoc channel instance just to retrieve the wait time) - add AddEvent overload by frequency (same reason as above) - add GetTxPowerForChannel overload by frequency (same reason as above) - remove channel addition by frequency, leading to incomplete tx channel creation (i.e. default values) + param duplication. This now mandates explicit external creation of channel instances to then be passed to the helper by pointer - remove AddSubBand with init params, now only by pointer (same reason as above) --- helper/lorawan-mac-helper.cc | 16 +- model/class-a-end-device-lorawan-mac.cc | 2 +- model/end-device-lorawan-mac.cc | 128 +++++++------ model/end-device-lorawan-mac.h | 14 -- model/gateway-lorawan-mac.cc | 9 +- model/logical-lora-channel-helper.cc | 239 ++++++------------------ model/logical-lora-channel-helper.h | 145 +++++--------- test/lorawan-test-suite.cc | 34 ++-- 8 files changed, 206 insertions(+), 381 deletions(-) diff --git a/helper/lorawan-mac-helper.cc b/helper/lorawan-mac-helper.cc index 6267ad37b3..c9b6a9f027 100644 --- a/helper/lorawan-mac-helper.cc +++ b/helper/lorawan-mac-helper.cc @@ -200,14 +200,14 @@ LorawanMacHelper::ApplyCommonAlohaConfigurations(Ptr lorawanMac) con // SubBands // ////////////// - Ptr channelHelper = CreateObject(); + auto channelHelper = Create(1); channelHelper->AddSubBand(Create(868, 868.6, 1, 14)); ////////////////////// // Default channels // ////////////////////// Ptr lc1 = Create(868.1, 0, 5); - channelHelper->AddChannel(lc1); + channelHelper->SetChannel(0, lc1); lorawanMac->SetLogicalLoraChannelHelper(channelHelper); @@ -306,7 +306,7 @@ LorawanMacHelper::ApplyCommonEuConfigurations(Ptr lorawanMac) const // SubBands // ////////////// - Ptr channelHelper = CreateObject(); + auto channelHelper = Create(16); channelHelper->AddSubBand(Create(863, 865, 0.001, 14)); channelHelper->AddSubBand(Create(865, 868, 0.01, 14)); channelHelper->AddSubBand(Create(868, 868.6, 0.01, 14)); @@ -320,9 +320,9 @@ LorawanMacHelper::ApplyCommonEuConfigurations(Ptr lorawanMac) const Ptr lc1 = Create(868.1, 0, 5); Ptr lc2 = Create(868.3, 0, 5); Ptr lc3 = Create(868.5, 0, 5); - channelHelper->AddChannel(lc1); - channelHelper->AddChannel(lc2); - channelHelper->AddChannel(lc3); + channelHelper->SetChannel(0, lc1); + channelHelper->SetChannel(1, lc2); + channelHelper->SetChannel(2, lc3); lorawanMac->SetLogicalLoraChannelHelper(channelHelper); @@ -421,14 +421,14 @@ LorawanMacHelper::ApplyCommonSingleChannelConfigurations(Ptr lorawan // SubBands // ////////////// - Ptr channelHelper = CreateObject(); + auto channelHelper = Create(1); channelHelper->AddSubBand(Create(868, 868.6, 0.01, 14)); ////////////////////// // Default channels // ////////////////////// Ptr lc1 = Create(868.1, 0, 5); - channelHelper->AddChannel(lc1); + channelHelper->SetChannel(0, lc1); lorawanMac->SetLogicalLoraChannelHelper(channelHelper); diff --git a/model/class-a-end-device-lorawan-mac.cc b/model/class-a-end-device-lorawan-mac.cc index 4cb9c18f12..d8a4cd77ac 100644 --- a/model/class-a-end-device-lorawan-mac.cc +++ b/model/class-a-end-device-lorawan-mac.cc @@ -554,7 +554,7 @@ ClassAEndDeviceLorawanMac::OnRxParamSetupReq(uint8_t rx1DrOffset, rx2DataRateAck = false; } - if (frequencyHz > 870000000 || frequencyHz < 863000000) + if (!m_channelHelper->IsFrequencyValid(frequencyHz / 1e6)) { NS_LOG_WARN("Invalid rx2 frequency"); channelAck = false; diff --git a/model/end-device-lorawan-mac.cc b/model/end-device-lorawan-mac.cc index c5aee92732..63f7b43ca7 100644 --- a/model/end-device-lorawan-mac.cc +++ b/model/end-device-lorawan-mac.cc @@ -18,7 +18,6 @@ #include "ns3/log.h" #include "ns3/simulator.h" -#include #include namespace ns3 @@ -490,7 +489,7 @@ EndDeviceLorawanMac::GetNextTransmissionDelay() // Pick a random channel to transmit on std::vector> logicalChannels; logicalChannels = - m_channelHelper->GetEnabledChannelList(); // Use a separate list to do the shuffle + m_channelHelper->GetRawChannelArray(); // Use a separate list to do the shuffle // logicalChannels = Shuffle (logicalChannels); Time waitingTime = Time::Max(); @@ -501,12 +500,15 @@ EndDeviceLorawanMac::GetNextTransmissionDelay() { // Pointer to the current channel Ptr logicalChannel = *it; - double frequencyMHz = logicalChannel->GetFrequency(); + if (logicalChannel && logicalChannel->IsEnabledForUplink()) + { + double frequencyMHz = logicalChannel->GetFrequency(); - waitingTime = std::min(waitingTime, m_channelHelper->GetWaitingTime(logicalChannel)); + waitingTime = std::min(waitingTime, m_channelHelper->GetWaitingTime(logicalChannel)); - NS_LOG_DEBUG("Waiting time before the next transmission in channel with frequency " - << frequencyMHz << " is = " << waitingTime.GetSeconds() << "."); + NS_LOG_DEBUG("Waiting time before the next transmission in channel with frequency " + << frequencyMHz << " is = " << waitingTime.GetSeconds() << "."); + } } waitingTime = GetNextClassTransmissionDelay(waitingTime); @@ -522,7 +524,7 @@ EndDeviceLorawanMac::GetChannelForTx() // Pick a random channel to transmit on std::vector> logicalChannels; logicalChannels = - m_channelHelper->GetEnabledChannelList(); // Use a separate list to do the shuffle + m_channelHelper->GetRawChannelArray(); // Use a separate list to do the shuffle logicalChannels = Shuffle(logicalChannels); // Try every channel @@ -531,24 +533,27 @@ EndDeviceLorawanMac::GetChannelForTx() { // Pointer to the current channel Ptr logicalChannel = *it; - double frequencyMHz = logicalChannel->GetFrequency(); + if (logicalChannel && logicalChannel->IsEnabledForUplink()) + { + double frequencyMHz = logicalChannel->GetFrequency(); - NS_LOG_DEBUG("Frequency of the current channel: " << frequencyMHz); + NS_LOG_DEBUG("Frequency of the current channel: " << frequencyMHz); - // Verify that we can send the packet - Time waitingTime = m_channelHelper->GetWaitingTime(logicalChannel); + // Verify that we can send the packet + Time waitingTime = m_channelHelper->GetWaitingTime(logicalChannel); - NS_LOG_DEBUG("Waiting time for current channel = " << waitingTime.GetSeconds()); + NS_LOG_DEBUG("Waiting time for current channel = " << waitingTime.GetSeconds()); - // Send immediately if we can - if (waitingTime == Seconds(0)) - { - return *it; - } - else - { - NS_LOG_DEBUG("Packet cannot be immediately transmitted on " - << "the current channel because of duty cycle limitations."); + // Send immediately if we can + if (waitingTime == Seconds(0)) + { + return *it; + } + else + { + NS_LOG_DEBUG("Packet cannot be immediately transmitted on " + << "the current channel because of duty cycle limitations."); + } } } return nullptr; // In this case, no suitable channel was found @@ -676,7 +681,7 @@ EndDeviceLorawanMac::OnLinkAdrReq(uint8_t dataRate, NS_ASSERT_MSG(!(chMaskCtrl & 0xF8), "chMaskCtrl field > 3 bits"); NS_ASSERT_MSG(!(nbTrans & 0xF0), "nbTrans field > 4 bits"); - auto channelList = m_channelHelper->GetChannelList(); + auto channels = m_channelHelper->GetRawChannelArray(); bool channelMaskAck = true; bool dataRateAck = true; @@ -691,9 +696,9 @@ EndDeviceLorawanMac::OnLinkAdrReq(uint8_t dataRate, // Channels 0 to 15 case 0: // Check if all enabled channels have a valid frequency - for (uint8_t i = 0; i < 16; ++i) + for (size_t i = 0; i < channels.size(); ++i) { - if ((chMask & 0b1 << i) && i >= channelList.size()) + if ((chMask & 0b1 << i) && !channels.at(i)) { NS_LOG_WARN("Invalid channel mask"); channelMaskAck = false; @@ -704,9 +709,9 @@ EndDeviceLorawanMac::OnLinkAdrReq(uint8_t dataRate, // All channels ON independently of the ChMask field value case 6: chMask = 0b0; - for (uint8_t i = 0; i < 16; ++i) + for (size_t i = 0; i < channels.size(); ++i) { - if (i < channelList.size()) + if (channels.at(i)) { chMask |= 0b1 << i; } @@ -728,15 +733,15 @@ EndDeviceLorawanMac::OnLinkAdrReq(uint8_t dataRate, // Temporary channel mask is built and validated if (!m_adr) // ADR disabled, only consider channel mask conf. { + /// \remark Original code considers this to be mobile-mode if (channelMaskAck) // valid channel mask { bool compatible = false; // Look for enabled channel that supports current data rate. - // Note: Original code checks for DR0 because this is considered mobile-mode - for (uint8_t i = 0; i < 16; ++i) + for (size_t i = 0; i < channels.size(); ++i) { - if ((chMask & 0b1 << i) && m_dataRate >= channelList[i]->GetMinimumDataRate() && - m_dataRate <= channelList[i]->GetMaximumDataRate()) + if ((chMask & 0b1 << i) && m_dataRate >= channels.at(i)->GetMinimumDataRate() && + m_dataRate <= channels.at(i)->GetMaximumDataRate()) { // Found compatible channel, break loop compatible = true; break; @@ -749,10 +754,12 @@ EndDeviceLorawanMac::OnLinkAdrReq(uint8_t dataRate, } else // apply channel mask configuration { - for (size_t i = 0; i < channelList.size(); ++i) + for (size_t i = 0; i < channels.size(); ++i) { - (chMask & 0b1 << i) ? channelList[i]->EnableForUplink() - : channelList[i]->DisableForUplink(); + if (auto c = channels.at(i); c) + { + (chMask & 0b1 << i) ? c->EnableForUplink() : c->DisableForUplink(); + } } dataRateAck = powerAck = false; // only ack channel mask } @@ -769,17 +776,31 @@ EndDeviceLorawanMac::OnLinkAdrReq(uint8_t dataRate, { bool compatible = false; // Look for enabled channel that supports config. data rate. - for (uint8_t i = 0; i < channelList.size() && i < 16; ++i) + for (size_t i = 0; i < channels.size(); ++i) { - if ((chMask & 0b1 << i) && dataRate >= channelList[i]->GetMinimumDataRate() && - dataRate <= channelList[i]->GetMaximumDataRate()) - { // Found compatible channel, break loop - compatible = true; - break; + if (chMask & 0b1 << i) // all enabled by chMask, even if it was invalid + { + if (auto c = channels.at(i); c) // exists + { + if (dataRate >= c->GetMinimumDataRate() && + dataRate <= c->GetMaximumDataRate()) + { // Found compatible channel, break loop + compatible = true; + break; + } + } + else // manages invalid case, checks with defaults + { + if (GetSfFromDataRate(dataRate) && GetBandwidthFromDataRate(dataRate)) + { // Found compatible (invalid) channel, break loop + compatible = true; + break; + } + } } } // Check if it is acceptable - if (!compatible || !GetSfFromDataRate(dataRate) || !GetBandwidthFromDataRate(dataRate)) + if (!compatible) { NS_LOG_WARN("Invalid data rate"); dataRateAck = false; @@ -799,10 +820,12 @@ EndDeviceLorawanMac::OnLinkAdrReq(uint8_t dataRate, // If no error, apply configurations if (channelMaskAck && dataRateAck && powerAck) { - for (size_t i = 0; i < channelList.size(); ++i) + for (size_t i = 0; i < channels.size(); ++i) { - (chMask & 0b1 << i) ? channelList[i]->EnableForUplink() - : channelList[i]->DisableForUplink(); + if (auto c = channels.at(i); c) + { + (chMask & 0b1 << i) ? c->EnableForUplink() : c->DisableForUplink(); + } } if (txPower != 0xF) // If value is 0xF, ignore config. { @@ -883,22 +906,6 @@ EndDeviceLorawanMac::OnNewChannelReq(uint8_t chIndex, m_macCommandList.emplace_back(Create(dataRateRangeOk, channelFrequencyOk)); } -void -EndDeviceLorawanMac::AddLogicalChannel(double frequencyMHz) -{ - NS_LOG_FUNCTION(this << frequencyMHz); - - m_channelHelper->AddChannel(frequencyMHz); -} - -void -EndDeviceLorawanMac::AddLogicalChannel(Ptr logicalChannel) -{ - NS_LOG_FUNCTION(this << logicalChannel); - - m_channelHelper->AddChannel(logicalChannel); -} - void EndDeviceLorawanMac::SetLogicalChannel(uint8_t chIndex, double frequencyMHz, @@ -920,7 +927,8 @@ EndDeviceLorawanMac::AddSubBand(double startFrequencyMHz, { NS_LOG_FUNCTION_NOARGS(); - m_channelHelper->AddSubBand(startFrequencyMHz, endFrequencyMHz, dutyCycle, maxTxPowerDbm); + m_channelHelper->AddSubBand( + Create(startFrequencyMHz, endFrequencyMHz, dutyCycle, maxTxPowerDbm)); } uint8_t diff --git a/model/end-device-lorawan-mac.h b/model/end-device-lorawan-mac.h index a3a363db48..5fc4cc98cd 100644 --- a/model/end-device-lorawan-mac.h +++ b/model/end-device-lorawan-mac.h @@ -318,13 +318,6 @@ class EndDeviceLorawanMac : public LorawanMac // Logical channel administration // //////////////////////////////////// - /** - * Add a logical channel to the helper. - * - * \param frequencyMHz The channel's center frequency [MHz]. - */ - void AddLogicalChannel(double frequencyMHz); - /** * Set a new logical channel in the helper. * @@ -338,13 +331,6 @@ class EndDeviceLorawanMac : public LorawanMac uint8_t minDataRate, uint8_t maxDataRate); - /** - * Add a logical channel to the helper. - * - * \param logicalChannel The logical channel to add. - */ - void AddLogicalChannel(Ptr logicalChannel); - /** * Add a subband to the logical channel helper. * diff --git a/model/gateway-lorawan-mac.cc b/model/gateway-lorawan-mac.cc index a91fbb3f0c..60c9000426 100644 --- a/model/gateway-lorawan-mac.cc +++ b/model/gateway-lorawan-mac.cc @@ -60,7 +60,7 @@ GatewayLorawanMac::Send(Ptr packet) packet->AddPacketTag(tag); // Make sure we can transmit this packet - if (m_channelHelper->GetWaitingTime(CreateObject(frequencyMHz)) > Time(0)) + if (GetWaitingTime(frequencyMHz) > Time(0)) { // We cannot send now! NS_LOG_WARN("Trying to send a packet but Duty Cycle won't allow it. Aborting."); @@ -82,11 +82,10 @@ GatewayLorawanMac::Send(Ptr packet) NS_LOG_DEBUG("Duration: " << duration.GetSeconds()); // Find the channel with the desired frequency - double sendingPower = - m_channelHelper->GetTxPowerForChannel(CreateObject(frequencyMHz)); + double sendingPower = m_channelHelper->GetTxPowerForChannel(frequencyMHz); // Add the event to the channelHelper to keep track of duty cycle - m_channelHelper->AddEvent(duration, CreateObject(frequencyMHz)); + m_channelHelper->AddEvent(duration, frequencyMHz); // Send the packet to the PHY layer to send it on the channel m_phy->Send(packet, params, frequencyMHz, sendingPower); @@ -143,7 +142,7 @@ GatewayLorawanMac::GetWaitingTime(double frequencyMHz) { NS_LOG_FUNCTION_NOARGS(); - return m_channelHelper->GetWaitingTime(CreateObject(frequencyMHz)); + return m_channelHelper->GetWaitingTime(frequencyMHz); } } // namespace lorawan } // namespace ns3 diff --git a/model/logical-lora-channel-helper.cc b/model/logical-lora-channel-helper.cc index 4bda6d0229..c0eb0393c3 100644 --- a/model/logical-lora-channel-helper.cc +++ b/model/logical-lora-channel-helper.cc @@ -8,7 +8,6 @@ #include "logical-lora-channel-helper.h" -#include "ns3/log.h" #include "ns3/simulator.h" namespace ns3 @@ -18,19 +17,8 @@ namespace lorawan NS_LOG_COMPONENT_DEFINE("LogicalLoraChannelHelper"); -NS_OBJECT_ENSURE_REGISTERED(LogicalLoraChannelHelper); - -TypeId -LogicalLoraChannelHelper::GetTypeId() -{ - static TypeId tid = - TypeId("ns3::LogicalLoraChannelHelper").SetParent().SetGroupName("lorawan"); - return tid; -} - -LogicalLoraChannelHelper::LogicalLoraChannelHelper() - : m_nextAggregatedTransmissionTime(Seconds(0)), - m_aggregatedDutyCycle(1) +LogicalLoraChannelHelper::LogicalLoraChannelHelper(uint8_t size) + : m_channelVec(size) { NS_LOG_FUNCTION(this); } @@ -38,224 +26,107 @@ LogicalLoraChannelHelper::LogicalLoraChannelHelper() LogicalLoraChannelHelper::~LogicalLoraChannelHelper() { NS_LOG_FUNCTION(this); + m_subBandList.clear(); + m_channelVec.clear(); } std::vector> -LogicalLoraChannelHelper::GetChannelList() -{ - NS_LOG_FUNCTION(this); - - // Make a copy of the channel vector - std::vector> vector; - vector.reserve(m_channelList.size()); - std::copy(m_channelList.begin(), m_channelList.end(), std::back_inserter(vector)); - - return vector; -} - -std::vector> -LogicalLoraChannelHelper::GetEnabledChannelList() +LogicalLoraChannelHelper::GetRawChannelArray() const { NS_LOG_FUNCTION(this); - - // Make a copy of the channel vector - std::vector> vector; - vector.reserve(m_channelList.size()); - std::copy(m_channelList.begin(), - m_channelList.end(), - std::back_inserter(vector)); // Working on a copy - - std::vector> channels; - std::vector>::iterator it; - for (it = vector.begin(); it != vector.end(); it++) - { - if ((*it)->IsEnabledForUplink()) - { - channels.push_back(*it); - } - } - - return channels; -} - -Ptr -LogicalLoraChannelHelper::GetSubBandFromChannel(Ptr channel) -{ - return GetSubBandFromFrequency(channel->GetFrequency()); + return m_channelVec; } Ptr -LogicalLoraChannelHelper::GetSubBandFromFrequency(double frequencyMHz) +LogicalLoraChannelHelper::GetSubBandFromFrequency(double frequencyMHz) const { - // Get the SubBand this frequency belongs to - std::list>::iterator it; - for (it = m_subBandList.begin(); it != m_subBandList.end(); it++) + NS_LOG_FUNCTION(this << frequencyMHz); + for (const auto& sb : m_subBandList) { if (sb->Contains(frequencyMHz)) { - return *it; + return sb; } } - - NS_LOG_ERROR("Requested frequency: " << frequencyMHz); - NS_ABORT_MSG("Warning: frequency is outside any known SubBand."); - - return nullptr; // If no SubBand is found, return 0 + NS_LOG_ERROR("[ERROR] Requested frequency " << frequencyMHz << "MHz outside known sub-bands."); + return nullptr; // If no SubBand is found, return nullptr } void -LogicalLoraChannelHelper::AddChannel(double frequencyMHz) -{ - NS_LOG_FUNCTION(this << frequencyMHz); +LogicalLoraChannelHelper::SetChannel(uint8_t chIndex, Ptr channel) - // Create the new channel and increment the counter - Ptr channel = Create(frequencyMHz, 0, 5); - - // Add it to the list - m_channelList.push_back(channel); - - NS_LOG_DEBUG("Added a channel. Current number of channels in list is " << m_channelList.size()); -} - -void -LogicalLoraChannelHelper::AddChannel(Ptr logicalChannel) { - NS_LOG_FUNCTION(this << logicalChannel); - - // Add it to the list - m_channelList.push_back(logicalChannel); -} - -void -LogicalLoraChannelHelper::SetChannel(uint8_t chIndex, Ptr logicalChannel) - -{ - NS_LOG_FUNCTION(this << chIndex << logicalChannel); - - m_channelList.at(chIndex) = logicalChannel; -} - -void -LogicalLoraChannelHelper::AddSubBand(double firstFrequencyMHz, - double lastFrequencyMHz, - double dutyCycle, - double maxTxPowerDbm) -{ - NS_LOG_FUNCTION(this << firstFrequencyMHz << lastFrequencyMHz); - - Ptr subBand = - Create(firstFrequencyMHz, lastFrequencyMHz, dutyCycle, maxTxPowerDbm); - - m_subBandList.push_back(subBand); + NS_LOG_FUNCTION(this << unsigned(chIndex) << channel); + NS_ASSERT_MSG(m_channelVec.size() > chIndex, "ChIndex > channel storage bounds"); + m_channelVec.at(chIndex) = channel; } void LogicalLoraChannelHelper::AddSubBand(Ptr subBand) { NS_LOG_FUNCTION(this << subBand); - - m_subBandList.push_back(subBand); + m_subBandList.emplace_back(subBand); } -void -LogicalLoraChannelHelper::RemoveChannel(Ptr logicalChannel) +Time +LogicalLoraChannelHelper::GetWaitingTime(Ptr channel) const { - // Search and remove the channel from the list - std::vector>::iterator it; - for (it = m_channelList.begin(); it != m_channelList.end(); it++) - { - Ptr currentChannel = *it; - if (currentChannel == logicalChannel) - { - m_channelList.erase(it); - return; - } - } + NS_LOG_FUNCTION(this << channel); + return GetWaitingTime(channel->GetFrequency()); } Time -LogicalLoraChannelHelper::GetAggregatedWaitingTime() +LogicalLoraChannelHelper::GetWaitingTime(double frequencyMHz) const { - // Aggregate waiting time - Time aggregatedWaitingTime = m_nextAggregatedTransmissionTime - Simulator::Now(); - - // Handle case in which waiting time is negative - aggregatedWaitingTime = Seconds(std::max(aggregatedWaitingTime.GetSeconds(), double(0))); - - NS_LOG_DEBUG("Aggregated waiting time: " << aggregatedWaitingTime.GetSeconds()); - - return aggregatedWaitingTime; + NS_LOG_FUNCTION(this << frequencyMHz); + auto subBand = GetSubBandFromFrequency(frequencyMHz); + NS_ASSERT_MSG(subBand, "Input frequency is out-of-band"); + Time waitingTime = subBand->GetNextTransmissionTime() - Now(); + waitingTime = Max(waitingTime, Time(0)); // Handle negative values + NS_LOG_DEBUG("waitingTime=" << waitingTime.As(Time::S)); + return waitingTime; } -Time -LogicalLoraChannelHelper::GetWaitingTime(Ptr channel) +void +LogicalLoraChannelHelper::AddEvent(Time duration, Ptr channel) { NS_LOG_FUNCTION(this << channel); - - // SubBand waiting time - Time subBandWaitingTime = - GetSubBandFromChannel(channel)->GetNextTransmissionTime() - Simulator::Now(); - - // Handle case in which waiting time is negative - subBandWaitingTime = Seconds(std::max(subBandWaitingTime.GetSeconds(), double(0))); - - NS_LOG_DEBUG("Waiting time: " << subBandWaitingTime.GetSeconds()); - - return subBandWaitingTime; + AddEvent(duration, channel->GetFrequency()); } void -LogicalLoraChannelHelper::AddEvent(Time duration, Ptr channel) +LogicalLoraChannelHelper::AddEvent(Time duration, double frequencyMHz) { - NS_LOG_FUNCTION(this << duration << channel); - - Ptr subBand = GetSubBandFromChannel(channel); - - double dutyCycle = subBand->GetDutyCycle(); - double timeOnAir = duration.GetSeconds(); - - // Computation of necessary waiting time on this sub-band - subBand->SetNextTransmissionTime(Simulator::Now() + Seconds(timeOnAir / dutyCycle - timeOnAir)); - - // Computation of necessary aggregate waiting time - m_nextAggregatedTransmissionTime = - Simulator::Now() + Seconds(timeOnAir / m_aggregatedDutyCycle - timeOnAir); - - NS_LOG_DEBUG("Time on air: " << timeOnAir); - NS_LOG_DEBUG("m_aggregatedDutyCycle: " << m_aggregatedDutyCycle); - NS_LOG_DEBUG("Current time: " << Simulator::Now().GetSeconds()); - NS_LOG_DEBUG("Next transmission on this sub-band allowed at time: " - << (subBand->GetNextTransmissionTime()).GetSeconds()); - NS_LOG_DEBUG("Next aggregated transmission allowed at time " - << m_nextAggregatedTransmissionTime.GetSeconds()); + NS_LOG_FUNCTION(this << duration << frequencyMHz); + NS_LOG_DEBUG("frequency=" << frequencyMHz << "MHz, timeOnAir=" << duration.As(Time::S)); + auto subBand = GetSubBandFromFrequency(frequencyMHz); + NS_ASSERT_MSG(subBand, "Input frequency is out-of-band"); + Time nextTxTime = Now() + duration / subBand->GetDutyCycle(); + subBand->SetNextTransmissionTime(nextTxTime); + NS_LOG_DEBUG("now=" << Now().As(Time::S) << ", nextTxTime=" << nextTxTime.As(Time::S)); } double -LogicalLoraChannelHelper::GetTxPowerForChannel(Ptr logicalChannel) +LogicalLoraChannelHelper::GetTxPowerForChannel(Ptr channel) const { - NS_LOG_FUNCTION_NOARGS(); - - // Get the maxTxPowerDbm from the SubBand this channel is in - std::list>::iterator it; - for (it = m_subBandList.begin(); it != m_subBandList.end(); it++) - { - // Check whether this channel is in this SubBand - if ((*it)->BelongsToSubBand(logicalChannel->GetFrequency())) - { - return (*it)->GetMaxTxPowerDbm(); - } - } - NS_ABORT_MSG("Logical channel doesn't belong to a known SubBand"); - - return 0; + NS_LOG_FUNCTION(this << channel); + return GetTxPowerForChannel(channel->GetFrequency()); } -void -LogicalLoraChannelHelper::DisableChannel(int index) +double +LogicalLoraChannelHelper::GetTxPowerForChannel(double frequencyMHz) const { - NS_LOG_FUNCTION(this << index); + NS_LOG_FUNCTION(this << frequencyMHz); + auto subBand = GetSubBandFromFrequency(frequencyMHz); + NS_ASSERT_MSG(subBand, "Input frequency is out-of-band"); + return subBand->GetMaxTxPowerDbm(); +} - m_channelList.at(index)->DisableForUplink(); +bool +LogicalLoraChannelHelper::IsFrequencyValid(double frequencyMHz) const +{ + return (bool)(GetSubBandFromFrequency(frequencyMHz)); } + } // namespace lorawan } // namespace ns3 diff --git a/model/logical-lora-channel-helper.h b/model/logical-lora-channel-helper.h index dfabaa2a74..a98e932dd3 100644 --- a/model/logical-lora-channel-helper.h +++ b/model/logical-lora-channel-helper.h @@ -13,11 +13,9 @@ #include "sub-band.h" #include "ns3/nstime.h" -#include "ns3/object.h" -#include "ns3/packet.h" +#include "ns3/ptr.h" +#include "ns3/simple-ref-count.h" -#include -#include #include namespace ns3 @@ -36,39 +34,36 @@ namespace lorawan * of SubBand objects and providing methods to query whether transmission on a * set channel is admissible or not. */ -class LogicalLoraChannelHelper : public Object +class LogicalLoraChannelHelper : public SimpleRefCount { public: /** - * Register this type. - * \return The object TypeId. + * Construct a LogicalLoraChannelHelper of a certain size. + * + * \param size The maximum number of transmission channels that can be installed on this device + * according to regional parameter specifications. */ - static TypeId GetTypeId(); + LogicalLoraChannelHelper(uint8_t size); - LogicalLoraChannelHelper(); //!< Default constructor - ~LogicalLoraChannelHelper() override; //!< Destructor + ~LogicalLoraChannelHelper(); //!< Destructor /** - * Get the time it is necessary to wait before transmitting again, according - * to the aggregate duty cycle timer. + * Get the time it is necessary to wait for before transmitting on a given channel. * - * \return The aggregate waiting time. + * \param channel A pointer to the channel we want to know the waiting time for. + * \return A Time instance containing the waiting time before transmission is allowed on the + * channel. */ - Time GetAggregatedWaitingTime(); + Time GetWaitingTime(Ptr channel) const; /** - * Get the time it is necessary to wait for before transmitting on a given - * channel. - * - * \remark This function does not take into account aggregate waiting time. - * Check on this should be performed before calling this function. + * Get the time it is necessary to wait for before transmitting on a given channel. * - * \param channel A pointer to the channel we want to know the waiting time. - * for. - * \return A Time instance containing the waiting time before transmission is. - * allowed on the channel. + * \param frequencyMHz The channel frequency [MHz] we want to know the waiting time of for. + * \return A Time instance containing the waiting time before transmission is allowed on the + * channel. */ - Time GetWaitingTime(Ptr channel); + Time GetWaitingTime(double frequencyMHz) const; /** * Register the transmission of a packet. @@ -79,55 +74,32 @@ class LogicalLoraChannelHelper : public Object void AddEvent(Time duration, Ptr channel); /** - * Get the list of LogicalLoraChannels currently registered on this helper. + * Register the transmission of a packet. * - * \return A list of the managed channels. + * \param duration The duration of the transmission event. + * \param frequencyMHz The carrier frequency the transmission was on. */ - std::vector> GetChannelList(); + void AddEvent(Time duration, double frequencyMHz); /** - * Get the list of LogicalLoraChannels currently registered on this helper - * that have been enabled for Uplink transmission with the channel mask. + * Get the frequency channel storage array of this device. * - * \return A list of the managed channels enabled for Uplink transmission. - */ - std::vector> GetEnabledChannelList(); - - /** - * Add a new channel to the list. + * By specifications, devices are required to hold an indexed structure + * of a certain size (region-dependent) for storing transmission channels. * - * \param frequencyMHz The frequency [MHz] of the channel to create. - */ - void AddChannel(double frequencyMHz); - - /** - * Add a new channel to the list. + * \remark Empty index slots hold nullptr. * - * \param logicalChannel A pointer to the channel to add to the list. + * \return An indexed vector of pointers to LogicalLoraChannels. */ - void AddChannel(Ptr logicalChannel); + std::vector> GetRawChannelArray() const; /** * Set a new channel at a fixed index. * * \param chIndex The index of the channel to substitute. - * \param logicalChannel A pointer to the channel to add to the list. - */ - void SetChannel(uint8_t chIndex, Ptr logicalChannel); - - /** - * Add a new SubBand to this helper. - * - * \param firstFrequencyMHz The first frequency of the subband, in MHz. - * \param lastFrequencyMHz The last frequency of the subband, in MHz. - * \param dutyCycle The duty cycle that needs to be enforced on this subband. - * \param maxTxPowerDbm The maximum transmission power [dBm] that can be used. - * on this SubBand. + * \param channel A pointer to the channel to add to the list. */ - void AddSubBand(double firstFrequencyMHz, - double lastFrequencyMHz, - double dutyCycle, - double maxTxPowerDbm); + void SetChannel(uint8_t chIndex, Ptr channel); /** * Add a new SubBand. @@ -137,68 +109,53 @@ class LogicalLoraChannelHelper : public Object void AddSubBand(Ptr subBand); /** - * Remove a channel. + * Returns the maximum transmission power [dBm] that is allowed on a channel. * - * \param channel A pointer to the channel we want to remove. + * \param channel The channel in question. + * \return The power in dBm. */ - void RemoveChannel(Ptr channel); + double GetTxPowerForChannel(Ptr channel) const; /** * Returns the maximum transmission power [dBm] that is allowed on a channel. * - * \param logicalChannel The power for which to check the maximum allowed. - * transmission power. + * \param frequencyMHz The carrier frequency of the channel in question. * \return The power in dBm. */ - double GetTxPowerForChannel(Ptr logicalChannel); + double GetTxPowerForChannel(double frequencyMHz) const; /** - * Get the SubBand a channel belongs to. + * Check if a frequency is valid, that is, if it belongs to any of the sub-bands registered in + * this class. * - * \param channel The channel whose SubBand we want to get. - * \return The SubBand the channel belongs to. + * \param frequencyMHz The frequency [MHz] to be evaluated. + * \return Whether the input frequency belongs to any of the registered sub-bands. */ - Ptr GetSubBandFromChannel(Ptr channel); + bool IsFrequencyValid(double frequencyMHz) const; + private: /** - * Get the SubBand a frequency belongs to. + * Get the SubBand a frequency belongs to, also used to test validity of a frequency. * * \param frequencyMHz The frequency [MHz] we want to check. - * \return The SubBand the frequency belongs to. + * \return The SubBand the frequency belongs to, nullptr if none. */ - Ptr GetSubBandFromFrequency(double frequencyMHz); + Ptr GetSubBandFromFrequency(double frequencyMHz) const; /** - * Disable the channel at a specified index. - * - * \param index The index of the channel to disable. + * A vector of the SubBands that are currently registered within this helper. */ - void DisableChannel(int index); - - private: - /** - * A list of the SubBands that are currently registered within this helper. - */ - std::list> m_subBandList; + std::vector> m_subBandList; /** * A vector of the LogicalLoraChannels that are currently registered within * this helper. This vector represents the node's channel mask. The first N * channels are the default ones for a fixed region. */ - std::vector> m_channelList; - - Time m_nextAggregatedTransmissionTime; //!< The next time at which - //! transmission will be possible - //! according to the aggregated - //! transmission timer - - double m_aggregatedDutyCycle; //!< The next time at which - //! transmission will be possible - //! according to the aggregated - //! transmission timer + std::vector> m_channelVec; }; -} // namespace lorawan +} // namespace lorawan } // namespace ns3 + #endif /* LOGICAL_LORA_CHANNEL_HELPER_H */ diff --git a/test/lorawan-test-suite.cc b/test/lorawan-test-suite.cc index 51fd80aa1e..df62ba0a36 100644 --- a/test/lorawan-test-suite.cc +++ b/test/lorawan-test-suite.cc @@ -930,7 +930,7 @@ LogicalLoraChannelTest::DoRun() /////////////////////////////////// // Setup - Ptr channelHelper = CreateObject(); + auto channelHelper = Create(16); auto subBand1 = Create(869.4, 869.65, 0.10, 27); channel1 = Create(868.1, 0, 5); channel2 = Create(868.3, 0, 5); @@ -944,16 +944,16 @@ LogicalLoraChannelTest::DoRun() // Add SubBands and LogicalLoraChannels to the helper channelHelper->AddSubBand(subBand); channelHelper->AddSubBand(subBand1); - channelHelper->AddChannel(channel1); - channelHelper->AddChannel(channel2); - channelHelper->AddChannel(channel3); + channelHelper->SetChannel(0, channel1); + channelHelper->SetChannel(1, channel2); + channelHelper->SetChannel(2, channel3); // Duty Cycle tests // (high level duty cycle behavior) /////////////////////////////////// channelHelper->AddEvent(Seconds(2), channel1); - Time expectedTimeOff = Seconds(2 / 0.01 - 2); + Time expectedTimeOff = Seconds(2 / 0.01); // Waiting time is computed correctly NS_TEST_EXPECT_MSG_EQ(channelHelper->GetWaitingTime(channel1), @@ -1727,10 +1727,11 @@ MacCommandTest::DoRun() NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetMaxNumberOfTransmissions()), unsigned(nbTrans), "m_nbTrans does not match nbTrans field of LinkAdrReq"); - auto channels = m_mac->GetLogicalLoraChannelHelper()->GetChannelList(); - for (size_t i = 0; i < channels.size() && i < 16; i++) + auto channels = m_mac->GetLogicalLoraChannelHelper()->GetRawChannelArray(); + for (size_t i = 0; i < channels.size(); i++) { - bool actual = channels.at(i + 16 * chMaskCntl)->IsEnabledForUplink(); + auto c = channels.at(i + 16 * chMaskCntl); + bool actual = (c) ? c->IsEnabledForUplink() : false; bool expected = (chMask & 0b1 << i); NS_TEST_EXPECT_MSG_EQ(actual, expected, "Channel " << i << " state != chMask"); } @@ -1761,10 +1762,11 @@ MacCommandTest::DoRun() NS_TEST_EXPECT_MSG_NE(unsigned(m_mac->GetMaxNumberOfTransmissions()), unsigned(nbTrans), "m_nbTrans expected to differ from nbTrans field of LinkAdrReq"); - auto channels = m_mac->GetLogicalLoraChannelHelper()->GetChannelList(); - for (size_t i = 0; i < channels.size() && i < 16; i++) + auto channels = m_mac->GetLogicalLoraChannelHelper()->GetRawChannelArray(); + for (size_t i = 0; i < channels.size(); i++) { - bool actual = channels.at(i + 16 * chMaskCntl)->IsEnabledForUplink(); + auto c = channels.at(i + 16 * chMaskCntl); + bool actual = (c) ? c->IsEnabledForUplink() : false; bool expected = (chMask & 0b1 << i); NS_TEST_EXPECT_MSG_EQ(actual, expected, "Channel " << i << " state != chMask"); } @@ -1794,11 +1796,13 @@ MacCommandTest::DoRun() NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetMaxNumberOfTransmissions()), 1, "m_nbTrans expected to be default value"); - auto channels = m_mac->GetLogicalLoraChannelHelper()->GetChannelList(); - for (size_t i = 0; i < channels.size() && i < 16; i++) + auto channels = m_mac->GetLogicalLoraChannelHelper()->GetRawChannelArray(); + for (size_t i = 0; i < channels.size(); i++) { - bool actual = channels.at(i + 16 * chMaskCntl)->IsEnabledForUplink(); - NS_TEST_EXPECT_MSG_EQ(actual, true, "Channel " << i << " state != default true"); + auto c = channels.at(i + 16 * chMaskCntl); + bool actual = (c) ? c->IsEnabledForUplink() : false; + bool expected = (uint16_t(0b111) & 0b1 << i); + NS_TEST_EXPECT_MSG_EQ(actual, expected, "Channel " << i << " state != default"); } NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1"); auto laa = DynamicCast(answers.at(0)); From 3cd45a2fcccdf93ee1d6f50b64f6efb4ff31d43c Mon Sep 17 00:00:00 2001 From: Alessandro Aimi Date: Sun, 17 Nov 2024 17:14:38 +0100 Subject: [PATCH 27/34] Rework MacCommand classes - remove unused destructors - remove setters (mandate initializer constructor use) - add missing getters for implemented commands - add implementation TODOs - improve printing and align teminology with specs - add overflow asserts for field with size < 8 bits - remove empty lines and boilerplate --- model/mac-command.cc | 492 ++++++++++++++----------------------------- model/mac-command.h | 81 +++---- 2 files changed, 208 insertions(+), 365 deletions(-) diff --git a/model/mac-command.cc b/model/mac-command.cc index fa665ee223..fdcf7fbf62 100644 --- a/model/mac-command.cc +++ b/model/mac-command.cc @@ -42,16 +42,14 @@ MacCommand::~MacCommand() enum MacCommandType MacCommand::GetCommandType() const { - NS_LOG_FUNCTION_NOARGS(); - + NS_LOG_FUNCTION(this); return m_commandType; } uint8_t MacCommand::GetSerializedSize() const { - NS_LOG_FUNCTION_NOARGS(); - + NS_LOG_FUNCTION(this); return m_serializedSize; } @@ -59,7 +57,6 @@ uint8_t MacCommand::GetCIDFromMacCommand(enum MacCommandType commandType) { NS_LOG_FUNCTION_NOARGS(); - switch (commandType) { case (INVALID): { @@ -111,43 +108,30 @@ MacCommand::GetCIDFromMacCommand(enum MacCommandType commandType) LinkCheckReq::LinkCheckReq() { - NS_LOG_FUNCTION_NOARGS(); + NS_LOG_FUNCTION(this); m_commandType = LINK_CHECK_REQ; m_serializedSize = 1; } -LinkCheckReq::~LinkCheckReq() -{ - NS_LOG_FUNCTION_NOARGS(); -} - void LinkCheckReq::Serialize(Buffer::Iterator& start) const { - NS_LOG_FUNCTION_NOARGS(); - - // Write the CID and we're done - uint8_t cid = GetCIDFromMacCommand(m_commandType); - start.WriteU8(cid); - NS_LOG_DEBUG("Serialized LinkCheckReq: " << unsigned(cid)); + NS_LOG_FUNCTION(this); + start.WriteU8(GetCIDFromMacCommand(m_commandType)); // Write the CID } uint8_t LinkCheckReq::Deserialize(Buffer::Iterator& start) { - NS_LOG_FUNCTION_NOARGS(); - - // Read the CID - start.ReadU8(); - + NS_LOG_FUNCTION(this); + start.ReadU8(); // Consume the CID return m_serializedSize; } void LinkCheckReq::Print(std::ostream& os) const { - NS_LOG_FUNCTION_NOARGS(); - + NS_LOG_FUNCTION(this); os << "LinkCheckReq()"; } @@ -156,11 +140,8 @@ LinkCheckReq::Print(std::ostream& os) const ////////////////// LinkCheckAns::LinkCheckAns() - : m_margin(0), - m_gwCnt(0) { NS_LOG_FUNCTION(this); - m_commandType = LINK_CHECK_ANS; m_serializedSize = 3; } @@ -170,7 +151,6 @@ LinkCheckAns::LinkCheckAns(uint8_t margin, uint8_t gwCnt) m_gwCnt(gwCnt) { NS_LOG_FUNCTION(this << unsigned(margin) << unsigned(gwCnt)); - m_commandType = LINK_CHECK_ANS; m_serializedSize = 3; } @@ -178,23 +158,17 @@ LinkCheckAns::LinkCheckAns(uint8_t margin, uint8_t gwCnt) void LinkCheckAns::Serialize(Buffer::Iterator& start) const { - NS_LOG_FUNCTION_NOARGS(); - - // Write the CID - start.WriteU8(GetCIDFromMacCommand(m_commandType)); - // Write the margin - start.WriteU8(m_margin); - // Write the gwCnt - start.WriteU8(m_gwCnt); + NS_LOG_FUNCTION(this); + start.WriteU8(GetCIDFromMacCommand(m_commandType)); // Write the CID + start.WriteU8(m_margin); // Write the margin + start.WriteU8(m_gwCnt); // Write the gwCnt } uint8_t LinkCheckAns::Deserialize(Buffer::Iterator& start) { - NS_LOG_FUNCTION_NOARGS(); - - // Consume the CID - start.ReadU8(); + NS_LOG_FUNCTION(this); + start.ReadU8(); // Consume the CID m_margin = start.ReadU8(); m_gwCnt = start.ReadU8(); return m_serializedSize; @@ -203,38 +177,20 @@ LinkCheckAns::Deserialize(Buffer::Iterator& start) void LinkCheckAns::Print(std::ostream& os) const { - NS_LOG_FUNCTION_NOARGS(); - + NS_LOG_FUNCTION(this); os << "LinkCheckAns("; - os << "margin=" << unsigned(m_margin); - os << ", gwCnt=" << unsigned(m_gwCnt); + os << "Margin=" << unsigned(m_margin); + os << ", GwCnt=" << unsigned(m_gwCnt); os << ")"; } -void -LinkCheckAns::SetMargin(uint8_t margin) -{ - NS_LOG_FUNCTION(this << unsigned(margin)); - - m_margin = margin; -} - uint8_t LinkCheckAns::GetMargin() const { NS_LOG_FUNCTION(this); - return m_margin; } -void -LinkCheckAns::SetGwCnt(uint8_t gwCnt) -{ - NS_LOG_FUNCTION(this << unsigned(gwCnt)); - - m_gwCnt = gwCnt; -} - uint8_t LinkCheckAns::GetGwCnt() const { @@ -243,14 +199,6 @@ LinkCheckAns::GetGwCnt() const return m_gwCnt; } -void -LinkCheckAns::IncrementGwCnt() -{ - NS_LOG_FUNCTION(this); - - m_gwCnt++; -} - //////////////// // LinkAdrReq // //////////////// @@ -258,7 +206,6 @@ LinkCheckAns::IncrementGwCnt() LinkAdrReq::LinkAdrReq() { NS_LOG_FUNCTION(this); - m_commandType = LINK_ADR_REQ; m_serializedSize = 5; } @@ -275,7 +222,10 @@ LinkAdrReq::LinkAdrReq(uint8_t dataRate, m_nbTrans(nbTrans) { NS_LOG_FUNCTION(this); - + NS_ASSERT_MSG(!(dataRate & 0xF0), "dataRate field > 4 bits"); + NS_ASSERT_MSG(!(txPower & 0xF0), "txPower field > 4 bits"); + NS_ASSERT_MSG(!(chMaskCntl & 0xF8), "chMaskCntl field > 3 bits"); + NS_ASSERT_MSG(!(nbTrans & 0xF0), "nbTrans field > 4 bits"); m_commandType = LINK_ADR_REQ; m_serializedSize = 5; } @@ -283,10 +233,8 @@ LinkAdrReq::LinkAdrReq(uint8_t dataRate, void LinkAdrReq::Serialize(Buffer::Iterator& start) const { - NS_LOG_FUNCTION_NOARGS(); - - // Write the CID - start.WriteU8(GetCIDFromMacCommand(m_commandType)); + NS_LOG_FUNCTION(this); + start.WriteU8(GetCIDFromMacCommand(m_commandType)); // Write the CID start.WriteU8(m_dataRate << 4 | (m_txPower & 0b1111)); start.WriteU16(m_chMask); start.WriteU8(m_chMaskCntl << 4 | (m_nbTrans & 0b1111)); @@ -295,10 +243,8 @@ LinkAdrReq::Serialize(Buffer::Iterator& start) const uint8_t LinkAdrReq::Deserialize(Buffer::Iterator& start) { - NS_LOG_FUNCTION_NOARGS(); - - // Consume the CID - start.ReadU8(); + NS_LOG_FUNCTION(this); + start.ReadU8(); // Consume the CID uint8_t firstByte = start.ReadU8(); m_dataRate = firstByte >> 4; m_txPower = firstByte & 0b1111; @@ -306,21 +252,19 @@ LinkAdrReq::Deserialize(Buffer::Iterator& start) uint8_t fourthByte = start.ReadU8(); m_chMaskCntl = fourthByte >> 4; m_nbTrans = fourthByte & 0b1111; - return m_serializedSize; } void LinkAdrReq::Print(std::ostream& os) const { - NS_LOG_FUNCTION_NOARGS(); - + NS_LOG_FUNCTION(this); os << "LinkAdrReq("; - os << "dataRate=" << unsigned(m_dataRate); - os << ", txPower=" << unsigned(m_txPower); - os << ", chMask=" << std::bitset<16>(m_chMask); - os << ", chMaskCntl=" << unsigned(m_chMaskCntl); - os << ", nbTrans=" << unsigned(m_nbTrans); + os << "DataRate=" << unsigned(m_dataRate); + os << ", TXPower=" << unsigned(m_txPower); + os << ", ChMask=" << std::bitset<16>(m_chMask); + os << ", ChMaskCntl=" << unsigned(m_chMaskCntl); + os << ", NbTrans=" << unsigned(m_nbTrans); os << ")"; } @@ -328,7 +272,6 @@ uint8_t LinkAdrReq::GetDataRate() const { NS_LOG_FUNCTION(this); - return m_dataRate; } @@ -336,7 +279,6 @@ uint8_t LinkAdrReq::GetTxPower() const { NS_LOG_FUNCTION(this); - return m_txPower; } @@ -344,13 +286,13 @@ uint16_t LinkAdrReq::GetChMask() const { NS_LOG_FUNCTION(this); - return m_chMask; } uint8_t LinkAdrReq::GetChMaskCtrl() const { + NS_LOG_FUNCTION(this); return m_chMaskCntl; } @@ -358,7 +300,6 @@ uint8_t LinkAdrReq::GetNbTrans() const { NS_LOG_FUNCTION(this); - return m_nbTrans; } @@ -369,7 +310,6 @@ LinkAdrReq::GetNbTrans() const LinkAdrAns::LinkAdrAns() { NS_LOG_FUNCTION(this); - m_commandType = LINK_ADR_ANS; m_serializedSize = 2; } @@ -380,7 +320,6 @@ LinkAdrAns::LinkAdrAns(bool powerAck, bool dataRateAck, bool channelMaskAck) m_channelMaskAck(channelMaskAck) { NS_LOG_FUNCTION(this); - m_commandType = LINK_ADR_ANS; m_serializedSize = 2; } @@ -388,12 +327,8 @@ LinkAdrAns::LinkAdrAns(bool powerAck, bool dataRateAck, bool channelMaskAck) void LinkAdrAns::Serialize(Buffer::Iterator& start) const { - NS_LOG_FUNCTION_NOARGS(); - - // Write the CID - start.WriteU8(GetCIDFromMacCommand(m_commandType)); - // We can assume that true will be converted to 1 and that false will be - // converted to 0 on any C++ compiler + NS_LOG_FUNCTION(this); + start.WriteU8(GetCIDFromMacCommand(m_commandType)); // Write the CID start.WriteU8((uint8_t(m_powerAck) << 2) | (uint8_t(m_dataRateAck) << 1) | uint8_t(m_channelMaskAck)); } @@ -401,47 +336,44 @@ LinkAdrAns::Serialize(Buffer::Iterator& start) const uint8_t LinkAdrAns::Deserialize(Buffer::Iterator& start) { - NS_LOG_FUNCTION_NOARGS(); - - // Consume the CID - start.ReadU8(); - + NS_LOG_FUNCTION(this); + start.ReadU8(); // Consume the CID uint8_t byte = start.ReadU8(); - m_powerAck = byte & 0b100; m_dataRateAck = byte & 0b10; m_channelMaskAck = byte & 0b1; - return m_serializedSize; } void LinkAdrAns::Print(std::ostream& os) const { - NS_LOG_FUNCTION_NOARGS(); - + NS_LOG_FUNCTION(this); os << "LinkAdrAns("; - os << "powerAck=" << m_powerAck; - os << ", dataRateAck=" << m_dataRateAck; - os << ", channelMaskAck=" << m_channelMaskAck; + os << "PowerACK=" << m_powerAck; + os << ", DataRateACK=" << m_dataRateAck; + os << ", ChannelMaskACK=" << m_channelMaskAck; os << ")"; } bool LinkAdrAns::GetPowerAck() const { + NS_LOG_FUNCTION(this); return m_powerAck; } bool LinkAdrAns::GetDataRateAck() const { + NS_LOG_FUNCTION(this); return m_dataRateAck; } bool LinkAdrAns::GetChannelMaskAck() const { + NS_LOG_FUNCTION(this); return m_channelMaskAck; } @@ -452,7 +384,6 @@ LinkAdrAns::GetChannelMaskAck() const DutyCycleReq::DutyCycleReq() { NS_LOG_FUNCTION(this); - m_commandType = DUTY_CYCLE_REQ; m_serializedSize = 2; } @@ -460,7 +391,6 @@ DutyCycleReq::DutyCycleReq() DutyCycleReq::DutyCycleReq(uint8_t maxDutyCycle) { NS_LOG_FUNCTION(this << unsigned(maxDutyCycle)); - NS_ASSERT_MSG(!(maxDutyCycle & 0xF0), "maxDutyCycle > 4 bits"); m_maxDutyCycle = maxDutyCycle; m_commandType = DUTY_CYCLE_REQ; @@ -470,32 +400,26 @@ DutyCycleReq::DutyCycleReq(uint8_t maxDutyCycle) void DutyCycleReq::Serialize(Buffer::Iterator& start) const { - NS_LOG_FUNCTION_NOARGS(); - - // Write the CID - start.WriteU8(GetCIDFromMacCommand(m_commandType)); + NS_LOG_FUNCTION(this); + start.WriteU8(GetCIDFromMacCommand(m_commandType)); // Write the CID start.WriteU8(m_maxDutyCycle); } uint8_t DutyCycleReq::Deserialize(Buffer::Iterator& start) { - NS_LOG_FUNCTION_NOARGS(); - - // Consume the CID - start.ReadU8(); + NS_LOG_FUNCTION(this); + start.ReadU8(); // Consume the CID m_maxDutyCycle = start.ReadU8(); - return m_serializedSize; } void DutyCycleReq::Print(std::ostream& os) const { - NS_LOG_FUNCTION_NOARGS(); - + NS_LOG_FUNCTION(this); os << "DutyCycleReq("; - os << "maxDutyCycle=" << unsigned(m_maxDutyCycle); + os << "MaxDutyCycle=" << unsigned(m_maxDutyCycle); os << ")"; } @@ -513,7 +437,6 @@ DutyCycleReq::GetMaxDutyCycle() const DutyCycleAns::DutyCycleAns() { NS_LOG_FUNCTION(this); - m_commandType = DUTY_CYCLE_ANS; m_serializedSize = 1; } @@ -521,38 +444,32 @@ DutyCycleAns::DutyCycleAns() void DutyCycleAns::Serialize(Buffer::Iterator& start) const { - NS_LOG_FUNCTION_NOARGS(); - - // Write the CID - start.WriteU8(GetCIDFromMacCommand(m_commandType)); + NS_LOG_FUNCTION(this); + start.WriteU8(GetCIDFromMacCommand(m_commandType)); // Write the CID } uint8_t DutyCycleAns::Deserialize(Buffer::Iterator& start) { - NS_LOG_FUNCTION_NOARGS(); - - // Consume the CID - start.ReadU8(); + NS_LOG_FUNCTION(this); + start.ReadU8(); // Consume the CID return m_serializedSize; } void DutyCycleAns::Print(std::ostream& os) const { - NS_LOG_FUNCTION_NOARGS(); - + NS_LOG_FUNCTION(this); os << "DutyCycleAns()"; } -////////////////// +///////////////////// // RxParamSetupReq // -////////////////// +///////////////////// RxParamSetupReq::RxParamSetupReq() { NS_LOG_FUNCTION(this); - m_commandType = RX_PARAM_SETUP_REQ; m_serializedSize = 5; } @@ -573,29 +490,21 @@ RxParamSetupReq::RxParamSetupReq(uint8_t rx1DrOffset, uint8_t rx2DataRate, doubl void RxParamSetupReq::Serialize(Buffer::Iterator& start) const { - NS_LOG_FUNCTION_NOARGS(); - - // Write the CID - start.WriteU8(GetCIDFromMacCommand(m_commandType)); - // Data serialization + NS_LOG_FUNCTION(this); + start.WriteU8(GetCIDFromMacCommand(m_commandType)); // Write the CID start.WriteU8((m_rx1DrOffset & 0b111) << 4 | (m_rx2DataRate & 0b1111)); uint32_t encodedFrequency = m_frequencyHz / 100; - NS_LOG_DEBUG(unsigned(encodedFrequency)); - NS_LOG_DEBUG(std::bitset<32>(encodedFrequency)); // Frequency is in little endian (lsb -> msb) - start.WriteU8(encodedFrequency & 0xff); // Least significant byte - start.WriteU8((encodedFrequency & 0xff00) >> 8); // Middle byte - start.WriteU8((encodedFrequency & 0xff0000) >> 16); // Most significant byte + start.WriteU8(encodedFrequency); // Least significant byte + start.WriteU8(encodedFrequency >> 8); // Middle byte + start.WriteU8(encodedFrequency >> 16); // Most significant byte } uint8_t RxParamSetupReq::Deserialize(Buffer::Iterator& start) { - NS_LOG_FUNCTION_NOARGS(); - - // Consume the CID - start.ReadU8(); - // Data serialization + NS_LOG_FUNCTION(this); + start.ReadU8(); // Consume the CID uint8_t firstByte = start.ReadU8(); m_rx1DrOffset = (firstByte & 0b1110000) >> 4; m_rx2DataRate = firstByte & 0b1111; @@ -604,21 +513,18 @@ RxParamSetupReq::Deserialize(Buffer::Iterator& start) encodedFrequency += start.ReadU8(); // Least significant byte encodedFrequency += start.ReadU8() << 8; // Middle byte encodedFrequency += start.ReadU8() << 16; // Most significant byte - NS_LOG_DEBUG(std::bitset<32>(encodedFrequency)); - m_frequencyHz = double(encodedFrequency) * 100; - + m_frequencyHz = encodedFrequency * 100; return m_serializedSize; } void RxParamSetupReq::Print(std::ostream& os) const { - NS_LOG_FUNCTION_NOARGS(); - + NS_LOG_FUNCTION(this); os << "RxParamSetupReq("; - os << "rx1DrOffset=" << unsigned(m_rx1DrOffset); - os << ", rx2DataRate=" << unsigned(m_rx2DataRate); - os << ", frequency=" << m_frequencyHz; + os << "RX1DROffset=" << unsigned(m_rx1DrOffset); + os << ", RX2DataRate=" << unsigned(m_rx2DataRate); + os << ", Frequency=" << uint32_t(m_frequencyHz); os << ")"; } @@ -626,7 +532,6 @@ uint8_t RxParamSetupReq::GetRx1DrOffset() { NS_LOG_FUNCTION(this); - return m_rx1DrOffset; } @@ -634,7 +539,6 @@ uint8_t RxParamSetupReq::GetRx2DataRate() { NS_LOG_FUNCTION(this); - return m_rx2DataRate; } @@ -642,7 +546,6 @@ double RxParamSetupReq::GetFrequency() { NS_LOG_FUNCTION(this); - return m_frequencyHz; } @@ -653,7 +556,6 @@ RxParamSetupReq::GetFrequency() RxParamSetupAns::RxParamSetupAns() { NS_LOG_FUNCTION(this); - m_commandType = RX_PARAM_SETUP_ANS; m_serializedSize = 2; } @@ -664,7 +566,6 @@ RxParamSetupAns::RxParamSetupAns(bool rx1DrOffsetAck, bool rx2DataRateAck, bool m_channelAck(channelAck) { NS_LOG_FUNCTION(this << rx1DrOffsetAck << rx2DataRateAck << channelAck); - m_commandType = RX_PARAM_SETUP_ANS; m_serializedSize = 2; } @@ -672,11 +573,8 @@ RxParamSetupAns::RxParamSetupAns(bool rx1DrOffsetAck, bool rx2DataRateAck, bool void RxParamSetupAns::Serialize(Buffer::Iterator& start) const { - NS_LOG_FUNCTION_NOARGS(); - - // Write the CID - start.WriteU8(GetCIDFromMacCommand(m_commandType)); - // Data serialization + NS_LOG_FUNCTION(this); + start.WriteU8(GetCIDFromMacCommand(m_commandType)); // Write the CID start.WriteU8(uint8_t(m_rx1DrOffsetAck) << 2 | uint8_t(m_rx2DataRateAck) << 1 | uint8_t(m_channelAck)); } @@ -684,47 +582,44 @@ RxParamSetupAns::Serialize(Buffer::Iterator& start) const uint8_t RxParamSetupAns::Deserialize(Buffer::Iterator& start) { - NS_LOG_FUNCTION_NOARGS(); - - // Consume the CID - start.ReadU8(); - + NS_LOG_FUNCTION(this); + start.ReadU8(); // Consume the CID uint8_t byte = start.ReadU8(); - m_rx1DrOffsetAck = (byte & 0b100) >> 2; m_rx2DataRateAck = (byte & 0b10) >> 1; m_channelAck = byte & 0b1; - return m_serializedSize; } void RxParamSetupAns::Print(std::ostream& os) const { - NS_LOG_FUNCTION_NOARGS(); - + NS_LOG_FUNCTION(this); os << "RxParamSetupAns("; - os << "m_rx1DrOffsetAck=" << m_rx1DrOffsetAck; - os << ", m_rx2DataRateAck=" << m_rx2DataRateAck; - os << ", m_channelAck=" << m_channelAck; + os << "RX1DROffsetACK=" << m_rx1DrOffsetAck; + os << ", RX2DataRateACK=" << m_rx2DataRateAck; + os << ", ChannelACK=" << m_channelAck; os << ")"; } bool RxParamSetupAns::GetRx1DrOffsetAck() const { + NS_LOG_FUNCTION(this); return m_rx1DrOffsetAck; } bool RxParamSetupAns::GetRx2DataRateAck() const { + NS_LOG_FUNCTION(this); return m_rx2DataRateAck; } bool RxParamSetupAns::GetChannelAck() const { + NS_LOG_FUNCTION(this); return m_channelAck; } @@ -735,7 +630,6 @@ RxParamSetupAns::GetChannelAck() const DevStatusReq::DevStatusReq() { NS_LOG_FUNCTION(this); - m_commandType = DEV_STATUS_REQ; m_serializedSize = 1; } @@ -743,28 +637,22 @@ DevStatusReq::DevStatusReq() void DevStatusReq::Serialize(Buffer::Iterator& start) const { - NS_LOG_FUNCTION_NOARGS(); - - // Write the CID - start.WriteU8(GetCIDFromMacCommand(m_commandType)); + NS_LOG_FUNCTION(this); + start.WriteU8(GetCIDFromMacCommand(m_commandType)); // Write the CID } uint8_t DevStatusReq::Deserialize(Buffer::Iterator& start) { - NS_LOG_FUNCTION_NOARGS(); - - // Consume the CID - start.ReadU8(); - + NS_LOG_FUNCTION(this); + start.ReadU8(); // Consume the CID return m_serializedSize; } void DevStatusReq::Print(std::ostream& os) const { - NS_LOG_FUNCTION_NOARGS(); - + NS_LOG_FUNCTION(this); os << "DevStatusReq()"; } @@ -775,7 +663,6 @@ DevStatusReq::Print(std::ostream& os) const DevStatusAns::DevStatusAns() { NS_LOG_FUNCTION(this); - m_commandType = DEV_STATUS_ANS; m_serializedSize = 3; } @@ -785,7 +672,7 @@ DevStatusAns::DevStatusAns(uint8_t battery, uint8_t margin) m_margin(margin) { NS_LOG_FUNCTION(this << unsigned(battery) << unsigned(margin)); - + NS_ASSERT_MSG(!(margin & 0xC0), "margin > 6 bits"); m_commandType = DEV_STATUS_ANS; m_serializedSize = 3; } @@ -793,10 +680,8 @@ DevStatusAns::DevStatusAns(uint8_t battery, uint8_t margin) void DevStatusAns::Serialize(Buffer::Iterator& start) const { - NS_LOG_FUNCTION_NOARGS(); - - // Write the CID - start.WriteU8(GetCIDFromMacCommand(m_commandType)); + NS_LOG_FUNCTION(this); + start.WriteU8(GetCIDFromMacCommand(m_commandType)); // Write the CID start.WriteU8(m_battery); start.WriteU8(m_margin); } @@ -804,21 +689,17 @@ DevStatusAns::Serialize(Buffer::Iterator& start) const uint8_t DevStatusAns::Deserialize(Buffer::Iterator& start) { - NS_LOG_FUNCTION_NOARGS(); - - // Consume the CID - start.ReadU8(); + NS_LOG_FUNCTION(this); + start.ReadU8(); // Consume the CID m_battery = start.ReadU8(); - m_margin = start.ReadU8() & 0b111111; - + m_margin = start.ReadU8(); return m_serializedSize; } void DevStatusAns::Print(std::ostream& os) const { - NS_LOG_FUNCTION_NOARGS(); - + NS_LOG_FUNCTION(this); os << "DevStatusAns("; os << "Battery=" << unsigned(m_battery); os << ", Margin=" << unsigned(m_margin); @@ -828,16 +709,14 @@ DevStatusAns::Print(std::ostream& os) const uint8_t DevStatusAns::GetBattery() const { - NS_LOG_FUNCTION_NOARGS(); - + NS_LOG_FUNCTION(this); return m_battery; } uint8_t DevStatusAns::GetMargin() const { - NS_LOG_FUNCTION_NOARGS(); - + NS_LOG_FUNCTION(this); return m_margin; } @@ -848,7 +727,6 @@ DevStatusAns::GetMargin() const NewChannelReq::NewChannelReq() { NS_LOG_FUNCTION(this); - m_commandType = NEW_CHANNEL_REQ; m_serializedSize = 6; } @@ -863,7 +741,8 @@ NewChannelReq::NewChannelReq(uint8_t chIndex, m_maxDataRate(maxDataRate) { NS_LOG_FUNCTION(this); - + NS_ASSERT_MSG(!(minDataRate & 0xF0), "minDataRate > 4 bits"); + NS_ASSERT_MSG(!(maxDataRate & 0xF0), "maxDataRate > 4 bits"); m_commandType = NEW_CHANNEL_REQ; m_serializedSize = 6; } @@ -871,79 +750,72 @@ NewChannelReq::NewChannelReq(uint8_t chIndex, void NewChannelReq::Serialize(Buffer::Iterator& start) const { - NS_LOG_FUNCTION_NOARGS(); - - // Write the CID - start.WriteU8(GetCIDFromMacCommand(m_commandType)); - + NS_LOG_FUNCTION(this); + start.WriteU8(GetCIDFromMacCommand(m_commandType)); // Write the CID start.WriteU8(m_chIndex); uint32_t encodedFrequency = m_frequencyHz / 100; // Frequency is in little endian (lsb -> msb) - start.WriteU8(encodedFrequency & 0xff); // Least significant byte - start.WriteU8((encodedFrequency & 0xff00) >> 8); // Middle byte - start.WriteU8((encodedFrequency & 0xff0000) >> 16); // Most significant byte + start.WriteU8(encodedFrequency); // Least significant byte + start.WriteU8(encodedFrequency >> 8); // Middle byte + start.WriteU8(encodedFrequency >> 16); // Most significant byte start.WriteU8((m_maxDataRate << 4) | (m_minDataRate & 0xf)); } uint8_t NewChannelReq::Deserialize(Buffer::Iterator& start) { - NS_LOG_FUNCTION_NOARGS(); - - // Consume the CID - start.ReadU8(); - // Read the data + NS_LOG_FUNCTION(this); + start.ReadU8(); // Consume the CID m_chIndex = start.ReadU8(); uint32_t encodedFrequency = 0; // Frequency is in little endian (lsb -> msb) encodedFrequency += start.ReadU8(); // Least significant byte encodedFrequency += start.ReadU8() << 8; // Middle byte encodedFrequency += start.ReadU8() << 16; // Most significant byte - m_frequencyHz = double(encodedFrequency) * 100; + m_frequencyHz = encodedFrequency * 100; uint8_t dataRateByte = start.ReadU8(); m_maxDataRate = dataRateByte >> 4; m_minDataRate = dataRateByte & 0xf; - return m_serializedSize; } void NewChannelReq::Print(std::ostream& os) const { - NS_LOG_FUNCTION_NOARGS(); - - os << "NewChannelReq()"; + NS_LOG_FUNCTION(this); + os << "NewChannelReq("; + os << "ChIndex=" << unsigned(m_chIndex); + os << ", Frequency=" << uint32_t(m_frequencyHz); + os << ", MaxDR=" << unsigned(m_maxDataRate); + os << ", MinDR=" << unsigned(m_minDataRate); + os << ")"; } uint8_t NewChannelReq::GetChannelIndex() const { - NS_LOG_FUNCTION_NOARGS(); - + NS_LOG_FUNCTION(this); return m_chIndex; } double NewChannelReq::GetFrequency() const { - NS_LOG_FUNCTION_NOARGS(); - + NS_LOG_FUNCTION(this); return m_frequencyHz; } uint8_t NewChannelReq::GetMinDataRate() const { - NS_LOG_FUNCTION_NOARGS(); - + NS_LOG_FUNCTION(this); return m_minDataRate; } uint8_t NewChannelReq::GetMaxDataRate() const { - NS_LOG_FUNCTION_NOARGS(); - + NS_LOG_FUNCTION(this); return m_maxDataRate; } @@ -954,7 +826,6 @@ NewChannelReq::GetMaxDataRate() const NewChannelAns::NewChannelAns() { NS_LOG_FUNCTION(this); - m_commandType = NEW_CHANNEL_ANS; m_serializedSize = 2; } @@ -964,7 +835,6 @@ NewChannelAns::NewChannelAns(bool dataRateRangeOk, bool channelFrequencyOk) m_channelFrequencyOk(channelFrequencyOk) { NS_LOG_FUNCTION(this); - m_commandType = NEW_CHANNEL_ANS; m_serializedSize = 2; } @@ -972,40 +842,46 @@ NewChannelAns::NewChannelAns(bool dataRateRangeOk, bool channelFrequencyOk) void NewChannelAns::Serialize(Buffer::Iterator& start) const { - NS_LOG_FUNCTION_NOARGS(); - - // Write the CID - start.WriteU8(GetCIDFromMacCommand(m_commandType)); - + NS_LOG_FUNCTION(this); + start.WriteU8(GetCIDFromMacCommand(m_commandType)); // Write the CID start.WriteU8((uint8_t(m_dataRateRangeOk) << 1) | uint8_t(m_channelFrequencyOk)); } uint8_t NewChannelAns::Deserialize(Buffer::Iterator& start) { - NS_LOG_FUNCTION_NOARGS(); - - // Consume the CID - start.ReadU8(); - // Read the data - uint8_t byte = start.ReadU8(); + NS_LOG_FUNCTION(this); + start.ReadU8(); // Consume the CID + uint8_t byte = start.ReadU8(); // Read the data m_dataRateRangeOk = (byte & 0b10) >> 1; m_channelFrequencyOk = (byte & 0b1); - return m_serializedSize; } void NewChannelAns::Print(std::ostream& os) const { - NS_LOG_FUNCTION_NOARGS(); - + NS_LOG_FUNCTION(this); os << "NewChannelAns("; os << "DataRateRangeOk=" << m_dataRateRangeOk; os << ", ChannelFrequencyOk=" << m_channelFrequencyOk; os << ")"; } +bool +NewChannelAns::GetDataRateRangeOk() const +{ + NS_LOG_FUNCTION(this); + return m_dataRateRangeOk; +} + +bool +NewChannelAns::GetChannelFrequencyOk() const +{ + NS_LOG_FUNCTION(this); + return m_channelFrequencyOk; +} + ////////////////////// // RxTimingSetupReq // ////////////////////// @@ -1013,7 +889,6 @@ NewChannelAns::Print(std::ostream& os) const RxTimingSetupReq::RxTimingSetupReq() { NS_LOG_FUNCTION(this); - m_commandType = RX_TIMING_SETUP_REQ; m_serializedSize = 2; } @@ -1022,7 +897,7 @@ RxTimingSetupReq::RxTimingSetupReq(uint8_t delay) : m_delay(delay) { NS_LOG_FUNCTION(this); - + NS_ASSERT_MSG(!(delay & 0xF0), "delay field > 4 bits"); m_commandType = RX_TIMING_SETUP_REQ; m_serializedSize = 2; } @@ -1030,32 +905,24 @@ RxTimingSetupReq::RxTimingSetupReq(uint8_t delay) void RxTimingSetupReq::Serialize(Buffer::Iterator& start) const { - NS_LOG_FUNCTION_NOARGS(); - - // Write the CID - start.WriteU8(GetCIDFromMacCommand(m_commandType)); - // Write the data - start.WriteU8(m_delay & 0xf); + NS_LOG_FUNCTION(this); + start.WriteU8(GetCIDFromMacCommand(m_commandType)); // Write the CID + start.WriteU8(m_delay & 0xF); // Write the data } uint8_t RxTimingSetupReq::Deserialize(Buffer::Iterator& start) { - NS_LOG_FUNCTION_NOARGS(); - - // Consume the CID - start.ReadU8(); - // Read the data - m_delay = start.ReadU8() & 0xf; - + NS_LOG_FUNCTION(this); + start.ReadU8(); // Consume the CID + m_delay = start.ReadU8() & 0xF; // Read the data return m_serializedSize; } void RxTimingSetupReq::Print(std::ostream& os) const { - NS_LOG_FUNCTION_NOARGS(); - + NS_LOG_FUNCTION(this); os << "RxTimingSetupReq()"; } @@ -1063,12 +930,7 @@ Time RxTimingSetupReq::GetDelay() { NS_LOG_FUNCTION(this); - - if (m_delay == 0) - { - return Seconds(1); - } - return Seconds(m_delay); + return Seconds((m_delay) ? m_delay : 0); } ////////////////// @@ -1078,7 +940,6 @@ RxTimingSetupReq::GetDelay() RxTimingSetupAns::RxTimingSetupAns() { NS_LOG_FUNCTION(this); - m_commandType = DEV_STATUS_REQ; m_serializedSize = 1; } @@ -1086,28 +947,22 @@ RxTimingSetupAns::RxTimingSetupAns() void RxTimingSetupAns::Serialize(Buffer::Iterator& start) const { - NS_LOG_FUNCTION_NOARGS(); - - // Write the CID - start.WriteU8(GetCIDFromMacCommand(m_commandType)); + NS_LOG_FUNCTION(this); + start.WriteU8(GetCIDFromMacCommand(m_commandType)); // Write the CID } uint8_t RxTimingSetupAns::Deserialize(Buffer::Iterator& start) { - NS_LOG_FUNCTION_NOARGS(); - - // Consume the CID - start.ReadU8(); - + NS_LOG_FUNCTION(this); + start.ReadU8(); // Consume the CID return m_serializedSize; } void RxTimingSetupAns::Print(std::ostream& os) const { - NS_LOG_FUNCTION_NOARGS(); - + NS_LOG_FUNCTION(this); os << "RxTimingSetupAns()"; } @@ -1118,7 +973,6 @@ RxTimingSetupAns::Print(std::ostream& os) const DlChannelAns::DlChannelAns() { NS_LOG_FUNCTION(this); - m_commandType = DEV_STATUS_REQ; m_serializedSize = 1; } @@ -1126,28 +980,22 @@ DlChannelAns::DlChannelAns() void DlChannelAns::Serialize(Buffer::Iterator& start) const { - NS_LOG_FUNCTION_NOARGS(); - - // Write the CID - start.WriteU8(GetCIDFromMacCommand(m_commandType)); + NS_LOG_FUNCTION(this); + start.WriteU8(GetCIDFromMacCommand(m_commandType)); // Write the CID } uint8_t DlChannelAns::Deserialize(Buffer::Iterator& start) { - NS_LOG_FUNCTION_NOARGS(); - - // Consume the CID - start.ReadU8(); - + NS_LOG_FUNCTION(this); + start.ReadU8(); // Consume the CID return m_serializedSize; } void DlChannelAns::Print(std::ostream& os) const { - NS_LOG_FUNCTION_NOARGS(); - + NS_LOG_FUNCTION(this); os << "DlChannelAns()"; } @@ -1158,7 +1006,6 @@ DlChannelAns::Print(std::ostream& os) const TxParamSetupReq::TxParamSetupReq() { NS_LOG_FUNCTION(this); - m_commandType = DEV_STATUS_REQ; m_serializedSize = 1; } @@ -1166,28 +1013,22 @@ TxParamSetupReq::TxParamSetupReq() void TxParamSetupReq::Serialize(Buffer::Iterator& start) const { - NS_LOG_FUNCTION_NOARGS(); - - // Write the CID - start.WriteU8(GetCIDFromMacCommand(m_commandType)); + NS_LOG_FUNCTION(this); + start.WriteU8(GetCIDFromMacCommand(m_commandType)); // Write the CID } uint8_t TxParamSetupReq::Deserialize(Buffer::Iterator& start) { - NS_LOG_FUNCTION_NOARGS(); - - // Consume the CID - start.ReadU8(); - + NS_LOG_FUNCTION(this); + start.ReadU8(); // Consume the CID return m_serializedSize; } void TxParamSetupReq::Print(std::ostream& os) const { - NS_LOG_FUNCTION_NOARGS(); - + NS_LOG_FUNCTION(this); os << "TxParamSetupReq()"; } @@ -1198,7 +1039,6 @@ TxParamSetupReq::Print(std::ostream& os) const TxParamSetupAns::TxParamSetupAns() { NS_LOG_FUNCTION(this); - m_commandType = DEV_STATUS_REQ; m_serializedSize = 1; } @@ -1206,28 +1046,22 @@ TxParamSetupAns::TxParamSetupAns() void TxParamSetupAns::Serialize(Buffer::Iterator& start) const { - NS_LOG_FUNCTION_NOARGS(); - - // Write the CID - start.WriteU8(GetCIDFromMacCommand(m_commandType)); + NS_LOG_FUNCTION(this); + start.WriteU8(GetCIDFromMacCommand(m_commandType)); // Write the CID } uint8_t TxParamSetupAns::Deserialize(Buffer::Iterator& start) { - NS_LOG_FUNCTION_NOARGS(); - - // Consume the CID - start.ReadU8(); - + NS_LOG_FUNCTION(this); + start.ReadU8(); // Consume the CID return m_serializedSize; } void TxParamSetupAns::Print(std::ostream& os) const { - NS_LOG_FUNCTION_NOARGS(); - + NS_LOG_FUNCTION(this); os << "TxParamSetupAns()"; } diff --git a/model/mac-command.h b/model/mac-command.h index 200e54b905..fe0b42af3d 100644 --- a/model/mac-command.h +++ b/model/mac-command.h @@ -125,8 +125,8 @@ class MacCommand : public Object class LinkCheckReq : public MacCommand { public: - LinkCheckReq(); - ~LinkCheckReq() override; //!< Destructor + LinkCheckReq(); //!< Default constructor + void Serialize(Buffer::Iterator& start) const override; uint8_t Deserialize(Buffer::Iterator& start) override; void Print(std::ostream& os) const override; @@ -157,13 +157,6 @@ class LinkCheckAns : public MacCommand uint8_t Deserialize(Buffer::Iterator& start) override; void Print(std::ostream& os) const override; - /** - * Set the demodulation margin value. - * - * \param margin The demodulation margin to set. - */ - void SetMargin(uint8_t margin); - /** * Get the demodulation margin value. * @@ -171,13 +164,6 @@ class LinkCheckAns : public MacCommand */ uint8_t GetMargin() const; - /** - * Set the gateway count value. - * - * \param gwCnt The count value to set. - */ - void SetGwCnt(uint8_t gwCnt); - /** * Get the gateway count value. * @@ -185,11 +171,6 @@ class LinkCheckAns : public MacCommand */ uint8_t GetGwCnt() const; - /** - * Increment this MacCommand's gwCnt value. - */ - void IncrementGwCnt(); - private: uint8_t m_margin; //!< This MAC command's demodulation margin value. uint8_t m_gwCnt; //!< This MAC command's gateway count value. @@ -207,7 +188,8 @@ class LinkCheckAns : public MacCommand class LinkAdrReq : public MacCommand { public: - LinkAdrReq(); + LinkAdrReq(); //!< Default constructor + /** * Constructor with given fields. * @@ -357,7 +339,8 @@ class LinkAdrAns : public MacCommand class DutyCycleReq : public MacCommand { public: - DutyCycleReq(); + DutyCycleReq(); //!< Default constructor + /** * Constructor providing initialization of all parameters. * @@ -408,7 +391,7 @@ class DutyCycleAns : public MacCommand class RxParamSetupReq : public MacCommand { public: - RxParamSetupReq(); + RxParamSetupReq(); //!< Default constructor /** * Constructor providing initialization of all fields. @@ -458,7 +441,8 @@ class RxParamSetupReq : public MacCommand class RxParamSetupAns : public MacCommand { public: - RxParamSetupAns(); + RxParamSetupAns(); //!< Default constructor + /** * Constructor with initialization of all parameters. * @@ -507,11 +491,13 @@ class RxParamSetupAns : public MacCommand * \ingroup lorawan * * Implementation of the DevStatusReq LoRaWAN MAC command. + * + * This command holds no variables, and just consists in the CID. */ class DevStatusReq : public MacCommand { public: - DevStatusReq(); + DevStatusReq(); //!< Default constructor void Serialize(Buffer::Iterator& start) const override; uint8_t Deserialize(Buffer::Iterator& start) override; @@ -570,7 +556,7 @@ class DevStatusAns : public MacCommand class NewChannelReq : public MacCommand { public: - NewChannelReq(); + NewChannelReq(); //!< Default constructor /** * Constructor providing initialization of all parameters. @@ -642,6 +628,23 @@ class NewChannelAns : public MacCommand uint8_t Deserialize(Buffer::Iterator& start) override; void Print(std::ostream& os) const override; + /** + * Get the DataRateRangOk field of the NewChannelAns command. + * + * \return true The data-rate range is compatible with the capabilities of the end-device. + * \return false The designated data-rate range exceeds the ones currently defined for this + * end-device. + */ + bool GetDataRateRangeOk() const; + + /** + * Get the ChannelFrequencyOk field of the NewChannelAns command. + * + * \return true The end-device is able to use this frequency. + * \return false The end-device cannot use this frequency. + */ + bool GetChannelFrequencyOk() const; + private: bool m_dataRateRangeOk; //!< The Data-rate range ok field bool m_channelFrequencyOk; //!< The Channel frequency ok field @@ -655,7 +658,7 @@ class NewChannelAns : public MacCommand class RxTimingSetupReq : public MacCommand { public: - RxTimingSetupReq(); + RxTimingSetupReq(); //!< Default constructor /** * Constructor providing initialization of all parameters. @@ -684,12 +687,12 @@ class RxTimingSetupReq : public MacCommand * * Implementation of the RxTimingSetupAns LoRaWAN MAC command. * - * This MAC command has an empty payload. + * This command holds no variables, and just consists in the CID. */ class RxTimingSetupAns : public MacCommand { public: - RxTimingSetupAns(); + RxTimingSetupAns(); //!< Default constructor void Serialize(Buffer::Iterator& start) const override; uint8_t Deserialize(Buffer::Iterator& start) override; @@ -701,12 +704,14 @@ class RxTimingSetupAns : public MacCommand /** * \ingroup lorawan * - * Implementation of the TxParamSetupAns LoRaWAN MAC command. + * Implementation of the TxParamSetupReq LoRaWAN MAC command. + * + * \todo implementation */ -class TxParamSetupAns : public MacCommand +class TxParamSetupReq : public MacCommand { public: - TxParamSetupAns(); //!< Default constructor + TxParamSetupReq(); //!< Default constructor void Serialize(Buffer::Iterator& start) const override; uint8_t Deserialize(Buffer::Iterator& start) override; @@ -718,12 +723,14 @@ class TxParamSetupAns : public MacCommand /** * \ingroup lorawan * - * Implementation of the TxParamSetupReq LoRaWAN MAC command. + * Implementation of the TxParamSetupAns LoRaWAN MAC command. + * + * This command holds no variables, and just consists in the CID. */ -class TxParamSetupReq : public MacCommand +class TxParamSetupAns : public MacCommand { public: - TxParamSetupReq(); + TxParamSetupAns(); //!< Default constructor void Serialize(Buffer::Iterator& start) const override; uint8_t Deserialize(Buffer::Iterator& start) override; @@ -736,6 +743,8 @@ class TxParamSetupReq : public MacCommand * \ingroup lorawan * * Implementation of the DlChannelAns LoRaWAN MAC command. + * + * \todo implementation */ class DlChannelAns : public MacCommand { From 3118f99d9592bfa446c0ac9b8fe1e0c420440c50 Mon Sep 17 00:00:00 2001 From: Alessandro Aimi Date: Sun, 17 Nov 2024 17:25:04 +0100 Subject: [PATCH 28/34] Refactor waitingTime to waitTime (English proofing) --- model/class-a-end-device-lorawan-mac.cc | 20 +++++++++----------- model/class-a-end-device-lorawan-mac.h | 6 +++--- model/end-device-lorawan-mac.cc | 4 ++-- model/end-device-lorawan-mac.h | 12 ++++++------ model/gateway-lorawan-mac.cc | 6 +++--- model/gateway-lorawan-mac.h | 2 +- model/gateway-status.cc | 6 +++--- model/logical-lora-channel-helper.cc | 14 +++++++------- model/logical-lora-channel-helper.h | 12 ++++++------ test/lorawan-test-suite.cc | 14 +++++++------- 10 files changed, 47 insertions(+), 49 deletions(-) diff --git a/model/class-a-end-device-lorawan-mac.cc b/model/class-a-end-device-lorawan-mac.cc index d8a4cd77ac..b124f8c8cf 100644 --- a/model/class-a-end-device-lorawan-mac.cc +++ b/model/class-a-end-device-lorawan-mac.cc @@ -18,8 +18,6 @@ #include "ns3/log.h" -#include - namespace ns3 { namespace lorawan @@ -450,7 +448,7 @@ ClassAEndDeviceLorawanMac::CloseSecondReceiveWindow() ///////////////////////// Time -ClassAEndDeviceLorawanMac::GetNextClassTransmissionDelay(Time waitingTime) +ClassAEndDeviceLorawanMac::GetNextClassTransmissionDelay(Time waitTime) { NS_LOG_FUNCTION_NOARGS(); @@ -471,8 +469,8 @@ ClassAEndDeviceLorawanMac::GetNextClassTransmissionDelay(Time waitingTime) Seconds(m_receiveWindowDurationInSymbols * tSym); NS_LOG_DEBUG("Duration until endSecondRxWindow for new transmission:" - << (endSecondRxWindow - Simulator::Now()).GetSeconds()); - waitingTime = std::max(waitingTime, endSecondRxWindow - Simulator::Now()); + << (endSecondRxWindow - Now()).As(Time::S)); + waitTime = Max(waitTime, endSecondRxWindow - Now()); } } // This is a retransmitted packet, it can not be sent until the end of @@ -482,15 +480,15 @@ ClassAEndDeviceLorawanMac::GetNextClassTransmissionDelay(Time waitingTime) double ack_timeout = m_uniformRV->GetValue(1, 3); // Compute the duration until ACK_TIMEOUT (It may be a negative number, but it doesn't // matter.) - Time retransmitWaitingTime = - Time(m_secondReceiveWindow.GetTs()) - Simulator::Now() + Seconds(ack_timeout); + Time retransmitWaitTime = + Time(m_secondReceiveWindow.GetTs()) - Now() + Seconds(ack_timeout); - NS_LOG_DEBUG("ack_timeout:" << ack_timeout << " retransmitWaitingTime:" - << retransmitWaitingTime.GetSeconds()); - waitingTime = std::max(waitingTime, retransmitWaitingTime); + NS_LOG_DEBUG("ack_timeout:" << ack_timeout + << " retransmitWaitTime:" << retransmitWaitTime.As(Time::S)); + waitTime = Max(waitTime, retransmitWaitTime); } - return waitingTime; + return waitTime; } uint8_t diff --git a/model/class-a-end-device-lorawan-mac.h b/model/class-a-end-device-lorawan-mac.h index 93ad5e2d12..e8d76c911d 100644 --- a/model/class-a-end-device-lorawan-mac.h +++ b/model/class-a-end-device-lorawan-mac.h @@ -96,14 +96,14 @@ class ClassAEndDeviceLorawanMac : public EndDeviceLorawanMac ///////////////////////// /** - * Find the minimum waiting time before the next possible transmission based + * Find the minimum wait time before the next possible transmission based * on end device's Class Type. * - * \param waitingTime The minimum waiting time that has to be respected, + * \param waitTime The minimum wait time that has to be respected, * irrespective of the class (e.g., because of duty cycle limitations). * \return The Time value. */ - Time GetNextClassTransmissionDelay(Time waitingTime) override; + Time GetNextClassTransmissionDelay(Time waitTime) override; /** * Get the data rate that will be used in the first receive window. diff --git a/model/end-device-lorawan-mac.cc b/model/end-device-lorawan-mac.cc index 63f7b43ca7..ea22b6c74a 100644 --- a/model/end-device-lorawan-mac.cc +++ b/model/end-device-lorawan-mac.cc @@ -473,10 +473,10 @@ EndDeviceLorawanMac::TxFinished(Ptr packet) } Time -EndDeviceLorawanMac::GetNextClassTransmissionDelay(Time waitingTime) +EndDeviceLorawanMac::GetNextClassTransmissionDelay(Time waitTime) { NS_LOG_FUNCTION_NOARGS(); - return waitingTime; + return waitTime; } Time diff --git a/model/end-device-lorawan-mac.h b/model/end-device-lorawan-mac.h index 5fc4cc98cd..a9d76a63b9 100644 --- a/model/end-device-lorawan-mac.h +++ b/model/end-device-lorawan-mac.h @@ -377,13 +377,13 @@ class EndDeviceLorawanMac : public LorawanMac LoraDeviceAddress m_address; //!< The address of this device. /** - * Find the minimum waiting time before the next possible transmission based + * Find the minimum wait time before the next possible transmission based * on end device's Class Type. * - * \param waitingTime Currently known minimum waiting time, possibly raised by this function. - * \return The updated minimum waiting time in Time format. + * \param waitTime Currently known minimum wait time, possibly raised by this function. + * \return The updated minimum wait time in Time format. */ - virtual Time GetNextClassTransmissionDelay(Time waitingTime); + virtual Time GetNextClassTransmissionDelay(Time waitTime); /** * Find a suitable channel for transmission. The channel is chosen among the @@ -448,9 +448,9 @@ class EndDeviceLorawanMac : public LorawanMac std::vector> Shuffle(std::vector> vector); /** - * Find the base minimum waiting time before the next possible transmission. + * Find the base minimum wait time before the next possible transmission. * - * \return The base minimum waiting time. + * \return The base minimum wait time. */ Time GetNextTransmissionDelay(); diff --git a/model/gateway-lorawan-mac.cc b/model/gateway-lorawan-mac.cc index 60c9000426..1799e0fc7c 100644 --- a/model/gateway-lorawan-mac.cc +++ b/model/gateway-lorawan-mac.cc @@ -60,7 +60,7 @@ GatewayLorawanMac::Send(Ptr packet) packet->AddPacketTag(tag); // Make sure we can transmit this packet - if (GetWaitingTime(frequencyMHz) > Time(0)) + if (GetWaitTime(frequencyMHz) > Time(0)) { // We cannot send now! NS_LOG_WARN("Trying to send a packet but Duty Cycle won't allow it. Aborting."); @@ -138,11 +138,11 @@ GatewayLorawanMac::TxFinished(Ptr packet) } Time -GatewayLorawanMac::GetWaitingTime(double frequencyMHz) +GatewayLorawanMac::GetWaitTime(double frequencyMHz) { NS_LOG_FUNCTION_NOARGS(); - return m_channelHelper->GetWaitingTime(frequencyMHz); + return m_channelHelper->GetWaitTime(frequencyMHz); } } // namespace lorawan } // namespace ns3 diff --git a/model/gateway-lorawan-mac.h b/model/gateway-lorawan-mac.h index 936d5bcc90..c174c6dbd7 100644 --- a/model/gateway-lorawan-mac.h +++ b/model/gateway-lorawan-mac.h @@ -59,7 +59,7 @@ class GatewayLorawanMac : public LorawanMac * \param frequencyMHz The frequency value [MHz]. * \return The next transmission time. */ - Time GetWaitingTime(double frequencyMHz); + Time GetWaitTime(double frequencyMHz); private: protected: diff --git a/model/gateway-status.cc b/model/gateway-status.cc index fafc9df581..8df603e07c 100644 --- a/model/gateway-status.cc +++ b/model/gateway-status.cc @@ -100,11 +100,11 @@ GatewayStatus::IsAvailableForTransmission(double frequencyMHz) } // Check that the gateway is not constrained by the duty cycle - Time waitingTime = m_gatewayMac->GetWaitingTime(frequencyMHz); - if (waitingTime > Seconds(0)) + Time waitTime = m_gatewayMac->GetWaitTime(frequencyMHz); + if (waitTime.IsStrictlyPositive()) { NS_LOG_INFO("Gateway cannot be used because of duty cycle"); - NS_LOG_INFO("Waiting time at current gateway: " << waitingTime.GetSeconds() << " seconds"); + NS_LOG_INFO("Wait time at current gateway: " << waitTime.As(Time::S)); return false; } diff --git a/model/logical-lora-channel-helper.cc b/model/logical-lora-channel-helper.cc index c0eb0393c3..e88c87af70 100644 --- a/model/logical-lora-channel-helper.cc +++ b/model/logical-lora-channel-helper.cc @@ -69,22 +69,22 @@ LogicalLoraChannelHelper::AddSubBand(Ptr subBand) } Time -LogicalLoraChannelHelper::GetWaitingTime(Ptr channel) const +LogicalLoraChannelHelper::GetWaitTime(Ptr channel) const { NS_LOG_FUNCTION(this << channel); - return GetWaitingTime(channel->GetFrequency()); + return GetWaitTime(channel->GetFrequency()); } Time -LogicalLoraChannelHelper::GetWaitingTime(double frequencyMHz) const +LogicalLoraChannelHelper::GetWaitTime(double frequencyMHz) const { NS_LOG_FUNCTION(this << frequencyMHz); auto subBand = GetSubBandFromFrequency(frequencyMHz); NS_ASSERT_MSG(subBand, "Input frequency is out-of-band"); - Time waitingTime = subBand->GetNextTransmissionTime() - Now(); - waitingTime = Max(waitingTime, Time(0)); // Handle negative values - NS_LOG_DEBUG("waitingTime=" << waitingTime.As(Time::S)); - return waitingTime; + Time waitTime = subBand->GetNextTransmissionTime() - Now(); + waitTime = Max(waitTime, Time(0)); // Handle negative values + NS_LOG_DEBUG("waitTime=" << waitTime.As(Time::S)); + return waitTime; } void diff --git a/model/logical-lora-channel-helper.h b/model/logical-lora-channel-helper.h index a98e932dd3..d6ea213ba1 100644 --- a/model/logical-lora-channel-helper.h +++ b/model/logical-lora-channel-helper.h @@ -50,20 +50,20 @@ class LogicalLoraChannelHelper : public SimpleRefCount /** * Get the time it is necessary to wait for before transmitting on a given channel. * - * \param channel A pointer to the channel we want to know the waiting time for. - * \return A Time instance containing the waiting time before transmission is allowed on the + * \param channel A pointer to the channel we want to know the wait time for. + * \return A Time instance containing the wait time before transmission is allowed on the * channel. */ - Time GetWaitingTime(Ptr channel) const; + Time GetWaitTime(Ptr channel) const; /** * Get the time it is necessary to wait for before transmitting on a given channel. * - * \param frequencyMHz The channel frequency [MHz] we want to know the waiting time of for. - * \return A Time instance containing the waiting time before transmission is allowed on the + * \param frequencyMHz The channel frequency [MHz] we want to know the wait time of for. + * \return A Time instance containing the wait time before transmission is allowed on the * channel. */ - Time GetWaitingTime(double frequencyMHz) const; + Time GetWaitTime(double frequencyMHz) const; /** * Register the transmission of a packet. diff --git a/test/lorawan-test-suite.cc b/test/lorawan-test-suite.cc index df62ba0a36..84cef906de 100644 --- a/test/lorawan-test-suite.cc +++ b/test/lorawan-test-suite.cc @@ -955,20 +955,20 @@ LogicalLoraChannelTest::DoRun() channelHelper->AddEvent(Seconds(2), channel1); Time expectedTimeOff = Seconds(2 / 0.01); - // Waiting time is computed correctly - NS_TEST_EXPECT_MSG_EQ(channelHelper->GetWaitingTime(channel1), + // Wait time is computed correctly + NS_TEST_EXPECT_MSG_EQ(channelHelper->GetWaitTime(channel1), expectedTimeOff, - "Waiting time doesn't behave as expected"); + "Wait time doesn't behave as expected"); // Duty Cycle involves the whole SubBand, not just a channel - NS_TEST_EXPECT_MSG_EQ(channelHelper->GetWaitingTime(channel2), + NS_TEST_EXPECT_MSG_EQ(channelHelper->GetWaitTime(channel2), expectedTimeOff, - "Waiting time doesn't behave as expected"); + "Wait time doesn't behave as expected"); // Other bands are not affected by this transmission - NS_TEST_EXPECT_MSG_EQ(channelHelper->GetWaitingTime(channel3), + NS_TEST_EXPECT_MSG_EQ(channelHelper->GetWaitTime(channel3), Time(0), - "Waiting time affects other subbands"); + "Wait time affects other subbands"); } /** From 8519d4ae659c22ed4326b9651407396dbc6e2a3a Mon Sep 17 00:00:00 2001 From: Alessandro Aimi Date: Mon, 18 Nov 2024 09:17:14 +0100 Subject: [PATCH 29/34] Rework EndDeviceLorawanMac class - re-implement GetNextTransmissionDelay and GetChannelForTx - remove now obsolete Shuffle method - add setter and getter for transmission power - correct ChMaskCntl spelling as per specifications - remove AddSubBand and SetLogicalChannel --- model/end-device-lorawan-mac.cc | 167 +++++++++++--------------------- model/end-device-lorawan-mac.h | 54 ++--------- model/mac-command.cc | 2 +- model/mac-command.h | 6 +- 4 files changed, 68 insertions(+), 161 deletions(-) diff --git a/model/end-device-lorawan-mac.cc b/model/end-device-lorawan-mac.cc index ea22b6c74a..5959df67f3 100644 --- a/model/end-device-lorawan-mac.cc +++ b/model/end-device-lorawan-mac.cc @@ -377,7 +377,7 @@ EndDeviceLorawanMac::ParseCommands(LoraFrameHeader frameHeader) OnLinkAdrReq(linkAdrReq->GetDataRate(), linkAdrReq->GetTxPower(), linkAdrReq->GetChMask(), - linkAdrReq->GetChMaskCtrl(), + linkAdrReq->GetChMaskCntl(), linkAdrReq->GetNbTrans()); break; } @@ -482,99 +482,57 @@ EndDeviceLorawanMac::GetNextClassTransmissionDelay(Time waitTime) Time EndDeviceLorawanMac::GetNextTransmissionDelay() { - NS_LOG_FUNCTION_NOARGS(); - - // Check duty cycle // - - // Pick a random channel to transmit on - std::vector> logicalChannels; - logicalChannels = - m_channelHelper->GetRawChannelArray(); // Use a separate list to do the shuffle - // logicalChannels = Shuffle (logicalChannels); - - Time waitingTime = Time::Max(); - - // Try every channel - std::vector>::iterator it; - for (it = logicalChannels.begin(); it != logicalChannels.end(); ++it) + NS_LOG_FUNCTION(this); + // Check duty cycle + /// \todo possibly move to LogicalChannelHelper + auto waitTime = Time::Max(); + for (const auto& channel : m_channelHelper->GetRawChannelArray()) { - // Pointer to the current channel - Ptr logicalChannel = *it; - if (logicalChannel && logicalChannel->IsEnabledForUplink()) + if (channel && channel->IsEnabledForUplink()) // Skip empty frequency channel slots { - double frequencyMHz = logicalChannel->GetFrequency(); - - waitingTime = std::min(waitingTime, m_channelHelper->GetWaitingTime(logicalChannel)); - - NS_LOG_DEBUG("Waiting time before the next transmission in channel with frequency " - << frequencyMHz << " is = " << waitingTime.GetSeconds() << "."); + auto curr = m_channelHelper->GetWaitTime(channel); + if (curr < waitTime) + { + waitTime = curr; + } + NS_LOG_DEBUG("frequency=" << channel->GetFrequency() << "MHz," + << " waitTime=" << waitTime.As(Time::S)); } } - - waitingTime = GetNextClassTransmissionDelay(waitingTime); - - return waitingTime; + return GetNextClassTransmissionDelay(waitTime); } Ptr EndDeviceLorawanMac::GetChannelForTx() { - NS_LOG_FUNCTION_NOARGS(); - - // Pick a random channel to transmit on - std::vector> logicalChannels; - logicalChannels = - m_channelHelper->GetRawChannelArray(); // Use a separate list to do the shuffle - logicalChannels = Shuffle(logicalChannels); - - // Try every channel - std::vector>::iterator it; - for (it = logicalChannels.begin(); it != logicalChannels.end(); ++it) + NS_LOG_FUNCTION(this); + /// \todo possibly move to LogicalChannelHelper + std::vector> candidates; + for (const auto& channel : m_channelHelper->GetRawChannelArray()) { - // Pointer to the current channel - Ptr logicalChannel = *it; - if (logicalChannel && logicalChannel->IsEnabledForUplink()) + if (channel && channel->IsEnabledForUplink()) // Skip empty frequency channel slots { - double frequencyMHz = logicalChannel->GetFrequency(); - - NS_LOG_DEBUG("Frequency of the current channel: " << frequencyMHz); - - // Verify that we can send the packet - Time waitingTime = m_channelHelper->GetWaitingTime(logicalChannel); - - NS_LOG_DEBUG("Waiting time for current channel = " << waitingTime.GetSeconds()); - - // Send immediately if we can - if (waitingTime == Seconds(0)) - { - return *it; - } - else + uint8_t minDr = channel->GetMinimumDataRate(); + uint8_t maxDr = channel->GetMaximumDataRate(); + Time waitTime = m_channelHelper->GetWaitTime(channel); + NS_LOG_DEBUG("Enabled channel: frequency=" + << channel->GetFrequency() << "MHz, minDr=" << unsigned(minDr) + << ", maxDr=" << unsigned(maxDr) << ", waitTime=" << waitTime.As(Time::S)); + if (m_dataRate >= minDr && m_dataRate <= maxDr && waitTime.IsZero()) { - NS_LOG_DEBUG("Packet cannot be immediately transmitted on " - << "the current channel because of duty cycle limitations."); + candidates.emplace_back(channel); } } } - return nullptr; // In this case, no suitable channel was found -} - -std::vector> -EndDeviceLorawanMac::Shuffle(std::vector> vector) -{ - NS_LOG_FUNCTION_NOARGS(); - - int size = vector.size(); - - for (int i = 0; i < size; ++i) + if (candidates.empty()) { - uint16_t random = std::floor(m_uniformRV->GetValue(0, size)); - Ptr temp = vector.at(random); - vector.at(random) = vector.at(i); - vector.at(i) = temp; + NS_LOG_DEBUG("No suitable TX channel found"); + return nullptr; } - - return vector; + uint8_t i = m_uniformRV->GetInteger(0, candidates.size() - 1); + auto channel = candidates.at(i); + NS_LOG_DEBUG("Selected channel with frequency=" << channel->GetFrequency() << "MHz"); + return channel; } ///////////////////////// @@ -638,6 +596,20 @@ EndDeviceLorawanMac::GetDataRate() return m_dataRate; } +void +EndDeviceLorawanMac::SetTransmissionPowerDbm(double txPowerDbm) +{ + NS_LOG_FUNCTION(this << txPowerDbm); + m_txPowerDbm = txPowerDbm; +} + +double +EndDeviceLorawanMac::GetTransmissionPowerDbm() +{ + NS_LOG_FUNCTION(this); + return m_txPowerDbm; +} + void EndDeviceLorawanMac::SetDeviceAddress(LoraDeviceAddress address) { @@ -667,18 +639,18 @@ void EndDeviceLorawanMac::OnLinkAdrReq(uint8_t dataRate, uint8_t txPower, uint16_t chMask, - uint8_t chMaskCtrl, + uint8_t chMaskCntl, uint8_t nbTrans) { NS_LOG_FUNCTION(this << unsigned(dataRate) << unsigned(txPower) << std::bitset<16>(chMask) - << unsigned(chMaskCtrl) << unsigned(nbTrans)); + << unsigned(chMaskCntl) << unsigned(nbTrans)); // Adapted from: github.com/Lora-net/SWL2001.git v4.3.1 // For the time being, this implementation is valid for the EU868 region NS_ASSERT_MSG(!(dataRate & 0xF0), "dataRate field > 4 bits"); NS_ASSERT_MSG(!(txPower & 0xF0), "txPower field > 4 bits"); - NS_ASSERT_MSG(!(chMaskCtrl & 0xF8), "chMaskCtrl field > 3 bits"); + NS_ASSERT_MSG(!(chMaskCntl & 0xF8), "chMaskCntl field > 3 bits"); NS_ASSERT_MSG(!(nbTrans & 0xF0), "nbTrans field > 4 bits"); auto channels = m_channelHelper->GetRawChannelArray(); @@ -688,10 +660,10 @@ EndDeviceLorawanMac::OnLinkAdrReq(uint8_t dataRate, bool powerAck = true; NS_LOG_DEBUG("Channel mask = " << std::bitset<16>(chMask) - << ", ChMaskCtrl = " << unsigned(chMaskCtrl)); + << ", ChMaskCtrl = " << unsigned(chMaskCntl)); // Check channel mask - switch (chMaskCtrl) + switch (chMaskCntl) { // Channels 0 to 15 case 0: @@ -906,31 +878,6 @@ EndDeviceLorawanMac::OnNewChannelReq(uint8_t chIndex, m_macCommandList.emplace_back(Create(dataRateRangeOk, channelFrequencyOk)); } -void -EndDeviceLorawanMac::SetLogicalChannel(uint8_t chIndex, - double frequencyMHz, - uint8_t minDataRate, - uint8_t maxDataRate) -{ - NS_LOG_FUNCTION(this << unsigned(chIndex) << frequencyMHz << unsigned(minDataRate) - << unsigned(maxDataRate)); - - m_channelHelper->SetChannel(chIndex, - Create(frequencyMHz, minDataRate, maxDataRate)); -} - -void -EndDeviceLorawanMac::AddSubBand(double startFrequencyMHz, - double endFrequencyMHz, - double dutyCycle, - double maxTxPowerDbm) -{ - NS_LOG_FUNCTION_NOARGS(); - - m_channelHelper->AddSubBand( - Create(startFrequencyMHz, endFrequencyMHz, dutyCycle, maxTxPowerDbm)); -} - uint8_t EndDeviceLorawanMac::GetLastKnownLinkMarginDb() const { @@ -959,11 +906,5 @@ EndDeviceLorawanMac::AddMacCommand(Ptr macCommand) m_macCommandList.push_back(macCommand); } -double -EndDeviceLorawanMac::GetTransmissionPowerDbm() -{ - return m_txPowerDbm; -} - } // namespace lorawan } // namespace ns3 diff --git a/model/end-device-lorawan-mac.h b/model/end-device-lorawan-mac.h index a9d76a63b9..2762584811 100644 --- a/model/end-device-lorawan-mac.h +++ b/model/end-device-lorawan-mac.h @@ -170,6 +170,13 @@ class EndDeviceLorawanMac : public LorawanMac */ double GetTransmissionPowerDbm(); + /** + * Set the transmission power of this end device. + * + * \param txPowerDbm The transmission ERP [dBm] value. + */ + void SetTransmissionPowerDbm(double txPowerDbm); + /** * Set the network address of this device. * @@ -268,13 +275,13 @@ class EndDeviceLorawanMac : public LorawanMac * \param dataRate The data rate value of the command. * \param txPower The transmission power value of the command. * \param chMask Mask of enabled channels of the command. - * \param chMaskCtrl Indicator of the 16 channel bank to apply the chMask to. + * \param chMaskCntl Indicator of the 16 channel bank to apply the chMask to. * \param nbTrans The number of repetitions prescribed by the command. */ void OnLinkAdrReq(uint8_t dataRate, uint8_t txPower, uint16_t chMask, - uint8_t chMaskCtrl, + uint8_t chMaskCntl, uint8_t nbTrans); /** @@ -314,36 +321,6 @@ class EndDeviceLorawanMac : public LorawanMac uint8_t minDataRate, uint8_t maxDataRate); - //////////////////////////////////// - // Logical channel administration // - //////////////////////////////////// - - /** - * Set a new logical channel in the helper. - * - * \param chIndex The channel's new index. - * \param frequencyMHz The channel's center frequency [MHz]. - * \param minDataRate The minimum data rate allowed on the channel. - * \param maxDataRate The maximum data rate allowed on the channel. - */ - void SetLogicalChannel(uint8_t chIndex, - double frequencyMHz, - uint8_t minDataRate, - uint8_t maxDataRate); - - /** - * Add a subband to the logical channel helper. - * - * \param startFrequencyMHz The SubBand's lowest frequency [MHz]. - * \param endFrequencyMHz The SubBand's highest frequency [MHz]. - * \param dutyCycle The SubBand's duty cycle, in fraction form. - * \param maxTxPowerDbm The maximum transmission power allowed on the SubBand. - */ - void AddSubBand(double startFrequencyMHz, - double endFrequencyMHz, - double dutyCycle, - double maxTxPowerDbm); - /** * Add a MAC command to the list of those that will be sent out in the next * packet. @@ -417,8 +394,7 @@ class EndDeviceLorawanMac : public LorawanMac struct LoraRetxParameters m_retxParams; /** - * An uniform random variable, used by the Shuffle method to randomly reorder - * the channel list. + * An uniform random variable, used to randomly pick from the channel list. */ Ptr m_uniformRV; @@ -437,16 +413,6 @@ class EndDeviceLorawanMac : public LorawanMac TracedCallback> m_requiredTxCallback; private: - /** - * Randomly shuffle a Ptr vector. - * - * Used to pick a random channel on which to send the packet. - * - * \param vector The vector of pointers to logical LoRa channels. - * \return The shuffled vector. - */ - std::vector> Shuffle(std::vector> vector); - /** * Find the base minimum wait time before the next possible transmission. * diff --git a/model/mac-command.cc b/model/mac-command.cc index fdcf7fbf62..853ff4e226 100644 --- a/model/mac-command.cc +++ b/model/mac-command.cc @@ -290,7 +290,7 @@ LinkAdrReq::GetChMask() const } uint8_t -LinkAdrReq::GetChMaskCtrl() const +LinkAdrReq::GetChMaskCntl() const { NS_LOG_FUNCTION(this); return m_chMaskCntl; diff --git a/model/mac-command.h b/model/mac-command.h index fe0b42af3d..2973bc8d5f 100644 --- a/model/mac-command.h +++ b/model/mac-command.h @@ -241,13 +241,13 @@ class LinkAdrReq : public MacCommand uint16_t GetChMask() const; /** - * Get the ChMaskCtrl field, used as an indicator of the 16-channel bank to apply the ChMask to. + * Get the ChMaskCntl field, used as an indicator of the 16-channel bank to apply the ChMask to. * * The interpretation of this field is region-dependent. * - * \return The ChMaskCtrl field. + * \return The ChMaskCntl field. */ - uint8_t GetChMaskCtrl() const; + uint8_t GetChMaskCntl() const; /** * Get the number of repeated transmissions prescribed by this MAC command. From d60bb4cc44e92cf6d7172b9ee128a4da05298f15 Mon Sep 17 00:00:00 2001 From: Alessandro Aimi Date: Sun, 17 Nov 2024 20:12:01 +0100 Subject: [PATCH 30/34] More LinkAdrReq test cases + use actual device matrix to test RX1Offset validity --- model/class-a-end-device-lorawan-mac.cc | 2 +- test/lorawan-test-suite.cc | 85 +++++++++++++++++++++++-- 2 files changed, 80 insertions(+), 7 deletions(-) diff --git a/model/class-a-end-device-lorawan-mac.cc b/model/class-a-end-device-lorawan-mac.cc index b124f8c8cf..a40748b0c4 100644 --- a/model/class-a-end-device-lorawan-mac.cc +++ b/model/class-a-end-device-lorawan-mac.cc @@ -540,7 +540,7 @@ ClassAEndDeviceLorawanMac::OnRxParamSetupReq(uint8_t rx1DrOffset, bool rx2DataRateAck = true; bool channelAck = true; - if (rx1DrOffset >= 6) + if (rx1DrOffset >= m_replyDataRateMatrix.at(m_dataRate).size()) { NS_LOG_WARN("Invalid rx1DrOffset"); rx1DrOffsetAck = false; diff --git a/test/lorawan-test-suite.cc b/test/lorawan-test-suite.cc index 84cef906de..84be6d62bb 100644 --- a/test/lorawan-test-suite.cc +++ b/test/lorawan-test-suite.cc @@ -1783,9 +1783,9 @@ MacCommandTest::DoRun() { // WARNING: default values are manually set here uint8_t dataRate = 12; uint8_t txPower = 8; - uint16_t chMask = 0b1100; + uint16_t chMask = 0b0; uint8_t chMaskCntl = 0; - uint8_t nbTrans = 0; + uint8_t nbTrans = 6; auto answers = RunMacCommand(dataRate, txPower, chMask, chMaskCntl, nbTrans); NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetDataRate()), 0, @@ -1812,6 +1812,79 @@ MacCommandTest::DoRun() NS_TEST_EXPECT_MSG_EQ(laa->GetPowerAck(), false, "PowerAck expected to be false"); } + Reset(); + // LinkAdrReq: invalid chMask, valid data rate and power + { // WARNING: default values are manually set here + uint8_t dataRate = 1; + uint8_t txPower = 7; + uint16_t chMask = 0b1000; // enable only non-exisitng channel + uint8_t chMaskCntl = 0; + uint8_t nbTrans = 3; + auto answers = RunMacCommand(dataRate, txPower, chMask, chMaskCntl, nbTrans); + NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetDataRate()), + 0, + "m_dataRate expected to be default value"); + NS_TEST_EXPECT_MSG_EQ(m_mac->GetTransmissionPowerDbm(), + 14, + "m_txPowerDbm expected to be default value"); + NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetMaxNumberOfTransmissions()), + 1, + "m_nbTrans expected to be default value"); + auto channels = m_mac->GetLogicalLoraChannelHelper()->GetRawChannelArray(); + for (size_t i = 0; i < channels.size(); i++) + { + auto c = channels.at(i + 16 * chMaskCntl); + bool actual = (c) ? c->IsEnabledForUplink() : false; + bool expected = (uint16_t(0b111) & 0b1 << i); + NS_TEST_EXPECT_MSG_EQ(actual, expected, "Channel " << i << " state != default"); + } + NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1"); + auto laa = DynamicCast(answers.at(0)); + NS_TEST_ASSERT_MSG_NE(laa, nullptr, "LinkAdrAns was expected, cmd type cast failed"); + NS_TEST_EXPECT_MSG_EQ(laa->GetChannelMaskAck(), false, "ChannelMaskAck != false"); + NS_TEST_EXPECT_MSG_EQ(laa->GetDataRateAck(), true, "DataRateAck expected to be true"); + NS_TEST_EXPECT_MSG_EQ(laa->GetPowerAck(), true, "PowerAck expected to be true"); + } + + Reset(); + // LinkAdrReq: fringe parameter values + { // WARNING: default values are manually set here + uint8_t dataRate = 0xF; + uint8_t txPower = 0xF; // 0x0F ignores config + uint16_t chMask = 0b0; // should be ignored because chMaskCntl is 6 + uint8_t chMaskCntl = 6; // all channels on + uint8_t nbTrans = 0; // restore default 1 + // Set device params to values different from default + m_mac->SetDataRate(3); + m_mac->SetTransmissionPowerDbm(12); + m_mac->SetMaxNumberOfTransmissions(15); + auto channels = m_mac->GetLogicalLoraChannelHelper()->GetRawChannelArray(); + channels.at(0)->DisableForUplink(); + auto answers = RunMacCommand(dataRate, txPower, chMask, chMaskCntl, nbTrans); + NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetDataRate()), + 3, + "m_dataRate expected to be default value"); + NS_TEST_EXPECT_MSG_EQ(m_mac->GetTransmissionPowerDbm(), + 12, + "m_txPowerDbm expected to be default value"); + NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetMaxNumberOfTransmissions()), + 1, + "m_nbTrans expected to be default value"); + for (size_t i = 0; i < channels.size(); i++) + { + auto c = channels.at(i); + bool actual = (c) ? c->IsEnabledForUplink() : false; + bool expected = (uint16_t(0b111) & 0b1 << i); + NS_TEST_EXPECT_MSG_EQ(actual, expected, "Channel " << i << " state != default"); + } + NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1"); + auto laa = DynamicCast(answers.at(0)); + NS_TEST_ASSERT_MSG_NE(laa, nullptr, "LinkAdrAns was expected, cmd type cast failed"); + NS_TEST_EXPECT_MSG_EQ(laa->GetChannelMaskAck(), true, "ChannelMaskAck != true"); + NS_TEST_EXPECT_MSG_EQ(laa->GetDataRateAck(), true, "DataRateAck expected to be true"); + NS_TEST_EXPECT_MSG_EQ(laa->GetPowerAck(), true, "PowerAck expected to be true"); + } + Reset(); // DutyCycleReq: duty cycle to 100% { @@ -1847,10 +1920,10 @@ MacCommandTest::DoRun() m_mac->SetDataRate(5); auto answers = RunMacCommand(rx1DrOffset, rx2DataRate, frequencyHz); NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetFirstReceiveWindowDataRate()), - 5 - rx1DrOffset, + unsigned(5 - rx1DrOffset), "Rx1DataRate does not match rx1DrOffset from RxParamSetupReq"); NS_TEST_EXPECT_MSG_EQ(unsigned(m_mac->GetSecondReceiveWindowDataRate()), - rx2DataRate, + unsigned(rx2DataRate), "Rx2DataRate does not match rx2DataRate from RxParamSetupReq"); NS_TEST_EXPECT_MSG_EQ(m_mac->GetSecondReceiveWindowFrequency(), frequencyHz / 1e6, @@ -1866,7 +1939,7 @@ MacCommandTest::DoRun() Reset(); // RxParamSetupReq: invalid rx1Dr, rx2Dr, frequency { // WARNING: default values are manually set here - uint8_t rx1DrOffset = 7; + uint8_t rx1DrOffset = 6; uint8_t rx2DataRate = 12; double frequencyHz = 871000000; m_mac->SetDataRate(5); @@ -1895,7 +1968,7 @@ MacCommandTest::DoRun() NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1"); auto dsa = DynamicCast(answers.at(0)); NS_TEST_ASSERT_MSG_NE(dsa, nullptr, "DevStatusAns was expected, cmd type cast failed"); - NS_TEST_EXPECT_MSG_EQ(unsigned(dsa->GetBattery()), 0, "Battery != 0 (external power)"); + NS_TEST_EXPECT_MSG_EQ(unsigned(dsa->GetBattery()), 0, "Battery expected == 0 (ext power)"); NS_TEST_EXPECT_MSG_EQ(unsigned(dsa->GetMargin()), 31, "Margin expected to be 31 (default)"); } } From b65e9584a2bcaedf3cd618c991aaa81cd2b23bec Mon Sep 17 00:00:00 2001 From: Alessandro Aimi Date: Sun, 17 Nov 2024 20:12:46 +0100 Subject: [PATCH 31/34] Implement OnNewChannelReq and add MAC command test cases --- model/end-device-lorawan-mac.cc | 57 +++++++++++++++++++++++++---- test/lorawan-test-suite.cc | 64 +++++++++++++++++++++++++++++++++ 2 files changed, 115 insertions(+), 6 deletions(-) diff --git a/model/end-device-lorawan-mac.cc b/model/end-device-lorawan-mac.cc index 5959df67f3..79ba7b8686 100644 --- a/model/end-device-lorawan-mac.cc +++ b/model/end-device-lorawan-mac.cc @@ -864,15 +864,60 @@ EndDeviceLorawanMac::OnNewChannelReq(uint8_t chIndex, uint8_t minDataRate, uint8_t maxDataRate) { - NS_LOG_FUNCTION(this); + NS_LOG_FUNCTION(this << unsigned(chIndex) << uint32_t(frequencyHz) << unsigned(minDataRate) + << unsigned(maxDataRate)); + + NS_ASSERT_MSG(!(minDataRate & 0xF0), "minDataRate field > 4 bits"); + NS_ASSERT_MSG(!(maxDataRate & 0xF0), "maxDataRate field > 4 bits"); - bool dataRateRangeOk = true; // XXX Check whether the new data rate range is ok - bool channelFrequencyOk = true; // XXX Check whether the frequency is ok + // Adapted from: github.com/Lora-net/SWL2001.git v4.3.1 + // For the time being, this implementation is valid for the EU868 region - // TODO Return false if one of the checks above failed - // TODO Create new channel in the LogicalLoraChannelHelper + bool dataRateRangeOk = true; + bool channelFrequencyOk = true; - SetLogicalChannel(chIndex, frequencyHz, minDataRate, maxDataRate); + // Valid Channel Index + if (chIndex < 3 || chIndex > m_channelHelper->GetRawChannelArray().size() - 1) + { + NS_LOG_WARN("[WARNING] Invalid channel index"); + dataRateRangeOk = channelFrequencyOk = false; + } + + // Valid Frequency + if (frequencyHz != 0 && !m_channelHelper->IsFrequencyValid(frequencyHz / 1e6)) + { + NS_LOG_WARN("[WARNING] Invalid frequency"); + channelFrequencyOk = false; + } + + // Valid DRMIN/MAX + if (!GetSfFromDataRate(minDataRate) || !GetBandwidthFromDataRate(minDataRate)) + { + NS_LOG_WARN("[WARNING] Invalid DR min"); + dataRateRangeOk = false; + } + + if (!GetSfFromDataRate(maxDataRate) || !GetBandwidthFromDataRate(maxDataRate)) + { + NS_LOG_WARN("[WARNING] Invalid DR max"); + dataRateRangeOk = false; + } + + if (maxDataRate < minDataRate) + { + NS_LOG_WARN("[WARNING] Invalid DR max < DR min"); + dataRateRangeOk = false; + } + + if (dataRateRangeOk && channelFrequencyOk) + { + auto channel = Create(frequencyHz / 1e6, minDataRate, maxDataRate); + (frequencyHz == 0) ? channel->DisableForUplink() : channel->EnableForUplink(); + m_channelHelper->SetChannel(chIndex, channel); + NS_LOG_DEBUG("MacTxFrequency[" << unsigned(chIndex) << "]=" << uint32_t(frequencyHz) + << ", DrMin=" << unsigned(minDataRate) + << ", DrMax=" << unsigned(maxDataRate)); + } NS_LOG_INFO("Adding NewChannelAns reply"); m_macCommandList.emplace_back(Create(dataRateRangeOk, channelFrequencyOk)); diff --git a/test/lorawan-test-suite.cc b/test/lorawan-test-suite.cc index 84be6d62bb..49ca69d8e2 100644 --- a/test/lorawan-test-suite.cc +++ b/test/lorawan-test-suite.cc @@ -1971,6 +1971,70 @@ MacCommandTest::DoRun() NS_TEST_EXPECT_MSG_EQ(unsigned(dsa->GetBattery()), 0, "Battery expected == 0 (ext power)"); NS_TEST_EXPECT_MSG_EQ(unsigned(dsa->GetMargin()), 31, "Margin expected to be 31 (default)"); } + + Reset(); + // NewChannelReq: add a new channel + { + uint8_t chIndex = 4; + double frequencyHz = 865100000; + uint8_t minDataRate = 1; + uint8_t maxDataRate = 4; + auto answers = RunMacCommand(chIndex, frequencyHz, minDataRate, maxDataRate); + NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1"); + auto c = m_mac->GetLogicalLoraChannelHelper()->GetRawChannelArray().at(chIndex); + NS_TEST_ASSERT_MSG_NE(c, nullptr, "Channel at chIndex slot expected not to be nullptr"); + NS_TEST_EXPECT_MSG_EQ(c->GetFrequency(), + frequencyHz / 1e6, + "Channel frequency expected to equal NewChannelReq frequency"); + NS_TEST_EXPECT_MSG_EQ(c->GetMinimumDataRate(), + unsigned(minDataRate), + "Channel minDataRate expected to equal NewChannelReq minDataRate"); + NS_TEST_EXPECT_MSG_EQ(c->GetMaximumDataRate(), + unsigned(maxDataRate), + "Channel maxDataRate expected to equal NewChannelReq maxDataRate"); + auto nca = DynamicCast(answers.at(0)); + NS_TEST_ASSERT_MSG_NE(nca, nullptr, "NewChannelAns was expected, cmd type cast failed"); + NS_TEST_EXPECT_MSG_EQ(nca->GetDataRateRangeOk(), true, "DataRateRangeOk != true"); + NS_TEST_EXPECT_MSG_EQ(nca->GetChannelFrequencyOk(), true, "ChannelFrequencyOk != true"); + } + + Reset(); + // NewChannelReq: invalid new channel + { // WARNING: default values are manually set here + uint8_t chIndex = 1; + double frequencyHz = 862000000; + uint8_t minDataRate = 14; + uint8_t maxDataRate = 13; + auto answers = RunMacCommand(chIndex, frequencyHz, minDataRate, maxDataRate); + NS_TEST_ASSERT_MSG_EQ(answers.size(), 1, "1 answer cmd was expected, found 0 or >1"); + double defaultFrequenciesMHz[3] = {868.1, 868.3, 868.5}; + auto channels = m_mac->GetLogicalLoraChannelHelper()->GetRawChannelArray(); + for (size_t i = 0; i < channels.size(); i++) + { + auto c = channels.at(i); + if (i > 2) + { + NS_TEST_ASSERT_MSG_EQ(c, nullptr, "Channel " << i << "expected to be nullptr"); + continue; + } + NS_TEST_EXPECT_MSG_EQ(c->GetFrequency(), + defaultFrequenciesMHz[i], + "Channel frequency expected to equal NewChannelReq frequency"); + NS_TEST_EXPECT_MSG_EQ(unsigned(c->GetMinimumDataRate()), + 0, + "Channel " << i << " minDataRate expected to be default"); + NS_TEST_EXPECT_MSG_EQ(unsigned(c->GetMaximumDataRate()), + 5, + "Channel " << i << " maxDataRate expected to be default"); + NS_TEST_EXPECT_MSG_EQ(c->IsEnabledForUplink(), + true, + "Channel " << i << " state expected to be active by default"); + } + auto nca = DynamicCast(answers.at(0)); + NS_TEST_ASSERT_MSG_NE(nca, nullptr, "NewChannelAns was expected, cmd type cast failed"); + NS_TEST_EXPECT_MSG_EQ(nca->GetDataRateRangeOk(), false, "DataRateRangeOk != false"); + NS_TEST_EXPECT_MSG_EQ(nca->GetChannelFrequencyOk(), false, "ChannelFrequencyOk != false"); + } } /** From 769086359b04042ef40762140168f563167f237a Mon Sep 17 00:00:00 2001 From: Alessandro Aimi Date: Mon, 18 Nov 2024 09:38:23 +0100 Subject: [PATCH 32/34] Time-related code improvements - better time printing using Time::As() - prefer more general Time(0) instead Seconds(0) or others when indicatign zero time - use time methods Time::IsZero(), Time::IsPositive(), etc. when working with time - prefer shorter Now() in place of Simulator::Now() --- examples/aloha-throughput.cc | 2 +- examples/complete-network-example.cc | 4 ++-- examples/frame-counter-update.cc | 6 ++--- helper/lora-helper.cc | 33 ++++++++++++++-------------- helper/lora-packet-tracker.cc | 10 ++++----- helper/periodic-sender-helper.cc | 4 ++-- model/end-device-lorawan-mac.cc | 8 +++---- model/end-device-status.cc | 4 ++-- model/gateway-lorawan-mac.cc | 4 ++-- model/gateway-status.cc | 4 ++-- model/lora-channel.cc | 2 +- model/lora-interference-helper.cc | 14 ++++++------ model/lora-radio-energy-model.cc | 10 ++++----- model/periodic-sender.cc | 6 ++--- model/simple-end-device-lora-phy.cc | 3 +-- 15 files changed, 56 insertions(+), 58 deletions(-) diff --git a/examples/aloha-throughput.cc b/examples/aloha-throughput.cc index 4bf7a5957f..7d4a7cac31 100644 --- a/examples/aloha-throughput.cc +++ b/examples/aloha-throughput.cc @@ -258,7 +258,7 @@ main(int argc, char* argv[]) appHelper.SetPacketSize(packetSize); ApplicationContainer appContainer = appHelper.Install(endDevices); - appContainer.Start(Seconds(0)); + appContainer.Start(Time(0)); appContainer.Stop(appStopTime); std::ofstream outputFile; diff --git a/examples/complete-network-example.cc b/examples/complete-network-example.cc index be2a2686db..633e16bd2d 100644 --- a/examples/complete-network-example.cc +++ b/examples/complete-network-example.cc @@ -305,7 +305,7 @@ main(int argc, char* argv[]) DoubleValue(10)); ApplicationContainer appContainer = appHelper.Install(endDevices); - appContainer.Start(Seconds(0)); + appContainer.Start(Time(0)); appContainer.Stop(appStopTime); /************************** @@ -353,7 +353,7 @@ main(int argc, char* argv[]) NS_LOG_INFO("Computing performance metrics..."); LoraPacketTracker& tracker = helper.GetPacketTracker(); - std::cout << tracker.CountMacPacketsGlobally(Seconds(0), appStopTime + Hours(1)) << std::endl; + std::cout << tracker.CountMacPacketsGlobally(Time(0), appStopTime + Hours(1)) << std::endl; return 0; } diff --git a/examples/frame-counter-update.cc b/examples/frame-counter-update.cc index 013c80acd1..73279e118e 100644 --- a/examples/frame-counter-update.cc +++ b/examples/frame-counter-update.cc @@ -239,14 +239,14 @@ main(int argc, char* argv[]) Time appStopTime = Seconds(simulationTimeSeconds); OneShotSenderHelper appHelper = OneShotSenderHelper(); - appHelper.SetSendTime(Seconds(0)); + appHelper.SetSendTime(Time(0)); ApplicationContainer appContainer = appHelper.Install(endDevices); appHelper.SetSendTime(Seconds(100)); appContainer.Add(appHelper.Install(endDevices)); appHelper.SetSendTime(Seconds(200)); appContainer.Add(appHelper.Install(endDevices)); - appContainer.Start(Seconds(0)); + appContainer.Start(Time(0)); appContainer.Stop(appStopTime); Simulator::Schedule(Seconds(110), &ChangeEndDevicePosition, endDevices.Get(0), true); @@ -298,7 +298,7 @@ main(int argc, char* argv[]) LoraPacketTracker& tracker = helper.GetPacketTracker(); NS_LOG_INFO("Printing total sent MAC-layer packets and successful MAC-layer packets"); - std::cout << tracker.CountMacPacketsGlobally(Seconds(0), appStopTime + Hours(1)) << std::endl; + std::cout << tracker.CountMacPacketsGlobally(Time(0), appStopTime + Hours(1)) << std::endl; return 0; } diff --git a/helper/lora-helper.cc b/helper/lora-helper.cc index 62ebe5c8f7..de38ed7bf2 100644 --- a/helper/lora-helper.cc +++ b/helper/lora-helper.cc @@ -20,8 +20,8 @@ namespace lorawan NS_LOG_COMPONENT_DEFINE("LoraHelper"); LoraHelper::LoraHelper() - : m_lastPhyPerformanceUpdate(Seconds(0)), - m_lastGlobalPerformanceUpdate(Seconds(0)) + : m_lastPhyPerformanceUpdate(Time(0)), + m_lastGlobalPerformanceUpdate(Time(0)) { } @@ -151,7 +151,7 @@ void LoraHelper::EnableSimulationTimePrinting(Time interval) { m_oldtime = std::time(nullptr); - Simulator::Schedule(Seconds(0), &LoraHelper::DoPrintSimulationTime, this, interval); + Simulator::Schedule(Time(0), &LoraHelper::DoPrintSimulationTime, this, interval); } void @@ -181,7 +181,7 @@ LoraHelper::DoPrintDeviceStatus(NodeContainer endDevices, { const char* c = filename.c_str(); std::ofstream outputFile; - if (Simulator::Now() == Seconds(0)) + if (Now().IsZero()) { // Delete contents of the file as it is opened outputFile.open(c, std::ofstream::out | std::ofstream::trunc); @@ -192,7 +192,7 @@ LoraHelper::DoPrintDeviceStatus(NodeContainer endDevices, outputFile.open(c, std::ofstream::out | std::ofstream::app); } - Time currentTime = Simulator::Now(); + Time currentTime = Now(); for (auto j = endDevices.Begin(); j != endDevices.End(); ++j) { Ptr object = *j; @@ -206,7 +206,7 @@ LoraHelper::DoPrintDeviceStatus(NodeContainer endDevices, int dr = int(mac->GetDataRate()); double txPower = mac->GetTransmissionPowerDbm(); Vector pos = position->GetPosition(); - outputFile << currentTime.GetSeconds() << " " << object->GetId() << " " << pos.x << " " + outputFile << currentTime.As(Time::S) << " " << object->GetId() << " " << pos.x << " " << pos.y << " " << dr << " " << unsigned(txPower) << std::endl; } // for (NodeContainer::Iterator j = gateways.Begin (); j != gateways.End (); ++j) @@ -245,7 +245,7 @@ LoraHelper::DoPrintPhyPerformance(NodeContainer gateways, std::string filename) const char* c = filename.c_str(); std::ofstream outputFile; - if (Simulator::Now() == Seconds(0)) + if (Now().IsZero()) { // Delete contents of the file as it is opened outputFile.open(c, std::ofstream::out | std::ofstream::trunc); @@ -259,14 +259,14 @@ LoraHelper::DoPrintPhyPerformance(NodeContainer gateways, std::string filename) for (auto it = gateways.Begin(); it != gateways.End(); ++it) { int systemId = (*it)->GetId(); - outputFile << Simulator::Now().GetSeconds() << " " << std::to_string(systemId) << " " + outputFile << Now().As(Time::S) << " " << std::to_string(systemId) << " " << m_packetTracker->PrintPhyPacketsPerGw(m_lastPhyPerformanceUpdate, - Simulator::Now(), + Now(), systemId) << std::endl; } - m_lastPhyPerformanceUpdate = Simulator::Now(); + m_lastPhyPerformanceUpdate = Now(); outputFile.close(); } @@ -292,7 +292,7 @@ LoraHelper::DoPrintGlobalPerformance(std::string filename) const char* c = filename.c_str(); std::ofstream outputFile; - if (Simulator::Now() == Seconds(0)) + if (Now().IsZero()) { // Delete contents of the file as it is opened outputFile.open(c, std::ofstream::out | std::ofstream::trunc); @@ -303,12 +303,11 @@ LoraHelper::DoPrintGlobalPerformance(std::string filename) outputFile.open(c, std::ofstream::out | std::ofstream::app); } - outputFile << Simulator::Now().GetSeconds() << " " - << m_packetTracker->CountMacPacketsGlobally(m_lastGlobalPerformanceUpdate, - Simulator::Now()) + outputFile << Now().As(Time::S) << " " + << m_packetTracker->CountMacPacketsGlobally(m_lastGlobalPerformanceUpdate, Now()) << std::endl; - m_lastGlobalPerformanceUpdate = Simulator::Now(); + m_lastGlobalPerformanceUpdate = Now(); outputFile.close(); } @@ -316,8 +315,8 @@ LoraHelper::DoPrintGlobalPerformance(std::string filename) void LoraHelper::DoPrintSimulationTime(Time interval) { - // NS_LOG_INFO ("Time: " << Simulator::Now().GetHours()); - std::cout << "Simulated time: " << Simulator::Now().GetHours() << " hours" << std::endl; + // NS_LOG_INFO ("Time: " << Now().As(Time::H)); + std::cout << "Simulated time: " << Now().As(Time::H) << std::endl; std::cout << "Real time from last call: " << std::time(nullptr) - m_oldtime << " seconds" << std::endl; m_oldtime = std::time(nullptr); diff --git a/helper/lora-packet-tracker.cc b/helper/lora-packet-tracker.cc index 534a404254..5c1290cae0 100644 --- a/helper/lora-packet-tracker.cc +++ b/helper/lora-packet-tracker.cc @@ -44,7 +44,7 @@ LoraPacketTracker::MacTransmissionCallback(Ptr packet) MacPacketStatus status; status.packet = packet; - status.sendTime = Simulator::Now(); + status.sendTime = Now(); status.senderId = Simulator::GetContext(); status.receivedTime = Time::Max(); @@ -60,11 +60,11 @@ LoraPacketTracker::RequiredTransmissionsCallback(uint8_t reqTx, { NS_LOG_INFO("Finished retransmission attempts for a packet"); NS_LOG_DEBUG("Packet: " << packet << "ReqTx " << unsigned(reqTx) << ", succ: " << success - << ", firstAttempt: " << firstAttempt.GetSeconds()); + << ", firstAttempt: " << firstAttempt.As(Time::S)); RetransmissionStatus entry; entry.firstAttempt = firstAttempt; - entry.finishTime = Simulator::Now(); + entry.finishTime = Now(); entry.reTxAttempts = reqTx; entry.successful = success; @@ -84,7 +84,7 @@ LoraPacketTracker::MacGwReceptionCallback(Ptr packet) if (it != m_macPacketTracker.end()) { (*it).second.receptionTimes.insert( - std::pair(Simulator::GetContext(), Simulator::Now())); + std::pair(Simulator::GetContext(), Now())); } else { @@ -106,7 +106,7 @@ LoraPacketTracker::TransmissionCallback(Ptr packet, uint32_t edId) // Create a packetStatus PacketStatus status; status.packet = packet; - status.sendTime = Simulator::Now(); + status.sendTime = Now(); status.senderId = edId; m_packetTracker.insert(std::pair, PacketStatus>(packet, status)); diff --git a/helper/periodic-sender-helper.cc b/helper/periodic-sender-helper.cc index bab6fbbf48..8e77524d07 100644 --- a/helper/periodic-sender-helper.cc +++ b/helper/periodic-sender-helper.cc @@ -77,7 +77,7 @@ PeriodicSenderHelper::InstallPriv(Ptr node) const Ptr app = m_factory.Create(); Time interval; - if (m_period == Seconds(0)) + if (m_period.IsZero()) { double intervalProb = m_intervalProb->GetValue(); NS_LOG_DEBUG("IntervalProb = " << intervalProb); @@ -106,7 +106,7 @@ PeriodicSenderHelper::InstallPriv(Ptr node) const } app->SetInterval(interval); - NS_LOG_DEBUG("Created an application with interval = " << interval.GetHours() << " hours"); + NS_LOG_DEBUG("Created an application with interval = " << interval.As(Time::H)); app->SetInitialDelay(Seconds(m_initialDelay->GetValue(0, interval.GetSeconds()))); app->SetPacketSize(m_pktSize); diff --git a/model/end-device-lorawan-mac.cc b/model/end-device-lorawan-mac.cc index 79ba7b8686..5a068f3e28 100644 --- a/model/end-device-lorawan-mac.cc +++ b/model/end-device-lorawan-mac.cc @@ -152,7 +152,7 @@ EndDeviceLorawanMac::Send(Ptr packet) // or because we are receiving, schedule a tx/retx later Time netxTxDelay = GetNextTransmissionDelay(); - if (netxTxDelay != Seconds(0)) + if (netxTxDelay.IsStrictlyPositive()) { postponeTransmission(netxTxDelay, packet); return; @@ -192,7 +192,7 @@ EndDeviceLorawanMac::postponeTransmission(Time netxTxDelay, Ptr packet) m_nextTx = Simulator::Schedule(netxTxDelay, &EndDeviceLorawanMac::DoSend, this, packet); NS_LOG_WARN("Attempting to send, but the aggregate duty cycle won't allow it. Scheduling a tx " "at a delay " - << netxTxDelay.GetSeconds() << "."); + << netxTxDelay.As(Time::S) << "."); } void @@ -253,7 +253,7 @@ EndDeviceLorawanMac::DoSend(Ptr packet) m_retxParams.packet = packet->Copy(); m_retxParams.retxLeft = m_nbTrans; m_retxParams.waitingAck = true; - m_retxParams.firstAttempt = Simulator::Now(); + m_retxParams.firstAttempt = Now(); m_retxParams.retxLeft = m_retxParams.retxLeft - 1; // decreasing the number of retransmissions @@ -545,7 +545,7 @@ EndDeviceLorawanMac::resetRetransmissionParameters() m_retxParams.waitingAck = false; m_retxParams.retxLeft = m_nbTrans; m_retxParams.packet = nullptr; - m_retxParams.firstAttempt = Seconds(0); + m_retxParams.firstAttempt = Time(0); // Cancel next retransmissions, if any Simulator::Cancel(m_nextTx); diff --git a/model/end-device-status.cc b/model/end-device-status.cc index a1a4bed1ad..0c237c26d2 100644 --- a/model/end-device-status.cc +++ b/model/end-device-status.cc @@ -288,7 +288,7 @@ EndDeviceStatus::InsertReceivedPacket(Ptr receivedPacket, const Ad GatewayList& gwList = it->second.gwList; PacketInfoPerGw gwInfo; - gwInfo.receivedTime = Simulator::Now(); + gwInfo.receivedTime = Now(); gwInfo.rxPower = rcvPower; gwInfo.gwAddress = gwAddress; gwList.insert(std::pair(gwAddress, gwInfo)); @@ -302,7 +302,7 @@ EndDeviceStatus::InsertReceivedPacket(Ptr receivedPacket, const Ad { NS_LOG_INFO("Packet was received for the first time"); PacketInfoPerGw gwInfo; - gwInfo.receivedTime = Simulator::Now(); + gwInfo.receivedTime = Now(); gwInfo.rxPower = rcvPower; gwInfo.gwAddress = gwAddress; info.gwList.insert(std::pair(gwAddress, gwInfo)); diff --git a/model/gateway-lorawan-mac.cc b/model/gateway-lorawan-mac.cc index 1799e0fc7c..89b4f0bcc5 100644 --- a/model/gateway-lorawan-mac.cc +++ b/model/gateway-lorawan-mac.cc @@ -60,7 +60,7 @@ GatewayLorawanMac::Send(Ptr packet) packet->AddPacketTag(tag); // Make sure we can transmit this packet - if (GetWaitTime(frequencyMHz) > Time(0)) + if (GetWaitTime(frequencyMHz).IsStrictlyPositive()) { // We cannot send now! NS_LOG_WARN("Trying to send a packet but Duty Cycle won't allow it. Aborting."); @@ -79,7 +79,7 @@ GatewayLorawanMac::Send(Ptr packet) // Get the duration Time duration = LoraPhy::GetOnAirTime(packet, params); - NS_LOG_DEBUG("Duration: " << duration.GetSeconds()); + NS_LOG_DEBUG("Duration: " << duration.As(Time::S)); // Find the channel with the desired frequency double sendingPower = m_channelHelper->GetTxPowerForChannel(frequencyMHz); diff --git a/model/gateway-status.cc b/model/gateway-status.cc index 8df603e07c..e6235d00d3 100644 --- a/model/gateway-status.cc +++ b/model/gateway-status.cc @@ -41,7 +41,7 @@ GatewayStatus::GatewayStatus(Address address, : m_address(address), m_netDevice(netDevice), m_gatewayMac(gwMac), - m_nextTransmissionTime(Seconds(0)) + m_nextTransmissionTime(Time(0)) { NS_LOG_FUNCTION(this); } @@ -86,7 +86,7 @@ GatewayStatus::IsAvailableForTransmission(double frequencyMHz) // We can't send multiple packets at once, see SX1301 V2.01 page 29 // Check that the gateway was not already "booked" - if (m_nextTransmissionTime > Simulator::Now() - MilliSeconds(1)) + if (m_nextTransmissionTime > Now() - MilliSeconds(1)) { NS_LOG_INFO("This gateway is already booked for a transmission"); return false; diff --git a/model/lora-channel.cc b/model/lora-channel.cc index debb11819b..5301f1d6e3 100644 --- a/model/lora-channel.cc +++ b/model/lora-channel.cc @@ -202,7 +202,7 @@ std::ostream& operator<<(std::ostream& os, const LoraChannelParameters& params) { os << "(rxPowerDbm: " << params.rxPowerDbm << ", SF: " << unsigned(params.sf) - << ", durationSec: " << params.duration.GetSeconds() + << ", durationSec: " << params.duration.As(Time::S) << ", frequencyMHz: " << params.frequencyMHz << ")"; return os; } diff --git a/model/lora-interference-helper.cc b/model/lora-interference-helper.cc index bb03a5cc1a..f06f411595 100644 --- a/model/lora-interference-helper.cc +++ b/model/lora-interference-helper.cc @@ -30,7 +30,7 @@ LoraInterferenceHelper::Event::Event(Time duration, uint8_t spreadingFactor, Ptr packet, double frequencyMHz) - : m_startTime(Simulator::Now()), + : m_startTime(Now()), m_endTime(m_startTime + duration), m_sf(spreadingFactor), m_rxPowerdBm(rxPowerdBm), @@ -92,7 +92,7 @@ LoraInterferenceHelper::Event::GetFrequency() const void LoraInterferenceHelper::Event::Print(std::ostream& stream) const { - stream << "(" << m_startTime.GetSeconds() << " s - " << m_endTime.GetSeconds() << " s), SF" + stream << "(" << m_startTime.As(Time::S) << " - " << m_endTime.As(Time::S) << "), SF" << unsigned(m_sf) << ", " << m_rxPowerdBm << " dBm, " << m_frequencyMHz << " MHz"; } @@ -187,7 +187,7 @@ LoraInterferenceHelper::Add(Time duration, Ptr packet, double frequencyMHz) { - NS_LOG_FUNCTION(this << duration.GetSeconds() << rxPower << unsigned(spreadingFactor) << packet + NS_LOG_FUNCTION(this << duration << rxPower << unsigned(spreadingFactor) << packet << frequencyMHz); // Create an event based on the parameters @@ -218,7 +218,7 @@ LoraInterferenceHelper::CleanOldEvents() // Cycle the events, and clean up if an event is old. for (auto it = m_events.begin(); it != m_events.end();) { - if ((*it)->GetEndTime() + oldEventThreshold < Simulator::Now()) + if ((*it)->GetEndTime() + oldEventThreshold < Now()) { it = m_events.erase(it); } @@ -266,7 +266,7 @@ LoraInterferenceHelper::IsDestroyedByInterference(PtrGetFrequency(); // Handy information about the time frame when the packet was received - Time now = Simulator::Now(); + Time now = Now(); Time duration = event->GetDuration(); Time packetStartTime = now - duration; @@ -308,7 +308,7 @@ LoraInterferenceHelper::IsDestroyedByInterference(Ptr event1 // Non-overlapping events if (e1 <= s2 || e2 <= s1) { - overlap = Seconds(0); + overlap = Time(0); } // event1 before event2 else if (s1 < s2) diff --git a/model/lora-radio-energy-model.cc b/model/lora-radio-energy-model.cc index 1bd1d91ccd..426c520262 100644 --- a/model/lora-radio-energy-model.cc +++ b/model/lora-radio-energy-model.cc @@ -210,8 +210,8 @@ LoraRadioEnergyModel::ChangeState(int newState) { NS_LOG_FUNCTION(this << newState); - Time duration = Simulator::Now() - m_lastUpdateTime; - NS_ASSERT(duration.GetNanoSeconds() >= 0); // check if duration is valid + Time duration = Now() - m_lastUpdateTime; + NS_ASSERT(duration.IsPositive()); // check if duration is valid // energy to decrease = current * voltage * time double energyToDecrease = 0.0; @@ -238,7 +238,7 @@ LoraRadioEnergyModel::ChangeState(int newState) m_totalEnergyConsumption += energyToDecrease; // update last update time stamp - m_lastUpdateTime = Simulator::Now(); + m_lastUpdateTime = Now(); m_nPendingChangeState++; @@ -357,8 +357,8 @@ LoraRadioEnergyModel::SetLoraRadioState(const EndDeviceLoraPhy::State state) stateName = "SLEEP"; break; } - NS_LOG_DEBUG("LoraRadioEnergyModel:Switching to state: " - << stateName << " at time = " << Simulator::Now().GetSeconds() << " s"); + NS_LOG_DEBUG("LoraRadioEnergyModel:Switching to state: " << stateName + << " at time = " << Now().As(Time::S)); } // -------------------------------------------------------------------------- // diff --git a/model/periodic-sender.cc b/model/periodic-sender.cc index e5b296fa70..580fd0d101 100644 --- a/model/periodic-sender.cc +++ b/model/periodic-sender.cc @@ -33,7 +33,7 @@ PeriodicSender::GetTypeId() .SetGroupName("lorawan") .AddAttribute("Interval", "The interval between packet sends of this app", - TimeValue(Seconds(0)), + TimeValue(Time(0)), MakeTimeAccessor(&PeriodicSender::GetInterval, &PeriodicSender::SetInterval), MakeTimeChecker()); @@ -134,8 +134,8 @@ PeriodicSender::StartApplication() // Schedule the next SendPacket event Simulator::Cancel(m_sendEvent); - NS_LOG_DEBUG("Starting up application with a first event with a " << m_initialDelay.GetSeconds() - << " seconds delay"); + NS_LOG_DEBUG("Starting up application with a first event with a " << m_initialDelay.As(Time::S) + << " delay"); m_sendEvent = Simulator::Schedule(m_initialDelay, &PeriodicSender::SendPacket, this); NS_LOG_DEBUG("Event Id: " << m_sendEvent.GetUid()); } diff --git a/model/simple-end-device-lora-phy.cc b/model/simple-end-device-lora-phy.cc index 6f452115cc..9b4a269da2 100644 --- a/model/simple-end-device-lora-phy.cc +++ b/model/simple-end-device-lora-phy.cc @@ -216,8 +216,7 @@ SimpleEndDeviceLoraPhy::StartReceive(Ptr packet, SwitchToRx(); // Schedule the end of the reception of the packet - NS_LOG_INFO("Scheduling reception of a packet. End in " << duration.GetSeconds() - << " seconds"); + NS_LOG_INFO("Scheduling reception of a packet. End in " << duration.As(Time::S)); Simulator::Schedule(duration, &LoraPhy::EndReceive, this, packet, event); From 7377e2b062895837d7099b6b51d97cb8538e3bf2 Mon Sep 17 00:00:00 2001 From: Alessandro Aimi Date: Mon, 18 Nov 2024 10:47:03 +0100 Subject: [PATCH 33/34] Fix new doxygen warnings --- model/class-a-end-device-lorawan-mac.h | 13 +++++++++++++ model/end-device-lorawan-mac.h | 15 --------------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/model/class-a-end-device-lorawan-mac.h b/model/class-a-end-device-lorawan-mac.h index e8d76c911d..e3d585ed58 100644 --- a/model/class-a-end-device-lorawan-mac.h +++ b/model/class-a-end-device-lorawan-mac.h @@ -67,8 +67,21 @@ class ClassAEndDeviceLorawanMac : public EndDeviceLorawanMac */ void Receive(Ptr packet) override; + /** + * Function called by lower layers to inform this layer that reception of a + * packet we were locked on failed. + * + * \param packet The packet we failed to receive. + */ void FailedReception(Ptr packet) override; + /** + * Perform the actions that are required after a packet send. + * + * This function handles opening of the first receive window. + * + * \param packet The packet that has just been transmitted. + */ void TxFinished(Ptr packet) override; /** diff --git a/model/end-device-lorawan-mac.h b/model/end-device-lorawan-mac.h index 2762584811..c802d39810 100644 --- a/model/end-device-lorawan-mac.h +++ b/model/end-device-lorawan-mac.h @@ -83,25 +83,10 @@ class EndDeviceLorawanMac : public LorawanMac // Receiving methods // /////////////////////// - /** - * Receive a packet. - * - * This method is typically registered as a callback in the underlying PHY - * layer so that it's called when a packet is going up the stack. - * - * \param packet The received packet. - */ void Receive(Ptr packet) override; void FailedReception(Ptr packet) override; - /** - * Perform the actions that are required after a packet send. - * - * This function handles opening of the first receive window. - * - * \param packet The packet that has just been transmitted. - */ void TxFinished(Ptr packet) override; ///////////////////////// From ee04065eec16e23ef4aa66577afdddf02537bcc7 Mon Sep 17 00:00:00 2001 From: Alessandro Aimi Date: Mon, 18 Nov 2024 12:37:25 +0100 Subject: [PATCH 34/34] Address clang-tidy-18 warnings --- model/end-device-lorawan-mac.cc | 2 +- test/lorawan-test-suite.cc | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/model/end-device-lorawan-mac.cc b/model/end-device-lorawan-mac.cc index 5a068f3e28..011a9e1822 100644 --- a/model/end-device-lorawan-mac.cc +++ b/model/end-device-lorawan-mac.cc @@ -752,7 +752,7 @@ EndDeviceLorawanMac::OnLinkAdrReq(uint8_t dataRate, { if (chMask & 0b1 << i) // all enabled by chMask, even if it was invalid { - if (auto c = channels.at(i); c) // exists + if (const auto& c = channels.at(i); c) // exists { if (dataRate >= c->GetMinimumDataRate() && dataRate <= c->GetMaximumDataRate()) diff --git a/test/lorawan-test-suite.cc b/test/lorawan-test-suite.cc index 49ca69d8e2..8cef45066d 100644 --- a/test/lorawan-test-suite.cc +++ b/test/lorawan-test-suite.cc @@ -1730,7 +1730,7 @@ MacCommandTest::DoRun() auto channels = m_mac->GetLogicalLoraChannelHelper()->GetRawChannelArray(); for (size_t i = 0; i < channels.size(); i++) { - auto c = channels.at(i + 16 * chMaskCntl); + const auto& c = channels.at(i + 16 * chMaskCntl); bool actual = (c) ? c->IsEnabledForUplink() : false; bool expected = (chMask & 0b1 << i); NS_TEST_EXPECT_MSG_EQ(actual, expected, "Channel " << i << " state != chMask"); @@ -1765,7 +1765,7 @@ MacCommandTest::DoRun() auto channels = m_mac->GetLogicalLoraChannelHelper()->GetRawChannelArray(); for (size_t i = 0; i < channels.size(); i++) { - auto c = channels.at(i + 16 * chMaskCntl); + const auto& c = channels.at(i + 16 * chMaskCntl); bool actual = (c) ? c->IsEnabledForUplink() : false; bool expected = (chMask & 0b1 << i); NS_TEST_EXPECT_MSG_EQ(actual, expected, "Channel " << i << " state != chMask"); @@ -1799,7 +1799,7 @@ MacCommandTest::DoRun() auto channels = m_mac->GetLogicalLoraChannelHelper()->GetRawChannelArray(); for (size_t i = 0; i < channels.size(); i++) { - auto c = channels.at(i + 16 * chMaskCntl); + const auto& c = channels.at(i + 16 * chMaskCntl); bool actual = (c) ? c->IsEnabledForUplink() : false; bool expected = (uint16_t(0b111) & 0b1 << i); NS_TEST_EXPECT_MSG_EQ(actual, expected, "Channel " << i << " state != default"); @@ -1833,7 +1833,7 @@ MacCommandTest::DoRun() auto channels = m_mac->GetLogicalLoraChannelHelper()->GetRawChannelArray(); for (size_t i = 0; i < channels.size(); i++) { - auto c = channels.at(i + 16 * chMaskCntl); + const auto& c = channels.at(i + 16 * chMaskCntl); bool actual = (c) ? c->IsEnabledForUplink() : false; bool expected = (uint16_t(0b111) & 0b1 << i); NS_TEST_EXPECT_MSG_EQ(actual, expected, "Channel " << i << " state != default"); @@ -1872,7 +1872,7 @@ MacCommandTest::DoRun() "m_nbTrans expected to be default value"); for (size_t i = 0; i < channels.size(); i++) { - auto c = channels.at(i); + const auto& c = channels.at(i); bool actual = (c) ? c->IsEnabledForUplink() : false; bool expected = (uint16_t(0b111) & 0b1 << i); NS_TEST_EXPECT_MSG_EQ(actual, expected, "Channel " << i << " state != default"); @@ -2011,7 +2011,7 @@ MacCommandTest::DoRun() auto channels = m_mac->GetLogicalLoraChannelHelper()->GetRawChannelArray(); for (size_t i = 0; i < channels.size(); i++) { - auto c = channels.at(i); + const auto& c = channels.at(i); if (i > 2) { NS_TEST_ASSERT_MSG_EQ(c, nullptr, "Channel " << i << "expected to be nullptr");