- Fixed error in MAC state machine when sending an ACK and enqueuing a data packet at the same time.
- Fixed error when switching the PHY transceiver while a switch is already in progress.
This commit is contained in:
@@ -207,6 +207,7 @@ void
|
||||
LrWpanMac::McpsDataRequest (McpsDataRequestParams params, Ptr<Packet> p)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << p);
|
||||
|
||||
McpsDataConfirmParams confirmParams;
|
||||
confirmParams.m_msduHandle = params.m_msduHandle;
|
||||
|
||||
@@ -383,12 +384,14 @@ LrWpanMac::McpsDataRequest (McpsDataRequestParams params, Ptr<Packet> p)
|
||||
void
|
||||
LrWpanMac::CheckQueue ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
// Pull a packet from the queue and start sending, if we are not already sending.
|
||||
if (m_lrWpanMacState == MAC_IDLE && !m_txQueue.empty () && m_txPkt == 0)
|
||||
if (m_lrWpanMacState == MAC_IDLE && !m_txQueue.empty () && m_txPkt == 0 && !m_setMacState.IsRunning ())
|
||||
{
|
||||
TxQueueElement *txQElement = m_txQueue.front ();
|
||||
m_txPkt = txQElement->txQPkt;
|
||||
Simulator::ScheduleNow (&LrWpanMac::SetLrWpanMacState, this, MAC_CSMA);
|
||||
m_setMacState = Simulator::ScheduleNow (&LrWpanMac::SetLrWpanMacState, this, MAC_CSMA);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -578,8 +581,10 @@ LrWpanMac::PdDataIndication (uint32_t psduLength, Ptr<Packet> p, uint8_t lqi)
|
||||
// Currently we simply restart CSMA/CA after sending the ACK.
|
||||
m_csmaCa->Cancel ();
|
||||
}
|
||||
// Cancel any pending MAC state change, ACKs have higher priority.
|
||||
m_setMacState.Cancel ();
|
||||
ChangeMacState (MAC_IDLE);
|
||||
Simulator::ScheduleNow (&LrWpanMac::SendAck, this, receivedMacHdr.GetSeqNum ());
|
||||
m_setMacState = Simulator::ScheduleNow (&LrWpanMac::SendAck, this, receivedMacHdr.GetSeqNum ());
|
||||
}
|
||||
|
||||
if (receivedMacHdr.IsData () && !m_mcpsDataIndicationCallback.IsNull ())
|
||||
@@ -606,7 +611,8 @@ LrWpanMac::PdDataIndication (uint32_t psduLength, Ptr<Packet> p, uint8_t lqi)
|
||||
m_mcpsDataConfirmCallback (confirmParams);
|
||||
}
|
||||
RemoveFirstTxQElement ();
|
||||
Simulator::ScheduleNow (&LrWpanMac::SetLrWpanMacState, this, MAC_IDLE);
|
||||
m_setMacState.Cancel ();
|
||||
m_setMacState = Simulator::ScheduleNow (&LrWpanMac::SetLrWpanMacState, this, MAC_IDLE);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -614,11 +620,13 @@ LrWpanMac::PdDataIndication (uint32_t psduLength, Ptr<Packet> p, uint8_t lqi)
|
||||
m_ackWaitTimeout.Cancel ();
|
||||
if (!PrepareRetransmission ())
|
||||
{
|
||||
Simulator::ScheduleNow (&LrWpanMac::SetLrWpanMacState, this, MAC_IDLE);
|
||||
m_setMacState.Cancel ();
|
||||
m_setMacState = Simulator::ScheduleNow (&LrWpanMac::SetLrWpanMacState, this, MAC_IDLE);
|
||||
}
|
||||
else
|
||||
{
|
||||
Simulator::ScheduleNow (&LrWpanMac::SetLrWpanMacState, this, MAC_CSMA);
|
||||
m_setMacState.Cancel ();
|
||||
m_setMacState = Simulator::ScheduleNow (&LrWpanMac::SetLrWpanMacState, this, MAC_CSMA);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -634,6 +642,8 @@ LrWpanMac::PdDataIndication (uint32_t psduLength, Ptr<Packet> p, uint8_t lqi)
|
||||
void
|
||||
LrWpanMac::SendAck (uint8_t seqno)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << static_cast<uint32_t> (seqno));
|
||||
|
||||
NS_ASSERT (m_lrWpanMacState == MAC_IDLE);
|
||||
|
||||
// Generate a corresponding ACK Frame.
|
||||
@@ -668,6 +678,8 @@ LrWpanMac::RemoveFirstTxQElement (void)
|
||||
void
|
||||
LrWpanMac::AckWaitTimeout (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
// TODO: If we are a PAN coordinator and this was an indirect transmission,
|
||||
// we will not initiate a retransmission. Instead we wait for the data
|
||||
// being extracted after a new data request command.
|
||||
@@ -684,6 +696,8 @@ LrWpanMac::AckWaitTimeout (void)
|
||||
bool
|
||||
LrWpanMac::PrepareRetransmission (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
if (m_retransmission >= m_macMaxFrameRetries)
|
||||
{
|
||||
// Maximum number of retransmissions has been reached.
|
||||
@@ -732,7 +746,8 @@ LrWpanMac::PdDataConfirm (LrWpanPhyEnumeration status)
|
||||
Time waitTime = MicroSeconds (GetMacAckWaitDuration () * 1000 * 1000 / m_phy->GetDataOrSymbolRate (false));
|
||||
NS_ASSERT (m_ackWaitTimeout.IsExpired());
|
||||
m_ackWaitTimeout = Simulator::Schedule (waitTime, &LrWpanMac::AckWaitTimeout, this);
|
||||
Simulator::ScheduleNow (&LrWpanMac::SetLrWpanMacState, this, MAC_ACK_PENDING);
|
||||
m_setMacState.Cancel ();
|
||||
m_setMacState = Simulator::ScheduleNow (&LrWpanMac::SetLrWpanMacState, this, MAC_ACK_PENDING);
|
||||
return;
|
||||
}
|
||||
else
|
||||
@@ -781,7 +796,8 @@ LrWpanMac::PdDataConfirm (LrWpanPhyEnumeration status)
|
||||
NS_FATAL_ERROR ("Transmission attempt failed with PHY status " << status);
|
||||
}
|
||||
|
||||
Simulator::ScheduleNow (&LrWpanMac::SetLrWpanMacState, this, MAC_IDLE);
|
||||
m_setMacState.Cancel ();
|
||||
m_setMacState = Simulator::ScheduleNow (&LrWpanMac::SetLrWpanMacState, this, MAC_IDLE);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -880,7 +896,7 @@ LrWpanMac::SetLrWpanMacState (LrWpanMacState macState)
|
||||
}
|
||||
else if (macState == MAC_CSMA)
|
||||
{
|
||||
NS_ASSERT (m_lrWpanMacState == MAC_IDLE);
|
||||
NS_ASSERT (m_lrWpanMacState == MAC_IDLE || m_lrWpanMacState == MAC_ACK_PENDING);
|
||||
|
||||
ChangeMacState (MAC_CSMA);
|
||||
m_phy->PlmeSetTRXStateRequest (IEEE_802_15_4_PHY_RX_ON);
|
||||
@@ -907,7 +923,7 @@ LrWpanMac::SetLrWpanMacState (LrWpanMacState macState)
|
||||
// remove the copy of the packet that was just sent
|
||||
RemoveFirstTxQElement ();
|
||||
|
||||
Simulator::ScheduleNow (&LrWpanMac::SetLrWpanMacState, this, MAC_IDLE);
|
||||
ChangeMacState (MAC_IDLE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -413,6 +413,7 @@ private:
|
||||
std::deque<TxQueueElement*> m_txQueue;
|
||||
uint8_t m_retransmission;
|
||||
EventId m_ackWaitTimeout;
|
||||
EventId m_setMacState;
|
||||
bool m_macRxOnWhenIdle;
|
||||
};
|
||||
|
||||
|
||||
@@ -254,7 +254,8 @@ LrWpanPhy::StartRx (Ptr<SpectrumSignalParameters> spectrumRxParams)
|
||||
|
||||
Ptr<LrWpanSpectrumSignalParameters> lrWpanRxParams = DynamicCast<LrWpanSpectrumSignalParameters> (spectrumRxParams);
|
||||
|
||||
if (m_trxState == IEEE_802_15_4_PHY_RX_ON)
|
||||
// Prevent PHY from receiving another packet while switching the transceiver state.
|
||||
if (m_trxState == IEEE_802_15_4_PHY_RX_ON && !m_setTRXState.IsRunning ())
|
||||
{
|
||||
if (lrWpanRxParams != 0)
|
||||
{
|
||||
@@ -407,47 +408,63 @@ LrWpanPhy::PdDataRequest (const uint32_t psduLength, Ptr<Packet> p)
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_trxState == IEEE_802_15_4_PHY_TX_ON)
|
||||
// Prevent PHY from sending a packet while switching the transceiver state.
|
||||
if (!m_setTRXState.IsRunning())
|
||||
{
|
||||
//send down
|
||||
NS_ASSERT (m_channel);
|
||||
if (m_trxState == IEEE_802_15_4_PHY_TX_ON)
|
||||
{
|
||||
//send down
|
||||
NS_ASSERT (m_channel);
|
||||
|
||||
// Remove a possible LQI tag from a previous transmission of the packet.
|
||||
LrWpanLqiTag lqiTag;
|
||||
p->RemovePacketTag (lqiTag);
|
||||
// Remove a possible LQI tag from a previous transmission of the packet.
|
||||
LrWpanLqiTag lqiTag;
|
||||
p->RemovePacketTag (lqiTag);
|
||||
|
||||
Ptr<LrWpanSpectrumSignalParameters> txParams = Create<LrWpanSpectrumSignalParameters> ();
|
||||
txParams->duration = CalculateTxTime (p);
|
||||
txParams->txPhy = GetObject<SpectrumPhy> ();
|
||||
txParams->psd = m_txPsd;
|
||||
txParams->txAntenna = m_antenna;
|
||||
Ptr<PacketBurst> pb = CreateObject<PacketBurst> ();
|
||||
pb->AddPacket (p);
|
||||
txParams->packetBurst = pb;
|
||||
m_channel->StartTx (txParams);
|
||||
m_pdDataRequest = Simulator::Schedule (txParams->duration, &LrWpanPhy::EndTx, this);
|
||||
ChangeTrxState (IEEE_802_15_4_PHY_BUSY_TX);
|
||||
m_phyTxBeginTrace (p);
|
||||
m_currentTxPacket.first = p;
|
||||
m_currentTxPacket.second = false;
|
||||
return;
|
||||
Ptr<LrWpanSpectrumSignalParameters> txParams = Create<LrWpanSpectrumSignalParameters> ();
|
||||
txParams->duration = CalculateTxTime (p);
|
||||
txParams->txPhy = GetObject<SpectrumPhy> ();
|
||||
txParams->psd = m_txPsd;
|
||||
txParams->txAntenna = m_antenna;
|
||||
Ptr<PacketBurst> pb = CreateObject<PacketBurst> ();
|
||||
pb->AddPacket (p);
|
||||
txParams->packetBurst = pb;
|
||||
m_channel->StartTx (txParams);
|
||||
m_pdDataRequest = Simulator::Schedule (txParams->duration, &LrWpanPhy::EndTx, this);
|
||||
ChangeTrxState (IEEE_802_15_4_PHY_BUSY_TX);
|
||||
m_phyTxBeginTrace (p);
|
||||
m_currentTxPacket.first = p;
|
||||
m_currentTxPacket.second = false;
|
||||
return;
|
||||
}
|
||||
else if ((m_trxState == IEEE_802_15_4_PHY_RX_ON)
|
||||
|| (m_trxState == IEEE_802_15_4_PHY_TRX_OFF)
|
||||
|| (m_trxState == IEEE_802_15_4_PHY_BUSY_TX) )
|
||||
{
|
||||
if (!m_pdDataConfirmCallback.IsNull ())
|
||||
{
|
||||
m_pdDataConfirmCallback (m_trxState);
|
||||
}
|
||||
// Drop packet, hit PhyTxDrop trace
|
||||
m_phyTxDropTrace (p);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_FATAL_ERROR ("This should be unreachable, or else state " << m_trxState << " should be added as a case");
|
||||
}
|
||||
}
|
||||
else if ((m_trxState == IEEE_802_15_4_PHY_RX_ON)
|
||||
|| (m_trxState == IEEE_802_15_4_PHY_TRX_OFF)
|
||||
|| (m_trxState == IEEE_802_15_4_PHY_BUSY_TX) )
|
||||
else
|
||||
{
|
||||
// TODO: This error code is not covered by the standard.
|
||||
// What is the correct behavior in this case?
|
||||
if (!m_pdDataConfirmCallback.IsNull ())
|
||||
{
|
||||
m_pdDataConfirmCallback (m_trxState);
|
||||
m_pdDataConfirmCallback (IEEE_802_15_4_PHY_UNSPECIFIED);
|
||||
}
|
||||
// Drop packet, hit PhyTxDrop trace
|
||||
m_phyTxDropTrace (p);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_FATAL_ERROR ("This should be unreachable, or else state " << m_trxState << " should be added as a case");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -553,6 +570,7 @@ LrWpanPhy::PlmeSetTRXStateRequest (LrWpanPhyEnumeration state)
|
||||
else
|
||||
{
|
||||
NS_LOG_DEBUG ("Cancel m_setTRXState");
|
||||
// Keep the transceiver state as the old state before the switching attempt.
|
||||
m_setTRXState.Cancel();
|
||||
}
|
||||
}
|
||||
@@ -627,8 +645,6 @@ LrWpanPhy::PlmeSetTRXStateRequest (LrWpanPhyEnumeration state)
|
||||
}
|
||||
|
||||
m_trxStatePending = IEEE_802_15_4_PHY_TX_ON;
|
||||
// Prevent PHY from receiving another packet while switching.
|
||||
ChangeTrxState (IEEE_802_15_4_PHY_IDLE);
|
||||
|
||||
// Delay for turnaround time
|
||||
// TODO: Does it also take aTurnaroundTime to switch the transceiver state,
|
||||
@@ -698,9 +714,6 @@ LrWpanPhy::PlmeSetTRXStateRequest (LrWpanPhyEnumeration state)
|
||||
// even when the transmitter is not busy? (6.9.1)
|
||||
m_trxStatePending = IEEE_802_15_4_PHY_RX_ON;
|
||||
|
||||
// Prevent PHY from sending another packet while switching.
|
||||
ChangeTrxState (IEEE_802_15_4_PHY_IDLE);
|
||||
|
||||
Time setTime = Seconds ( (double) aTurnaroundTime / GetDataOrSymbolRate (false));
|
||||
m_setTRXState = Simulator::Schedule (setTime, &LrWpanPhy::EndSetTRXState, this);
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user