A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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:554
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:626
void SetupLowListener(Ptr< MacLow > low)
Set up listener for MacLow events.
Definition: dcf-manager.cc:365
void SetWifiRemoteStationManager(Ptr< WifiRemoteStationManager > remoteManager)
Set WifiRemoteStationsManager this EdcaTxopN is associated to.
Definition: edca-txop-n.cc:356
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:556
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:3268
BlockAckManager * m_baManager
Definition: edca-txop-n.h:561
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:868
void SetLow(Ptr< MacLow > low)
Set MacLow associated with this EdcaTxopN.
Definition: edca-txop-n.cc:441
WifiTxVector m_currentTxVector
TXVECTOR used for the current packet transmission.
Definition: mac-low.h:1380
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:1379
void AddTestCase(TestCase *testCase, enum TestDuration duration)
Add an individual child TestCase to this test suite.
Definition: test.cc:297
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:341
Manage a set of ns3::DcfStateHandle a set of independent ns3::DcfState, each of which represents a si...
Definition: dcf-manager.h:262
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.
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:334
void SetPhy(Ptr< WifiPhy > phy)
Set up WifiPhy associated with this MacLow.
Definition: mac-low.cc:518
void SetMsduAggregator(Ptr< MsduAggregator > aggr)
void SetSlot(Time slotTime)
Definition: dcf-manager.cc:377
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:1372
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:1333
virtual void ConfigureStandard(enum WifiPhyStandard standard)
Configure the PHY-level parameters for different Wi-Fi standard.
void SetTxMiddle(MacTxMiddle *txMiddle)
Definition: edca-txop-n.cc:427
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:1334
void SetAddress(Mac48Address ad)
Set MAC address of this MacLow.
Definition: mac-low.cc:548
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:704
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:542
Ptr< MpduAggregator > m_mpduAggregator
Ptr< WifiMacQueue > GetEdcaQueue() const
Return the packet queue associated with this EdcaTxopN.
Definition: edca-txop-n.cc:378
Ptr< WifiRemoteStationManager > m_manager
uint16_t GetSequenceNumber(void) const
Return the sequence number of the header.