wifi: (fixes #2470) Protect ADDBA handshake
This commit is contained in:
@@ -56,6 +56,11 @@ us a note on ns-developers mailing list.</p>
|
||||
<ul>
|
||||
<li>The attributes <b>RegularWifiMac::HtSupported</b>, <b>RegularWifiMac::VhtSupported</b>, <b>RegularWifiMac::HeSupported</b>, <b>RegularWifiMac::RifsSupported</b>, <b>WifiPhy::ShortGuardEnabled</b>, <b>WifiPhy::GuardInterval</b> and <b>WifiPhy::GreenfieldEnabled</b> have been deprecated. Intead, it is advised to use <b>WifiNetDevice::HtConfiguration</b>, <b>WifiNetDevice::VhtConfiguration</b> and <b>WifiNetDevice::HeConfiguration</b>.
|
||||
</li>
|
||||
<li>A new attribute <b>WifiPhy::PostReceptionErrorModel</b> has been added to force specific packet drops.
|
||||
</li>
|
||||
</li>
|
||||
<li>New attributes <b>QosTxop::AddBaResponseTimeout</b> and <b>QosTxop::FailedAddBaTimeout</b> have been added to set the timeout to wait for an ADDBA response after the ACK to the ADDBA request is received and to set the timeout after a failed BA agreement, respectively.
|
||||
</li>
|
||||
</ul>
|
||||
<h2>Changes to existing API:</h2>
|
||||
<ul>
|
||||
@@ -71,6 +76,7 @@ us a note on ns-developers mailing list.</p>
|
||||
</ul>
|
||||
<h2>Changed behavior:</h2>
|
||||
<ul>
|
||||
<li>The wifi ADDBA handshake process is now protected with the use of two timeouts who makes sure we do not end up in a blocked situation. If the handshake process is not established, packets that are in the queue are sent as normal MPDUs. Once handshake is successfully established, A-MPDUs can be transmitted.</li>
|
||||
</ul>
|
||||
|
||||
<hr>
|
||||
|
||||
@@ -27,6 +27,7 @@ New user-visible features
|
||||
Bugs fixed
|
||||
----------
|
||||
|
||||
- Bug 2470 - wifi: Handshake to setup the Block Ack Agreement is not protected
|
||||
- Bug 2992 - lte: Send method of the LteUeNetDevice doesn't use protocolNumber parameter
|
||||
- Bug 2997 - lte: EpcTft::PacketFilter::Matches does not use ipv6 address to match an IP packet
|
||||
- Bug 2860 - mobility: Set Z coordinate for position-allocation classes
|
||||
|
||||
@@ -104,8 +104,12 @@ BlockAckManager::ExistsAgreementInState (Mac48Address recipient, uint8_t tid,
|
||||
return it->second.first.IsEstablished ();
|
||||
case OriginatorBlockAckAgreement::PENDING:
|
||||
return it->second.first.IsPending ();
|
||||
case OriginatorBlockAckAgreement::UNSUCCESSFUL:
|
||||
return it->second.first.IsUnsuccessful ();
|
||||
case OriginatorBlockAckAgreement::REJECTED:
|
||||
return it->second.first.IsRejected ();
|
||||
case OriginatorBlockAckAgreement::NO_REPLY:
|
||||
return it->second.first.IsNoReply ();
|
||||
case OriginatorBlockAckAgreement::RESET:
|
||||
return it->second.first.IsReset ();
|
||||
default:
|
||||
NS_FATAL_ERROR ("Invalid state for block ack agreement");
|
||||
}
|
||||
@@ -138,6 +142,12 @@ BlockAckManager::CreateAgreement (const MgtAddBaRequestHeader *reqHdr, Mac48Addr
|
||||
agreement.SetState (OriginatorBlockAckAgreement::PENDING);
|
||||
PacketQueue queue;
|
||||
std::pair<OriginatorBlockAckAgreement, PacketQueue> value (agreement, queue);
|
||||
if (ExistsAgreement (recipient, reqHdr->GetTid ()))
|
||||
{
|
||||
// Delete agreement if it exists and in RESET state
|
||||
NS_ASSERT (ExistsAgreementInState (recipient, reqHdr->GetTid (), OriginatorBlockAckAgreement::RESET));
|
||||
m_agreements.erase (key);
|
||||
}
|
||||
m_agreements.insert (std::make_pair (key, value));
|
||||
m_blockPackets (recipient, reqHdr->GetTid ());
|
||||
}
|
||||
@@ -710,15 +720,31 @@ BlockAckManager::NotifyAgreementEstablished (Mac48Address recipient, uint8_t tid
|
||||
}
|
||||
|
||||
void
|
||||
BlockAckManager::NotifyAgreementUnsuccessful (Mac48Address recipient, uint8_t tid)
|
||||
BlockAckManager::NotifyAgreementRejected (Mac48Address recipient, uint8_t tid)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << recipient << +tid);
|
||||
AgreementsI it = m_agreements.find (std::make_pair (recipient, tid));
|
||||
NS_ASSERT (it != m_agreements.end ());
|
||||
if (it != m_agreements.end ())
|
||||
{
|
||||
it->second.first.SetState (OriginatorBlockAckAgreement::UNSUCCESSFUL);
|
||||
}
|
||||
it->second.first.SetState (OriginatorBlockAckAgreement::REJECTED);
|
||||
}
|
||||
|
||||
void
|
||||
BlockAckManager::NotifyAgreementNoReply (Mac48Address recipient, uint8_t tid)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << recipient << +tid);
|
||||
AgreementsI it = m_agreements.find (std::make_pair (recipient, tid));
|
||||
NS_ASSERT (it != m_agreements.end ());
|
||||
it->second.first.SetState (OriginatorBlockAckAgreement::NO_REPLY);
|
||||
m_unblockPackets (recipient, tid);
|
||||
}
|
||||
|
||||
void
|
||||
BlockAckManager::NotifyAgreementReset (Mac48Address recipient, uint8_t tid)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << recipient << +tid);
|
||||
AgreementsI it = m_agreements.find (std::make_pair (recipient, tid));
|
||||
NS_ASSERT (it != m_agreements.end ());
|
||||
it->second.first.SetState (OriginatorBlockAckAgreement::RESET);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -761,7 +787,7 @@ BlockAckManager::SwitchToBlockAckIfNeeded (Mac48Address recipient, uint8_t tid,
|
||||
{
|
||||
NS_LOG_FUNCTION (this << recipient << +tid << startingSeq);
|
||||
NS_ASSERT (!ExistsAgreementInState (recipient, tid, OriginatorBlockAckAgreement::PENDING));
|
||||
if (!ExistsAgreementInState (recipient, tid, OriginatorBlockAckAgreement::UNSUCCESSFUL) && ExistsAgreement (recipient, tid))
|
||||
if (!ExistsAgreementInState (recipient, tid, OriginatorBlockAckAgreement::REJECTED) && ExistsAgreement (recipient, tid))
|
||||
{
|
||||
uint32_t packets = m_queue->GetNPacketsByTidAndAddress (tid, recipient) +
|
||||
GetNBufferedPackets (recipient, tid);
|
||||
|
||||
@@ -225,11 +225,27 @@ public:
|
||||
* \param recipient Address of peer station involved in block ack mechanism.
|
||||
* \param tid Traffic ID of transmitted packet.
|
||||
*
|
||||
* Marks an agreement as unsuccessful. This happens if <i>recipient</i> station reject block ack setup
|
||||
* Marks an agreement as rejected. This happens if <i>recipient</i> station reject block ack setup
|
||||
* by an ADDBA Response frame with a failure status code. For now we assume that every QoS station accepts
|
||||
* a block ack setup.
|
||||
*/
|
||||
void NotifyAgreementUnsuccessful (Mac48Address recipient, uint8_t tid);
|
||||
void NotifyAgreementRejected (Mac48Address recipient, uint8_t tid);
|
||||
/**
|
||||
* \param recipient Address of peer station involved in block ack mechanism.
|
||||
* \param tid Traffic ID of transmitted packet.
|
||||
*
|
||||
* Marks an agreement after not receiving response to ADDBA request. During this state
|
||||
* any packets in queue will be transmitted using normal MPDU. This also unblock
|
||||
* recipient adress.
|
||||
*/
|
||||
void NotifyAgreementNoReply (Mac48Address recipient, uint8_t tid);
|
||||
/**
|
||||
* \param recipient Address of peer station involved in block ack mechanism.
|
||||
* \param tid Traffic ID of transmitted packet.
|
||||
*
|
||||
* Set BA agreement to a transitory state to reset it after not receiving response to ADDBA request.
|
||||
*/
|
||||
void NotifyAgreementReset (Mac48Address recipient, uint8_t tid);
|
||||
/**
|
||||
* \param recipient Address of peer station involved in block ack mechanism.
|
||||
* \param tid Traffic ID of transmitted packet.
|
||||
|
||||
@@ -2594,8 +2594,8 @@ MacLow::AggregateToAmpdu (Ptr<const Packet> packet, const WifiMacHeader hdr)
|
||||
|
||||
if (!hdr.GetAddr1 ().IsBroadcast () && edcaIt->second->GetMpduAggregator () != 0)
|
||||
{
|
||||
//Have to make sure that their exist a block Ack agreement before sending an AMPDU (BlockAck Manager)
|
||||
if (edcaIt->second->GetBaAgreementExists (hdr.GetAddr1 (), tid))
|
||||
//Have to make sure that the block ACK agreement is established before sending an AMPDU (BlockAck Manager)
|
||||
if (edcaIt->second->GetBaAgreementEstablished (hdr.GetAddr1 (), tid))
|
||||
{
|
||||
/* here is performed mpdu aggregation */
|
||||
/* MSDU aggregation happened in edca if the user asked for it so m_currentPacket may contains a normal packet or a A-MSDU*/
|
||||
@@ -2849,7 +2849,7 @@ MacLow::AggregateToAmpdu (Ptr<const Packet> packet, const WifiMacHeader hdr)
|
||||
{
|
||||
InsertInTxQueue (packet, peekedHdr, tstamp, tid);
|
||||
}
|
||||
if (edcaIt->second->GetBaAgreementExists (hdr.GetAddr1 (), tid))
|
||||
if (edcaIt->second->GetBaAgreementEstablished (hdr.GetAddr1 (), tid))
|
||||
{
|
||||
edcaIt->second->CompleteAmpduTransfer (peekedHdr.GetAddr1 (), tid);
|
||||
}
|
||||
|
||||
@@ -65,9 +65,21 @@ OriginatorBlockAckAgreement::IsInactive (void) const
|
||||
}
|
||||
|
||||
bool
|
||||
OriginatorBlockAckAgreement::IsUnsuccessful (void) const
|
||||
OriginatorBlockAckAgreement::IsRejected (void) const
|
||||
{
|
||||
return (m_state == UNSUCCESSFUL) ? true : false;
|
||||
return (m_state == REJECTED) ? true : false;
|
||||
}
|
||||
|
||||
bool
|
||||
OriginatorBlockAckAgreement::IsNoReply (void) const
|
||||
{
|
||||
return (m_state == NO_REPLY) ? true : false;
|
||||
}
|
||||
|
||||
bool
|
||||
OriginatorBlockAckAgreement::IsReset (void) const
|
||||
{
|
||||
return (m_state == RESET) ? true : false;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -28,7 +28,37 @@ namespace ns3 {
|
||||
/**
|
||||
* \ingroup wifi
|
||||
* Maintains the state and information about transmitted MPDUs with ack policy block ack
|
||||
* for an originator station.
|
||||
* for an originator station. The state diagram is as follows:
|
||||
*
|
||||
\verbatim
|
||||
--------------
|
||||
| REJECTED |
|
||||
--------------
|
||||
^
|
||||
receive ADDBAResponse |
|
||||
status code = failure |
|
||||
|
|
||||
| receive ADDBAResponse
|
||||
/------------\ send ADDBARequest ---------------- status code = success ----------------
|
||||
| START |------------------>| PENDING |------------------------>| ESTABLISHED |-----
|
||||
\------------/ ---------------- ---------------- |
|
||||
^ | / ^ ^ |
|
||||
| no ADDBAResponse | receive BlockAck / | | | receive BlockAck
|
||||
| v retryPkts + queuePkts / | | | retryPkts + queuePkts
|
||||
| ---------------- < / | | | >=
|
||||
|--------------------------| NO_REPLY | blockAckThreshold / | | | blockAckThreshold
|
||||
Reset after timeout ---------------- / | | |
|
||||
v | ----------|
|
||||
--------------- |
|
||||
| INACTIVE | |
|
||||
--------------- |
|
||||
send a MPDU (Normal Ack) | |
|
||||
retryPkts + queuePkts | |
|
||||
>= | |
|
||||
blockAckThreshold |----------------
|
||||
\endverbatim
|
||||
*
|
||||
* See also OriginatorBlockAckAgreement::State
|
||||
*/
|
||||
class OriginatorBlockAckAgreement : public BlockAckAgreement
|
||||
{
|
||||
@@ -45,25 +75,6 @@ public:
|
||||
*/
|
||||
OriginatorBlockAckAgreement (Mac48Address recipient, uint8_t tid);
|
||||
~OriginatorBlockAckAgreement ();
|
||||
/* receive ADDBAResponse
|
||||
* send ADDBARequest --------------- status code = success ---------------
|
||||
* ----------------->| PENDING |------------------------>| ESTABLISHED |-----
|
||||
* --------------- --------------- |
|
||||
* | / ^ ^ |
|
||||
* receive ADDBAResponse | receive BlockAck / | | | receive BlockAck
|
||||
* status code = failure | retryPkts + queuePkts / | | | retryPkts + queuePkts
|
||||
* v < / | | | >=
|
||||
* --------------- blockAckThreshold / | | | blockAckThreshold
|
||||
* | UNSUCCESSFUL | / | | |
|
||||
* --------------- v | ----------|
|
||||
* -------------- |
|
||||
* | INACTIVE | |
|
||||
* -------------- |
|
||||
* send a MPDU (Normal Ack) | |
|
||||
* retryPkts + queuePkts | |
|
||||
* >= | |
|
||||
* blockAckThreshold |----------------
|
||||
*/
|
||||
/**
|
||||
* Represents the state for this agreement.
|
||||
*
|
||||
@@ -82,17 +93,18 @@ public:
|
||||
* m_blockAckThreshold (see ns3::BlockAckManager). In these conditions the agreement becomes
|
||||
* INACTIVE until that the number of packets reaches the value of m_blockAckThreshold again.
|
||||
*
|
||||
* UNSUCCESSFUL (not used for now):
|
||||
* The agreement's state becomes UNSUCCESSFUL if:
|
||||
* NO_REPLY
|
||||
* No reply after an ADDBA request. In this state the originator will send the rest of packets
|
||||
* in queue using normal MPDU.
|
||||
*
|
||||
* - its previous state was PENDING and an ADDBAResponse frame wasn't received from
|
||||
* recipient station within an interval of time defined by m_bAckSetupTimeout attribute
|
||||
* in ns3::WifiMac.
|
||||
* - an ADDBAResponse frame is received from recipient and the Status Code field is set
|
||||
* to failure.
|
||||
* RESET
|
||||
* A transient state to mark the agreement for reinitialzation after failed ADDBA request.
|
||||
* Since it is a temporary state, it is not included in the state diagram above. In this
|
||||
* state the next transmission will be treated as if the BA agreement is not created yet.
|
||||
*
|
||||
* In both cases for station addressed by BlockAckAgreement::m_peer and for
|
||||
* TID BlockAckAgreement::m_tid block ack mechanism won't be used.
|
||||
* REJECTED (not used for now):
|
||||
* The agreement's state becomes REJECTED if an ADDBAResponse frame is received from recipient
|
||||
* and the Status Code field is set to failure.
|
||||
*/
|
||||
/// State enumeration
|
||||
enum State
|
||||
@@ -100,7 +112,9 @@ public:
|
||||
PENDING,
|
||||
ESTABLISHED,
|
||||
INACTIVE,
|
||||
UNSUCCESSFUL
|
||||
NO_REPLY,
|
||||
RESET,
|
||||
REJECTED
|
||||
};
|
||||
/**
|
||||
* Set the current state.
|
||||
@@ -130,12 +144,26 @@ public:
|
||||
*/
|
||||
bool IsInactive (void) const;
|
||||
/**
|
||||
* Check if the current state of this agreement is UNSUCCESSFUL.
|
||||
* Check if the current state of this agreement is NO_REPLY.
|
||||
*
|
||||
* \return true if the current state of this agreement is UNSUCCESSFUL,
|
||||
* \return true if the current state of this agreement is NO_REPLY,
|
||||
* false otherwise
|
||||
*/
|
||||
bool IsUnsuccessful (void) const;
|
||||
bool IsNoReply (void) const;
|
||||
/**
|
||||
* Check if the current state of this agreement is RESET.
|
||||
*
|
||||
* \return true if the current state of this agreement is RESET,
|
||||
* false otherwise
|
||||
*/
|
||||
bool IsReset (void) const;
|
||||
/**
|
||||
* Check if the current state of this agreement is REJECTED.
|
||||
*
|
||||
* \return true if the current state of this agreement is REJECTED,
|
||||
* false otherwise
|
||||
*/
|
||||
bool IsRejected (void) const;
|
||||
/**
|
||||
* Notifies a packet's transmission with ack policy Block Ack.
|
||||
*
|
||||
|
||||
@@ -52,6 +52,22 @@ QosTxop::GetTypeId (void)
|
||||
.SetParent<ns3::Txop> ()
|
||||
.SetGroupName ("Wifi")
|
||||
.AddConstructor<QosTxop> ()
|
||||
.AddAttribute ("AddBaResponseTimeout",
|
||||
"The timeout to wait for ADDBA response after the ACK to "
|
||||
"ADDBA request is received.",
|
||||
TimeValue (MilliSeconds (1)),
|
||||
MakeTimeAccessor (&QosTxop::SetAddBaResponseTimeout,
|
||||
&QosTxop::GetAddBaResponseTimeout),
|
||||
MakeTimeChecker ())
|
||||
.AddAttribute ("FailedAddBaTimeout",
|
||||
"The timeout after a failed BA agreement. During this "
|
||||
"timeout, the originator resumes sending packets using normal "
|
||||
"MPDU. After that, BA agreement is reset and the originator "
|
||||
"will retry BA negotiation.",
|
||||
TimeValue (MilliSeconds (200)),
|
||||
MakeTimeAccessor (&QosTxop::SetFailedAddBaTimeout,
|
||||
&QosTxop::GetFailedAddBaTimeout),
|
||||
MakeTimeChecker ())
|
||||
.AddTraceSource ("BackoffTrace",
|
||||
"Trace source for backoff values",
|
||||
MakeTraceSourceAccessor (&QosTxop::m_backoffTrace),
|
||||
@@ -106,9 +122,9 @@ QosTxop::DoDispose (void)
|
||||
}
|
||||
|
||||
bool
|
||||
QosTxop::GetBaAgreementExists (Mac48Address address, uint8_t tid) const
|
||||
QosTxop::GetBaAgreementEstablished (Mac48Address address, uint8_t tid) const
|
||||
{
|
||||
return m_baManager->ExistsAgreement (address, tid);
|
||||
return m_baManager->ExistsAgreementInState (address, tid, OriginatorBlockAckAgreement::ESTABLISHED);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -196,7 +212,8 @@ QosTxop::NotifyAccessGranted (void)
|
||||
m_currentPacketTimestamp = item->GetTimeStamp ();
|
||||
if (m_currentHdr.IsQosData () && !m_currentHdr.GetAddr1 ().IsBroadcast ()
|
||||
&& m_stationManager->GetQosSupported (m_currentHdr.GetAddr1 ())
|
||||
&& !m_baManager->ExistsAgreement (m_currentHdr.GetAddr1 (), m_currentHdr.GetQosTid ())
|
||||
&& (!m_baManager->ExistsAgreement (m_currentHdr.GetAddr1 (), m_currentHdr.GetQosTid ())
|
||||
|| m_baManager->ExistsAgreementInState (m_currentHdr.GetAddr1 (), m_currentHdr.GetQosTid (), OriginatorBlockAckAgreement::RESET))
|
||||
&& SetupBlockAckIfNeeded ())
|
||||
{
|
||||
return;
|
||||
@@ -442,7 +459,7 @@ QosTxop::MissedCts (void)
|
||||
uint8_t tid = GetTid (m_currentPacket, m_currentHdr);
|
||||
m_low->FlushAggregateQueue (tid);
|
||||
|
||||
if (GetBaAgreementExists (m_currentHdr.GetAddr1 (), tid))
|
||||
if (GetBaAgreementEstablished (m_currentHdr.GetAddr1 (), tid))
|
||||
{
|
||||
NS_LOG_DEBUG ("Transmit Block Ack Request");
|
||||
CtrlBAckRequestHeader reqHdr;
|
||||
@@ -505,18 +522,29 @@ QosTxop::GotAck (void)
|
||||
WifiActionHeader actionHdr;
|
||||
Ptr<Packet> p = m_currentPacket->Copy ();
|
||||
p->RemoveHeader (actionHdr);
|
||||
if (actionHdr.GetCategory () == WifiActionHeader::BLOCK_ACK
|
||||
&& actionHdr.GetAction ().blockAck == WifiActionHeader::BLOCK_ACK_DELBA)
|
||||
if (actionHdr.GetCategory () == WifiActionHeader::BLOCK_ACK)
|
||||
{
|
||||
MgtDelBaHeader delBa;
|
||||
p->PeekHeader (delBa);
|
||||
if (delBa.IsByOriginator ())
|
||||
if (actionHdr.GetAction ().blockAck == WifiActionHeader::BLOCK_ACK_DELBA)
|
||||
{
|
||||
m_baManager->DestroyAgreement (m_currentHdr.GetAddr1 (), delBa.GetTid ());
|
||||
MgtDelBaHeader delBa;
|
||||
p->PeekHeader (delBa);
|
||||
if (delBa.IsByOriginator ())
|
||||
{
|
||||
m_baManager->DestroyAgreement (m_currentHdr.GetAddr1 (), delBa.GetTid ());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_low->DestroyBlockAckAgreement (m_currentHdr.GetAddr1 (), delBa.GetTid ());
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (actionHdr.GetAction ().blockAck == WifiActionHeader::BLOCK_ACK_ADDBA_REQUEST)
|
||||
{
|
||||
m_low->DestroyBlockAckAgreement (m_currentHdr.GetAddr1 (), delBa.GetTid ());
|
||||
// Setup addba response timeout
|
||||
MgtAddBaRequestHeader addBa;
|
||||
p->PeekHeader (addBa);
|
||||
Simulator::Schedule (m_addBaResponseTimeout,
|
||||
&QosTxop::AddBaResponseTimeout, this,
|
||||
m_currentHdr.GetAddr1 (), addBa.GetTid ());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -567,11 +595,25 @@ QosTxop::MissedAck (void)
|
||||
{
|
||||
m_txFailedCallback (m_currentHdr);
|
||||
}
|
||||
if (m_currentHdr.IsAction ())
|
||||
{
|
||||
WifiActionHeader actionHdr;
|
||||
m_currentPacket->PeekHeader (actionHdr);
|
||||
if (actionHdr.GetCategory () == WifiActionHeader::BLOCK_ACK)
|
||||
{
|
||||
uint8_t tid = GetTid (m_currentPacket, m_currentHdr);
|
||||
if (m_baManager->ExistsAgreementInState (m_currentHdr.GetAddr1 (), tid, OriginatorBlockAckAgreement::PENDING))
|
||||
{
|
||||
NS_LOG_DEBUG ("No ACK after ADDBA request");
|
||||
m_baManager->NotifyAgreementNoReply (m_currentHdr.GetAddr1 (), tid);
|
||||
Simulator::Schedule (m_failedAddBaTimeout, &QosTxop::ResetBa, this, m_currentHdr.GetAddr1 (), tid);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (GetAmpduExist (m_currentHdr.GetAddr1 ()) || m_currentHdr.IsQosData ())
|
||||
{
|
||||
uint8_t tid = GetTid (m_currentPacket, m_currentHdr);
|
||||
|
||||
if (GetBaAgreementExists (m_currentHdr.GetAddr1 (), tid))
|
||||
if (GetBaAgreementEstablished (m_currentHdr.GetAddr1 (), tid))
|
||||
{
|
||||
//send Block ACK Request in order to shift WinStart at the receiver
|
||||
NS_LOG_DEBUG ("Transmit Block Ack Request");
|
||||
@@ -955,7 +997,7 @@ QosTxop::NeedFragmentation (void) const
|
||||
|| GetAmpduExist (m_currentHdr.GetAddr1 ())
|
||||
|| (m_stationManager->GetHtSupported ()
|
||||
&& m_currentHdr.IsQosData ()
|
||||
&& GetBaAgreementExists (m_currentHdr.GetAddr1 (), GetTid (m_currentPacket, m_currentHdr))
|
||||
&& GetBaAgreementEstablished (m_currentHdr.GetAddr1 (), GetTid (m_currentPacket, m_currentHdr))
|
||||
&& GetMpduAggregator ()->GetMaxAmpduSize () >= m_currentPacket->GetSize ()))
|
||||
{
|
||||
//MSDU is not fragmented when it is transmitted using an HT-immediate or
|
||||
@@ -1238,7 +1280,7 @@ QosTxop::GotAddBaResponse (const MgtAddBaResponseHeader *respHdr, Mac48Address r
|
||||
else
|
||||
{
|
||||
NS_LOG_DEBUG ("discard ADDBA response" << recipient);
|
||||
m_baManager->NotifyAgreementUnsuccessful (recipient, tid);
|
||||
m_baManager->NotifyAgreementRejected (recipient, tid);
|
||||
}
|
||||
}
|
||||
RestartAccessIfNeeded ();
|
||||
@@ -1559,6 +1601,55 @@ QosTxop::BaTxFailed (const WifiMacHeader &hdr)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
QosTxop::AddBaResponseTimeout (Mac48Address recipient, uint8_t tid)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << recipient << +tid);
|
||||
// If agreement is still pending, ADDBA response is not received
|
||||
if (m_baManager->ExistsAgreementInState (recipient, tid, OriginatorBlockAckAgreement::PENDING))
|
||||
{
|
||||
m_baManager->NotifyAgreementNoReply (recipient, tid);
|
||||
Simulator::Schedule (m_failedAddBaTimeout, &QosTxop::ResetBa, this, m_currentHdr.GetAddr1 (), tid);
|
||||
m_backoffTrace = m_rng->GetInteger (0, GetCw ());
|
||||
StartBackoffNow (m_backoffTrace);
|
||||
RestartAccessIfNeeded ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
QosTxop::ResetBa (Mac48Address recipient, uint8_t tid)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << recipient << +tid);
|
||||
NS_ASSERT (m_baManager->ExistsAgreementInState (recipient, tid, OriginatorBlockAckAgreement::NO_REPLY));
|
||||
m_baManager->NotifyAgreementReset (recipient, tid);
|
||||
}
|
||||
|
||||
void
|
||||
QosTxop::SetAddBaResponseTimeout (Time addBaResponseTimeout)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << addBaResponseTimeout);
|
||||
m_addBaResponseTimeout = addBaResponseTimeout;
|
||||
}
|
||||
|
||||
Time
|
||||
QosTxop::GetAddBaResponseTimeout (void) const
|
||||
{
|
||||
return m_addBaResponseTimeout;
|
||||
}
|
||||
|
||||
void
|
||||
QosTxop::SetFailedAddBaTimeout (Time failedAddBaTimeout)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << failedAddBaTimeout);
|
||||
m_failedAddBaTimeout = failedAddBaTimeout;
|
||||
}
|
||||
|
||||
Time
|
||||
QosTxop::GetFailedAddBaTimeout (void) const
|
||||
{
|
||||
return m_failedAddBaTimeout;
|
||||
}
|
||||
|
||||
bool
|
||||
QosTxop::IsQosTxop (void) const
|
||||
{
|
||||
|
||||
@@ -147,12 +147,12 @@ public:
|
||||
* \param address recipient address of the peer station
|
||||
* \param tid traffic ID.
|
||||
*
|
||||
* \return true if a block ack agreement exists, false otherwise.
|
||||
* \return true if a block ack agreement is established, false otherwise.
|
||||
*
|
||||
* Checks if a block ack agreement exists with station addressed by
|
||||
* Checks if a block ack agreement is established with station addressed by
|
||||
* <i>recipient</i> for tid <i>tid</i>.
|
||||
*/
|
||||
bool GetBaAgreementExists (Mac48Address address, uint8_t tid) const;
|
||||
bool GetBaAgreementEstablished (Mac48Address address, uint8_t tid) const;
|
||||
/**
|
||||
* \param recipient address of peer station involved in block ack mechanism.
|
||||
* \param tid Ttraffic ID of transmitted packet.
|
||||
@@ -349,6 +349,31 @@ public:
|
||||
* \param enableAmpdu flag whether A-MPDU is used or not.
|
||||
*/
|
||||
void SetAmpduExist (Mac48Address dest, bool enableAmpdu);
|
||||
/**
|
||||
* Set the timeout to wait for ADDBA response.
|
||||
*
|
||||
* \param addBaResponseTimeout the timeout to wait for ADDBA response
|
||||
*/
|
||||
void SetAddBaResponseTimeout (Time addBaResponseTimeout);
|
||||
/**
|
||||
* Get the timeout for ADDBA response.
|
||||
*
|
||||
* \returns the timeout to wait for ADDBA response
|
||||
*/
|
||||
Time GetAddBaResponseTimeout (void) const;
|
||||
/**
|
||||
* Set the timeout for failed BA agreement. During the timeout period,
|
||||
* all packets will be transmitted using normal MPDU.
|
||||
*
|
||||
* \param failedAddBaTimeout the timeout for failed BA agreement
|
||||
*/
|
||||
void SetFailedAddBaTimeout (Time failedAddBaTimeout);
|
||||
/**
|
||||
* Get the timeout for failed BA agreement.
|
||||
*
|
||||
* \returns the timeout for failed BA agreement
|
||||
*/
|
||||
Time GetFailedAddBaTimeout (void) const;
|
||||
|
||||
/**
|
||||
* Return the next sequence number for the given header.
|
||||
@@ -533,6 +558,20 @@ private:
|
||||
* \returns the TXOP fragment offset
|
||||
*/
|
||||
uint32_t GetTxopFragmentOffset (uint32_t fragmentNumber) const;
|
||||
/**
|
||||
* Callback when ADDBA response is not received after timeout.
|
||||
*
|
||||
* \param recipient MAC address of recipient
|
||||
* \param tid traffic ID
|
||||
*/
|
||||
void AddBaResponseTimeout (Mac48Address recipient, uint8_t tid);
|
||||
/**
|
||||
* Reset BA agreement after BA negotiation failed.
|
||||
*
|
||||
* \param recipient MAC address of recipient
|
||||
* \param tid traffic ID
|
||||
*/
|
||||
void ResetBa (Mac48Address recipient, uint8_t tid);
|
||||
|
||||
void DoDispose (void);
|
||||
void DoInitialize (void);
|
||||
@@ -551,6 +590,8 @@ private:
|
||||
Time m_startTxop; //!< the start TXOP time
|
||||
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
|
||||
Time m_failedAddBaTimeout; //!< timeout after failed BA agreement
|
||||
|
||||
TracedValue<uint32_t> m_backoffTrace; //!< backoff trace value
|
||||
TracedValue<uint32_t> m_cwTrace; //!< CW trace value
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "ns3/pointer.h"
|
||||
#include "ns3/mobility-model.h"
|
||||
#include "ns3/random-variable-stream.h"
|
||||
#include "ns3/error-model.h"
|
||||
#include "wifi-phy.h"
|
||||
#include "wifi-phy-tag.h"
|
||||
#include "ampdu-tag.h"
|
||||
@@ -298,6 +299,14 @@ WifiPhy::GetTypeId (void)
|
||||
PointerValue (),
|
||||
MakePointerAccessor (&WifiPhy::m_frameCaptureModel),
|
||||
MakePointerChecker <FrameCaptureModel> ())
|
||||
.AddAttribute ("PostReceptionErrorModel",
|
||||
"An optional packet error model can be added to the receive "
|
||||
"packet process after any propagation-based (SNR-based) error "
|
||||
"models have been applied. Typically this is used to force "
|
||||
"specific packet drops, for testing purposes.",
|
||||
PointerValue (),
|
||||
MakePointerAccessor (&WifiPhy::m_postReceptionErrorModel),
|
||||
MakePointerChecker<ErrorModel> ())
|
||||
.AddTraceSource ("PhyTxBegin",
|
||||
"Trace source indicating a packet "
|
||||
"has begun transmitting over the channel medium",
|
||||
@@ -387,6 +396,7 @@ WifiPhy::DoDispose (void)
|
||||
m_mobility = 0;
|
||||
m_state = 0;
|
||||
m_wifiRadioEnergyModel = 0;
|
||||
m_postReceptionErrorModel = 0;
|
||||
m_deviceRateSet.clear ();
|
||||
m_deviceMcsSet.clear ();
|
||||
}
|
||||
@@ -718,6 +728,13 @@ WifiPhy::SetErrorRateModel (const Ptr<ErrorRateModel> rate)
|
||||
m_interference.SetNumberOfReceiveAntennas (GetNumberOfAntennas ());
|
||||
}
|
||||
|
||||
void
|
||||
WifiPhy::SetPostReceptionErrorModel (const Ptr<ErrorModel> em)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << em);
|
||||
m_postReceptionErrorModel = em;
|
||||
}
|
||||
|
||||
void
|
||||
WifiPhy::SetFrameCaptureModel (const Ptr<FrameCaptureModel> model)
|
||||
{
|
||||
@@ -2588,7 +2605,14 @@ WifiPhy::EndReceive (Ptr<Packet> packet, WifiPreamble preamble, MpduType mpdutyp
|
||||
NS_LOG_DEBUG ("mode=" << (event->GetPayloadMode ().GetDataRate (event->GetTxVector ())) <<
|
||||
", snr(dB)=" << RatioToDb (snrPer.snr) << ", per=" << snrPer.per << ", size=" << packet->GetSize ());
|
||||
|
||||
if (m_random->GetValue () > snrPer.per)
|
||||
//
|
||||
// There are two error checks: PER and receive error model check.
|
||||
// PER check models is typical for Wi-Fi and is based on signal modulation;
|
||||
// Receive error model is optional, if we have an error model and
|
||||
// it indicates that the packet is corrupt, drop the packet.
|
||||
//
|
||||
if (m_random->GetValue () > snrPer.per &&
|
||||
!(m_postReceptionErrorModel && m_postReceptionErrorModel->IsCorrupt (packet)))
|
||||
{
|
||||
NotifyRxEnd (packet);
|
||||
SignalNoiseDbm signalNoise;
|
||||
|
||||
@@ -41,6 +41,7 @@ class WifiPhyStateHelper;
|
||||
class FrameCaptureModel;
|
||||
class WifiRadioEnergyModel;
|
||||
class UniformRandomVariable;
|
||||
class ErrorModel;
|
||||
|
||||
/// SignalNoiseDbm structure
|
||||
struct SignalNoiseDbm
|
||||
@@ -1409,6 +1410,18 @@ public:
|
||||
* \param rate the error rate model
|
||||
*/
|
||||
void SetErrorRateModel (const Ptr<ErrorRateModel> rate);
|
||||
/**
|
||||
* Attach a receive ErrorModel to the WifiPhy.
|
||||
*
|
||||
* The WifiPhy may optionally include an ErrorModel in
|
||||
* the packet receive chain. The error model is additive
|
||||
* to any modulation-based error model based on SNR, and
|
||||
* is typically used to force specific packet losses or
|
||||
* for testing purposes.
|
||||
*
|
||||
* \param em Ptr to the ErrorModel.
|
||||
*/
|
||||
void SetPostReceptionErrorModel (const Ptr<ErrorModel> em);
|
||||
/**
|
||||
* Sets the frame capture model.
|
||||
*
|
||||
@@ -1777,6 +1790,7 @@ private:
|
||||
Ptr<Event> m_currentEvent; //!< Hold the current event
|
||||
Ptr<FrameCaptureModel> m_frameCaptureModel; //!< Frame capture model
|
||||
Ptr<WifiRadioEnergyModel> m_wifiRadioEnergyModel; //!< Wifi radio energy model
|
||||
Ptr<ErrorModel> m_postReceptionErrorModel; //!< Error model for receive packet events
|
||||
|
||||
Callback<void> m_capabilitiesChangedCallback; //!< Callback when PHY capabilities changed
|
||||
};
|
||||
|
||||
@@ -128,6 +128,7 @@ AmpduAggregationTest::DoRun (void)
|
||||
reqHdr.SetTimeout (0);
|
||||
reqHdr.SetStartingSequence (0);
|
||||
m_mac->GetBEQueue ()->m_baManager->CreateAgreement (&reqHdr, hdr.GetAddr1 ());
|
||||
m_mac->GetBEQueue ()->m_baManager->NotifyAgreementEstablished (hdr.GetAddr1 (), 0, 0);
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "ns3/pointer.h"
|
||||
#include "ns3/rng-seed-manager.h"
|
||||
#include "ns3/config.h"
|
||||
#include "ns3/error-model.h"
|
||||
#include "ns3/packet-socket-server.h"
|
||||
#include "ns3/packet-socket-client.h"
|
||||
#include "ns3/packet-socket-helper.h"
|
||||
@@ -605,8 +606,6 @@ Bug730TestCase::DoRun (void)
|
||||
{
|
||||
m_received = 0;
|
||||
|
||||
Config::SetDefault ("ns3::WifiRemoteStationManager::FragmentationThreshold", StringValue ("2304"));
|
||||
|
||||
NodeContainer wifiStaNode;
|
||||
wifiStaNode.Create (1);
|
||||
|
||||
@@ -899,7 +898,6 @@ SetChannelFrequencyTest::DoRun ()
|
||||
NS_TEST_ASSERT_MSG_EQ (phySta->GetChannelWidth (), 40, "802.11 5GHz configuration");
|
||||
NS_TEST_ASSERT_MSG_EQ (phySta->GetFrequency (), 5220, "802.11 5GHz configuration");
|
||||
}
|
||||
// modify cases 13 and 14 to avoid Config::SetDefault ()
|
||||
{
|
||||
// case 13
|
||||
WifiHelper wifi;
|
||||
@@ -1268,9 +1266,6 @@ Bug2483TestCase::SendPacketBurst (uint8_t numPackets, Ptr<NetDevice> sourceDevic
|
||||
void
|
||||
Bug2483TestCase::DoRun (void)
|
||||
{
|
||||
Config::SetDefault ("ns3::WifiRemoteStationManager::RtsCtsThreshold", StringValue ("500")); // so as to force RTS/CTS for data frames
|
||||
Config::SetDefault ("ns3::WifiPhy::CcaMode1Threshold", DoubleValue (-62.0));
|
||||
|
||||
uint16_t channelWidth = 40; // at least 40 MHz expected here
|
||||
|
||||
NodeContainer wifiStaNode;
|
||||
@@ -1295,12 +1290,14 @@ Bug2483TestCase::DoRun (void)
|
||||
spectrumPhy.Set ("ChannelWidth", UintegerValue (channelWidth));
|
||||
spectrumPhy.Set ("TxPowerStart", DoubleValue (10));
|
||||
spectrumPhy.Set ("TxPowerEnd", DoubleValue (10));
|
||||
spectrumPhy.Set ("CcaMode1Threshold", DoubleValue (-62.0));
|
||||
|
||||
WifiHelper wifi;
|
||||
wifi.SetStandard (WIFI_PHY_STANDARD_80211ac);
|
||||
wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager",
|
||||
"DataMode", StringValue ("VhtMcs8"),
|
||||
"ControlMode", StringValue ("VhtMcs8"));
|
||||
"ControlMode", StringValue ("VhtMcs8"),
|
||||
"RtsCtsThreshold", StringValue ("500")); // so as to force RTS/CTS for data frames
|
||||
|
||||
WifiMacHelper mac;
|
||||
mac.SetType ("ns3::StaWifiMac");
|
||||
@@ -1700,6 +1697,227 @@ StaWifiMacScanningTestCase::DoRun (void)
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/**
|
||||
* Make sure that the ADDBA handshake process is protected.
|
||||
*
|
||||
* The scenario considers an access point and a station. It utilizes
|
||||
* ReceiveListErrorModel to drop by force ADDBA request on STA or ADDBA
|
||||
* response on AP. The AP sends 5 packets of each 1000 bytes (thus generating
|
||||
* BA agreement), 2 times during the test at 0.5s and 0.8s. We only drop the
|
||||
* first ADDBA request/response of the first BA negotiation. Therefore, we
|
||||
* expect that the packets still in queue after the failed BA agreement will be
|
||||
* sent with normal MPDU, and packets queued after that should be sent with
|
||||
* A-MPDU.
|
||||
*
|
||||
* This test consider 2 cases:
|
||||
*
|
||||
* 1. ADDBA request packets are blocked on receive at STA, triggering
|
||||
* transmission failure at AP
|
||||
* 2. ADDBA response packets are blocked on receive at AP, STA stops
|
||||
* retransmission of ADDBA response
|
||||
*
|
||||
* See \bugid{2470}
|
||||
*/
|
||||
|
||||
class Bug2470TestCase : public TestCase
|
||||
{
|
||||
public:
|
||||
Bug2470TestCase ();
|
||||
virtual ~Bug2470TestCase ();
|
||||
virtual void DoRun (void);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Callback when packet is received
|
||||
* \param context node context
|
||||
* \param p the received packet
|
||||
* \param channelFreqMhz the channel frequency in MHz
|
||||
* \param txVector the TX vector
|
||||
* \param aMpdu the A-MPDU info
|
||||
* \param signalNoise the signal noise in dBm
|
||||
*/
|
||||
void RxCallback (std::string context, Ptr<const Packet> p, uint16_t channelFreqMhz, WifiTxVector txVector, MpduInfo aMpdu, SignalNoiseDbm signalNoise);
|
||||
/**
|
||||
* Callback when packet is dropped
|
||||
* \param context node context
|
||||
* \param p the received packet
|
||||
*/
|
||||
void RxDropCallback (std::string context, Ptr<const Packet> p);
|
||||
/**
|
||||
* Triggers the arrival of a burst of 1000 Byte-long packets in the source device
|
||||
* \param numPackets number of packets in burst
|
||||
* \param sourceDevice pointer to the source NetDevice
|
||||
* \param destination address of the destination device
|
||||
*/
|
||||
void SendPacketBurst (uint32_t numPackets, Ptr<NetDevice> sourceDevice, Address& destination) const;
|
||||
/**
|
||||
* Run subtest for this test suite
|
||||
* \param apErrorModel ErrorModel used for AP
|
||||
* \param staErrorModel ErrorModel used for STA
|
||||
*/
|
||||
void RunSubtest (PointerValue apErrorModel, PointerValue staErrorModel);
|
||||
|
||||
uint8_t m_receivedNormalMpduCount; ///< Count received normal MPDU packets on STA
|
||||
uint8_t m_receivedAmpduCount; ///< Count received A-MPDU packets on STA
|
||||
uint8_t m_droppedActionCount; ///< Count dropped ADDBA request/response
|
||||
};
|
||||
|
||||
Bug2470TestCase::Bug2470TestCase ()
|
||||
: TestCase ("Test case for Bug 2470"),
|
||||
m_receivedNormalMpduCount (0),
|
||||
m_receivedAmpduCount (0),
|
||||
m_droppedActionCount (0)
|
||||
{
|
||||
}
|
||||
|
||||
Bug2470TestCase::~Bug2470TestCase ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Bug2470TestCase::RxCallback (std::string context, Ptr<const Packet> p, uint16_t channelFreqMhz, WifiTxVector txVector, MpduInfo aMpdu, SignalNoiseDbm signalNoise)
|
||||
{
|
||||
Ptr<Packet> packet = p->Copy ();
|
||||
if (aMpdu.type != MpduType::NORMAL_MPDU)
|
||||
{
|
||||
m_receivedAmpduCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
WifiMacHeader hdr;
|
||||
packet->RemoveHeader (hdr);
|
||||
if (hdr.IsData ())
|
||||
{
|
||||
m_receivedNormalMpduCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Bug2470TestCase::RxDropCallback (std::string context, Ptr<const Packet> p)
|
||||
{
|
||||
Ptr<Packet> packet = p->Copy ();
|
||||
WifiMacHeader hdr;
|
||||
packet->RemoveHeader (hdr);
|
||||
if (hdr.IsAction ())
|
||||
{
|
||||
m_droppedActionCount++;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Bug2470TestCase::SendPacketBurst (uint32_t numPackets, Ptr<NetDevice> sourceDevice,
|
||||
Address& destination) const
|
||||
{
|
||||
for (uint32_t i = 0; i < numPackets; i++)
|
||||
{
|
||||
Ptr<Packet> pkt = Create<Packet> (1000); // 1000 dummy bytes of data
|
||||
sourceDevice->Send (pkt, destination, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Bug2470TestCase::RunSubtest (PointerValue apErrorModel, PointerValue staErrorModel)
|
||||
{
|
||||
RngSeedManager::SetSeed (1);
|
||||
RngSeedManager::SetRun (1);
|
||||
|
||||
NodeContainer wifiApNode, wifiStaNode;
|
||||
wifiApNode.Create (1);
|
||||
wifiStaNode.Create (1);
|
||||
|
||||
YansWifiPhyHelper phy = YansWifiPhyHelper::Default ();
|
||||
YansWifiChannelHelper channel = YansWifiChannelHelper::Default ();
|
||||
phy.SetChannel (channel.Create ());
|
||||
|
||||
WifiHelper wifi;
|
||||
wifi.SetStandard (WIFI_PHY_STANDARD_80211n_5GHZ);
|
||||
wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager",
|
||||
"DataMode", StringValue ("HtMcs7"),
|
||||
"ControlMode", StringValue ("HtMcs7"));
|
||||
|
||||
WifiMacHelper mac;
|
||||
NetDeviceContainer apDevice;
|
||||
phy.Set ("PostReceptionErrorModel", apErrorModel);
|
||||
mac.SetType ("ns3::ApWifiMac", "EnableBeaconJitter", BooleanValue (false));
|
||||
apDevice = wifi.Install (phy, mac, wifiApNode);
|
||||
|
||||
NetDeviceContainer staDevice;
|
||||
phy.Set ("PostReceptionErrorModel", staErrorModel);
|
||||
mac.SetType ("ns3::StaWifiMac");
|
||||
staDevice = wifi.Install (phy, mac, wifiStaNode);
|
||||
|
||||
MobilityHelper mobility;
|
||||
Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
|
||||
positionAlloc->Add (Vector (0.0, 0.0, 0.0));
|
||||
positionAlloc->Add (Vector (1.0, 0.0, 0.0));
|
||||
mobility.SetPositionAllocator (positionAlloc);
|
||||
|
||||
mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
|
||||
mobility.Install (wifiApNode);
|
||||
mobility.Install (wifiStaNode);
|
||||
|
||||
Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/MonitorSnifferRx", MakeCallback (&Bug2470TestCase::RxCallback, this));
|
||||
Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/PhyRxDrop", MakeCallback (&Bug2470TestCase::RxDropCallback, this));
|
||||
|
||||
Simulator::Schedule (Seconds (0.5), &Bug2470TestCase::SendPacketBurst, this, 5, apDevice.Get (0), staDevice.Get (0)->GetAddress ());
|
||||
Simulator::Schedule (Seconds (0.8), &Bug2470TestCase::SendPacketBurst, this, 5, apDevice.Get (0), staDevice.Get (0)->GetAddress ());
|
||||
|
||||
Simulator::Stop (Seconds (1.0));
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
}
|
||||
|
||||
void
|
||||
Bug2470TestCase::DoRun (void)
|
||||
{
|
||||
// Create ReceiveListErrorModel to corrupt ADDBA req packet. We use ReceiveListErrorModel
|
||||
// instead of ListErrorModel since packet UID is incremented between simulations. But
|
||||
// problem may occur because of random stream, therefore we suppress usage of RNG as
|
||||
// much as possible (i.e., removing beacon jitter).
|
||||
Ptr<ReceiveListErrorModel> staPem = CreateObject<ReceiveListErrorModel> ();
|
||||
std::list<uint32_t> blackList;
|
||||
// Block ADDBA request 6 times (== maximum number of MAC frame transmissions in the addba response timeout interval)
|
||||
blackList.push_back (8);
|
||||
blackList.push_back (9);
|
||||
blackList.push_back (10);
|
||||
blackList.push_back (11);
|
||||
blackList.push_back (12);
|
||||
blackList.push_back (13);
|
||||
staPem->SetList (blackList);
|
||||
|
||||
{
|
||||
RunSubtest (PointerValue (), PointerValue (staPem));
|
||||
NS_TEST_ASSERT_MSG_EQ (m_droppedActionCount, 6, "ADDBA request packet is not dropped correctly");
|
||||
// There are two sets of 5 packets to be transmitted. The first 5 packets should be sent by normal
|
||||
// MPDU because of failed ADDBA handshake. For the second set, the first packet should be sent by
|
||||
// normal MPDU, and the rest with A-MPDU. In total we expect to receive 2 normal MPDU packets and
|
||||
// 8 A-MPDU packets.
|
||||
NS_TEST_ASSERT_MSG_EQ (m_receivedNormalMpduCount, 2, "Receiving incorrect number of normal MPDU packet on subtest 1");
|
||||
NS_TEST_ASSERT_MSG_EQ (m_receivedAmpduCount, 8, "Receiving incorrect number of A-MPDU packet on subtest 1");
|
||||
}
|
||||
|
||||
m_receivedNormalMpduCount = 0;
|
||||
m_receivedAmpduCount = 0;
|
||||
m_droppedActionCount = 0;
|
||||
Ptr<ReceiveListErrorModel> apPem = CreateObject<ReceiveListErrorModel> ();
|
||||
blackList.clear ();
|
||||
// Block ADDBA request 3 times (== maximum number of MAC frame transmissions in the addba response timeout interval)
|
||||
blackList.push_back (4);
|
||||
blackList.push_back (5);
|
||||
blackList.push_back (6);
|
||||
apPem->SetList (blackList);
|
||||
|
||||
{
|
||||
RunSubtest (PointerValue (apPem), PointerValue ());
|
||||
NS_TEST_ASSERT_MSG_EQ (m_droppedActionCount, 3, "ADDBA response packet is not dropped correctly");
|
||||
// Similar to subtest 1, we also expect to receive 6 normal MPDU packets and 4 A-MPDU packets.
|
||||
NS_TEST_ASSERT_MSG_EQ (m_receivedNormalMpduCount, 6, "Receiving incorrect number of normal MPDU packet on subtest 2");
|
||||
NS_TEST_ASSERT_MSG_EQ (m_receivedAmpduCount, 4, "Receiving incorrect number of A-MPDU packet on subtest 2");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup wifi-test
|
||||
* \ingroup tests
|
||||
@@ -1725,6 +1943,7 @@ WifiTestSuite::WifiTestSuite ()
|
||||
AddTestCase (new Bug2483TestCase, TestCase::QUICK); //Bug 2483
|
||||
AddTestCase (new Bug2831TestCase, TestCase::QUICK); //Bug 2831
|
||||
AddTestCase (new StaWifiMacScanningTestCase, TestCase::QUICK); //Bug 2399
|
||||
AddTestCase (new Bug2470TestCase, TestCase::QUICK); //Bug 2470
|
||||
}
|
||||
|
||||
static WifiTestSuite g_wifiTestSuite; ///< the test suite
|
||||
|
||||
Reference in New Issue
Block a user