wifi: Add new useful QosTxop methods

This commit is contained in:
Stefano Avallone
2020-11-25 19:45:38 +01:00
parent 1209d58fb7
commit edc9601742
5 changed files with 186 additions and 6 deletions

View File

@@ -95,6 +95,7 @@ QosTxop::QosTxop ()
: m_typeOfStation (STA),
m_blockAckType (COMPRESSED_BLOCK_ACK),
m_startTxop (Seconds (0)),
m_txopDuration (Seconds (0)),
m_isAccessRequestedForRts (false),
m_currentIsFragmented (false)
{
@@ -415,6 +416,88 @@ QosTxop::DequeuePeekedFrame (Ptr<const WifiMacQueueItem> peekedItem, WifiTxVecto
return item;
}
Ptr<const WifiMacQueueItem>
QosTxop::PeekNextMpdu (uint8_t tid, Mac48Address recipient)
{
return PeekNextMpdu ({nullptr, WifiMacQueue::EMPTY}, tid, recipient);
}
Ptr<const WifiMacQueueItem>
QosTxop::PeekNextMpdu (WifiMacQueueItem::QueueIteratorPair queueIt, uint8_t tid, Mac48Address recipient)
{
NS_LOG_FUNCTION (this << +tid << recipient);
// lambda to peek the next frame
auto peek = [this, &tid, &recipient, &queueIt] () -> WifiMacQueue::ConstIterator
{
if (tid == 8 && recipient.IsBroadcast ()) // undefined TID and recipient
{
return queueIt.queue->PeekFirstAvailable (m_qosBlockedDestinations, queueIt.it);
}
if (m_qosBlockedDestinations->IsBlocked (recipient, tid))
{
return queueIt.queue->end ();
}
return queueIt.queue->PeekByTidAndAddress (tid, recipient, queueIt.it);
};
if (queueIt.queue == nullptr && queueIt.it == WifiMacQueue::EMPTY)
{
// check if there is a packet in the BlockAckManager retransmit queue
queueIt.queue = PeekPointer (m_baManager->GetRetransmitQueue ());
}
if (queueIt.queue == PeekPointer (m_baManager->GetRetransmitQueue ()))
{
queueIt.it = peek ();
// remove old packets
while (queueIt.it != m_baManager->GetRetransmitQueue ()->end () && IsQosOldPacket (*queueIt.it))
{
NS_LOG_DEBUG ("Removing an old packet from BlockAckManager retransmit queue: " << **queueIt.it);
queueIt.it = m_baManager->GetRetransmitQueue ()->Remove (queueIt.it);
queueIt.it = peek ();
}
if (queueIt.it != m_baManager->GetRetransmitQueue ()->end ())
{
NS_LOG_DEBUG ("Packet peeked from BlockAckManager retransmit queue: " << **queueIt.it);
return *queueIt.it;
}
// otherwise, check if there is a packet in the EDCA queue
queueIt = {PeekPointer (m_queue), WifiMacQueue::EMPTY};
}
queueIt.it = peek ();
if (queueIt.it != m_queue->end ())
{
// peek the next sequence number and check if it is within the transmit window
// in case of QoS data frame
uint16_t sequence = m_txMiddle->PeekNextSequenceNumberFor (&(*queueIt.it)->GetHeader ());
if ((*queueIt.it)->GetHeader ().IsQosData ())
{
Mac48Address recipient = (*queueIt.it)->GetHeader ().GetAddr1 ();
uint8_t tid = (*queueIt.it)->GetHeader ().GetQosTid ();
if (GetBaAgreementEstablished (recipient, tid)
&& !IsInWindow (sequence, GetBaStartingSequence (recipient, tid), GetBaBufferSize (recipient, tid)))
{
NS_LOG_DEBUG ("Packet beyond the end of the current transmit window");
return 0;
}
}
WifiMacHeader& hdr = (*queueIt.it)->GetHeader ();
// Assign a sequence number if this is not a fragment nor a retransmission
if (!(*queueIt.it)->IsFragment () && !hdr.IsRetry ())
{
hdr.SetSequenceNumber (sequence);
}
NS_LOG_DEBUG ("Packet peeked from EDCA queue: " << **queueIt.it);
return *queueIt.it;
}
return 0;
}
MacLowTransmissionParameters
QosTxop::GetTransmissionParameters (Ptr<const WifiMacQueueItem> frame) const
{
@@ -1156,6 +1239,52 @@ QosTxop::TerminateTxop (void)
RestartAccessIfNeeded ();
}
void
QosTxop::NotifyChannelAccessed (Time txopDuration)
{
NS_LOG_FUNCTION (this << txopDuration);
NS_ASSERT (txopDuration != Time::Min ());
m_startTxop = Simulator::Now ();
m_txopDuration = txopDuration;
Txop::NotifyChannelAccessed ();
}
bool
QosTxop::IsTxopStarted (void) const
{
NS_LOG_FUNCTION (this << !m_startTxop.IsZero ());
return (!m_startTxop.IsZero ());
}
void
QosTxop::NotifyChannelReleased (void)
{
NS_LOG_FUNCTION (this);
if (m_startTxop.IsStrictlyPositive ())
{
NS_LOG_DEBUG ("Terminating TXOP. Duration = " << Simulator::Now () - m_startTxop);
m_txopTrace (m_startTxop, Simulator::Now () - m_startTxop);
}
m_startTxop = Seconds (0);
Txop::NotifyChannelReleased ();
}
Time
QosTxop::GetRemainingTxop (void) const
{
NS_ASSERT (m_startTxop.IsStrictlyPositive ());
Time remainingTxop = m_txopDuration;
remainingTxop -= (Simulator::Now () - m_startTxop);
if (remainingTxop.IsStrictlyNegative ())
{
remainingTxop = Seconds (0);
}
NS_LOG_FUNCTION (this << remainingTxop);
return remainingTxop;
}
Time
QosTxop::GetTxopRemaining (void) const
{

View File

@@ -125,6 +125,8 @@ public:
void EndTxNoAck (void);
void RestartAccessIfNeeded (void);
void StartAccessIfNeeded (void);
virtual void NotifyChannelAccessed (Time txopDuration);
void NotifyChannelReleased (void);
Time GetTxopRemaining (void) const;
bool NeedFragmentation (void) const;
Ptr<Packet> GetFragmentPacket (WifiMacHeader *hdr);
@@ -383,6 +385,39 @@ public:
Ptr<WifiMacQueueItem> DequeuePeekedFrame (Ptr<const WifiMacQueueItem> peekedItem, WifiTxVector txVector,
bool aggregate = true, uint32_t ampduSize = 0,
Time ppduDurationLimit = Time::Min ());
/**
* Peek the next frame to transmit to the given receiver and of the given
* TID from the block ack manager retransmit queue first and, if not found, from
* the EDCA queue. If <i>tid</i> is equal to 8 (invalid value) and <i>recipient</i>
* is the broadcast address, the first available frame is returned.
* Note that A-MSDU aggregation is never attempted (this is relevant if the
* frame is peeked from the EDCA queue). If the frame is peeked from the EDCA
* queue, it is assigned a sequence number peeked from MacTxMiddle.
*
* \param tid traffic ID.
* \param recipient the receiver station address.
* \returns the peeked frame.
*/
Ptr<const WifiMacQueueItem> PeekNextMpdu (uint8_t tid = 8,
Mac48Address recipient = Mac48Address::GetBroadcast ());
/**
* Peek the next frame to transmit to the given receiver and of the given
* TID from the block ack manager retransmit queue first and, if not found, from
* the EDCA queue. If <i>tid</i> is equal to 8 (invalid value) and <i>recipient</i>
* is the broadcast address, the first available frame is returned.
* Note that A-MSDU aggregation is never attempted (this is relevant if the
* frame is peeked from the EDCA queue). If the frame is peeked from the EDCA
* queue, it is assigned a sequence number peeked from MacTxMiddle.
*
* \param queueIt the QueueIteratorPair pointing to the queue item from which the
* search for an MPDU starts, if the QueueIteratorPair is valid
* \param tid traffic ID.
* \param recipient the receiver station address.
* \returns the peeked frame.
*/
Ptr<const WifiMacQueueItem> PeekNextMpdu (WifiMacQueueItem::QueueIteratorPair queueIt,
uint8_t tid = 8,
Mac48Address recipient = Mac48Address::GetBroadcast ());
/**
* Compute the MacLow transmission parameters for the given frame. Allowed frames
* are those handled by a QosTxop (QoS data frames, BlockAckReq frames, ADDBA
@@ -437,6 +472,19 @@ public:
*/
Mac48Address MapDestAddressForAggregation (const WifiMacHeader &hdr);
/**
* Return true if a TXOP has started.
*
* \return true if a TXOP has started, false otherwise.
*/
virtual bool IsTxopStarted (void) const;
/**
* Return the remaining duration in the current TXOP.
*
* \return the remaining duration in the current TXOP.
*/
virtual Time GetRemainingTxop (void) const;
protected:
// Overridden from Txop
void DoDispose (void);
@@ -542,6 +590,7 @@ private:
Time m_currentPacketTimestamp; //!< the current packet timestamp
uint16_t m_blockAckInactivityTimeout; //!< the BlockAck inactivity timeout value (in TUs, i.e. blocks of 1024 microseconds)
Time m_startTxop; //!< the start TXOP time
Time m_txopDuration; //!< the duration of a TXOP
bool m_isAccessRequestedForRts; //!< flag whether access is requested to transmit a RTS frame
bool m_currentIsFragmented; //!< flag whether current packet is fragmented
Time m_addBaResponseTimeout; //!< timeout for ADDBA response

View File

@@ -471,9 +471,9 @@ Txop::NotifyAccessRequested (void)
}
void
Txop::NotifyChannelAccessed (void)
Txop::NotifyChannelAccessed (Time txopDuration)
{
NS_LOG_FUNCTION (this);
NS_LOG_FUNCTION (this << txopDuration);
m_access = GRANTED;
}

View File

@@ -341,9 +341,11 @@ public:
/**
* Called by the FrameExchangeManager to notify that channel access has
* been granted.
* been granted for the given amount of time.
*
* \param txopDuration the duration of the TXOP gained (zero for DCF)
*/
virtual void NotifyChannelAccessed (void);
virtual void NotifyChannelAccessed (Time txopDuration = Seconds (0));
/**
* Called by the FrameExchangeManager to notify the completion of the transmissions.
* This method generates a new backoff and restarts access if needed.

View File

@@ -61,7 +61,7 @@ private:
/// Inherited
void DoDispose (void);
void NotifyChannelAccessed (void);
void NotifyChannelAccessed (Time txopDuration = Seconds (0));
typedef std::pair<uint64_t,uint64_t> ExpectedGrant; //!< the expected grant typedef
typedef std::list<ExpectedGrant> ExpectedGrants; //!< the collection of expected grants typedef
@@ -431,7 +431,7 @@ TxopTest<TxopType>::DoDispose (void)
template <typename TxopType>
void
TxopTest<TxopType>::NotifyChannelAccessed (void)
TxopTest<TxopType>::NotifyChannelAccessed (Time txopDuration)
{
Txop::m_access = Txop::NOT_REQUESTED;
m_test->NotifyAccessGranted (m_i);