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/object-factory.h"
24 #include "ns3/simulator.h"
25 #include "ns3/wifi-mac-queue.h"
26 #include "ns3/mac-low.h"
27 #include "ns3/edca-txop-n.h"
28 #include "ns3/yans-wifi-phy.h"
29 #include "ns3/mac-tx-middle.h"
30 #include "ns3/dcf-manager.h"
31 #include "ns3/ampdu-tag.h"
32 #include "ns3/wifi-mac-trailer.h"
33 #include "ns3/msdu-standard-aggregator.h"
34 #include "ns3/mpdu-standard-aggregator.h"
35 #include "ns3/log.h"
36 
37 using namespace ns3;
38 
40 {
41 public:
43 
44 private:
45  virtual void DoRun (void);
54 };
55 
57  : TestCase ("Check the correctness of MPDU aggregation operations")
58 {
59 }
60 
61 void
63 {
64  /*
65  * Create and configure phy layer.
66  */
67  m_phy = CreateObject<YansWifiPhy> ();
69 
70  /*
71  * Create and configure manager.
72  */
74  m_factory.SetTypeId ("ns3::ConstantRateWifiManager");
75  m_factory.Set ("DataMode", StringValue ("HtMcs7"));
78  m_manager->SetHtSupported (true);
79 
80  /*
81  * Create and configure mac layer.
82  */
83  m_low = CreateObject<MacLow> ();
84  m_low->SetPhy (m_phy);
86  m_low->SetAddress (Mac48Address ("00:00:00:00:00:01"));
87 
88  m_dcfManager = new DcfManager ();
92 
93  m_edca = CreateObject<EdcaTxopN> ();
94  m_edca->SetLow (m_low);
98 
99  m_txMiddle = new MacTxMiddle ();
102 
103  /*
104  * Configure MPDU aggregation.
105  */
107  m_factory.SetTypeId ("ns3::MpduStandardAggregator");
108  m_factory.Set ("MaxAmpduSize", UintegerValue (65535));
111 
112  /*
113  * Create a dummy packet of 1500 bytes and fill mac header fields.
114  */
115  Ptr<const Packet> pkt = Create<Packet> (1500);
116  Ptr<Packet> currentAggregatedPacket = Create<Packet> ();
117  WifiMacHeader hdr;
118  hdr.SetAddr1 (Mac48Address ("00:00:00:00:00:02"));
119  hdr.SetAddr2 (Mac48Address ("00:00:00:00:00:01"));
120  hdr.SetType (WIFI_MAC_QOSDATA);
121  hdr.SetQosTid (0);
122  uint16_t sequence = m_txMiddle->GetNextSequenceNumberfor (&hdr);
123  hdr.SetSequenceNumber (sequence);
124  hdr.SetFragmentNumber (0);
125  hdr.SetNoMoreFragments ();
126  hdr.SetNoRetry ();
127 
128  /*
129  * Establish agreement.
130  */
131  MgtAddBaRequestHeader reqHdr;
132  reqHdr.SetImmediateBlockAck ();
133  reqHdr.SetTid (0);
134  reqHdr.SetBufferSize (0);
135  reqHdr.SetTimeout (0);
136  reqHdr.SetStartingSequence (0);
137  m_edca->m_baManager->CreateAgreement (&reqHdr, hdr.GetAddr1 ());
138 
139  //-----------------------------------------------------------------------------------------------------
140 
141  /*
142  * Test behavior when no other packets are in the queue
143  */
144  m_low->m_currentHdr = hdr;
145  m_low->m_currentPacket = pkt->Copy();
147 
148  bool isAmpdu = m_low->IsAmpdu (pkt, hdr);
149  NS_TEST_EXPECT_MSG_EQ (isAmpdu, false, "a single packet should not result in an A-MPDU");
150  NS_TEST_EXPECT_MSG_EQ (m_low->m_aggregateQueue->GetSize (), 0, "aggregation queue is not flushed");
151 
152  //-----------------------------------------------------------------------------------------------------
153 
154  /*
155  * Test behavior when 2 more packets are in the queue
156  */
157  Ptr<const Packet> pkt1 = Create<Packet> (1500);
158  Ptr<const Packet> pkt2 = Create<Packet> (1500);
159  WifiMacHeader hdr1, hdr2;
160 
161  hdr1.SetAddr1 (Mac48Address ("00:00:00:00:00:02"));
162  hdr1.SetAddr2 (Mac48Address ("00:00:00:00:00:01"));
163  hdr1.SetType (WIFI_MAC_QOSDATA);
164  hdr1.SetQosTid (0);
165 
166  hdr2.SetAddr1 (Mac48Address ("00:00:00:00:00:02"));
167  hdr2.SetAddr2 (Mac48Address ("00:00:00:00:00:01"));
168  hdr2.SetType (WIFI_MAC_QOSDATA);
169  hdr2.SetQosTid (0);
170 
171  m_edca->GetEdcaQueue ()->Enqueue (pkt1, hdr1);
172  m_edca->GetEdcaQueue ()->Enqueue (pkt2, hdr2);
173 
174  isAmpdu = m_low->IsAmpdu (pkt, hdr);
175  uint32_t aggregationQueueSize = m_low->m_aggregateQueue->GetSize ();
176  NS_TEST_EXPECT_MSG_EQ (isAmpdu, true, "MPDU aggregation failed");
177  NS_TEST_EXPECT_MSG_EQ (m_low->m_currentPacket->GetSize (), 4606, "A-MPDU size is not correct");
178  NS_TEST_EXPECT_MSG_EQ (aggregationQueueSize, 3, "aggregation queue should not be empty");
179  NS_TEST_EXPECT_MSG_EQ (m_edca->GetEdcaQueue ()->GetSize (), 0, "queue should be empty");
180 
181  Ptr <const Packet> dequeuedPacket;
182  WifiMacHeader dequeuedHdr;
183  uint32_t i = 0;
184  for (; aggregationQueueSize > 0; aggregationQueueSize--, i++)
185  {
186  dequeuedPacket = m_low->m_aggregateQueue->Dequeue (&dequeuedHdr);
187  NS_TEST_EXPECT_MSG_EQ (dequeuedHdr.GetSequenceNumber (), i, "wrong sequence number");
188  }
189  NS_TEST_EXPECT_MSG_EQ (aggregationQueueSize, 0, "aggregation queue should be empty");
190 
191  //-----------------------------------------------------------------------------------------------------
192 
193  /*
194  * Test behavior when the 802.11n station and another non-QoS station are associated to the AP.
195  * 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.
196  * This is used to reproduce bug 2224.
197  */
198  pkt1 = Create<Packet> (1500);
199  pkt2 = Create<Packet> (1500);
200  hdr1.SetAddr1 (Mac48Address ("00:00:00:00:00:02"));
201  hdr1.SetAddr2 (Mac48Address ("00:00:00:00:00:01"));
202  hdr1.SetType (WIFI_MAC_QOSDATA);
203  hdr1.SetQosTid (0);
204  hdr1.SetSequenceNumber (3);
205  hdr2.SetAddr1 (Mac48Address ("00:00:00:00:00:03"));
206  hdr2.SetAddr2 (Mac48Address ("00:00:00:00:00:01"));
207  hdr2.SetType (WIFI_MAC_DATA);
208  hdr2.SetQosTid (0);
209 
210  Ptr<const Packet> pkt3 = Create<Packet> (1500);
211  WifiMacHeader hdr3;
212  hdr3.SetSequenceNumber (0);
213  hdr3.SetAddr1 (Mac48Address ("00:00:00:00:00:03"));
214  hdr3.SetAddr2 (Mac48Address ("00:00:00:00:00:01"));
215  hdr3.SetType (WIFI_MAC_DATA);
216  hdr3.SetQosTid (0);
217 
218  m_edca->GetEdcaQueue ()->Enqueue (pkt3, hdr3);
219 
220  isAmpdu = m_low->IsAmpdu (pkt1, hdr1);
221  NS_TEST_EXPECT_MSG_EQ (isAmpdu, false, "a single packet for this destination should not result in an A-MPDU");
222  NS_TEST_EXPECT_MSG_EQ (m_low->m_aggregateQueue->GetSize (), 0, "aggregation queue is not flushed");
223 
224  m_edca->m_currentHdr = hdr2;
225  m_edca->m_currentPacket = pkt2->Copy ();
226  isAmpdu = m_low->IsAmpdu (pkt2, hdr2);
227  NS_TEST_EXPECT_MSG_EQ (isAmpdu, false, "no MPDU aggregation should be performed if there is no agreement");
228  NS_TEST_EXPECT_MSG_EQ (m_low->m_aggregateQueue->GetSize (), 0, "aggregation queue is not flushed");
229 
230  m_manager->SetMaxSlrc (0); //set to 0 in order to fake that the maximum number of retries has been reached
231  m_edca->MissedAck();
232 
233  NS_TEST_EXPECT_MSG_EQ (m_edca->m_currentPacket, 0, "packet should be discarded");
234  m_edca->GetEdcaQueue ()->Remove (pkt3);
235 
236  Simulator::Destroy ();
237  delete m_txMiddle;
238  delete m_dcfManager;
239 }
240 
241 
243 {
244 public:
246 
247 private:
248  virtual void DoRun (void);
256 };
257 
259  : TestCase ("Check the correctness of two-level aggregation operations")
260 {
261 }
262 
263 void
265 {
266  /*
267  * Create and configure phy layer.
268  */
269  m_phy = CreateObject<YansWifiPhy> ();
271 
272  /*
273  * Create and configure manager.
274  */
276  m_factory.SetTypeId ("ns3::ConstantRateWifiManager");
277  m_factory.Set ("DataMode", StringValue ("HtMcs7"));
280 
281  /*
282  * Create and configure maclayer.
283  */
284  m_low = CreateObject<MacLow> ();
285  m_low->SetPhy (m_phy);
287 
288  m_edca = CreateObject<EdcaTxopN> ();
289  m_edca->SetLow (m_low);
293 
294  /*
295  * Configure aggregation.
296  */
297  m_msduAggregator = CreateObject<MsduStandardAggregator> ();
298  m_mpduAggregator = CreateObject<MpduStandardAggregator> ();
299 
301  m_mpduAggregator->SetMaxAmpduSize (65535);
302 
304  m_edca->SetMpduAggregator (m_mpduAggregator);
305 
306  /*
307  * Create dummy packets of 1500 bytes and fill mac header fields that will be used for the tests.
308  */
309  Ptr<const Packet> pkt = Create<Packet> (1500);
310  Ptr<Packet> currentAggregatedPacket = Create<Packet> ();
311  WifiMacHeader hdr, peekedHdr;
312  hdr.SetAddr1 (Mac48Address ("00:00:00:00:00:01"));
313  hdr.SetAddr2 (Mac48Address ("00:00:00:00:00:02"));
314  hdr.SetType (WIFI_MAC_QOSDATA);
315  hdr.SetQosTid (0);
316  Time tstamp;
317 
318  //-----------------------------------------------------------------------------------------------------
319 
320  /*
321  * Test MSDU aggregation of two packets using MacLow::PerformMsduAggregation.
322  * It checks whether aggregation succeeded:
323  * - returned packet should be different from 0;
324  * - A-MSDU frame size should be 3030 bytes (= 2 packets + headers + padding);
325  * - one packet should be removed from the queue (the other packet is removed later in MacLow::AggregateToAmpdu) .
326  */
327  m_edca->GetEdcaQueue ()->Enqueue (pkt, hdr);
328  m_edca->GetEdcaQueue ()->Enqueue (pkt, hdr);
329 
330  Ptr<const Packet> peekedPacket = m_edca->GetEdcaQueue ()->PeekByTidAndAddress (&peekedHdr, 0,
331  WifiMacHeader::ADDR1,
332  hdr.GetAddr1 (),
333  &tstamp);
334  m_low->m_currentPacket = peekedPacket->Copy ();
335  m_low->m_currentHdr = peekedHdr;
337 
338  Ptr<Packet> packet = m_low->PerformMsduAggregation (peekedPacket, &peekedHdr, &tstamp, currentAggregatedPacket, 0);
339 
340  bool result = (packet != 0);
341  NS_TEST_EXPECT_MSG_EQ (result, true, "aggregation failed");
342  NS_TEST_EXPECT_MSG_EQ (packet->GetSize (), 3030, "wrong packet size");
343  NS_TEST_EXPECT_MSG_EQ (m_edca->GetEdcaQueue ()->GetSize (), 0, "aggregated packets not removed from the queue");
344 
345  //-----------------------------------------------------------------------------------------------------
346 
347  /*
348  * Aggregation is refused when the maximum size is reached.
349  * It checks whether MSDU aggregation has been rejected because the maximum MPDU size is set to 0 (returned packet should be equal to 0).
350  * 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.
351  */
353  m_factory.SetTypeId ("ns3::MpduStandardAggregator");
354  m_factory.Set ("MaxAmpduSize", UintegerValue (0));
355  m_mpduAggregator = m_factory.Create<MpduAggregator> ();
356  m_edca->SetMpduAggregator (m_mpduAggregator);
357 
358  m_edca->GetEdcaQueue ()->Enqueue (pkt, hdr);
359  packet = m_low->PerformMsduAggregation (peekedPacket, &peekedHdr, &tstamp, currentAggregatedPacket, 0);
360 
361  result = (packet != 0);
362  NS_TEST_EXPECT_MSG_EQ (result, false, "maximum aggregated frame size check failed");
363 
364  //-----------------------------------------------------------------------------------------------------
365 
366  /*
367  * Aggregation does not occur zhen there is no more packets in the queue.
368  * It checks whether MSDU aggregation has been rejected because there is no packets ready in the queue (returned packet should be equal to 0).
369  * This test is needed to ensure that there is no issue when the queue is empty.
370  */
371  m_mpduAggregator->SetMaxAmpduSize (4095);
372 
373  m_edca->GetEdcaQueue ()->Remove (pkt);
374  m_edca->GetEdcaQueue ()->Remove (pkt);
375  packet = m_low->PerformMsduAggregation (peekedPacket, &peekedHdr, &tstamp, currentAggregatedPacket, 0);
376 
377  result = (packet != 0);
378  NS_TEST_EXPECT_MSG_EQ (result, false, "aggregation failed to stop as queue is empty");
379  Simulator::Destroy ();
380 }
381 
382 
383 //-----------------------------------------------------------------------------
385 {
386 public:
388 };
389 
391  : TestSuite ("aggregation-wifi", UNIT)
392 {
393  AddTestCase (new AmpduAggregationTest, TestCase::QUICK);
394  AddTestCase (new TwoLevelAggregationTest, TestCase::QUICK);
395 }
396 
Abstract class that concrete mpdu aggregators have to implement.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:102
Ptr< const Packet > m_currentPacket
Definition: edca-txop-n.h:577
virtual void DoRun(void)
Implementation to actually run this TestCase.
HT OFDM PHY for the 5 GHz band (clause 20)
Ptr< WifiRemoteStationManager > m_manager
Hold variables of type string.
Definition: string.h:41
void CreateAgreement(const MgtAddBaRequestHeader *reqHdr, Mac48Address recipient)
A suite of tests to run.
Definition: test.h:1333
void SetImmediateBlockAck()
Enable immediate Block ACK.
void SetBufferSize(uint16_t size)
Set buffer size.
Implement the header for management frames of type add block ack request.
Definition: mgt-headers.h:667
void SetupLowListener(Ptr< MacLow > low)
Set up listener for MacLow events.
Definition: dcf-manager.cc:384
void SetWifiRemoteStationManager(Ptr< WifiRemoteStationManager > remoteManager)
Set WifiRemoteStationsManager this EdcaTxopN is associated to.
Definition: edca-txop-n.cc:363
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:278
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:792
WifiMacHeader m_currentHdr
Definition: edca-txop-n.h:579
encapsulates test code
Definition: test.h:1147
virtual void SetupPhy(Ptr< WifiPhy > phy)
Set up PHY associated with this device since it is the object that knows the full set of transmit rat...
Best Effort.
Definition: qos-utils.h:39
Ptr< MsduAggregator > m_msduAggregator
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:3284
BlockAckManager * m_baManager
Definition: edca-txop-n.h:584
Handles sequence numbering of IEEE 802.11 data frames.
Definition: mac-tx-middle.h:39
void MissedAck(void)
Event handler when an ACK is missed.
Definition: edca-txop-n.cc:960
void SetLow(Ptr< MacLow > low)
Set MacLow associated with this EdcaTxopN.
Definition: edca-txop-n.cc:461
WifiTxVector m_currentTxVector
TXVECTOR used for the current packet transmission.
Definition: mac-low.h:1390
void SetAddr1(Mac48Address address)
Fill the Address 1 field with the given address.
Ptr< WifiMacQueue > m_aggregateQueue
Queue used for MPDU aggregation.
Definition: mac-low.h:1389
void AddTestCase(TestCase *testCase, enum TestDuration duration)
Add an individual child TestCase to this test suite.
Definition: test.cc:298
Ptr< Object > Create(void) const
Create an Object instance of the configured TypeId.
Hold an unsigned integer type.
Definition: uinteger.h:44
void SetTid(uint8_t tid)
Set Traffic ID (TID).
void SetupPhyListener(Ptr< WifiPhy > phy)
Set up listener for Phy events.
Definition: dcf-manager.cc:360
Manage a set of ns3::DcfStateHandle a set of independent ns3::DcfState, each of which represents a si...
Definition: dcf-manager.h:279
void SetStartingSequence(uint16_t seq)
Set the starting sequence number.
hold a list of per-remote-station state.
Ptr< MpduAggregator > m_mpduAggregator
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:122
uint16_t GetNextSequenceNumberfor(const WifiMacHeader *hdr)
Return the next sequence number for the given header.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
void SetAccessCategory(enum AcIndex ac)
Set the access category of this EDCAF.
static WifiAggregationTestSuite g_wifiAggregationTestSuite
void SetMpduAggregator(Ptr< MpduAggregator > aggr)
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.
virtual void SetMaxAmsduSize(uint32_t maxSize)=0
void SetManager(DcfManager *manager)
Set DcfManager this EdcaTxopN is associated to.
Definition: edca-txop-n.cc:341
void SetPhy(Ptr< WifiPhy > phy)
Set up WifiPhy associated with this MacLow.
Definition: mac-low.cc:519
void SetMsduAggregator(Ptr< MsduAggregator > aggr)
virtual void ConfigureStandard(enum WifiPhyStandard standard)
Configure the PHY-level parameters for different Wi-Fi standard.
Definition: wifi-phy.cc:1026
void SetSlot(Time slotTime)
Definition: dcf-manager.cc:396
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:1381
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.
void CompleteConfig(void)
Complete block ACK configuration.
Ptr< Packet > m_currentPacket
Current packet transmitted/to be transmitted.
Definition: mac-low.h:1343
void SetTxMiddle(MacTxMiddle *txMiddle)
Definition: edca-txop-n.cc:448
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:911
WifiMacHeader m_currentHdr
Header of the current transmitted packet.
Definition: mac-low.h:1344
void SetAddress(Mac48Address ad)
Set MAC address of this MacLow.
Definition: mac-low.cc:549
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:705
Ptr< YansWifiPhy > m_phy
Implements the IEEE 802.11 MAC header.
void SetWifiRemoteStationManager(Ptr< WifiRemoteStationManager > manager)
Set up WifiRemoteStationManager associated with this MacLow.
Definition: mac-low.cc:543
Ptr< MpduAggregator > m_mpduAggregator
Ptr< WifiMacQueue > GetEdcaQueue() const
Return the packet queue associated with this EdcaTxopN.
Definition: edca-txop-n.cc:385
Ptr< WifiRemoteStationManager > m_manager
uint16_t GetSequenceNumber(void) const
Return the sequence number of the header.