A Discrete-Event Network Simulator
API
wifi-aggregation-test.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2015
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Sébastien Deronne <sebastien.deronne@gmail.com>
19  */
20 
21 #include "ns3/string.h"
22 #include "ns3/test.h"
23 #include "ns3/simulator.h"
24 #include "ns3/wifi-mac-queue.h"
25 #include "ns3/mac-low.h"
26 #include "ns3/qos-txop.h"
27 #include "ns3/yans-wifi-phy.h"
28 #include "ns3/mac-tx-middle.h"
29 #include "ns3/msdu-aggregator.h"
30 #include "ns3/mpdu-aggregator.h"
31 #include "ns3/mgt-headers.h"
32 #include "ns3/wifi-remote-station-manager.h"
33 
34 using namespace ns3;
35 
43 {
44 public:
46 
47 private:
48  virtual void DoRun (void);
57 };
58 
60  : TestCase ("Check the correctness of MPDU aggregation operations")
61 {
62 }
63 
64 void
66 {
67  /*
68  * Create and configure phy layer.
69  */
70  m_phy = CreateObject<YansWifiPhy> ();
72 
73  /*
74  * Create and configure manager.
75  */
77  m_factory.SetTypeId ("ns3::ConstantRateWifiManager");
78  m_factory.Set ("DataMode", StringValue ("HtMcs7"));
81  m_manager->SetHtSupported (true);
82 
83  /*
84  * Create and configure mac layer.
85  */
86  m_low = CreateObject<MacLow> ();
87  m_low->SetPhy (m_phy);
89  m_low->SetAddress (Mac48Address ("00:00:00:00:00:01"));
90 
91  m_channelAccessManager = CreateObject<ChannelAccessManager> ();
95 
96  m_txop = CreateObject<QosTxop> ();
101 
102  m_txMiddle = Create<MacTxMiddle> ();
105 
106  /*
107  * Configure MPDU aggregation.
108  */
110  m_factory.SetTypeId ("ns3::MpduAggregator");
114 
115  /*
116  * Create a dummy packet of 1500 bytes and fill mac header fields.
117  */
118  Ptr<const Packet> pkt = Create<Packet> (1500);
119  Ptr<Packet> currentAggregatedPacket = Create<Packet> ();
120  WifiMacHeader hdr;
121  hdr.SetAddr1 (Mac48Address ("00:00:00:00:00:02"));
122  hdr.SetAddr2 (Mac48Address ("00:00:00:00:00:01"));
123  hdr.SetType (WIFI_MAC_QOSDATA);
124  hdr.SetQosTid (0);
125  uint16_t sequence = m_txMiddle->GetNextSequenceNumberFor (&hdr);
126  hdr.SetSequenceNumber (sequence);
127  hdr.SetFragmentNumber (0);
128  hdr.SetNoMoreFragments ();
129  hdr.SetNoRetry ();
130 
131  /*
132  * Establish agreement.
133  */
134  MgtAddBaRequestHeader reqHdr;
135  reqHdr.SetImmediateBlockAck ();
136  reqHdr.SetTid (0);
137  reqHdr.SetBufferSize (0);
138  reqHdr.SetTimeout (0);
139  reqHdr.SetStartingSequence (0);
140  m_txop->m_baManager->CreateAgreement (&reqHdr, hdr.GetAddr1 ());
141 
142  //-----------------------------------------------------------------------------------------------------
143 
144  /*
145  * Test behavior when no other packets are in the queue
146  */
147  m_low->m_currentHdr = hdr;
148  m_low->m_currentPacket = pkt->Copy ();
150 
151  bool isAmpdu = m_low->IsAmpdu (pkt, hdr);
152  NS_TEST_EXPECT_MSG_EQ (isAmpdu, false, "a single packet should not result in an A-MPDU");
153  NS_TEST_EXPECT_MSG_EQ (m_low->m_aggregateQueue[0]->GetNPackets (), 0, "aggregation queue is not flushed");
154 
155  //-----------------------------------------------------------------------------------------------------
156 
157  /*
158  * Test behavior when 2 more packets are in the queue
159  */
160  Ptr<const Packet> pkt1 = Create<Packet> (1500);
161  Ptr<const Packet> pkt2 = Create<Packet> (1500);
162  WifiMacHeader hdr1, hdr2;
163 
164  hdr1.SetAddr1 (Mac48Address ("00:00:00:00:00:02"));
165  hdr1.SetAddr2 (Mac48Address ("00:00:00:00:00:01"));
166  hdr1.SetType (WIFI_MAC_QOSDATA);
167  hdr1.SetQosTid (0);
168 
169  hdr2.SetAddr1 (Mac48Address ("00:00:00:00:00:02"));
170  hdr2.SetAddr2 (Mac48Address ("00:00:00:00:00:01"));
171  hdr2.SetType (WIFI_MAC_QOSDATA);
172  hdr2.SetQosTid (0);
173 
174  m_txop->GetWifiMacQueue ()->Enqueue (Create<WifiMacQueueItem> (pkt1, hdr1));
175  m_txop->GetWifiMacQueue ()->Enqueue (Create<WifiMacQueueItem> (pkt2, hdr2));
176 
177  isAmpdu = m_low->IsAmpdu (pkt, hdr);
178  uint32_t aggregationQueueSize = m_low->m_aggregateQueue[0]->GetNPackets ();
179  NS_TEST_EXPECT_MSG_EQ (isAmpdu, true, "MPDU aggregation failed");
180  NS_TEST_EXPECT_MSG_EQ (m_low->m_currentPacket->GetSize (), 4606, "A-MPDU size is not correct");
181  NS_TEST_EXPECT_MSG_EQ (aggregationQueueSize, 3, "aggregation queue should not be empty");
182  NS_TEST_EXPECT_MSG_EQ (m_txop->GetWifiMacQueue ()->GetNPackets (), 0, "queue should be empty");
183 
184  Ptr <WifiMacQueueItem> dequeuedItem;
185  WifiMacHeader dequeuedHdr;
186  uint32_t i = 0;
187  for (; aggregationQueueSize > 0; aggregationQueueSize--, i++)
188  {
189  dequeuedItem = m_low->m_aggregateQueue[0]->Dequeue ();
190  dequeuedHdr = dequeuedItem->GetHeader ();
191  NS_TEST_EXPECT_MSG_EQ (dequeuedHdr.GetSequenceNumber (), i, "wrong sequence number");
192  }
193  NS_TEST_EXPECT_MSG_EQ (aggregationQueueSize, 0, "aggregation queue should be empty");
194 
195  //-----------------------------------------------------------------------------------------------------
196 
197  /*
198  * Test behavior when the 802.11n station and another non-QoS station are associated to the AP.
199  * The AP sends an A-MPDU to the 802.11n station followed by the last retransmission of a non-QoS data frame to the non-QoS station.
200  * This is used to reproduce bug 2224.
201  */
202  pkt1 = Create<Packet> (1500);
203  pkt2 = Create<Packet> (1500);
204  hdr1.SetAddr1 (Mac48Address ("00:00:00:00:00:02"));
205  hdr1.SetAddr2 (Mac48Address ("00:00:00:00:00:01"));
206  hdr1.SetType (WIFI_MAC_QOSDATA);
207  hdr1.SetQosTid (0);
208  hdr1.SetSequenceNumber (3);
209  hdr2.SetAddr1 (Mac48Address ("00:00:00:00:00:03"));
210  hdr2.SetAddr2 (Mac48Address ("00:00:00:00:00:01"));
211  hdr2.SetType (WIFI_MAC_DATA);
212  hdr2.SetQosTid (0);
213 
214  Ptr<const Packet> pkt3 = Create<Packet> (1500);
215  WifiMacHeader hdr3;
216  hdr3.SetSequenceNumber (0);
217  hdr3.SetAddr1 (Mac48Address ("00:00:00:00:00:03"));
218  hdr3.SetAddr2 (Mac48Address ("00:00:00:00:00:01"));
219  hdr3.SetType (WIFI_MAC_DATA);
220  hdr3.SetQosTid (0);
221 
222  m_txop->GetWifiMacQueue ()->Enqueue (Create<WifiMacQueueItem> (pkt3, hdr3));
223 
224  isAmpdu = m_low->IsAmpdu (pkt1, hdr1);
225  NS_TEST_EXPECT_MSG_EQ (isAmpdu, false, "a single packet for this destination should not result in an A-MPDU");
226  NS_TEST_EXPECT_MSG_EQ (m_low->m_aggregateQueue[0]->GetNPackets (), 0, "aggregation queue is not flushed");
227 
228  m_txop->m_currentHdr = hdr2;
229  m_txop->m_currentPacket = pkt2->Copy ();
230  isAmpdu = m_low->IsAmpdu (pkt2, hdr2);
231  NS_TEST_EXPECT_MSG_EQ (isAmpdu, false, "no MPDU aggregation should be performed if there is no agreement");
232  NS_TEST_EXPECT_MSG_EQ (m_low->m_aggregateQueue[0]->GetNPackets (), 0, "aggregation queue is not flushed");
233 
234  m_manager->SetMaxSsrc (0); //set to 0 in order to fake that the maximum number of retries has been reached
235  m_txop->MissedAck ();
236 
237  NS_TEST_EXPECT_MSG_EQ (m_txop->m_currentPacket, 0, "packet should be discarded");
238  m_txop->GetWifiMacQueue ()->Remove (pkt3);
239 
240  Simulator::Destroy ();
241 
242  m_txMiddle = 0;
243 
244  m_low->Dispose ();
245  m_low = 0;
246 
247  m_txop->Dispose ();
248  m_txop = 0;
249 
252 }
253 
261 {
262 public:
264 
265 private:
266  virtual void DoRun (void);
274 };
275 
277  : TestCase ("Check the correctness of two-level aggregation operations")
278 {
279 }
280 
281 void
283 {
284  /*
285  * Create and configure phy layer.
286  */
287  m_phy = CreateObject<YansWifiPhy> ();
289 
290  /*
291  * Create and configure manager.
292  */
294  m_factory.SetTypeId ("ns3::ConstantRateWifiManager");
295  m_factory.Set ("DataMode", StringValue ("HtMcs7"));
298 
299  /*
300  * Create and configure maclayer.
301  */
302  m_low = CreateObject<MacLow> ();
303  m_low->SetPhy (m_phy);
305 
306  m_txop = CreateObject<QosTxop> ();
311 
312  /*
313  * Configure aggregation.
314  */
315  m_msduAggregator = CreateObject<MsduAggregator> ();
316  m_mpduAggregator = CreateObject<MpduAggregator> ();
317 
320 
323 
324  /*
325  * Create dummy packets of 1500 bytes and fill mac header fields that will be used for the tests.
326  */
327  Ptr<const Packet> pkt = Create<Packet> (1500);
328  Ptr<Packet> currentAggregatedPacket = Create<Packet> ();
329  WifiMacHeader hdr, peekedHdr;
330  hdr.SetAddr1 (Mac48Address ("00:00:00:00:00:01"));
331  hdr.SetAddr2 (Mac48Address ("00:00:00:00:00:02"));
332  hdr.SetType (WIFI_MAC_QOSDATA);
333  hdr.SetQosTid (0);
334  Time tstamp;
335 
336  //-----------------------------------------------------------------------------------------------------
337 
338  /*
339  * Test MSDU aggregation of two packets using MacLow::PerformMsduAggregation.
340  * It checks whether aggregation succeeded:
341  * - returned packet should be different from 0;
342  * - A-MSDU frame size should be 3030 bytes (= 2 packets + headers + padding);
343  * - one packet should be removed from the queue (the other packet is removed later in MacLow::AggregateToAmpdu) .
344  */
345  m_txop->GetWifiMacQueue ()->Enqueue (Create<WifiMacQueueItem> (pkt, hdr));
346  m_txop->GetWifiMacQueue ()->Enqueue (Create<WifiMacQueueItem> (pkt, hdr));
347 
348  Ptr<const WifiMacQueueItem> peekedItem = m_txop->GetWifiMacQueue ()->PeekByTidAndAddress (0, hdr.GetAddr1 ());
349  Ptr<const Packet> peekedPacket = peekedItem->GetPacket ();
350  peekedHdr = peekedItem->GetHeader ();
351  tstamp = peekedItem->GetTimeStamp ();
352  m_low->m_currentPacket = peekedPacket->Copy ();
353  m_low->m_currentHdr = peekedHdr;
355 
356  Ptr<Packet> packet = m_low->PerformMsduAggregation (peekedPacket, &peekedHdr, &tstamp, currentAggregatedPacket, 0);
357 
358  bool result = (packet != 0);
359  NS_TEST_EXPECT_MSG_EQ (result, true, "aggregation failed");
360  NS_TEST_EXPECT_MSG_EQ (packet->GetSize (), 3030, "wrong packet size");
361  NS_TEST_EXPECT_MSG_EQ (m_txop->GetWifiMacQueue ()->GetNPackets (), 0, "aggregated packets not removed from the queue");
362 
363  //-----------------------------------------------------------------------------------------------------
364 
365  /*
366  * Aggregation is refused when the maximum size is reached.
367  * It checks whether MSDU aggregation has been rejected because the maximum MPDU size is set to 0 (returned packet should be equal to 0).
368  * This test is needed to ensure that no packets are removed from the queue in MacLow::PerformMsduAggregation, since aggregation will no occur in MacLow::AggregateToAmpdu.
369  */
371  m_factory.SetTypeId ("ns3::MpduAggregator");
375 
376  m_txop->GetWifiMacQueue ()->Enqueue (Create<WifiMacQueueItem> (pkt, hdr));
377  packet = m_low->PerformMsduAggregation (peekedPacket, &peekedHdr, &tstamp, currentAggregatedPacket, 0);
378 
379  result = (packet != 0);
380  NS_TEST_EXPECT_MSG_EQ (result, false, "maximum aggregated frame size check failed");
381 
382  //-----------------------------------------------------------------------------------------------------
383 
384  /*
385  * Aggregation does not occur when there is no more packets in the queue.
386  * It checks whether MSDU aggregation has been rejected because there is no packets ready in the queue (returned packet should be equal to 0).
387  * This test is needed to ensure that there is no issue when the queue is empty.
388  */
390 
391  m_txop->GetWifiMacQueue ()->Remove (pkt);
392  m_txop->GetWifiMacQueue ()->Remove (pkt);
393  packet = m_low->PerformMsduAggregation (peekedPacket, &peekedHdr, &tstamp, currentAggregatedPacket, 0);
394 
395  result = (packet != 0);
396  NS_TEST_EXPECT_MSG_EQ (result, false, "aggregation failed to stop as queue is empty");
397 
398  Simulator::Destroy ();
399 
400  m_low->Dispose ();
401  m_low = 0;
402 
403  m_txop->Dispose ();
404  m_txop = 0;
405 }
406 
407 
415 {
416 public:
418 };
419 
421  : TestSuite ("aggregation-wifi", UNIT)
422 {
423  AddTestCase (new AmpduAggregationTest, TestCase::QUICK);
424  AddTestCase (new TwoLevelAggregationTest, TestCase::QUICK);
425 }
426 
Aggregator used to construct A-MPDUs.
void Dispose(void)
Dispose of this Object.
Definition: object.cc:214
void MissedAck(void)
Event handler when an ACK is missed.
Definition: qos-txop.cc:556
Wifi Aggregation Test Suite.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:102
Ptr< QosTxop > m_txop
QosTxop.
virtual void DoRun(void)
Implementation to actually run this TestCase.
HT PHY for the 5 GHz band (clause 20)
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:831
Ptr< WifiRemoteStationManager > m_manager
remote station manager
Hold variables of type string.
Definition: string.h:41
Ptr< MacLow > m_low
MacLow.
ObjectFactory m_factory
factory
A suite of tests to run.
Definition: test.h:1342
void SetImmediateBlockAck()
Enable immediate Block ACK.
void SetPhy(const Ptr< WifiPhy > phy)
Set up WifiPhy associated with this MacLow.
Definition: mac-low.cc:250
void SetBufferSize(uint16_t size)
Set buffer size.
void SetChannelAccessManager(const Ptr< ChannelAccessManager > manager)
Set ChannelAccessManager this Txop is associated to.
Definition: txop.cc:109
Implement the header for management frames of type add block ack request.
Definition: mgt-headers.h:997
void SetupPhyListener(Ptr< WifiPhy > phy)
Set up listener for Phy events.
Time GetTimeStamp(void) const
Get the timestamp included in this item.
void SetTypeId(TypeId tid)
Set the TypeId of the Objects to be created by this factory.
#define NS_TEST_EXPECT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report if not.
Definition: test.h:285
virtual WifiTxVector GetDataTxVector(Ptr< const Packet > packet, const WifiMacHeader *hdr) const
Return a TXVECTOR for the DATA frame given the destination.
Definition: mac-low.cc:1144
encapsulates test code
Definition: test.h:1155
void SetAccessCategory(AcIndex ac)
Set the access category of this EDCAF.
Definition: qos-txop.cc:1163
ObjectFactory m_factory
factory
Best Effort.
Definition: qos-utils.h:40
Ptr< YansWifiPhy > m_phy
Phy.
Ptr< MsduAggregator > m_msduAggregator
A-MSDU aggregator.
Ptr< MacTxMiddle > m_txMiddle
MacTxMiddle.
void SetMsduAggregator(const Ptr< MsduAggregator > aggr)
Set the aggregator used to construct A-MSDU subframes.
Definition: qos-txop.cc:1202
WifiTxVector m_currentTxVector
TXVECTOR used for the current packet transmission.
Definition: mac-low.h:960
const WifiMacHeader & GetHeader(void) const
Get the header stored in this item.
void SetAddr1(Mac48Address address)
Fill the Address 1 field with the given address.
uint16_t GetNextSequenceNumberFor(const WifiMacHeader *hdr)
Return the next sequence number for the given header.
Ptr< Object > Create(void) const
Create an Object instance of the configured TypeId.
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
void SetTid(uint8_t tid)
Set Traffic ID (TID).
Ptr< BlockAckManager > m_baManager
the Block ACK manager
Definition: qos-txop.h:545
void SetMaxSsrc(uint32_t maxSsrc)
Sets the maximum STA short retry count (SSRC).
void SetStartingSequence(uint16_t seq)
Set the starting sequence number.
Ptr< WifiMacQueue > m_aggregateQueue[8]
Queues per TID used for MPDU aggregation.
Definition: mac-low.h:958
virtual void SetupPhy(const Ptr< WifiPhy > phy)
Set up PHY associated with this device since it is the object that knows the full set of transmit rat...
hold a list of per-remote-station state.
Ptr< MpduAggregator > m_mpduAggregator
A-MPDU aggregrator.
virtual void SetHtSupported(bool enable)
Enable or disable HT capability support.
Ptr< const Packet > GetPacket(void) const
Get the packet stored in this item.
void SetMpduAggregator(const Ptr< MpduAggregator > aggr)
Set the aggregator used to construct A-MPDU subframes.
Definition: qos-txop.cc:1209
Every class exported by the ns3 library is enclosed in the ns3 namespace.
uint16_t GetSequenceNumber(void) const
Return the sequence number of the header.
static WifiAggregationTestSuite g_wifiAggregationTestSuite
the test suite
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:121
an EUI-48 address
Definition: mac48-address.h:43
Ptr< const Packet > m_currentPacket
the current packet
Definition: txop.h:521
void Set(std::string name, const AttributeValue &value)
Set an attribute to be set during construction.
void SetMacLow(const Ptr< MacLow > low)
Set MacLow associated with this Txop.
Definition: txop.cc:123
Two Level Aggregation Test.
void SetWifiRemoteStationManager(const Ptr< WifiRemoteStationManager > remoteManager)
Set WifiRemoteStationsManager this QosTxop is associated to.
Definition: qos-txop.cc:121
Ptr< QosTxop > m_txop
QosTxop.
Ampdu Aggregation Test.
void SetMaxAmpduSize(uint16_t maxSize)
Sets the maximum A-MPDU size in bytes.
Instantiate subclasses of ns3::Object.
virtual void DoRun(void)
Implementation to actually run this TestCase.
void SetSequenceNumber(uint16_t seq)
Set the sequence number of the header.
Ptr< Packet > m_currentPacket
Current packet transmitted/to be transmitted.
Definition: mac-low.h:906
Ptr< ChannelAccessManager > m_channelAccessManager
channel access manager
void SetTxMiddle(const Ptr< MacTxMiddle > txMiddle)
Set MacTxMiddle this Txop is associated to.
Definition: txop.cc:116
Ptr< WifiMacQueue > GetWifiMacQueue() const
Return the packet queue associated with this Txop.
Definition: txop.cc:168
void CompleteConfig(void)
Complete block ACK configuration.
Definition: qos-txop.cc:1404
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1030
WifiMacHeader m_currentHdr
Header of the current transmitted packet.
Definition: mac-low.h:907
void SetAddress(Mac48Address ad)
Set MAC address of this MacLow.
Definition: mac-low.cc:280
virtual void ConfigureStandard(WifiPhyStandard standard)
Configure the PHY-level parameters for different Wi-Fi standard.
Definition: wifi-phy.cc:1119
Ptr< Packet > PerformMsduAggregation(Ptr< const Packet > packet, WifiMacHeader *hdr, Time *tstamp, Ptr< Packet > currentAmpduPacket, uint8_t blockAckSize)
Perform MSDU aggregation for a given MPDU in an A-MPDU.
Definition: mac-low.cc:2897
void SetTimeout(uint16_t timeout)
Set timeout.
WifiMacHeader m_currentHdr
the current header
Definition: txop.h:522
bool IsAmpdu(Ptr< const Packet > packet, const WifiMacHeader hdr)
Checks if the given packet will be aggregated to an A-MPDU or not.
Definition: mac-low.cc:462
Ptr< YansWifiPhy > m_phy
Phy.
void SetupLow(Ptr< MacLow > low)
Set up listener for MacLow events.
Ptr< MacLow > m_low
MacLow.
void SetWifiRemoteStationManager(const Ptr< WifiRemoteStationManager > manager)
Set up WifiRemoteStationManager associated with this MacLow.
Definition: mac-low.cc:274
Implements the IEEE 802.11 MAC header.
void SetMaxAmsduSize(uint16_t maxSize)
Sets the maximum A-MSDU size in bytes.
Ptr< MpduAggregator > m_mpduAggregator
A-MPDU aggregator.
Ptr< WifiRemoteStationManager > m_manager
remote station manager