A Discrete-Event Network Simulator
API
block-ack-test-suite.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2009, 2010 MIRKO BANCHI
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: Mirko Banchi <mk.banchi@gmail.com>
19  */
20 
21 #include "ns3/test.h"
22 #include "ns3/string.h"
23 #include "ns3/qos-utils.h"
24 #include "ns3/ctrl-headers.h"
25 #include "ns3/packet.h"
26 #include "ns3/wifi-net-device.h"
27 #include "ns3/ap-wifi-mac.h"
28 #include "ns3/wifi-mac-header.h"
29 #include "ns3/mobility-helper.h"
30 #include "ns3/yans-wifi-helper.h"
31 #include "ns3/packet-socket-server.h"
32 #include "ns3/packet-socket-client.h"
33 #include "ns3/packet-socket-helper.h"
34 #include "ns3/config.h"
35 #include "ns3/pointer.h"
36 
37 using namespace ns3;
38 
53 //-------------------------------------------------------------------------------------
54 
55 /* ----- = old packets
56  * +++++ = new packets
57  *
58  * CASE A: startSeq < endSeq
59  * - - +
60  * initial buffer state: 0 16 56000
61  *
62  *
63  * 0 4095
64  * |------|++++++++++++++++|-----|
65  * ^ ^
66  * | startSeq | endSeq = 4000
67  *
68  * first received packet's sequence control = 64016 (seqNum = 4001, fragNum = 0) -
69  * second received packet's sequence control = 63984 (seqNum = 3999, fragNum = 0) +
70  * 4001 is older seq number so this packet should be inserted at the buffer's begin.
71  * 3999 is previous element of older of new packets: it should be inserted at the end of buffer.
72  *
73  * expected buffer state: 64016 0 16 56000 63984
74  *
75  */
77 {
78 public:
80  virtual ~PacketBufferingCaseA ();
81 private:
82  virtual void DoRun (void);
83  std::list<uint16_t> m_expectedBuffer;
84 };
85 
87  : TestCase ("Check correct order of buffering when startSequence < endSeq")
88 {
89  m_expectedBuffer.push_back (64016);
90  m_expectedBuffer.push_back (0);
91  m_expectedBuffer.push_back (16);
92  m_expectedBuffer.push_back (56000);
93  m_expectedBuffer.push_back (63984);
94 }
95 
97 {
98 }
99 
100 void
102 {
103  std::list<uint16_t> m_buffer;
104  std::list<uint16_t>::iterator i,j;
105  m_buffer.push_back (0);
106  m_buffer.push_back (16);
107  m_buffer.push_back (56000);
108 
109  uint16_t endSeq = 4000;
110 
111  uint16_t receivedSeq = 4001 * 16;
112  uint32_t mappedSeq = QosUtilsMapSeqControlToUniqueInteger (receivedSeq, endSeq);
113  /* cycle to right position for this packet */
114  for (i = m_buffer.begin (); i != m_buffer.end (); i++)
115  {
116  if (QosUtilsMapSeqControlToUniqueInteger ((*i), endSeq) >= mappedSeq)
117  {
118  //position found
119  break;
120  }
121  }
122  m_buffer.insert (i, receivedSeq);
123 
124  receivedSeq = 3999 * 16;
125  mappedSeq = QosUtilsMapSeqControlToUniqueInteger (receivedSeq, endSeq);
126  /* cycle to right position for this packet */
127  for (i = m_buffer.begin (); i != m_buffer.end (); i++)
128  {
129  if (QosUtilsMapSeqControlToUniqueInteger ((*i), endSeq) >= mappedSeq)
130  {
131  //position found
132  break;
133  }
134  }
135  m_buffer.insert (i, receivedSeq);
136 
137  for (i = m_buffer.begin (), j = m_expectedBuffer.begin (); i != m_buffer.end (); i++, j++)
138  {
139  NS_TEST_EXPECT_MSG_EQ (*i, *j, "error in buffer order");
140  }
141 }
142 
143 
174 {
175 public:
177  virtual ~PacketBufferingCaseB ();
178 private:
179  virtual void DoRun (void);
180  std::list<uint16_t> m_expectedBuffer;
181 };
182 
184  : TestCase ("Check correct order of buffering when startSequence > endSeq")
185 {
186  m_expectedBuffer.push_back (240);
187  m_expectedBuffer.push_back (241);
188  m_expectedBuffer.push_back (256);
189  m_expectedBuffer.push_back (64000);
190  m_expectedBuffer.push_back (64800);
191  m_expectedBuffer.push_back (16);
192 }
193 
195 {
196 }
197 
198 void
200 {
201  std::list<uint16_t> m_buffer;
202  std::list<uint16_t>::iterator i,j;
203  m_buffer.push_back (256);
204  m_buffer.push_back (64000);
205  m_buffer.push_back (16);
206 
207  uint16_t endSeq = 10;
208 
209  uint16_t receivedSeq = 15 * 16;
210  uint32_t mappedSeq = QosUtilsMapSeqControlToUniqueInteger (receivedSeq, endSeq);
211  /* cycle to right position for this packet */
212  for (i = m_buffer.begin (); i != m_buffer.end (); i++)
213  {
214  if (QosUtilsMapSeqControlToUniqueInteger ((*i), endSeq) >= mappedSeq)
215  {
216  //position found
217  break;
218  }
219  }
220  m_buffer.insert (i, receivedSeq);
221 
222  receivedSeq = 15 * 16 + 1;
223  mappedSeq = QosUtilsMapSeqControlToUniqueInteger (receivedSeq, endSeq);
224  /* cycle to right position for this packet */
225  for (i = m_buffer.begin (); i != m_buffer.end (); i++)
226  {
227  if (QosUtilsMapSeqControlToUniqueInteger ((*i), endSeq) >= mappedSeq)
228  {
229  //position found
230  break;
231  }
232  }
233  m_buffer.insert (i, receivedSeq);
234 
235  receivedSeq = 4050 * 16;
236  mappedSeq = QosUtilsMapSeqControlToUniqueInteger (receivedSeq, endSeq);
237  /* cycle to right position for this packet */
238  for (i = m_buffer.begin (); i != m_buffer.end (); i++)
239  {
240  if (QosUtilsMapSeqControlToUniqueInteger ((*i), endSeq) >= mappedSeq)
241  {
242  //position found
243  break;
244  }
245  }
246  m_buffer.insert (i, receivedSeq);
247 
248  for (i = m_buffer.begin (), j = m_expectedBuffer.begin (); i != m_buffer.end (); i++, j++)
249  {
250  NS_TEST_EXPECT_MSG_EQ (*i, *j, "error in buffer order");
251  }
252 }
253 
254 
262 {
263 public:
265 private:
266  virtual void DoRun ();
268 };
269 
271  : TestCase ("Check the correctness of block ack compressed bitmap")
272 {
273 }
274 
275 void
277 {
279 
280  //Case 1: startSeq < endSeq
281  // 179 242
283  for (uint16_t i = 179; i < 220; i++)
284  {
286  }
287  for (uint16_t i = 225; i <= 242; i++)
288  {
290  }
291  NS_TEST_EXPECT_MSG_EQ (m_blockAckHdr.GetCompressedBitmap (), 0xffffc1ffffffffffLL, "error in compressed bitmap");
293  NS_TEST_EXPECT_MSG_EQ (m_blockAckHdr.GetCompressedBitmap (), 0xffffc1ffffffffffLL, "error in compressed bitmap");
294  NS_TEST_EXPECT_MSG_EQ (m_blockAckHdr.IsPacketReceived (220), false, "error in compressed bitmap");
295  NS_TEST_EXPECT_MSG_EQ (m_blockAckHdr.IsPacketReceived (225), true, "error in compressed bitmap");
296  NS_TEST_EXPECT_MSG_EQ (m_blockAckHdr.IsPacketReceived (1500), false, "error in compressed bitmap");
297 
299 
300  //Case 2: startSeq > endSeq
301  // 4090 58
303  for (uint16_t i = 4090; i != 10; i = (i + 1) % 4096)
304  {
306  }
307  for (uint16_t i = 22; i < 25; i++)
308  {
310  }
311  NS_TEST_EXPECT_MSG_EQ (m_blockAckHdr.GetCompressedBitmap (), 0x00000000007000ffffLL, "error in compressed bitmap");
313  NS_TEST_EXPECT_MSG_EQ (m_blockAckHdr.GetCompressedBitmap (), 0x00000000007000ffffLL, "error in compressed bitmap");
314  NS_TEST_EXPECT_MSG_EQ (m_blockAckHdr.IsPacketReceived (4090), true, "error in compressed bitmap");
315  NS_TEST_EXPECT_MSG_EQ (m_blockAckHdr.IsPacketReceived (4095), true, "error in compressed bitmap");
316  NS_TEST_EXPECT_MSG_EQ (m_blockAckHdr.IsPacketReceived (10), false, "error in compressed bitmap");
317  NS_TEST_EXPECT_MSG_EQ (m_blockAckHdr.IsPacketReceived (35), false, "error in compressed bitmap");
318  NS_TEST_EXPECT_MSG_EQ (m_blockAckHdr.IsPacketReceived (80), false, "error in compressed bitmap");
319 }
320 
321 
336 {
341  {
342  void Trace (Time startTime, Time duration);
344  };
345 
346 public:
349 
350  virtual void DoRun (void);
351 
352 
353 private:
354  uint32_t m_received;
355  uint16_t m_txTotal;
356  uint16_t m_nBar;
357  uint16_t m_nBa;
358 
365  void L7Receive (std::string context, Ptr<const Packet> p, const Address &adr);
372  void Transmit (std::string context, Ptr<const Packet> p, double power);
378  void Receive (std::string context, Ptr<const Packet> p);
379 };
380 
381 void
383 {
384  if (duration > m_max)
385  {
386  m_max = duration;
387  }
388 }
389 
391  : TestCase ("Test case for Block Ack Policy with aggregation disabled"),
392  m_received (0),
393  m_txTotal (0),
394  m_nBar (0),
395  m_nBa (0)
396 {
397 }
398 
400 {
401 }
402 
403 void
405 {
406  if (p->GetSize () == 1400)
407  {
408  m_received++;
409  }
410 }
411 
412 void
413 BlockAckAggregationDisabledTest::Transmit (std::string context, Ptr<const Packet> p, double power)
414 {
415  WifiMacHeader hdr;
416  p->PeekHeader (hdr);
417 
418  if (hdr.IsQosData ())
419  {
420  m_txTotal++;
421  NS_TEST_EXPECT_MSG_EQ ((m_txTotal == 1 || hdr.IsQosBlockAck ()), true, "Unexpected QoS ack policy");
422  }
423  else if (hdr.IsBlockAckReq ())
424  {
425  m_nBar++;
426  }
427 }
428 
429 void
431 {
432  WifiMacHeader hdr;
433  p->PeekHeader (hdr);
434 
435  if (hdr.IsBlockAck ())
436  {
437  m_nBa++;
438  }
439 }
440 
441 void
443 {
444  NodeContainer wifiStaNode;
445  wifiStaNode.Create (1);
446 
448  wifiApNode.Create (1);
449 
450  YansWifiChannelHelper channel = YansWifiChannelHelper::Default ();
451  YansWifiPhyHelper phy = YansWifiPhyHelper::Default ();
452  phy.SetChannel (channel.Create ());
453 
455  wifi.SetStandard (WIFI_PHY_STANDARD_80211a);
456  wifi.SetRemoteStationManager ("ns3::IdealWifiManager");
457 
459  Ssid ssid = Ssid ("ns-3-ssid");
460  mac.SetType ("ns3::StaWifiMac",
461  "QosSupported", BooleanValue (true),
462  "Ssid", SsidValue (ssid),
463  /* setting blockack threshold for sta's BE queue */
464  "BE_BlockAckThreshold", UintegerValue (2),
465  "ActiveProbing", BooleanValue (false));
466 
468  staDevices = wifi.Install (phy, mac, wifiStaNode);
469 
470  mac.SetType ("ns3::ApWifiMac",
471  "QosSupported", BooleanValue (true),
472  "Ssid", SsidValue (ssid),
473  "BeaconGeneration", BooleanValue (true));
474 
476  apDevices = wifi.Install (phy, mac, wifiApNode);
477 
479  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
480 
481  positionAlloc->Add (Vector (0.0, 0.0, 0.0));
482  positionAlloc->Add (Vector (1.0, 0.0, 0.0));
483  mobility.SetPositionAllocator (positionAlloc);
484 
485  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
486  mobility.Install (wifiApNode);
487  mobility.Install (wifiStaNode);
488 
489  Ptr<WifiNetDevice> ap_device = DynamicCast<WifiNetDevice> (apDevices.Get (0));
490  Ptr<WifiNetDevice> sta_device = DynamicCast<WifiNetDevice> (staDevices.Get (0));
491 
492  // Disable A-MPDU aggregation
493  sta_device->GetMac ()->SetAttribute ("BE_MaxAmpduSize", UintegerValue (0));
494  TxopDurationTracer txopTracer;
495 
496  PacketSocketAddress socket;
497  socket.SetSingleDevice (sta_device->GetIfIndex ());
498  socket.SetPhysicalAddress (ap_device->GetAddress ());
499  socket.SetProtocol (1);
500 
501  // give packet socket powers to nodes.
502  PacketSocketHelper packetSocket;
503  packetSocket.Install (wifiStaNode);
504  packetSocket.Install (wifiApNode);
505 
506  Ptr<PacketSocketClient> client = CreateObject<PacketSocketClient> ();
507  client->SetAttribute ("PacketSize", UintegerValue (1400));
508  client->SetAttribute ("MaxPackets", UintegerValue (14));
509  client->SetAttribute ("Interval", TimeValue (MicroSeconds (0)));
510  client->SetRemote (socket);
511  wifiStaNode.Get (0)->AddApplication (client);
512  client->SetStartTime (Seconds (1));
513  client->SetStopTime (Seconds (3.0));
514 
515  Ptr<PacketSocketServer> server = CreateObject<PacketSocketServer> ();
516  server->SetLocal (socket);
517  wifiApNode.Get (0)->AddApplication (server);
518  server->SetStartTime (Seconds (0.0));
519  server->SetStopTime (Seconds (4.0));
520 
521  Config::Connect ("/NodeList/*/ApplicationList/0/$ns3::PacketSocketServer/Rx", MakeCallback (&BlockAckAggregationDisabledTest::L7Receive, this));
522  Config::Connect ("/NodeList/0/DeviceList/0/Phy/PhyTxBegin", MakeCallback (&BlockAckAggregationDisabledTest::Transmit, this));
523  Config::Connect ("/NodeList/0/DeviceList/0/Phy/PhyRxBegin", MakeCallback (&BlockAckAggregationDisabledTest::Receive, this));
524 
525  Simulator::Stop (Seconds (5));
526  Simulator::Run ();
527 
528  Simulator::Destroy ();
529 
530  // The client application generates 14 packets, so we expect that the wifi PHY
531  // layer transmits 14 MPDUs, the server application receives 14 packets, and
532  // a BAR is transmitted after each MPDU but the first one (because a BA agreement
533  // is established before transmitting the second MPDU).
534  NS_TEST_EXPECT_MSG_EQ (m_txTotal, 14, "Unexpected number of transmitted packets");
535  NS_TEST_EXPECT_MSG_EQ (m_received, 14, "Unexpected number of received packets");
536  NS_TEST_EXPECT_MSG_EQ (m_nBar, 13, "Unexpected number of Block Ack Requests");
537  NS_TEST_EXPECT_MSG_EQ (m_nBa, 13, "Unexpected number of Block Ack Responses");
538 }
539 
547 {
548 public:
550 };
551 
553  : TestSuite ("wifi-block-ack", UNIT)
554 {
555  AddTestCase (new PacketBufferingCaseA, TestCase::QUICK);
556  AddTestCase (new PacketBufferingCaseB, TestCase::QUICK);
557  AddTestCase (new CtrlBAckResponseHeaderTest, TestCase::QUICK);
558  AddTestCase (new BlockAckAggregationDisabledTest, TestCase::QUICK);
559 }
560 
uint32_t AddApplication(Ptr< Application > application)
Associate an Application to this Node.
Definition: node.cc:157
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< uint16_t > m_expectedBuffer
expected test buffer
AttributeValue implementation for Boolean.
Definition: boolean.h:36
void SetLocal(PacketSocketAddress addr)
set the local address and protocol to be used
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:852
Make it easy to create and manage PHY objects for the yans model.
A suite of tests to run.
Definition: test.h:1342
uint32_t m_received
received packets
an address for a packet socket
#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
staDevices
Definition: third.py:96
void Transmit(std::string context, Ptr< const Packet > p, double power)
Callback invoked when PHY transmits a packet.
encapsulates test code
Definition: test.h:1155
Keeps the maximum duration among all TXOPs.
helps to create WifiNetDevice objects
Definition: wifi-helper.h:299
void SetStartingSequence(uint16_t seq)
Set the starting sequence number from the given raw sequence control field.
CtrlBAckResponseHeader m_blockAckHdr
block ack header
Give ns3::PacketSocket powers to ns3::Node.
void SetSingleDevice(uint32_t device)
Set the address to match only a specified NetDevice.
uint16_t m_nBar
transmitted BlockAckReq frames
Address GetAddress(void) const
a polymophic address class
Definition: address.h:90
bool IsBlockAck(void) const
Return true if the header is a Block ACK header.
virtual void DoRun(void)
Implementation to actually run this TestCase.
channel
Definition: third.py:85
mobility
Definition: third.py:101
phy
Definition: third.py:86
bool IsBlockAckReq(void) const
Return true if the header is a Block ACK Request header.
AttributeValue implementation for Time.
Definition: nstime.h:1124
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
Hold an unsigned integer type.
Definition: uinteger.h:44
double startTime
ssid
Definition: third.py:93
holds a vector of ns3::NetDevice pointers
mac
Definition: third.py:92
uint64_t GetCompressedBitmap(void) const
Return the compressed bitmap from the block ACK response header.
bool IsPacketReceived(uint16_t seq) const
Check if the packet with the given sequence number was ACKed in this Block ACK response.
uint16_t m_txTotal
transmitted data packets
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Definition: packet.cc:290
Headers for Block ack response.
Definition: ctrl-headers.h:193
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:1489
wifiApNode
Definition: third.py:83
uint16_t m_nBa
received BlockAck frames
void Connect(std::string path, const CallbackBase &cb)
Definition: config.cc:871
Packet Buffering Case B.
virtual void DoRun(void)
Implementation to actually run this TestCase.
OFDM PHY for the 5 GHz band (Clause 17)
Every class exported by the ns3 library is enclosed in the ns3 namespace.
void SetPhysicalAddress(const Address address)
Set the destination address.
keep track of a set of node pointers.
void SetType(BlockAckType type)
Set the block ACK type.
Test for Block Ack Policy with aggregation disabled.
manage and create wifi channel objects for the yans model.
create MAC layers for a ns3::WifiNetDevice.
void ResetBitmap(void)
Reset the bitmap to 0.
The IEEE 802.11 SSID Information Element.
Definition: ssid.h:35
wifi
Definition: third.py:89
Helper class used to assign positions and mobility models to nodes.
bool IsQosBlockAck(void) const
Return if the QoS ACK policy is Block ACK.
void SetReceivedPacket(uint16_t seq)
Set the bitmap that the packet with the given sequence number was received.
Packet Buffering Case A.
Ptr< WifiMac > GetMac(void) const
void SetRemote(PacketSocketAddress addr)
set the remote address and protocol to be used
uint32_t QosUtilsMapSeqControlToUniqueInteger(uint16_t seqControl, uint16_t endSequence)
Next function is useful to correctly sort buffered packets under block ack.
Definition: qos-utils.cc:73
virtual void DoRun()
Implementation to actually run this TestCase.
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1062
AttributeValue implementation for Ssid.
Definition: ssid.h:110
void SetProtocol(uint16_t protocol)
Set the protocol.
void Add(Vector v)
Add a position to the list of positions.
Block Ack Test Suite.
Ptr< Node > Get(uint32_t i) const
Get the Ptr<Node> stored in this container at a given index.
void L7Receive(std::string context, Ptr< const Packet > p, const Address &adr)
Function to trace packets received by the server application.
apDevices
Definition: third.py:99
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:1078
Test for block ack header.
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
void Receive(std::string context, Ptr< const Packet > p)
Callback invoked when PHY receives a packet.
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:185
virtual void DoRun(void)
Implementation to actually run this TestCase.
static BlockAckTestSuite g_blockAckTestSuite
the test suite
std::list< uint16_t > m_expectedBuffer
expected test buffer
void SetStartTime(Time start)
Specify application start time.
Definition: application.cc:69
Implements the IEEE 802.11 MAC header.