lr-wpan: Queue pointer fixes and queue limits addition

This commit is contained in:
Alberto Gallegos
2022-10-09 21:34:00 +09:00
committed by Alberto Gallegos Ramonet
parent f957f3996e
commit 0367e17772
5 changed files with 189 additions and 68 deletions

View File

@@ -49,6 +49,8 @@ Changes from ns-3.36 to ns-3.37
* Adds support for **LrWpanMac** devices association.
* Pan Id compression is now possible in **LrWpanMac** when transmitting data frames. i.e. When src and dst pan ID are the same, only one PanId is used, making the MAC header 2 bytes smaller. See IEEE 802.15.4-2006 (7.5.6.1).
* Add O2I Low/High Building Penetration Losses in 3GPP propagation loss model (`ThreeGppPropagationLossModel`) according to **3GPP TR 38.901 7.4.3.1**. Currently, UMa, UMi and RMa scenarios are supported.
* Replace **LrWpanMac** Tx Queue and Ind Tx Queue pointers for smart pointers.
* Add **LrWpanMac** packet traces and queue limits to Tx queue and Ind Tx queue.
### Changes to build system

View File

@@ -30,6 +30,7 @@ Release 3-dev
- (utils) `utils/bench-simulator` has been moved to `utils/bench-scheduler` to better reflect what it actually tests
- (utils) `utils/bench-scheduler` has been enhanced to test multiple schedulers.
- (lte) LTE handover failure is now handled for joining and leaving timeouts, RACH failure, and preamble allocation failure.
- (lr-wpan) !1131 - Add support for configurable tx queue and ind tx queue limits.
### Bugs fixed
@@ -47,6 +48,7 @@ Release 3-dev
- (wifi) Fix the TID of QoS Null frames in response to BSRP TF
- (core) #756 - Fix `CsvReader::GetValueAs()` functions for `char` arguments
- #758 - Fix warnings about `for` loops with variables that are "too small" to fully represent the data being looped
- (lr-wpan) #692 - Replace raw pointers for smart pointers in Tx queue and Ind Tx queue.
Release 3.36.1
--------------

View File

@@ -175,6 +175,14 @@ Bootstrap (a.k.a. network initialization) is possible with a combination of scan
Bootstrap as whole depends on procedures that also take place on higher layers of devices and coordinators. These procedures are briefly described in the standard but out of its scope (See IEE 802.15.4-2011 Section 5.1.3.1.). However, these procedures are necessary for a "complete bootstrap" process. In the examples in |ns3|, these high layer procedures are only briefly implemented to demonstrate a complete example that shows the use of scan and association. A full high layer (e.g. such as those found in Zigbee and Thread protocol stacks) should complete these procedures more robustly.
MAC queues
++++++++++
By default, ``Tx queue`` and ``Ind Tx queue`` (the pending transaction list) are not limited but they can configure to drop packets after they
reach a limit of elements (transaction overflow). Additionally, the ``Ind Tx queue`` drop packets when the packet has been longer than
``macTransactionPersistenceTime`` (transaction expiration). Expiration of packets in the Tx queue is not supported.
Finally, packets in the ``Tx queue`` may be dropped due to excessive transmission retries or channel access failure.
PHY
###
@@ -285,16 +293,16 @@ Scope and Limitations
Future versions of this document will contain a PICS proforma similar to
Appendix D of IEEE 802.15.4-2006. The current emphasis is on direct transmissions
running on both, slotted and unslotted mode (CSMA/CA) of 802.15.4 operation for use in Zigbee.
Indirect data transmissions are not supported but planned for a future update.
Devices are capable of associating with a single PAN coordinator. Interference is modeled as AWGN but this is currently not thoroughly tested.
The standard describes the support of multiple PHY band-modulations but currently, only 250kbps O-QPSK (channel page 0) is supported.
The NetDevice Tx queue is not limited, i.e., packets are never dropped
due to queue becoming full. They may be dropped due to excessive transmission
retries or channel access failure.
Active and passive MAC scans are able to obtain a LQI value from a beacon frame, however, the scan primitives assumes LQI is correctly implemented and does not check the validity of its value.
- Indirect data transmissions are not supported but planned for a future update.
- Devices are capable of associating with a single PAN coordinator. Interference is modeled as AWGN but this is currently not thoroughly tested.
- The standard describes the support of multiple PHY band-modulations but currently, only 250kbps O-QPSK (channel page 0) is supported.
- Active and passive MAC scans are able to obtain a LQI value from a beacon frame, however, the scan primitives assumes LQI is correctly implemented and does not check the validity of its value.
- Configuration of Rx Sensitivity and ED thresholds are currently not supported.
- Orphan scans are not supported.
- Disassociation primitives are not supported.
- Security is not supported.
- Beacon enabled mode GTS are not supported.
References
==========

View File

@@ -70,6 +70,16 @@ LrWpanMac::GetTypeId()
"dequeued from the transaction queue",
MakeTraceSourceAccessor(&LrWpanMac::m_macTxDequeueTrace),
"ns3::Packet::TracedCallback")
.AddTraceSource("MacIndTxEnqueue",
"Trace source indicating a packet has been "
"enqueued in the indirect transaction queue",
MakeTraceSourceAccessor(&LrWpanMac::m_macIndTxEnqueueTrace),
"ns3::Packet::TracedCallback")
.AddTraceSource("MacIndTxDequeue",
"Trace source indicating a packet has was "
"dequeued from the indirect transaction queue",
MakeTraceSourceAccessor(&LrWpanMac::m_macIndTxDequeueTrace),
"ns3::Packet::TracedCallback")
.AddTraceSource("MacTx",
"Trace source indicating a packet has "
"arrived for transmission by this device",
@@ -85,6 +95,12 @@ LrWpanMac::GetTypeId()
"dropped during transmission",
MakeTraceSourceAccessor(&LrWpanMac::m_macTxDropTrace),
"ns3::Packet::TracedCallback")
.AddTraceSource("MacIndTxDrop",
"Trace source indicating a packet has been "
"dropped from the indirect transaction queue"
"(The pending transaction list)",
MakeTraceSourceAccessor(&LrWpanMac::m_macIndTxDropTrace),
"ns3::Packet::TracedCallback")
.AddTraceSource("MacPromiscRx",
"A packet has been received by this device, "
"has been passed up from the physical layer "
@@ -190,6 +206,9 @@ LrWpanMac::LrWpanMac()
m_macResponseWaitTime = aBaseSuperframeDuration * 32;
m_assocRespCmdWaitTime = 960;
m_maxTxQueueSize = m_txQueue.max_size();
m_maxIndTxQueueSize = m_indTxQueue.max_size();
Ptr<UniformRandomVariable> uniformVar = CreateObject<UniformRandomVariable>();
uniformVar->SetAttribute("Min", DoubleValue(0.0));
uniformVar->SetAttribute("Max", DoubleValue(255.0));
@@ -230,14 +249,16 @@ LrWpanMac::DoDispose()
for (uint32_t i = 0; i < m_txQueue.size(); i++)
{
m_txQueue[i]->txQPkt = nullptr;
delete m_txQueue[i];
m_txQueue[i]->txQMsduHandle = 0;
}
m_txQueue.clear();
for (uint32_t i = 0; i < m_indTxQueue.size(); i++)
{
m_indTxQueue[i]->txQPkt = nullptr;
m_indTxQueue[i].release();
m_indTxQueue[i]->seqNum = 0;
m_indTxQueue[i]->dstExtAddress = nullptr;
m_indTxQueue[i]->dstShortAddress = nullptr;
}
m_indTxQueue.clear();
@@ -480,22 +501,11 @@ LrWpanMac::McpsDataRequest(McpsDataRequestParams params, Ptr<Packet> p)
}
p->AddTrailer(macTrailer);
if (m_txQueue.size() == m_txQueue.max_size())
{
confirmParams.m_status = IEEE_802_15_4_TRANSACTION_OVERFLOW;
if (!m_mcpsDataConfirmCallback.IsNull())
{
m_mcpsDataConfirmCallback(confirmParams);
}
}
else
{
NS_LOG_ERROR(this << " Indirect transmissions not currently supported");
// Note: The current Pending transaction list should work for indirect transmissions.
// However, this is not tested yet. For now, we block the use of indirect transmissions.
// TODO: Save packet in the Pending Transaction list.
// EnqueueInd (p);
}
NS_LOG_ERROR(this << " Indirect transmissions not currently supported");
// Note: The current Pending transaction list should work for indirect transmissions.
// However, this is not tested yet. For now, we block the use of indirect transmissions.
// TODO: Save packet in the Pending Transaction list.
// EnqueueInd (p);
}
else
{
@@ -516,12 +526,10 @@ LrWpanMac::McpsDataRequest(McpsDataRequestParams params, Ptr<Packet> p)
}
p->AddTrailer(macTrailer);
m_macTxEnqueueTrace(p);
TxQueueElement* txQElement = new TxQueueElement;
Ptr<TxQueueElement> txQElement = Create<TxQueueElement>();
txQElement->txQMsduHandle = params.m_msduHandle;
txQElement->txQPkt = p;
m_txQueue.push_back(txQElement);
EnqueueTxQElement(txQElement);
CheckQueue();
}
}
@@ -911,9 +919,9 @@ LrWpanMac::SendBeaconRequestCommand()
commandPacket->AddTrailer(macTrailer);
TxQueueElement* txQElement = new TxQueueElement;
Ptr<TxQueueElement> txQElement = Create<TxQueueElement>();
txQElement->txQPkt = commandPacket;
m_txQueue.push_back(txQElement);
EnqueueTxQElement(txQElement);
CheckQueue();
}
@@ -960,9 +968,9 @@ LrWpanMac::SendAssocRequestCommand()
commandPacket->AddTrailer(macTrailer);
TxQueueElement* txQElement = new TxQueueElement;
Ptr<TxQueueElement> txQElement = Create<TxQueueElement>();
txQElement->txQPkt = commandPacket;
m_txQueue.push_back(txQElement);
EnqueueTxQElement(txQElement);
CheckQueue();
}
@@ -1019,9 +1027,9 @@ LrWpanMac::SendDataRequestCommand()
commandPacket->AddTrailer(macTrailer);
// Set the Command packet to be transmitted
TxQueueElement* txQElement = new TxQueueElement;
Ptr<TxQueueElement> txQElement = Create<TxQueueElement>();
txQElement->txQPkt = commandPacket;
m_txQueue.push_back(txQElement);
EnqueueTxQElement(txQElement);
CheckQueue();
}
@@ -1035,12 +1043,12 @@ LrWpanMac::SendAssocResponseCommand(Ptr<Packet> rxDataReqPkt)
NS_ASSERT(receivedMacPayload.GetCommandFrameType() == CommandPayloadHeader::DATA_REQ);
IndTxQueueElement* indTxQElement = new IndTxQueueElement;
Ptr<IndTxQueueElement> indTxQElement = Create<IndTxQueueElement>();
bool elementFound;
elementFound = DequeueInd(receivedMacHdr.GetExtSrcAddr(), indTxQElement);
if (elementFound)
{
TxQueueElement* txQElement = new TxQueueElement;
Ptr<TxQueueElement> txQElement = Create<TxQueueElement>();
txQElement->txQPkt = indTxQElement->txQPkt;
m_txQueue.emplace_back(txQElement);
}
@@ -1448,7 +1456,7 @@ LrWpanMac::CheckQueue()
// check MAC is not in a IFS
if (!m_ifsEvent.IsRunning())
{
TxQueueElement* txQElement = m_txQueue.front();
Ptr<TxQueueElement> txQElement = m_txQueue.front();
m_txPkt = txQElement->txQPkt;
m_setMacState =
@@ -2192,7 +2200,7 @@ LrWpanMac::PdDataIndication(uint32_t psduLength, Ptr<Packet> p, uint8_t lqi)
{
if (!m_mcpsDataConfirmCallback.IsNull())
{
TxQueueElement* txQElement = m_txQueue.front();
Ptr<TxQueueElement> txQElement = m_txQueue.front();
McpsDataConfirmParams confirmParams;
confirmParams.m_msduHandle = txQElement->txQMsduHandle;
confirmParams.m_status = IEEE_802_15_4_SUCCESS;
@@ -2270,10 +2278,32 @@ LrWpanMac::SendAck(uint8_t seqno)
m_phy->PlmeSetTRXStateRequest(IEEE_802_15_4_PHY_TX_ON);
}
void
LrWpanMac::EnqueueTxQElement(Ptr<TxQueueElement> txQElement)
{
if (m_txQueue.size() < m_maxTxQueueSize)
{
m_txQueue.emplace_back(txQElement);
m_macTxEnqueueTrace(txQElement->txQPkt);
}
else
{
if (!m_mcpsDataConfirmCallback.IsNull())
{
McpsDataConfirmParams confirmParams;
confirmParams.m_msduHandle = txQElement->txQMsduHandle;
confirmParams.m_status = IEEE_802_15_4_TRANSACTION_OVERFLOW;
m_mcpsDataConfirmCallback(confirmParams);
}
NS_LOG_DEBUG("TX Queue with size " << m_txQueue.size() << " is full, dropping packet");
m_macTxDropTrace(txQElement->txQPkt);
}
}
void
LrWpanMac::RemoveFirstTxQElement()
{
TxQueueElement* txQElement = m_txQueue.front();
Ptr<TxQueueElement> txQElement = m_txQueue.front();
Ptr<const Packet> p = txQElement->txQPkt;
m_numCsmacaRetry += m_csmaCa->GetNB() + 1;
@@ -2286,7 +2316,7 @@ LrWpanMac::RemoveFirstTxQElement()
}
txQElement->txQPkt = nullptr;
delete txQElement;
txQElement = nullptr;
m_txQueue.pop_front();
m_txPkt = nullptr;
m_retransmission = 0;
@@ -2427,7 +2457,7 @@ LrWpanMac::PrepareRetransmission()
{
// Maximum number of retransmissions has been reached.
// remove the copy of the DATA packet that was just sent
TxQueueElement* txQElement = m_txQueue.front();
Ptr<TxQueueElement> txQElement = m_txQueue.front();
m_macTxDropTrace(txQElement->txQPkt);
if (!m_mcpsDataConfirmCallback.IsNull())
{
@@ -2453,7 +2483,7 @@ LrWpanMac::PrepareRetransmission()
void
LrWpanMac::EnqueueInd(Ptr<Packet> p)
{
std::unique_ptr<IndTxQueueElement> indTxQElement = std::make_unique<IndTxQueueElement>();
Ptr<IndTxQueueElement> indTxQElement = Create<IndTxQueueElement>();
LrWpanMacHeader peekedMacHdr;
p->PeekHeader(peekedMacHdr);
@@ -2487,18 +2517,37 @@ LrWpanMac::EnqueueInd(Ptr<Packet> p)
m_macTransactionPersistenceTime;
}
double symbolRate = m_phy->GetDataOrSymbolRate(false);
Time expireTime = Seconds(unit / symbolRate);
expireTime += Simulator::Now();
indTxQElement->expireTime = expireTime;
indTxQElement->txQPkt = p;
m_indTxQueue.emplace_back(std::move(indTxQElement));
if (m_indTxQueue.size() < m_maxIndTxQueueSize)
{
double symbolRate = m_phy->GetDataOrSymbolRate(false);
Time expireTime = Seconds(unit / symbolRate);
expireTime += Simulator::Now();
indTxQElement->expireTime = expireTime;
indTxQElement->txQPkt = p;
m_indTxQueue.emplace_back(indTxQElement);
m_macIndTxEnqueueTrace(p);
}
else
{
if (!m_mlmeCommStatusIndicationCallback.IsNull())
{
LrWpanMacHeader peekedMacHdr;
indTxQElement->txQPkt->PeekHeader(peekedMacHdr);
MlmeCommStatusIndicationParams commStatusParams;
commStatusParams.m_panId = m_macPanId;
commStatusParams.m_srcAddrMode = LrWpanMacHeader::EXTADDR;
commStatusParams.m_srcExtAddr = peekedMacHdr.GetExtSrcAddr();
commStatusParams.m_dstAddrMode = LrWpanMacHeader::EXTADDR;
commStatusParams.m_dstExtAddr = peekedMacHdr.GetExtDstAddr();
commStatusParams.m_status = MLMECOMMSTATUS_TRANSACTION_OVERFLOW;
m_mlmeCommStatusIndicationCallback(commStatusParams);
}
m_macIndTxDropTrace(p);
}
}
bool
LrWpanMac::DequeueInd(Mac64Address dst, IndTxQueueElement* entry)
LrWpanMac::DequeueInd(Mac64Address dst, Ptr<IndTxQueueElement> entry)
{
PurgeInd();
@@ -2507,6 +2556,7 @@ LrWpanMac::DequeueInd(Mac64Address dst, IndTxQueueElement* entry)
if ((*iter)->dstExtAddress == dst)
{
*entry = **iter;
m_macIndTxDequeueTrace((*iter)->txQPkt->Copy());
m_indTxQueue.erase(iter);
return true;
}
@@ -2523,7 +2573,7 @@ LrWpanMac::PurgeInd()
{
// Transaction expired, remove and send proper confirmation/indication to a higher layer
LrWpanMacHeader peekedMacHdr;
m_indTxQueue[i]->txQPkt->Copy()->PeekHeader(peekedMacHdr);
m_indTxQueue[i]->txQPkt->PeekHeader(peekedMacHdr);
if (peekedMacHdr.IsCommand())
{
@@ -2551,7 +2601,7 @@ LrWpanMac::PurgeInd()
m_mcpsDataConfirmCallback(confParams);
}
}
m_macTxDropTrace(m_indTxQueue[i]->txQPkt);
m_macIndTxDropTrace(m_indTxQueue[i]->txQPkt->Copy());
m_indTxQueue.erase(m_indTxQueue.begin() + i);
}
else
@@ -2642,7 +2692,7 @@ LrWpanMac::RemovePendTxQElement(Ptr<Packet> p)
if (((*it)->dstExtAddress == peekedMacHdr.GetExtDstAddr()) &&
((*it)->seqNum == peekedMacHdr.GetSeqNum()))
{
m_macPendTxDequeueTrace(p);
m_macIndTxDequeueTrace(p);
m_indTxQueue.erase(it);
break;
}
@@ -2652,7 +2702,7 @@ LrWpanMac::RemovePendTxQElement(Ptr<Packet> p)
if (((*it)->dstShortAddress == peekedMacHdr.GetShortDstAddr()) &&
((*it)->seqNum == peekedMacHdr.GetSeqNum()))
{
m_macPendTxDequeueTrace(p);
m_macIndTxDequeueTrace(p);
m_indTxQueue.erase(it);
break;
}
@@ -2741,7 +2791,7 @@ LrWpanMac::PdDataConfirm(LrWpanPhyEnumeration status)
{
McpsDataConfirmParams confirmParams;
NS_ASSERT_MSG(m_txQueue.size() > 0, "TxQsize = 0");
TxQueueElement* txQElement = m_txQueue.front();
Ptr<TxQueueElement> txQElement = m_txQueue.front();
confirmParams.m_msduHandle = txQElement->txQMsduHandle;
confirmParams.m_status = IEEE_802_15_4_SUCCESS;
m_mcpsDataConfirmCallback(confirmParams);
@@ -2846,7 +2896,7 @@ LrWpanMac::PdDataConfirm(LrWpanPhyEnumeration status)
if (!macHdr.IsAcknowledgment())
{
NS_ASSERT_MSG(m_txQueue.size() > 0, "TxQsize = 0");
TxQueueElement* txQElement = m_txQueue.front();
Ptr<TxQueueElement> txQElement = m_txQueue.front();
m_macTxDropTrace(txQElement->txQPkt);
if (!m_mcpsDataConfirmCallback.IsNull())
{
@@ -3335,6 +3385,18 @@ LrWpanMac::SetAssociationStatus(LrWpanAssociationStatus status)
m_associationStatus = status;
}
void
LrWpanMac::SetTxQMaxSize(uint32_t queueSize)
{
m_maxTxQueueSize = queueSize;
}
void
LrWpanMac::SetIndTxQMaxSize(uint32_t queueSize)
{
m_maxIndTxQueueSize = queueSize;
}
uint16_t
LrWpanMac::GetPanId() const
{

View File

@@ -1097,6 +1097,20 @@ class LrWpanMac : public Object
*/
void SetAssociationStatus(LrWpanAssociationStatus status);
/**
* Set the max size of the transmit queue.
*
* \param queueSize The transmit queue size.
*/
void SetTxQMaxSize(uint32_t queueSize);
/**
* Set the max size of the indirect transmit queue (Pending Transaction list)
*
* \param queueSize The indirect transmit queue size.
*/
void SetIndTxQMaxSize(uint32_t queueSize);
// MAC PIB attributes
/**
@@ -1445,7 +1459,7 @@ class LrWpanMac : public Object
/**
* Helper structure for managing transmission queue elements.
*/
struct TxQueueElement
struct TxQueueElement : public SimpleRefCount<TxQueueElement>
{
uint8_t txQMsduHandle; //!< MSDU Handle
Ptr<Packet> txQPkt; //!< Queued packet
@@ -1454,7 +1468,7 @@ class LrWpanMac : public Object
/**
* Helper structure for managing pending transaction list elements (Indirect transmissions).
*/
struct IndTxQueueElement
struct IndTxQueueElement : public SimpleRefCount<IndTxQueueElement>
{
uint8_t seqNum; //!< The sequence number of the queued packet
Mac16Address dstShortAddress; //!< The destination short Mac Address
@@ -1560,6 +1574,13 @@ class LrWpanMac : public Object
*/
void SendAck(uint8_t seqno);
/**
* Add an element to the transmission queue.
*
* \param txQElement The element added to the Tx Queue.
*/
void EnqueueTxQElement(Ptr<TxQueueElement> txQElement);
/**
* Remove the tip of the transmission queue, including clean up related to the
* last packet transmission.
@@ -1609,7 +1630,7 @@ class LrWpanMac : public Object
* transaction list. \param entry The dequeued element from the pending transaction list.
* \return The status of the dequeue
*/
bool DequeueInd(Mac64Address dst, IndTxQueueElement* entry);
bool DequeueInd(Mac64Address dst, Ptr<IndTxQueueElement> entry);
/**
* Purge expired transactions from the pending transactions list.
@@ -1687,13 +1708,21 @@ class LrWpanMac : public Object
*/
TracedCallback<Ptr<const Packet>> m_macTxDequeueTrace;
/**
* The trace source fired when packets come into the "top" of the device
* at the L3/L2 transition, when being queued for indirect transmission
* (pending transaction list).
* \see class CallBackTraceSource
*/
TracedCallback<Ptr<const Packet>> m_macIndTxEnqueueTrace;
/**
* The trace source fired when packets are dequeued from the
* L3/l2 pending transaction list.
* L3/l2 indirect transmission queue (Pending transaction list).
*
* \see class CallBackTraceSource
*/
TracedCallback<Ptr<const Packet>> m_macPendTxDequeueTrace;
TracedCallback<Ptr<const Packet>> m_macIndTxDequeueTrace;
/**
* The trace source fired when packets are being sent down to L1.
@@ -1719,6 +1748,14 @@ class LrWpanMac : public Object
*/
TracedCallback<Ptr<const Packet>> m_macTxDropTrace;
/**
* The trace source fired when packets are dropped due to indirect Tx queue
* overflows or expiration.
*
* \see class CallBackTraceSource
*/
TracedCallback<Ptr<const Packet>> m_macIndTxDropTrace;
/**
* The trace source fired for packets successfully received by the device
* immediately before being forwarded up to higher layers (at the L2/L3
@@ -1918,13 +1955,23 @@ class LrWpanMac : public Object
/**
* The transmit queue used by the MAC.
*/
std::deque<TxQueueElement*> m_txQueue;
std::deque<Ptr<TxQueueElement>> m_txQueue;
/**
* The indirect transmit queue used by the MAC pending messages (a.k.a. The pending transaction
* The indirect transmit queue used by the MAC pending messages (The pending transaction
* list).
*/
std::deque<std::unique_ptr<IndTxQueueElement>> m_indTxQueue;
std::deque<Ptr<IndTxQueueElement>> m_indTxQueue;
/**
* The maximum size of the transmit queue.
*/
uint32_t m_maxTxQueueSize;
/**
* The maximum size of the indirect transmit queue (The pending transaction list).
*/
uint32_t m_maxIndTxQueueSize;
/**
* The list of PAN descriptors accumulated during channel scans, used to select a PAN to