signetlabdei / lorawan

An ns-3 module for simulation of LoRaWAN networks
GNU General Public License v2.0
182 stars 130 forks source link

Transmission disappearing when sent before second Rx window #163

Open klementc opened 4 months ago

klementc commented 4 months ago

Expected Behavior

Hello, if I send two uplink packets from the same node in a short time, I encounter 2 different behaviors for the second packet's transmission. The expected behavior is for the second packet to be scheduled after making sure the reception windows of the first packet are closed, and DC rules are respected.

Actual Behavior

I encounter 2 different behaviors depending on the timestamp of the Send() function:

  1. The second send() is made after the second reception window of the first packet is closed. In this case, the DC delay is computed, and the packet is delayed to later. In this case, the packet is sent after the delay expired.
  2. The second send() is made before the second reception window of the first packet is closed. In this case, the second packet is never sent, despite the logs notifying the scheduling of the send event after a delay.

Steps to Reproduce the Problem

I modify the simple-network-example to add a second transmission:

diff --git a/examples/simple-network-example.cc b/examples/simple-network-example.cc
index c1714e0..0787efd 100644
--- a/examples/simple-network-example.cc
+++ b/examples/simple-network-example.cc
@@ -150,7 +150,8 @@ main(int argc, char* argv[])
     oneShotSenderHelper.SetSendTime(Seconds(2));

     oneShotSenderHelper.Install(endDevices);
-
+    oneShotSenderHelper.SetSendTime(Seconds(4));
+    oneShotSenderHelper.Install(endDevices);
     /******************
      * Set Data Rates *
      ******************/

In this case, the (parsed) logs output:

#+BEGIN_SRC output
[FIRST PACKET RECEIVED WITH NO PROBLEM, FIRST RX WINDOW FINISHED, NOW SEND THE SECOND PACKET]
+4.000000000s 0 OneShotSender:SendPacket(0x582a2e609110)
+4.000000000s 0 EndDeviceLorawanMac:Send(0x582a2e607000, 0x582a2e6074c0)
+4.000000000s 0 EndDeviceLorawanMac:GetNextTransmissionDelay()
+4.000000000s 0 LogicalLoraChannelHelper:GetEnabledChannelList(0x582a2e607078)
+4.000000000s 0 LogicalLoraChannelHelper:GetWaitingTime(0x582a2e607078, 0x582a2e606970)
+4.000000000s 0 LogicalLoraChannelHelper:GetWaitingTime(): Waiting time: 3.09414
+4.000000000s 0 EndDeviceLorawanMac:GetNextTransmissionDelay(): Waiting time before the next transmission in channel with frequecy 868.1 is = 3.09414.
+4.000000000s 0 LogicalLoraChannelHelper:GetWaitingTime(0x582a2e607078, 0x582a2e606790)
+4.000000000s 0 LogicalLoraChannelHelper:GetWaitingTime(): Waiting time: 3.09414
+4.000000000s 0 EndDeviceLorawanMac:GetNextTransmissionDelay(): Waiting time before the next transmission in channel with frequecy 868.3 is = 3.09414.
+4.000000000s 0 LogicalLoraChannelHelper:GetWaitingTime(0x582a2e607078, 0x582a2e6067d0)
+4.000000000s 0 LogicalLoraChannelHelper:GetWaitingTime(): Waiting time: 3.09414
+4.000000000s 0 EndDeviceLorawanMac:GetNextTransmissionDelay(): Waiting time before the next transmission in channel with frequecy 868.5 is = 3.09414.
+4.000000000s 0 ClassAEndDeviceLorawanMac:GetNextClassTransmissionDelay()
+4.000000000s 0 ClassAEndDeviceLorawanMac:GetNextClassTransmissionDelay(): Attempting to send when there are receive windows: Transmission postponed.
+4.000000000s 0 LorawanMac:GetSfFromDataRate(0x582a2e607000, 0)
+4.000000000s 0 LorawanMac:GetBandwidthFromDataRate(0x582a2e607000, 0)
+4.000000000s 0 ClassAEndDeviceLorawanMac:GetNextClassTransmissionDelay(): Duration until endSecondRxWindow for new transmission:0.3136
+4.000000000s 0 EndDeviceLorawanMac:postponeTransmission(0x582a2e607000)
+4.000000000s 0 EndDeviceLorawanMac:postponeTransmission(): Attempting to send, but the aggregate duty cycle won't allow it. Scheduling a tx at a delay 3.09414.
+4.051456010s 0 ClassAEndDeviceLorawanMac:OpenSecondReceiveWindow()
+4.051456010s 0 EndDeviceLoraPhy:GetState()
+4.051456010s 0 EndDeviceLoraPhy:SwitchToStandby()
+4.051456010s 0 ClassAEndDeviceLorawanMac:OpenSecondReceiveWindow(): Using parameters: 869.525Hz, DR0
+4.051456010s 0 LorawanMac:GetSfFromDataRate(0x582a2e607000, 0)
+4.051456010s 0 LorawanMac:GetSfFromDataRate(0x582a2e607000, 0)
+4.051456010s 0 LorawanMac:GetBandwidthFromDataRate(0x582a2e607000, 0)
+4.313600010s 0 ClassAEndDeviceLorawanMac:CloseSecondReceiveWindow()
+4.313600010s 0 EndDeviceLoraPhy:GetState()
+4.313600010s 0 EndDeviceLoraPhy:SwitchToSleep()
+4.313600010s 0 ClassAEndDeviceLorawanMac:CloseSecondReceiveWindow(): We have 8 transmissions left. We were not transmitting confirmed messages.
OneShotSender:~OneShotSender()
OneShotSender:~OneShotSender()
#+END_SRC

We observe the delayed scheduling of the second packet transmission 3.09414 seconds after its supposed emission time. However, the transmission never starts. If using a Tx time later than the second receive window (i.e. 4.3136), the second packet is delayed in a similar way, and sent successfully after this delay.

I think this behavior shouldn't happen and the postponed transmission should take place after considering DC rules.

The reason for this to happen is the resetRetransmissionParameters() function called in CloseSecondReceiveWindow() that cancels the future transmission. Simulator::Cancel(m_nextTx); deletes the future Tx, causing this issue.

If this is the expected behavior, how should I schedule the tx of multiple packets from the application

Specifications

non-det-alle commented 4 months ago

Hello Clément,

Yes, we are aware of this problem (among others!) in the current implementation of the MAC layer. In general, real LoRaWAN applications would not request two uplink transmission in such a short time span (2 seconds). As you noted, the responsibility not to schedule a second uplink transmission in such a short time frame is currently left to the user. I agree that in the future it should be prevented to avoid unexpected behavior; it is already on the list of planned changes to this module in the dedicated issue.

I'll take this chance to write down how - in my opinion - the intended behavior should be; then we can see whether to take the time to implement it, or just patch your issue for now.

If we look at an actual implementation of the LoRaWAN MAC layer, we see that you should not be able to transmit a new packet neither while the device is still busy with the reception procedure (i.e., the 2 reception windows), nor if there are further retransmission scheduled for a previous packet. The way they prevent you from doing that is by having an internal task scheduler, acting as a size-1 buffer for send events. The send task is only launched if the MAC layer is IDLE, i.e., not planning to open a reception window, not planning to retransmit a packet, etc.

Interestingly, this implementation seems to interrupt the retransmission procedure if no channel with available duty-cycle is found after closing the 2nd reception window. Note that here the duty-cycle is managed in 1 hour periods (i.e., with a 1% DC you'd have 36 cumulative seconds to use for TX in the band for the current hour), providing more time management flexibility than our implementation.

For now, you may want to avoid scheduling a second call to Send while the device is still in the process of opening reception windows. I'll leave this issue open for further discussion and updates.

klementc commented 4 months ago

Hello, thank you for your answer. I know that it is uncommon to have applications sending messages within such short delays, but I am interested in simulating what would happen in such situations. I guess for now the best is to rely on callbacks to wait for the finish of the second window before sending new packets, thank you