Lora-net/LoRaMac-node

Dutycycle-related deadlock in ScheduleTx

Closed this issue · 0 comments

I think there is a deadlock in the function ScheduleTx which manifests itself at the end of a dutycycle-enforced quiet period while the MAC is retransmitting an uplink. If RegionNextChannel returns a zero DutyCycleWaitTime, the function forgoes creating TxDelayedTimer and returns immediately:

LoRaMac-node/src/mac/LoRaMac.c

Lines 2911 to 2933 in bc9a93e

// Select channel
status = RegionNextChannel( Nvm.MacGroup2.Region, &nextChan, &MacCtx.Channel, &MacCtx.DutyCycleWaitTime, &Nvm.MacGroup1.AggregatedTimeOff );
if( status != LORAMAC_STATUS_OK )
{
if( ( status == LORAMAC_STATUS_DUTYCYCLE_RESTRICTED ) &&
( allowDelayedTx == true ) )
{
// Allow delayed transmissions. We have to allow it in case
// the MAC must retransmit a frame with the frame repetitions
if( MacCtx.DutyCycleWaitTime != 0 )
{// Send later - prepare timer
MacCtx.MacState |= LORAMAC_TX_DELAYED;
TimerSetValue( &MacCtx.TxDelayedTimer, MacCtx.DutyCycleWaitTime );
TimerStart( &MacCtx.TxDelayedTimer );
}
return LORAMAC_STATUS_OK;
}
else
{// State where the MAC cannot send a frame
return status;
}
}

Thus, ScheduleTx is never re-executed and the MAC is stuck in a busy state forever. McpsConfirm for the uplink will never get invoked.

The fix is to move the statement return LORAMAC_STATUS_OK inside the block where the delayed timer is started. I have submitted a PR with the fix: #1287