wifi: Add new useful QosTxop methods
This commit is contained in:
@@ -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
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user