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/wifi-psdu.h"
26 #include "ns3/sta-wifi-mac.h"
27 #include "ns3/yans-wifi-phy.h"
28 #include "ns3/mac-tx-middle.h"
29 #include "ns3/mac-low.h"
30 #include "ns3/msdu-aggregator.h"
31 #include "ns3/mpdu-aggregator.h"
32 #include "ns3/wifi-net-device.h"
33 #include "ns3/ht-configuration.h"
34 #include "ns3/vht-configuration.h"
35 #include "ns3/he-configuration.h"
36 #include "ns3/node-container.h"
37 #include "ns3/yans-wifi-helper.h"
38 #include "ns3/mobility-helper.h"
39 #include "ns3/pointer.h"
40 #include "ns3/packet-socket-server.h"
41 #include "ns3/packet-socket-client.h"
42 #include "ns3/packet-socket-helper.h"
43 #include <iterator>
44 
45 using namespace ns3;
46 
54 {
55 public:
57 
58 private:
59  virtual void DoRun (void);
65 };
66 
68  : TestCase ("Check the correctness of MPDU aggregation operations")
69 {
70 }
71 
72 void
74 {
75  /*
76  * Create device and attach HT configuration.
77  */
78  m_device = CreateObject<WifiNetDevice> ();
79  Ptr<HtConfiguration> htConfiguration = CreateObject<HtConfiguration> ();
80  m_device->SetHtConfiguration (htConfiguration);
81 
82  /*
83  * Create and configure phy layer.
84  */
85  m_phy = CreateObject<YansWifiPhy> ();
89 
90  /*
91  * Create and configure manager.
92  */
94  m_factory.SetTypeId ("ns3::ConstantRateWifiManager");
95  m_factory.Set ("DataMode", StringValue ("HtMcs7"));
99 
100  /*
101  * Create and configure mac layer.
102  */
103  m_mac = CreateObject<StaWifiMac> ();
107  m_mac->SetAddress (Mac48Address ("00:00:00:00:00:01"));
109  m_device->SetMac (m_mac);
110 
111  /*
112  * Configure MPDU aggregation.
113  */
114  m_mac->SetAttribute ("BE_MaxAmpduSize", UintegerValue (65535));
115  HtCapabilities htCapabilities;
116  htCapabilities.SetMaxAmpduLength (65535);
117  m_manager->AddStationHtCapabilities (Mac48Address ("00:00:00:00:00:02"), htCapabilities);
118  m_manager->AddStationHtCapabilities (Mac48Address ("00:00:00:00:00:03"), htCapabilities);
119 
120  /*
121  * Create a dummy packet of 1500 bytes and fill mac header fields.
122  */
123  Ptr<const Packet> pkt = Create<Packet> (1500);
124  Ptr<Packet> currentAggregatedPacket = Create<Packet> ();
125  WifiMacHeader hdr;
126  hdr.SetAddr1 (Mac48Address ("00:00:00:00:00:02"));
127  hdr.SetAddr2 (Mac48Address ("00:00:00:00:00:01"));
128  hdr.SetType (WIFI_MAC_QOSDATA);
129  hdr.SetQosTid (0);
130  uint16_t sequence = m_mac->m_txMiddle->GetNextSequenceNumberFor (&hdr);
131  hdr.SetSequenceNumber (sequence);
132  hdr.SetFragmentNumber (0);
133  hdr.SetNoMoreFragments ();
134  hdr.SetNoRetry ();
135 
136  /*
137  * Establish agreement.
138  */
139  MgtAddBaRequestHeader reqHdr;
140  reqHdr.SetImmediateBlockAck ();
141  reqHdr.SetTid (0);
142  reqHdr.SetBufferSize (64);
143  reqHdr.SetTimeout (0);
144  reqHdr.SetStartingSequence (0);
145  m_mac->GetBEQueue ()->m_baManager->CreateAgreement (&reqHdr, hdr.GetAddr1 ());
146  m_mac->GetBEQueue ()->m_baManager->NotifyAgreementEstablished (hdr.GetAddr1 (), 0, 0);
147 
148  //-----------------------------------------------------------------------------------------------------
149 
150  /*
151  * Test behavior when no other packets are in the queue
152  */
153  WifiTxVector txVector = m_mac->GetBEQueue ()->GetLow ()->GetDataTxVector (Create<const WifiMacQueueItem> (pkt, hdr));
154 
155  auto mpduList = m_mac->GetBEQueue ()->GetLow ()->GetMpduAggregator ()->GetNextAmpdu (Create<WifiMacQueueItem> (pkt, hdr),
156  txVector);
157  NS_TEST_EXPECT_MSG_EQ (mpduList.empty (), true, "a single packet should not result in an A-MPDU");
158 
159  //-----------------------------------------------------------------------------------------------------
160 
161  /*
162  * Test behavior when 2 more packets are in the queue
163  */
164  Ptr<const Packet> pkt1 = Create<Packet> (1500);
165  Ptr<const Packet> pkt2 = Create<Packet> (1500);
166  WifiMacHeader hdr1, hdr2;
167 
168  hdr1.SetAddr1 (Mac48Address ("00:00:00:00:00:02"));
169  hdr1.SetAddr2 (Mac48Address ("00:00:00:00:00:01"));
170  hdr1.SetType (WIFI_MAC_QOSDATA);
171  hdr1.SetQosTid (0);
172 
173  hdr2.SetAddr1 (Mac48Address ("00:00:00:00:00:02"));
174  hdr2.SetAddr2 (Mac48Address ("00:00:00:00:00:01"));
175  hdr2.SetType (WIFI_MAC_QOSDATA);
176  hdr2.SetQosTid (0);
177 
178  m_mac->GetBEQueue ()->GetWifiMacQueue ()->Enqueue (Create<WifiMacQueueItem> (pkt1, hdr1));
179  m_mac->GetBEQueue ()->GetWifiMacQueue ()->Enqueue (Create<WifiMacQueueItem> (pkt2, hdr2));
180 
181  mpduList = m_mac->GetBEQueue ()->GetLow ()->GetMpduAggregator ()->GetNextAmpdu (Create<WifiMacQueueItem> (pkt, hdr),
182  txVector);
183  Ptr<WifiPsdu> psdu = Create<WifiPsdu> (mpduList);
184 
185  NS_TEST_EXPECT_MSG_EQ (mpduList.empty (), false, "MPDU aggregation failed");
186  NS_TEST_EXPECT_MSG_EQ (psdu->GetSize (), 4606, "A-MPDU size is not correct");
187  NS_TEST_EXPECT_MSG_EQ (mpduList.size (), 3, "A-MPDU should contain 3 MPDUs");
188  NS_TEST_EXPECT_MSG_EQ (m_mac->GetBEQueue ()->GetWifiMacQueue ()->GetNPackets (), 0, "queue should be empty");
189 
190  Ptr <WifiMacQueueItem> dequeuedItem;
191  WifiMacHeader dequeuedHdr;
192  for (uint32_t i = 0; i < psdu->GetNMpdus (); i++)
193  {
194  NS_TEST_EXPECT_MSG_EQ (psdu->GetHeader (i).GetSequenceNumber (), i, "wrong sequence number");
195  }
196 
197  //-----------------------------------------------------------------------------------------------------
198 
199  /*
200  * Test behavior when the 802.11n station and another non-QoS station are associated to the AP.
201  * 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.
202  * This is used to reproduce bug 2224.
203  */
204  pkt1 = Create<Packet> (1500);
205  pkt2 = Create<Packet> (1500);
206  hdr1.SetAddr1 (Mac48Address ("00:00:00:00:00:02"));
207  hdr1.SetAddr2 (Mac48Address ("00:00:00:00:00:01"));
208  hdr1.SetType (WIFI_MAC_QOSDATA);
209  hdr1.SetQosTid (0);
210  hdr1.SetSequenceNumber (3);
211  hdr2.SetAddr1 (Mac48Address ("00:00:00:00:00:03"));
212  hdr2.SetAddr2 (Mac48Address ("00:00:00:00:00:01"));
213  hdr2.SetType (WIFI_MAC_QOSDATA);
214  hdr2.SetQosTid (0);
215 
216  Ptr<const Packet> pkt3 = Create<Packet> (1500);
217  WifiMacHeader hdr3;
218  hdr3.SetSequenceNumber (0);
219  hdr3.SetAddr1 (Mac48Address ("00:00:00:00:00:03"));
220  hdr3.SetAddr2 (Mac48Address ("00:00:00:00:00:01"));
221  hdr3.SetType (WIFI_MAC_QOSDATA);
222  hdr3.SetQosTid (0);
223 
224  m_mac->GetBEQueue ()->GetWifiMacQueue ()->Enqueue (Create<WifiMacQueueItem> (pkt3, hdr3));
225 
226  mpduList = m_mac->GetBEQueue ()->GetLow ()->GetMpduAggregator ()->GetNextAmpdu (Create<WifiMacQueueItem> (pkt1, hdr1),
227  txVector);
228  NS_TEST_EXPECT_MSG_EQ (mpduList.empty (), true, "a single packet for this destination should not result in an A-MPDU");
229 
230  mpduList = m_mac->GetBEQueue ()->GetLow ()->GetMpduAggregator ()->GetNextAmpdu (Create<WifiMacQueueItem> (pkt2, hdr2),
231  txVector);
232  NS_TEST_EXPECT_MSG_EQ (mpduList.empty (), true, "no MPDU aggregation should be performed if there is no agreement");
233 
234  m_manager->SetMaxSsrc (0); //set to 0 in order to fake that the maximum number of retries has been reached
235  m_mac->GetBEQueue ()->m_currentHdr = hdr2;
236  m_mac->GetBEQueue ()->m_currentPacket = pkt2->Copy ();
237  m_mac->GetBEQueue ()->MissedAck ();
238 
239  NS_TEST_EXPECT_MSG_EQ (m_mac->GetBEQueue ()->m_currentPacket, 0, "packet should be discarded");
240  m_mac->GetBEQueue ()->GetWifiMacQueue ()->Remove (pkt3);
241 
242  Simulator::Destroy ();
243 
244  m_manager->Dispose ();
245  m_manager = 0;
246 
247  m_device->Dispose ();
248  m_device = 0;
249 
250  htConfiguration = 0;
251 }
252 
260 {
261 public:
263 
264 private:
265  virtual void DoRun (void);
271 };
272 
274  : TestCase ("Check the correctness of two-level aggregation operations")
275 {
276 }
277 
278 void
280 {
281  /*
282  * Create device and attach HT configuration.
283  */
284  m_device = CreateObject<WifiNetDevice> ();
285  Ptr<HtConfiguration> htConfiguration = CreateObject<HtConfiguration> ();
286  m_device->SetHtConfiguration (htConfiguration);
287 
288  /*
289  * Create and configure phy layer.
290  */
291  m_phy = CreateObject<YansWifiPhy> ();
294  m_device->SetPhy (m_phy);
295 
296  /*
297  * Create and configure manager.
298  */
300  m_factory.SetTypeId ("ns3::ConstantRateWifiManager");
301  m_factory.Set ("DataMode", StringValue ("HtMcs7"));
305 
306  /*
307  * Create and configure mac layer.
308  */
309  m_mac = CreateObject<StaWifiMac> ();
313  m_mac->SetAddress (Mac48Address ("00:00:00:00:00:01"));
315  m_device->SetMac (m_mac);
316 
317  /*
318  * Configure aggregation.
319  */
320  m_mac->SetAttribute ("BE_MaxAmsduSize", UintegerValue (4095));
321  m_mac->SetAttribute ("BE_MaxAmpduSize", UintegerValue (65535));
322  HtCapabilities htCapabilities;
323  htCapabilities.SetMaxAmsduLength (7935);
324  htCapabilities.SetMaxAmpduLength (65535);
325  m_manager->AddStationHtCapabilities (Mac48Address ("00:00:00:00:00:02"), htCapabilities);
326 
327  /*
328  * Create dummy packets of 1500 bytes and fill mac header fields that will be used for the tests.
329  */
330  Ptr<const Packet> pkt = Create<Packet> (1500);
331  Ptr<Packet> currentAggregatedPacket = Create<Packet> ();
332  WifiMacHeader hdr;
333  hdr.SetAddr1 (Mac48Address ("00:00:00:00:00:02"));
334  hdr.SetAddr2 (Mac48Address ("00:00:00:00:00:01"));
335  hdr.SetType (WIFI_MAC_QOSDATA);
336  hdr.SetQosTid (0);
337 
338  //-----------------------------------------------------------------------------------------------------
339 
340  /*
341  * Test MSDU aggregation of two packets using MsduAggregator::GetNextAmsdu.
342  * It checks whether aggregation succeeded:
343  * - returned packet should be different from 0;
344  * - A-MSDU frame size should be 3030 bytes (= 2 packets + headers + padding);
345  * - one packet should be removed from the queue (the other packet is removed later in MacLow::AggregateToAmpdu) .
346  */
347  m_mac->GetBEQueue ()->GetWifiMacQueue ()->Enqueue (Create<WifiMacQueueItem> (pkt, hdr));
348  m_mac->GetBEQueue ()->GetWifiMacQueue ()->Enqueue (Create<WifiMacQueueItem> (pkt, hdr));
349 
350  WifiTxVector txVector = m_mac->GetBEQueue ()->GetLow ()->GetDataTxVector (Create<const WifiMacQueueItem> (pkt, hdr));
351 
353  item = m_mac->GetBEQueue ()->GetLow ()->GetMsduAggregator ()->GetNextAmsdu (hdr.GetAddr1 (), 0, txVector,
354  currentAggregatedPacket->GetSize ());
355  bool result = (item != 0);
356  NS_TEST_EXPECT_MSG_EQ (result, true, "aggregation failed");
357  NS_TEST_EXPECT_MSG_EQ (item->GetPacket ()->GetSize (), 3030, "wrong packet size");
358  NS_TEST_EXPECT_MSG_EQ (m_mac->GetBEQueue ()->GetWifiMacQueue ()->GetNPackets (), 0, "aggregated packets not removed from the queue");
359 
360  //-----------------------------------------------------------------------------------------------------
361 
362  /*
363  * Aggregation is refused when the maximum size is reached.
364  * It checks whether MSDU aggregation has been rejected because the maximum MPDU size is set to 0 (returned packet should be equal to 0).
365  * This test is needed to ensure that no packets are removed from the queue in
366  * MsduAggregator::GetNextAmsdu, since aggregation will no occur in MacLow::AggregateToAmpdu.
367  */
368  m_mac->SetAttribute ("BE_MaxAmpduSize", UintegerValue (65535));
369 
370  m_mac->GetBEQueue ()->GetWifiMacQueue ()->Enqueue (Create<WifiMacQueueItem> (pkt, hdr));
371 
372  item = m_mac->GetBEQueue ()->GetLow ()->GetMsduAggregator ()->GetNextAmsdu (hdr.GetAddr1 (), 0, txVector,
373  currentAggregatedPacket->GetSize ());
374  result = (item != 0);
375  NS_TEST_EXPECT_MSG_EQ (result, false, "maximum aggregated frame size check failed");
376 
377  //-----------------------------------------------------------------------------------------------------
378 
379  /*
380  * Aggregation does not occur when there is no more packets in the queue.
381  * It checks whether MSDU aggregation has been rejected because there is no packets ready in the queue (returned packet should be equal to 0).
382  * This test is needed to ensure that there is no issue when the queue is empty.
383  */
384  m_mac->SetAttribute ("BE_MaxAmpduSize", UintegerValue (4095));
385 
386  m_mac->GetBEQueue ()->GetWifiMacQueue ()->Remove (pkt);
387  m_mac->GetBEQueue ()->GetWifiMacQueue ()->Remove (pkt);
388 
389  item = m_mac->GetBEQueue ()->GetLow ()->GetMsduAggregator ()->GetNextAmsdu (hdr.GetAddr1 (), 0, txVector,
390  currentAggregatedPacket->GetSize ());
391 
392  result = (item != 0);
393  NS_TEST_EXPECT_MSG_EQ (result, false, "aggregation failed to stop as queue is empty");
394 
395  //-----------------------------------------------------------------------------------------------------
396 
397  /*
398  * Aggregation of MPDUs is stopped to prevent that the PPDU duration exceeds the TXOP limit.
399  * In this test, the VI AC is used, which has a default TXOP limit of 3008 microseconds.
400  */
401 
402  // Establish agreement.
403  uint8_t tid = 5;
404  MgtAddBaRequestHeader reqHdr;
405  reqHdr.SetImmediateBlockAck ();
406  reqHdr.SetTid (tid);
407  reqHdr.SetBufferSize (64);
408  reqHdr.SetTimeout (0);
409  reqHdr.SetStartingSequence (0);
410  m_mac->GetVIQueue ()->m_baManager->CreateAgreement (&reqHdr, hdr.GetAddr1 ());
411  m_mac->GetVIQueue ()->m_baManager->NotifyAgreementEstablished (hdr.GetAddr1 (), tid, 0);
412 
413  m_mac->SetAttribute ("VI_MaxAmsduSize", UintegerValue (3050)); // max 2 MSDUs per A-MSDU
414  m_mac->SetAttribute ("VI_MaxAmpduSize", UintegerValue (65535));
415  m_manager->SetAttribute ("DataMode", StringValue ("HtMcs2")); // 19.5Mbps
416 
417  pkt = Create<Packet> (1400);
418  hdr.SetQosTid (tid);
419 
420  // Add 10 MSDUs to the EDCA queue
421  for (uint8_t i = 0; i < 10; i++)
422  {
423  m_mac->GetVIQueue ()->GetWifiMacQueue ()->Enqueue (Create<WifiMacQueueItem> (pkt, hdr));
424  }
425 
426  txVector = m_mac->GetVIQueue ()->GetLow ()->GetDataTxVector (Create<const WifiMacQueueItem> (pkt, hdr));
427  Time txopLimit = m_mac->GetVIQueue ()->GetTxopLimit (); // 3.008 ms
428 
429  // Compute the first MPDU to be aggregated in an A-MPDU. It must contain an A-MSDU
430  // aggregating two MSDUs
431  Ptr<WifiMacQueueItem> mpdu = m_mac->GetVIQueue ()->GetLow ()->GetMsduAggregator ()->GetNextAmsdu (hdr.GetAddr1 (), tid,
432  txVector, 0, txopLimit);
433  NS_TEST_EXPECT_MSG_EQ (m_mac->GetVIQueue ()->GetWifiMacQueue ()->GetNPackets (), 8, "There must be 8 MSDUs left in EDCA queue");
434 
435  auto mpduList = m_mac->GetVIQueue ()->GetLow ()->GetMpduAggregator ()->GetNextAmpdu (mpdu, txVector, txopLimit);
436 
437  // The maximum number of bytes that can be transmitted in a TXOP is (approximately, as we
438  // do not consider that the preamble is transmitted at a different rate):
439  // 19.5 Mbps * 3.008 ms = 7332 bytes
440  // Given that the max A-MSDU size is set to 3050, an A-MSDU will contain two MSDUs and have
441  // a size of 2 * 1400 (MSDU size) + 2 * 14 (A-MSDU subframe header size) + 2 (one padding field) = 2830 bytes
442  // Hence, we expect that the A-MPDU will consist of:
443  // - 2 MPDUs containing each an A-MSDU. The size of each MPDU is 2830 (A-MSDU) + 30 (header+trailer) = 2860
444  // - 1 MPDU containing a single MSDU. The size of such MPDU is 1400 (MSDU) + 30 (header+trailer) = 1430
445  // The size of the A-MPDU is 4 + 2860 + 4 + 2860 + 4 + 1430 = 7162
446  NS_TEST_EXPECT_MSG_EQ (mpduList.empty (), false, "aggregation failed");
447  NS_TEST_EXPECT_MSG_EQ (mpduList.size (), 3, "Unexpected number of MPDUs in the A-MPDU");
448  NS_TEST_EXPECT_MSG_EQ (mpduList.at (0)->GetSize (), 2860, "Unexpected size of the first MPDU");
449  NS_TEST_EXPECT_MSG_EQ (mpduList.at (1)->GetSize (), 2860, "Unexpected size of the second MPDU");
450  NS_TEST_EXPECT_MSG_EQ (mpduList.at (2)->GetSize (), 1430, "Unexpected size of the first MPDU");
451  NS_TEST_EXPECT_MSG_EQ (m_mac->GetVIQueue ()->GetWifiMacQueue ()->GetNPackets (), 5,
452  "Unexpected number of MSDUs left in the EDCA queue");
453 
454  Ptr<WifiPsdu> psdu = Create<WifiPsdu> (mpduList);
455  NS_TEST_EXPECT_MSG_EQ (psdu->GetSize (), 7162, "Unexpected size of the A-MPDU");
456 
457  Simulator::Destroy ();
458 
459  m_device->Dispose ();
460  m_device = 0;
461  htConfiguration = 0;
462 }
463 
471 {
472 public:
474 
475 private:
476  void DoRun (void);
482  void DoRunSubTest (uint16_t bufferSize);
488 };
489 
491  : TestCase ("Check the correctness of 802.11ax aggregation operations")
492 {
493 }
494 
495 void
496 HeAggregationTest::DoRunSubTest (uint16_t bufferSize)
497 {
498  /*
499  * Create device and attach configurations.
500  */
501  m_device = CreateObject<WifiNetDevice> ();
502  Ptr<HtConfiguration> htConfiguration = CreateObject<HtConfiguration> ();
503  m_device->SetHtConfiguration (htConfiguration);
504  Ptr<VhtConfiguration> vhtConfiguration = CreateObject<VhtConfiguration> ();
505  m_device->SetVhtConfiguration (vhtConfiguration);
506  Ptr<HeConfiguration> heConfiguration = CreateObject<HeConfiguration> ();
507  m_device->SetHeConfiguration (heConfiguration);
508 
509  /*
510  * Create and configure phy layer.
511  */
512  m_phy = CreateObject<YansWifiPhy> ();
515  m_device->SetPhy (m_phy);
516 
517  /*
518  * Create and configure manager.
519  */
521  m_factory.SetTypeId ("ns3::ConstantRateWifiManager");
522  m_factory.Set ("DataMode", StringValue ("HeMcs11"));
526 
527  /*
528  * Create and configure mac layer.
529  */
530  m_mac = CreateObject<StaWifiMac> ();
534  m_mac->SetAddress (Mac48Address ("00:00:00:00:00:01"));
536  m_device->SetMac (m_mac);
537 
538  /*
539  * Configure aggregation.
540  */
541  HeCapabilities heCapabilities;
542  m_manager->AddStationHeCapabilities (Mac48Address ("00:00:00:00:00:02"), heCapabilities);
543 
544  /*
545  * Create a dummy packet of 100 bytes and fill mac header fields.
546  */
547  Ptr<const Packet> pkt = Create<Packet> (100);
548  Ptr<Packet> currentAggregatedPacket = Create<Packet> ();
549  WifiMacHeader hdr;
550  hdr.SetAddr1 (Mac48Address ("00:00:00:00:00:02"));
551  hdr.SetAddr2 (Mac48Address ("00:00:00:00:00:01"));
552  hdr.SetType (WIFI_MAC_QOSDATA);
553  hdr.SetQosTid (0);
554  uint16_t sequence = m_mac->m_txMiddle->GetNextSequenceNumberFor (&hdr);
555  hdr.SetSequenceNumber (sequence);
556  hdr.SetFragmentNumber (0);
557  hdr.SetNoMoreFragments ();
558  hdr.SetNoRetry ();
559 
560  /*
561  * Establish agreement.
562  */
563  MgtAddBaRequestHeader reqHdr;
564  reqHdr.SetImmediateBlockAck ();
565  reqHdr.SetTid (0);
566  reqHdr.SetBufferSize (bufferSize);
567  reqHdr.SetTimeout (0);
568  reqHdr.SetStartingSequence (0);
569  m_mac->GetBEQueue ()->m_baManager->CreateAgreement (&reqHdr, hdr.GetAddr1 ());
570  m_mac->GetBEQueue ()->m_baManager->NotifyAgreementEstablished (hdr.GetAddr1 (), 0, 0);
571 
572  /*
573  * Test behavior when 300 packets are ready for transmission but negociated buffer size is 64
574  */
575  for (uint16_t i = 0; i < 300; i++)
576  {
577  Ptr<const Packet> pkt = Create<Packet> (100);
578  WifiMacHeader hdr;
579 
580  hdr.SetAddr1 (Mac48Address ("00:00:00:00:00:02"));
581  hdr.SetAddr2 (Mac48Address ("00:00:00:00:00:01"));
582  hdr.SetType (WIFI_MAC_QOSDATA);
583  hdr.SetQosTid (0);
584 
585  m_mac->GetBEQueue ()->GetWifiMacQueue ()->Enqueue (Create<WifiMacQueueItem> (pkt, hdr));
586  }
587 
588  WifiTxVector txVector = m_mac->GetBEQueue ()->GetLow ()->GetDataTxVector (Create<const WifiMacQueueItem> (pkt, hdr));
589 
590  auto mpduList = m_mac->GetBEQueue ()->GetLow ()->GetMpduAggregator ()-> GetNextAmpdu (Create<WifiMacQueueItem> (pkt, hdr),
591  txVector);
592  NS_TEST_EXPECT_MSG_EQ (mpduList.empty (), false, "MPDU aggregation failed");
593  NS_TEST_EXPECT_MSG_EQ (mpduList.size (), bufferSize, "A-MPDU should countain " << bufferSize << " MPDUs");
594  uint16_t expectedRemainingPacketsInQueue = 300 - bufferSize + 1;
595  NS_TEST_EXPECT_MSG_EQ (m_mac->GetBEQueue ()->GetWifiMacQueue ()->GetNPackets (), expectedRemainingPacketsInQueue, "queue should contain 300 - "<< bufferSize - 1 << " = "<< expectedRemainingPacketsInQueue << " packets");
596 
597  Simulator::Destroy ();
598 
599  m_manager->Dispose ();
600  m_manager = 0;
601 
602  m_device->Dispose ();
603  m_device = 0;
604 
605  htConfiguration = 0;
606  vhtConfiguration = 0;
607  heConfiguration = 0;
608 }
609 
610 void
612 {
613  DoRunSubTest (64);
614  DoRunSubTest (256);
615 }
616 
637 {
638 public:
640  virtual ~PreservePacketsInAmpdus ();
641 
642  virtual void DoRun (void);
643 
644 
645 private:
646  std::list<Ptr<const Packet>> m_packetList;
647  std::vector<std::size_t> m_nMpdus;
648  std::vector<std::size_t> m_nMsdus;
649 
654  void NotifyMacTransmit (Ptr<const Packet> packet);
661  void NotifyPsduForwardedDown (Ptr<const WifiPsdu> psdu, WifiTxVector txVector, double txPowerW);
667 };
668 
670  : TestCase ("Test case to check that the Wifi Mac forwards up the same packets received at sender side.")
671 {
672 }
673 
675 {
676 }
677 
678 void
680 {
681  m_packetList.push_back (packet);
682 }
683 
684 void
686 {
687  if (!psdu->GetHeader (0).IsQosData ())
688  {
689  return;
690  }
691 
692  m_nMpdus.push_back (psdu->GetNMpdus ());
693 
694  for (auto& mpdu : *PeekPointer (psdu))
695  {
696  std::size_t dist = std::distance (mpdu->begin (), mpdu->end ());
697  // the list of aggregated MSDUs is empty if the MPDU includes a non-aggregated MSDU
698  m_nMsdus.push_back (dist > 0 ? dist : 1);
699  }
700 }
701 
702 void
704 {
705  auto it = std::find (m_packetList.begin (), m_packetList.end (), p);
706  NS_TEST_EXPECT_MSG_EQ ((it != m_packetList.end ()), true, "Packet being forwarded up not found");
707  m_packetList.erase (it);
708 }
709 
710 void
712 {
713  NodeContainer wifiStaNode;
714  wifiStaNode.Create (1);
715 
717  wifiApNode.Create (1);
718 
719  YansWifiChannelHelper channel = YansWifiChannelHelper::Default ();
720  YansWifiPhyHelper phy = YansWifiPhyHelper::Default ();
721  phy.SetChannel (channel.Create ());
722 
724  wifi.SetStandard (WIFI_PHY_STANDARD_80211n_5GHZ);
725  wifi.SetRemoteStationManager ("ns3::IdealWifiManager");
726 
728  Ssid ssid = Ssid ("ns-3-ssid");
729  mac.SetType ("ns3::StaWifiMac",
730  "BE_MaxAmsduSize", UintegerValue (4500),
731  "BE_MaxAmpduSize", UintegerValue (7500),
732  "Ssid", SsidValue (ssid),
733  /* setting blockack threshold for sta's BE queue */
734  "BE_BlockAckThreshold", UintegerValue (2),
735  "ActiveProbing", BooleanValue (false));
736 
738  staDevices = wifi.Install (phy, mac, wifiStaNode);
739 
740  mac.SetType ("ns3::ApWifiMac",
741  "Ssid", SsidValue (ssid),
742  "BeaconGeneration", BooleanValue (true));
743 
745  apDevices = wifi.Install (phy, mac, wifiApNode);
746 
748  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
749 
750  positionAlloc->Add (Vector (0.0, 0.0, 0.0));
751  positionAlloc->Add (Vector (1.0, 0.0, 0.0));
752  mobility.SetPositionAllocator (positionAlloc);
753 
754  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
755  mobility.Install (wifiApNode);
756  mobility.Install (wifiStaNode);
757 
758  Ptr<WifiNetDevice> ap_device = DynamicCast<WifiNetDevice> (apDevices.Get (0));
759  Ptr<WifiNetDevice> sta_device = DynamicCast<WifiNetDevice> (staDevices.Get (0));
760 
761  PacketSocketAddress socket;
762  socket.SetSingleDevice (sta_device->GetIfIndex ());
763  socket.SetPhysicalAddress (ap_device->GetAddress ());
764  socket.SetProtocol (1);
765 
766  // install packet sockets on nodes.
767  PacketSocketHelper packetSocket;
768  packetSocket.Install (wifiStaNode);
769  packetSocket.Install (wifiApNode);
770 
771  Ptr<PacketSocketClient> client = CreateObject<PacketSocketClient> ();
772  client->SetAttribute ("PacketSize", UintegerValue (1000));
773  client->SetAttribute ("MaxPackets", UintegerValue (8));
774  client->SetAttribute ("Interval", TimeValue (Seconds (1)));
775  client->SetRemote (socket);
776  wifiStaNode.Get (0)->AddApplication (client);
777  client->SetStartTime (Seconds (1));
778  client->SetStopTime (Seconds (3.0));
779  Simulator::Schedule (Seconds (1.5), &PacketSocketClient::SetAttribute, client,
780  "Interval", TimeValue (MicroSeconds (0)));
781 
782  Ptr<PacketSocketServer> server = CreateObject<PacketSocketServer> ();
783  server->SetLocal (socket);
784  wifiApNode.Get (0)->AddApplication (server);
785  server->SetStartTime (Seconds (0.0));
786  server->SetStopTime (Seconds (4.0));
787 
788  PointerValue ptr;
789  sta_device->GetMac ()->GetAttribute ("BE_Txop", ptr);
790  Ptr<QosTxop> qosTxop = ptr.Get<QosTxop> ();
791 
792  sta_device->GetMac ()->TraceConnectWithoutContext ("MacTx",
794  qosTxop->GetLow ()->GetPhy ()->TraceConnectWithoutContext ("PhyTxPsduBegin",
796  ap_device->GetMac ()->TraceConnectWithoutContext ("MacRx",
798 
799  Simulator::Stop (Seconds (5));
800  Simulator::Run ();
801 
802  Simulator::Destroy ();
803 
804  // Two packets are transmitted. The first one is an MPDU containing a single MSDU.
805  // The second one is an A-MPDU containing two MPDUs: the first MPDU contains 4 MSDUs
806  // and the second MPDU contains 3 MSDUs
807  NS_TEST_EXPECT_MSG_EQ (m_nMpdus.size (), 2, "Unexpected number of transmitted packets");
808  NS_TEST_EXPECT_MSG_EQ (m_nMsdus.size (), 3, "Unexpected number of transmitted MPDUs");
809  NS_TEST_EXPECT_MSG_EQ (m_nMpdus[0], 1, "Unexpected number of MPDUs in the first A-MPDU");
810  NS_TEST_EXPECT_MSG_EQ (m_nMsdus[0], 1, "Unexpected number of MSDUs in the first MPDU");
811  NS_TEST_EXPECT_MSG_EQ (m_nMpdus[1], 2, "Unexpected number of MPDUs in the second A-MPDU");
812  NS_TEST_EXPECT_MSG_EQ (m_nMsdus[1], 4, "Unexpected number of MSDUs in the second MPDU");
813  NS_TEST_EXPECT_MSG_EQ (m_nMsdus[2], 3, "Unexpected number of MSDUs in the third MPDU");
814  // All the packets must have been forwarded up at the receiver
815  NS_TEST_EXPECT_MSG_EQ (m_packetList.empty (), true, "Some packets have not been forwarded up");
816 }
817 
825 {
826 public:
828 };
829 
831  : TestSuite ("wifi-aggregation", UNIT)
832 {
833  AddTestCase (new AmpduAggregationTest, TestCase::QUICK);
834  AddTestCase (new TwoLevelAggregationTest, TestCase::QUICK);
835  AddTestCase (new HeAggregationTest, TestCase::QUICK);
836  AddTestCase (new PreservePacketsInAmpdus, TestCase::QUICK);
837 }
838 
void Dispose(void)
Dispose of this Object.
Definition: object.cc:214
Ptr< StaWifiMac > m_mac
Mac.
void SetWifiPhy(const Ptr< WifiPhy > phy)
ObjectFactory m_factory
factory
uint32_t AddApplication(Ptr< Application > application)
Associate an Application to this Node.
Definition: node.cc:157
void MissedAck(void)
Event handler when an ACK is missed.
Definition: qos-txop.cc:817
Wifi Aggregation Test Suite.
Test for A-MSDU and A-MPDU aggregation.
void SetStopTime(Time stop)
Specify application stop time.
Definition: application.cc:75
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:102
std::list< Ptr< const Packet > > m_packetList
List of packets passed to the MAC.
virtual void DoRun(void)
Implementation to actually run this TestCase.
AttributeValue implementation for Boolean.
Definition: boolean.h:36
void SetLocal(PacketSocketAddress addr)
set the local address and protocol to be used
HT PHY for the 5 GHz band (clause 20)
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:852
std::vector< std::size_t > m_nMpdus
Number of MPDUs in PSDUs passed to the PHY.
Ptr< WifiRemoteStationManager > m_manager
remote station manager
Hold variables of type string.
Definition: string.h:41
Make it easy to create and manage PHY objects for the yans model.
void NotifyMacTransmit(Ptr< const Packet > packet)
Callback invoked when an MSDU is passed to the MAC.
ObjectFactory m_factory
factory
A suite of tests to run.
Definition: test.h:1341
void SetImmediateBlockAck()
Enable immediate Block ACK.
Handle packet fragmentation and retransmissions for QoS data frames as well as MSDU aggregation (A-MS...
Definition: qos-txop.h:92
void SetBufferSize(uint16_t size)
Set buffer size.
Implement the header for management frames of type add block ack request.
Definition: mgt-headers.h:1003
an address for a packet socket
U * PeekPointer(const Ptr< U > &p)
Definition: ptr.h:566
void SetHtConfiguration(Ptr< HtConfiguration > htConfiguration)
The HT Capabilities Information ElementThis class knows how to serialise and deserialise the HT Capab...
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:283
void ConfigureStandard(WifiPhyStandard standard)
Definition: wifi-mac.cc:270
staDevices
Definition: third.py:103
Ptr< WifiNetDevice > m_device
WifiNetDevice.
encapsulates test code
Definition: test.h:1153
Ptr< StaWifiMac > m_mac
Mac.
ObjectFactory m_factory
factory
helps to create WifiNetDevice objects
Definition: wifi-helper.h:300
Ptr< YansWifiPhy > m_phy
Phy.
Give ns3::PacketSocket powers to ns3::Node.
void SetSingleDevice(uint32_t device)
Set the address to match only a specified NetDevice.
Address GetAddress(void) const
void SetWifiRemoteStationManager(const Ptr< WifiRemoteStationManager > stationManager)
Set up WifiRemoteStationManager associated with this StaWifiMac.
channel
Definition: third.py:92
mobility
Definition: third.py:108
uint32_t GetSize(void) const
Return the size of the PSDU.
Definition: wifi-psdu.cc:260
void NotifyMacForwardUp(Ptr< const Packet > p)
Callback invoked when the receiver MAC forwards a packet up to the upper layer.
phy
Definition: third.py:93
void SetDevice(const Ptr< NetDevice > device)
Sets the device this PHY is associated with.
Definition: wifi-phy.cc:724
void SetHeConfiguration(Ptr< HeConfiguration > heConfiguration)
HE PHY for the 5 GHz band (clause 26)
Ptr< WifiRemoteStationManager > m_manager
remote station manager
void SetAddr1(Mac48Address address)
Fill the Address 1 field with the given address.
void SetDevice(const Ptr< NetDevice > device)
Sets the device this PHY is associated with.
Definition: wifi-mac.cc:221
AttributeValue implementation for Time.
Definition: nstime.h:1126
Ptr< Object > Create(void) const
Create an Object instance of the configured TypeId.
void SetMac(const Ptr< WifiMac > mac)
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
Ptr< WifiNetDevice > m_device
WifiNetDevice.
void SetMaxAmpduLength(uint32_t maxampdulength)
Set the maximum AMPDU length.
Hold an unsigned integer type.
Definition: uinteger.h:44
void SetTid(uint8_t tid)
Set Traffic ID (TID).
ssid
Definition: third.py:100
void AddStationHtCapabilities(Mac48Address from, HtCapabilities htcapabilities)
Records HT capabilities of the remote station.
Ptr< BlockAckManager > m_baManager
the Block ACK manager
Definition: qos-txop.h:633
holds a vector of ns3::NetDevice pointers
mac
Definition: third.py:99
void SetAddress(Mac48Address address)
void SetMaxSsrc(uint32_t maxSsrc)
Sets the maximum STA short retry count (SSRC).
Ptr< StaWifiMac > m_mac
Mac.
void SetStartingSequence(uint16_t seq)
Set the starting sequence number.
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:1610
wifiApNode
Definition: third.py:90
void NotifyPsduForwardedDown(Ptr< const WifiPsdu > psdu, WifiTxVector txVector, double txPowerW)
Callback invoked when the sender MAC passes a PSDU(s) to the PHY.
Ptr< WifiNetDevice > m_device
WifiNetDevice.
void AddStationHeCapabilities(Mac48Address from, HeCapabilities hecapabilities)
Records HE capabilities of the remote station.
void SetMaxAmsduLength(uint16_t maxamsdulength)
Set the maximum AMSDU length.
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.
const WifiMacHeader & GetHeader(std::size_t i) const
Get the header of the i-th MPDU.
Definition: wifi-psdu.cc:266
void DoRunSubTest(uint16_t bufferSize)
Run test for a given buffer size.
Ptr< const Packet > GetPacket(void) const
Get the packet stored in this item.
bool TraceConnectWithoutContext(std::string name, const CallbackBase &cb)
Connect a TraceSource to a Callback without a context.
Definition: object-base.cc:295
Ptr< MacLow > GetLow(void) const
Return the MacLow associated with this Txop.
Definition: txop.cc:366
std::size_t GetNMpdus(void) const
Return the number of MPDUs constituting the PSDU.
Definition: wifi-psdu.cc:319
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.
keep track of a set of node pointers.
Hold objects of type Ptr<T>.
Definition: pointer.h:36
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:531
void Set(std::string name, const AttributeValue &value)
Set an attribute to be set during construction.
Ptr< QosTxop > GetVIQueue(void) const
Accessor for the AC_VI channel access function.
manage and create wifi channel objects for the yans model.
create MAC layers for a ns3::WifiNetDevice.
The IEEE 802.11 SSID Information Element.
Definition: ssid.h:35
Two Level Aggregation Test.
Ampdu Aggregation Test.
wifi
Definition: third.py:96
Helper class used to assign positions and mobility models to nodes.
Instantiate subclasses of ns3::Object.
void SetPhy(const Ptr< WifiPhy > phy)
Ptr< QosTxop > GetBEQueue(void) const
Accessor for the AC_BE channel access function.
Ptr< WifiMac > GetMac(void) const
void DoRun(void)
Implementation to actually run this TestCase.
virtual void DoRun(void)
Implementation to actually run this TestCase.
void SetSequenceNumber(uint16_t seq)
Set the sequence number of the header.
void SetRemote(PacketSocketAddress addr)
set the remote address and protocol to be used
802.11ax aggregation test which permits 64 or 256 MPDUs in A-MPDU according to the negociated buffer ...
virtual void DoRun(void)
Implementation to actually run this TestCase.
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1064
AttributeValue implementation for Ssid.
Definition: ssid.h:110
Ptr< WifiMacQueue > GetWifiMacQueue() const
Return the packet queue associated with this Txop.
Definition: txop.cc:178
Ptr< T > Get(void) const
Definition: pointer.h:201
void Add(Vector v)
Add a position to the list of positions.
Ptr< Node > Get(uint32_t i) const
Get the Ptr<Node> stored in this container at a given index.
apDevices
Definition: third.py:106
void Install(Ptr< Node > node) const
Aggregate an instance of a ns3::PacketSocketFactory onto the provided node.
bool IsQosData(void) const
Return true if the Type is DATA and Subtype is one of the possible values for QoS DATA...
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1080
Ptr< YansWifiPhy > m_phy
Phy.
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
virtual void ConfigureStandard(WifiPhyStandard standard)
Configure the PHY-level parameters for different Wi-Fi standard.
Definition: wifi-phy.cc:1248
void SetTimeout(uint16_t timeout)
Set timeout.
WifiMacHeader m_currentHdr
the current header
Definition: txop.h:532
Ptr< YansWifiPhy > m_phy
Phy.
The IEEE 802.11ax HE Capabilities.
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:187
void SetStartTime(Time start)
Specify application start time.
Definition: application.cc:69
void SetVhtConfiguration(Ptr< VhtConfiguration > vhtConfiguration)
Ptr< MacTxMiddle > m_txMiddle
TX middle (aggregation etc.)
std::vector< std::size_t > m_nMsdus
Number of MSDUs in MPDUs passed to the PHY.
Implements the IEEE 802.11 MAC header.
void SetRemoteStationManager(const Ptr< WifiRemoteStationManager > manager)
Ptr< WifiRemoteStationManager > m_manager
remote station manager
Time GetTxopLimit(void) const
Return the TXOP limit.
Definition: txop.cc:302