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/edca-txop-n.h"
27 #include "ns3/yans-wifi-phy.h"
28 #include "ns3/mac-tx-middle.h"
29 #include "ns3/dcf-manager.h"
30 #include "ns3/msdu-aggregator.h"
31 #include "ns3/mpdu-aggregator.h"
32 
33 using namespace ns3;
34 
42 {
43 public:
45 
46 private:
47  virtual void DoRun (void);
56 };
57 
59  : TestCase ("Check the correctness of MPDU aggregation operations")
60 {
61 }
62 
63 void
65 {
66  /*
67  * Create and configure phy layer.
68  */
69  m_phy = CreateObject<YansWifiPhy> ();
71 
72  /*
73  * Create and configure manager.
74  */
76  m_factory.SetTypeId ("ns3::ConstantRateWifiManager");
77  m_factory.Set ("DataMode", StringValue ("HtMcs7"));
80  m_manager->SetHtSupported (true);
81 
82  /*
83  * Create and configure mac layer.
84  */
85  m_low = CreateObject<MacLow> ();
86  m_low->SetPhy (m_phy);
88  m_low->SetAddress (Mac48Address ("00:00:00:00:00:01"));
89 
90  m_dcfManager = CreateObject<DcfManager> ();
94 
95  m_edca = CreateObject<EdcaTxopN> ();
96  m_edca->SetLow (m_low);
100 
101  m_txMiddle = Create<MacTxMiddle> ();
104 
105  /*
106  * Configure MPDU aggregation.
107  */
109  m_factory.SetTypeId ("ns3::MpduAggregator");
113 
114  /*
115  * Create a dummy packet of 1500 bytes and fill mac header fields.
116  */
117  Ptr<const Packet> pkt = Create<Packet> (1500);
118  Ptr<Packet> currentAggregatedPacket = Create<Packet> ();
119  WifiMacHeader hdr;
120  hdr.SetAddr1 (Mac48Address ("00:00:00:00:00:02"));
121  hdr.SetAddr2 (Mac48Address ("00:00:00:00:00:01"));
122  hdr.SetType (WIFI_MAC_QOSDATA);
123  hdr.SetQosTid (0);
124  uint16_t sequence = m_txMiddle->GetNextSequenceNumberFor (&hdr);
125  hdr.SetSequenceNumber (sequence);
126  hdr.SetFragmentNumber (0);
127  hdr.SetNoMoreFragments ();
128  hdr.SetNoRetry ();
129 
130  /*
131  * Establish agreement.
132  */
133  MgtAddBaRequestHeader reqHdr;
134  reqHdr.SetImmediateBlockAck ();
135  reqHdr.SetTid (0);
136  reqHdr.SetBufferSize (0);
137  reqHdr.SetTimeout (0);
138  reqHdr.SetStartingSequence (0);
139  m_edca->m_baManager->CreateAgreement (&reqHdr, hdr.GetAddr1 ());
140 
141  //-----------------------------------------------------------------------------------------------------
142 
143  /*
144  * Test behavior when no other packets are in the queue
145  */
146  m_low->m_currentHdr = hdr;
147  m_low->m_currentPacket = pkt->Copy ();
149 
150  bool isAmpdu = m_low->IsAmpdu (pkt, hdr);
151  NS_TEST_EXPECT_MSG_EQ (isAmpdu, false, "a single packet should not result in an A-MPDU");
152  NS_TEST_EXPECT_MSG_EQ (m_low->m_aggregateQueue[0]->GetNPackets (), 0, "aggregation queue is not flushed");
153 
154  //-----------------------------------------------------------------------------------------------------
155 
156  /*
157  * Test behavior when 2 more packets are in the queue
158  */
159  Ptr<const Packet> pkt1 = Create<Packet> (1500);
160  Ptr<const Packet> pkt2 = Create<Packet> (1500);
161  WifiMacHeader hdr1, hdr2;
162 
163  hdr1.SetAddr1 (Mac48Address ("00:00:00:00:00:02"));
164  hdr1.SetAddr2 (Mac48Address ("00:00:00:00:00:01"));
165  hdr1.SetType (WIFI_MAC_QOSDATA);
166  hdr1.SetQosTid (0);
167 
168  hdr2.SetAddr1 (Mac48Address ("00:00:00:00:00:02"));
169  hdr2.SetAddr2 (Mac48Address ("00:00:00:00:00:01"));
170  hdr2.SetType (WIFI_MAC_QOSDATA);
171  hdr2.SetQosTid (0);
172 
173  m_edca->GetQueue ()->Enqueue (Create<WifiMacQueueItem> (pkt1, hdr1));
174  m_edca->GetQueue ()->Enqueue (Create<WifiMacQueueItem> (pkt2, hdr2));
175 
176  isAmpdu = m_low->IsAmpdu (pkt, hdr);
177  uint32_t aggregationQueueSize = m_low->m_aggregateQueue[0]->GetNPackets ();
178  NS_TEST_EXPECT_MSG_EQ (isAmpdu, true, "MPDU aggregation failed");
179  NS_TEST_EXPECT_MSG_EQ (m_low->m_currentPacket->GetSize (), 4606, "A-MPDU size is not correct");
180  NS_TEST_EXPECT_MSG_EQ (aggregationQueueSize, 3, "aggregation queue should not be empty");
181  NS_TEST_EXPECT_MSG_EQ (m_edca->GetQueue ()->GetNPackets (), 0, "queue should be empty");
182 
183  Ptr <WifiMacQueueItem> dequeuedItem;
184  WifiMacHeader dequeuedHdr;
185  uint32_t i = 0;
186  for (; aggregationQueueSize > 0; aggregationQueueSize--, i++)
187  {
188  dequeuedItem = m_low->m_aggregateQueue[0]->Dequeue ();
189  dequeuedHdr = dequeuedItem->GetHeader ();
190  NS_TEST_EXPECT_MSG_EQ (dequeuedHdr.GetSequenceNumber (), i, "wrong sequence number");
191  }
192  NS_TEST_EXPECT_MSG_EQ (aggregationQueueSize, 0, "aggregation queue should be empty");
193 
194  //-----------------------------------------------------------------------------------------------------
195 
196  /*
197  * Test behavior when the 802.11n station and another non-QoS station are associated to the AP.
198  * 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.
199  * This is used to reproduce bug 2224.
200  */
201  pkt1 = Create<Packet> (1500);
202  pkt2 = Create<Packet> (1500);
203  hdr1.SetAddr1 (Mac48Address ("00:00:00:00:00:02"));
204  hdr1.SetAddr2 (Mac48Address ("00:00:00:00:00:01"));
205  hdr1.SetType (WIFI_MAC_QOSDATA);
206  hdr1.SetQosTid (0);
207  hdr1.SetSequenceNumber (3);
208  hdr2.SetAddr1 (Mac48Address ("00:00:00:00:00:03"));
209  hdr2.SetAddr2 (Mac48Address ("00:00:00:00:00:01"));
210  hdr2.SetType (WIFI_MAC_DATA);
211  hdr2.SetQosTid (0);
212 
213  Ptr<const Packet> pkt3 = Create<Packet> (1500);
214  WifiMacHeader hdr3;
215  hdr3.SetSequenceNumber (0);
216  hdr3.SetAddr1 (Mac48Address ("00:00:00:00:00:03"));
217  hdr3.SetAddr2 (Mac48Address ("00:00:00:00:00:01"));
218  hdr3.SetType (WIFI_MAC_DATA);
219  hdr3.SetQosTid (0);
220 
221  m_edca->GetQueue ()->Enqueue (Create<WifiMacQueueItem> (pkt3, hdr3));
222 
223  isAmpdu = m_low->IsAmpdu (pkt1, hdr1);
224  NS_TEST_EXPECT_MSG_EQ (isAmpdu, false, "a single packet for this destination should not result in an A-MPDU");
225  NS_TEST_EXPECT_MSG_EQ (m_low->m_aggregateQueue[0]->GetNPackets (), 0, "aggregation queue is not flushed");
226 
227  m_edca->m_currentHdr = hdr2;
228  m_edca->m_currentPacket = pkt2->Copy ();
229  isAmpdu = m_low->IsAmpdu (pkt2, hdr2);
230  NS_TEST_EXPECT_MSG_EQ (isAmpdu, false, "no MPDU aggregation should be performed if there is no agreement");
231  NS_TEST_EXPECT_MSG_EQ (m_low->m_aggregateQueue[0]->GetNPackets (), 0, "aggregation queue is not flushed");
232 
233  m_manager->SetMaxSlrc (0); //set to 0 in order to fake that the maximum number of retries has been reached
234  m_edca->MissedAck ();
235 
236  NS_TEST_EXPECT_MSG_EQ (m_edca->m_currentPacket, 0, "packet should be discarded");
237  m_edca->GetQueue ()->Remove (pkt3);
238 
239  Simulator::Destroy ();
240 
241  m_txMiddle = 0;
242 
243  m_low->Dispose ();
244  m_low = 0;
245 
246  m_edca->Dispose ();
247  m_edca = 0;
248 
249  m_dcfManager->Dispose ();
250  m_dcfManager = 0;
251 }
252 
260 {
261 public:
263 
264 private:
265  virtual void DoRun (void);
273 };
274 
276  : TestCase ("Check the correctness of two-level aggregation operations")
277 {
278 }
279 
280 void
282 {
283  /*
284  * Create and configure phy layer.
285  */
286  m_phy = CreateObject<YansWifiPhy> ();
288 
289  /*
290  * Create and configure manager.
291  */
293  m_factory.SetTypeId ("ns3::ConstantRateWifiManager");
294  m_factory.Set ("DataMode", StringValue ("HtMcs7"));
297 
298  /*
299  * Create and configure maclayer.
300  */
301  m_low = CreateObject<MacLow> ();
302  m_low->SetPhy (m_phy);
304 
305  m_edca = CreateObject<EdcaTxopN> ();
306  m_edca->SetLow (m_low);
310 
311  /*
312  * Configure aggregation.
313  */
314  m_msduAggregator = CreateObject<MsduAggregator> ();
315  m_mpduAggregator = CreateObject<MpduAggregator> ();
316 
318  m_mpduAggregator->SetMaxAmpduSize (65535);
319 
321  m_edca->SetMpduAggregator (m_mpduAggregator);
322 
323  /*
324  * Create dummy packets of 1500 bytes and fill mac header fields that will be used for the tests.
325  */
326  Ptr<const Packet> pkt = Create<Packet> (1500);
327  Ptr<Packet> currentAggregatedPacket = Create<Packet> ();
328  WifiMacHeader hdr, peekedHdr;
329  hdr.SetAddr1 (Mac48Address ("00:00:00:00:00:01"));
330  hdr.SetAddr2 (Mac48Address ("00:00:00:00:00:02"));
331  hdr.SetType (WIFI_MAC_QOSDATA);
332  hdr.SetQosTid (0);
333  Time tstamp;
334 
335  //-----------------------------------------------------------------------------------------------------
336 
337  /*
338  * Test MSDU aggregation of two packets using MacLow::PerformMsduAggregation.
339  * It checks whether aggregation succeeded:
340  * - returned packet should be different from 0;
341  * - A-MSDU frame size should be 3030 bytes (= 2 packets + headers + padding);
342  * - one packet should be removed from the queue (the other packet is removed later in MacLow::AggregateToAmpdu) .
343  */
344  m_edca->GetQueue ()->Enqueue (Create<WifiMacQueueItem> (pkt, hdr));
345  m_edca->GetQueue ()->Enqueue (Create<WifiMacQueueItem> (pkt, hdr));
346 
347  Ptr<const WifiMacQueueItem> peekedItem = m_edca->GetQueue ()->PeekByTidAndAddress (0, WifiMacHeader::ADDR1,
348  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_edca->GetQueue ()->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");
372  m_mpduAggregator = m_factory.Create<MpduAggregator> ();
373  m_mpduAggregator->SetMaxAmpduSize (65535);
374  m_edca->SetMpduAggregator (m_mpduAggregator);
375 
376  m_edca->GetQueue ()->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  */
389  m_mpduAggregator->SetMaxAmpduSize (4095);
390 
391  m_edca->GetQueue ()->Remove (pkt);
392  m_edca->GetQueue ()->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_edca->Dispose ();
404  m_edca = 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
Ptr< const Packet > GetPacket(void) const
Get the packet stored in this item.
Wifi Aggregation Test Suite.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:102
virtual void DoRun(void)
Implementation to actually run this TestCase.
HT PHY for the 5 GHz band (clause 20)
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:257
void SetBufferSize(uint16_t size)
Set buffer size.
Implement the header for management frames of type add block ack request.
Definition: mgt-headers.h:983
void SetAccessCategory(AcIndex ac)
Set the access category of this EDCAF.
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
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:821
void SetManager(const Ptr< DcfManager > manager)
Set DcfManager this DcaTxop is associated to.
Definition: dca-txop.cc:101
encapsulates test code
Definition: test.h:1155
void SetWifiRemoteStationManager(const Ptr< WifiRemoteStationManager > remoteManager)
Set WifiRemoteStationsManager this EdcaTxopN is associated to.
Definition: edca-txop-n.cc:116
Time GetTimeStamp(void) const
Get the timestamp included in this item.
ObjectFactory m_factory
factory
Best Effort.
Definition: qos-utils.h:41
Ptr< YansWifiPhy > m_phy
Phy.
Ptr< MsduAggregator > m_msduAggregator
A-MSDU aggregator.
Ptr< Packet > PerformMsduAggregation(Ptr< const Packet > packet, WifiMacHeader *hdr, Time *tstamp, Ptr< Packet > currentAmpduPacket, uint16_t blockAckSize)
Perform MSDU aggregation for a given MPDU in an A-MPDU.
Definition: mac-low.cc:2760
Ptr< MacTxMiddle > m_txMiddle
MacTxMiddle.
void MissedAck(void)
Event handler when an ACK is missed.
Definition: edca-txop-n.cc:549
WifiTxVector m_currentTxVector
TXVECTOR used for the current packet transmission.
Definition: mac-low.h:914
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.
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
Ptr< Object > Create(void) const
Create an Object instance of the configured TypeId.
void SetTid(uint8_t tid)
Set Traffic ID (TID).
void SetupPhyListener(Ptr< WifiPhy > phy)
Set up listener for Phy events.
Definition: dcf-manager.cc:141
void SetMsduAggregator(const Ptr< MsduAggregator > aggr)
Set the aggregator used to construct A-MSDU subframes.
void SetStartingSequence(uint16_t seq)
Set the starting sequence number.
void SetupLow(Ptr< MacLow > low)
Set up listener for MacLow events.
Definition: dcf-manager.cc:165
Ptr< WifiMacQueue > m_aggregateQueue[8]
Queues per TID used for MPDU aggregation.
Definition: mac-low.h:912
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< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:121
Every class exported by the ns3 library is enclosed in the ns3 namespace.
static WifiAggregationTestSuite g_wifiAggregationTestSuite
the test suite
WifiMacHeader m_currentHdr
the current header
Definition: dca-txop.h:420
const WifiMacHeader & GetHeader(void) const
Get the header stored in this item.
Ptr< WifiMacQueue > GetQueue() const
Return the packet queue associated with this DcaTxop.
Definition: dca-txop.cc:160
an EUI-48 address
Definition: mac48-address.h:43
void Set(std::string name, const AttributeValue &value)
Set an attribute to be set during construction.
Ptr< const Packet > m_currentPacket
the current packet
Definition: dca-txop.h:419
Two Level Aggregation Test.
Ampdu Aggregation Test.
void SetLow(const Ptr< MacLow > low)
Set MacLow associated with this DcaTxop.
Definition: dca-txop.cc:115
void SetTxMiddle(const Ptr< MacTxMiddle > txMiddle)
Set MacTxMiddle this DcaTxop is associated to.
Definition: dca-txop.cc:108
void SetMaxAmpduSize(uint16_t maxSize)
Sets the maximum A-MPDU size in bytes.
void SetSlot(Time slotTime)
Definition: dcf-manager.cc:172
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:1054
Instantiate subclasses of ns3::Object.
void SetMaxSlrc(uint32_t maxSlrc)
Sets the maximum STA long retry count (SLRC).
virtual void DoRun(void)
Implementation to actually run this TestCase.
void SetSequenceNumber(uint16_t seq)
Set the sequence number of the header.
Ptr< EdcaTxopN > m_edca
EDCA.
void CompleteConfig(void)
Complete block ACK configuration.
Ptr< Packet > m_currentPacket
Current packet transmitted/to be transmitted.
Definition: mac-low.h:866
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1023
WifiMacHeader m_currentHdr
Header of the current transmitted packet.
Definition: mac-low.h:867
void SetAddress(Mac48Address ad)
Set MAC address of this MacLow.
Definition: mac-low.cc:287
virtual void ConfigureStandard(WifiPhyStandard standard)
Configure the PHY-level parameters for different Wi-Fi standard.
Definition: wifi-phy.cc:1137
Ptr< BlockAckManager > m_baManager
the Block ACK manager
Definition: edca-txop-n.h:524
void SetTimeout(uint16_t timeout)
Set timeout.
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:445
Ptr< YansWifiPhy > m_phy
Phy.
Ptr< MacLow > m_low
MacLow.
void SetMpduAggregator(const Ptr< MpduAggregator > aggr)
Set the aggregator used to construct A-MPDU subframes.
void SetWifiRemoteStationManager(const Ptr< WifiRemoteStationManager > manager)
Set up WifiRemoteStationManager associated with this MacLow.
Definition: mac-low.cc:281
Implements the IEEE 802.11 MAC header.
Ptr< DcfManager > m_dcfManager
DCF manager.
void SetMaxAmsduSize(uint16_t maxSize)
Sets the maximum A-MSDU size in bytes.
Ptr< MpduAggregator > m_mpduAggregator
A-MPDU aggregator.
Ptr< EdcaTxopN > m_edca
EDCA.
Ptr< WifiRemoteStationManager > m_manager
remote station manager
uint16_t GetSequenceNumber(void) const
Return the sequence number of the header.