A Discrete-Event Network Simulator
API
lr-wpan-ifs-test.cc
Go to the documentation of this file.
1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2019 Ritsumeikan University, Shiga, Japan
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:
19  * Alberto Gallegos Ramonet <ramonet@fc.ritsumei.ac.jp>
20  */
21 
22 #include <ns3/log.h>
23 #include <ns3/core-module.h>
24 #include <ns3/lr-wpan-module.h>
25 #include <ns3/propagation-loss-model.h>
26 #include <ns3/propagation-delay-model.h>
27 #include <ns3/simulator.h>
28 #include <ns3/single-model-spectrum-channel.h>
29 #include <ns3/constant-position-mobility-model.h>
30 #include <ns3/packet.h>
31 #include "ns3/rng-seed-manager.h"
32 
33 #include <iostream>
34 #include <iomanip>
35 
36 using namespace ns3;
37 
38 NS_LOG_COMPONENT_DEFINE ("lr-wpan-ifs-test");
39 
40 
48 {
49 public:
51  virtual ~LrWpanDataIfsTestCase ();
52 
53 private:
60  static void DataConfirm (LrWpanDataIfsTestCase *testcase,
62  McpsDataConfirmParams params);
63 
70  static void DataReceivedDev0 (LrWpanDataIfsTestCase *testcase,
73 
80  static void PhyDataRxStart (LrWpanDataIfsTestCase *testcase,
83 
90  static void DataReceivedDev1 (LrWpanDataIfsTestCase *testcase,
93 
100  static void IfsEnd (LrWpanDataIfsTestCase *testcase,
102  Time IfsTime);
103 
104 
105 
106  virtual void DoRun (void);
111 
112 
113 };
114 
115 
117  : TestCase ("Lrwpan: IFS tests")
118 {}
119 
121 {}
122 
123 void
125 {
126  // get the end time of transmission
127  testcase->m_lastTxTime = Simulator::Now ();
128 }
129 
130 void
132 {
133  // Callback for Data received in the Dev0
134  Ptr<Packet> RxPacket = p->Copy ();
135  LrWpanMacHeader receivedMacHdr;
136  RxPacket->RemoveHeader (receivedMacHdr);
137 
138  if (receivedMacHdr.IsAcknowledgment ())
139  {
140  testcase->m_ackRxTime = Simulator::Now ();
141  std::cout << Simulator::Now ().GetSeconds () << " | Dev0 (Node 0) received Acknowledgment.\n";
142  }
143  else if (receivedMacHdr.GetShortDstAddr ().IsBroadcast ())
144  {
145  std::cout << Simulator::Now ().GetSeconds () << " | Dev0 (Node 0) received Broadcast. \n";
146  }
147 
148 }
149 
150 void
152 {
153  //get the start time the phy in dev 0 ( Node 0) start receiving a frame
154  testcase->m_phyStartRx = Simulator::Now ();
155 }
156 
157 void
159 {
160  // Callback for Data received in the Dev1
161  Ptr<Packet> RxPacket = p->Copy ();
162  LrWpanMacHeader receivedMacHdr;
163  RxPacket->RemoveHeader (receivedMacHdr);
164 
165  if (receivedMacHdr.GetShortDstAddr ().IsBroadcast ())
166  {
167  std::cout << Simulator::Now ().GetSeconds () << " | Dev1 (Node 1) received Broadcast. \n";
168 
169  // Bcst received, respond with another bcst
170 
171  Ptr<Packet> p0 = Create<Packet> (50); // 50 bytes of dummy data
172  McpsDataRequestParams params1;
173  params1.m_dstPanId = 0;
174  params1.m_srcAddrMode = SHORT_ADDR;
175  params1.m_dstAddrMode = SHORT_ADDR;
176  params1.m_dstAddr = Mac16Address ("ff:ff");
177  params1.m_msduHandle = 0;
178 
179  Simulator::ScheduleNow (&LrWpanMac::McpsDataRequest,
180  dev->GetMac (), params1,p0);
181  }
182 
183 }
184 
185 
186 void
188 {
189  // take the time of the end of the IFS
190  testcase->m_endIfs = Simulator::Now ();
191 }
192 
193 
194 void
196 {
197  // Test of Interframe Spaces (IFS)
198 
199  // The MAC layer needs a finite amount of time to process the data received from the PHY.
200  // To allow this, to successive transmitted frames must be separated for at least one IFS.
201  // The IFS size depends on the transmitted frame. This test verifies that the IFS is correctly
202  // implemented and its size correspond to the situations described by the standard.
203  // For more info see IEEE 802.15.4-2011 Section 5.1.1.3
204 
207  LogComponentEnable ("LrWpanPhy", LOG_LEVEL_DEBUG);
208  LogComponentEnable ("LrWpanMac", LOG_LEVEL_DEBUG);
209  LogComponentEnable ("LrWpanCsmaCa", LOG_LEVEL_DEBUG);
210 
211  // Create 2 nodes, and a NetDevice for each one
212  Ptr<Node> n0 = CreateObject <Node> ();
213  Ptr<Node> n1 = CreateObject <Node> ();
214 
215  Ptr<LrWpanNetDevice> dev0 = CreateObject<LrWpanNetDevice> ();
216  Ptr<LrWpanNetDevice> dev1 = CreateObject<LrWpanNetDevice> ();
217 
218  dev0->SetAddress (Mac16Address ("00:01"));
219  dev1->SetAddress (Mac16Address ("00:02"));
220 
221  // Each device must be attached to the same channel
222  Ptr<SingleModelSpectrumChannel> channel = CreateObject<SingleModelSpectrumChannel> ();
223  Ptr<LogDistancePropagationLossModel> propModel = CreateObject<LogDistancePropagationLossModel> ();
224  Ptr<ConstantSpeedPropagationDelayModel> delayModel = CreateObject<ConstantSpeedPropagationDelayModel> ();
225  channel->AddPropagationLossModel (propModel);
226  channel->SetPropagationDelayModel (delayModel);
227 
228  dev0->SetChannel (channel);
229  dev1->SetChannel (channel);
230 
231  // To complete configuration, a LrWpanNetDevice must be added to a node
232  n0->AddDevice (dev0);
233  n1->AddDevice (dev1);
234 
235  // Connect to trace files in the MAC layer
236  dev0->GetMac ()->TraceConnectWithoutContext ("IfsEnd", MakeBoundCallback (&LrWpanDataIfsTestCase::IfsEnd, this, dev0));
237  dev0->GetMac ()->TraceConnectWithoutContext ("MacRx", MakeBoundCallback (&LrWpanDataIfsTestCase::DataReceivedDev0, this, dev0));
238  dev0->GetPhy ()->TraceConnectWithoutContext ("PhyRxBegin", MakeBoundCallback (&LrWpanDataIfsTestCase::PhyDataRxStart, this, dev0));
239  dev1->GetMac ()->TraceConnectWithoutContext ("MacRx", MakeBoundCallback (&LrWpanDataIfsTestCase::DataReceivedDev1, this, dev1));
240 
241  Ptr<ConstantPositionMobilityModel> sender0Mobility = CreateObject<ConstantPositionMobilityModel> ();
242  sender0Mobility->SetPosition (Vector (0,0,0));
243  dev0->GetPhy ()->SetMobility (sender0Mobility);
244  Ptr<ConstantPositionMobilityModel> sender1Mobility = CreateObject<ConstantPositionMobilityModel> ();
245  // Configure position 10 m distance
246  sender1Mobility->SetPosition (Vector (0,10,0));
247  dev1->GetPhy ()->SetMobility (sender1Mobility);
248 
251  dev0->GetMac ()->SetMcpsDataConfirmCallback (cb0);
252 
255  dev1->GetMac ()->SetMcpsDataConfirmCallback (cb1);
256 
257  Ptr<Packet> p0 = Create<Packet> (2);
258  McpsDataRequestParams params;
259  params.m_dstPanId = 0;
260 
261  params.m_srcAddrMode = SHORT_ADDR;
262  params.m_dstAddrMode = SHORT_ADDR;
263  params.m_dstAddr = Mac16Address ("00:02");
264  params.m_msduHandle = 0;
265 
266  Time ifsSize;
267 
269 
270  Simulator::ScheduleWithContext (1, Seconds (0.0),
271  &LrWpanMac::McpsDataRequest,
272  dev0->GetMac (), params, p0);
273 
274 
275  Simulator::Run ();
276 
277  // MPDU = MAC header (11 bytes) + MSDU (2 bytes)+ MAC trailer (2 bytes) = 15)
278  // MPDU (15 bytes) < 18 bytes therefore IFS = SIFS
279  // SIFS = 12 symbols (192 Microseconds on a 2.4Ghz O-QPSK PHY)
280  ifsSize = m_endIfs - m_lastTxTime;
281  NS_TEST_EXPECT_MSG_EQ (ifsSize, Time (MicroSeconds (192)), "Wrong Short InterFrame Space (SIFS) Size after dataframe Tx");
282  std::cout << "----------------------------------\n";
283 
285 
286  p0 = Create<Packet> (6);
287 
288  Simulator::ScheduleWithContext (1, Seconds (0.0),
289  &LrWpanMac::McpsDataRequest,
290  dev0->GetMac (), params, p0);
291 
292 
293  Simulator::Run ();
294 
295  // MPDU = MAC header (11 bytes) + MSDU (6 bytes)+ MAC trailer (2 bytes) = 19)
296  // MPDU (19 bytes) > 18 bytes therefore IFS = LIFS
297  // LIFS = 40 symbols (640 Microseconds on a 2.4Ghz O-QPSK PHY)
298  ifsSize = m_endIfs - m_lastTxTime;
299  NS_TEST_EXPECT_MSG_EQ (ifsSize, Time (MicroSeconds (640)), "Wrong Long InterFrame Space (LIFS) Size after dataframe Tx");
300  std::cout << "----------------------------------\n";
301 
303 
304  params.m_txOptions = TX_OPTION_ACK;
305  p0 = Create<Packet> (2);
306 
307  Simulator::ScheduleWithContext (1, Seconds (0.0),
308  &LrWpanMac::McpsDataRequest,
309  dev0->GetMac (), params, p0);
310 
311  Simulator::Run ();
312 
313  // MPDU = MAC header (11 bytes) + MSDU (2 bytes)+ MAC trailer (2 bytes) = 15)
314  // MPDU (15 bytes) < 18 bytes therefore IFS = SIFS
315  // SIFS = 12 symbols (192 Microseconds on a 2.4Ghz O-QPSK PHY)
316  ifsSize = m_endIfs - m_ackRxTime;
317  NS_TEST_EXPECT_MSG_EQ (ifsSize, Time (MicroSeconds (192)), "Wrong Short InterFrame Space (SIFS) Size after ACK Rx");
318  std::cout << "----------------------------------\n";
319 
321 
322  params.m_txOptions = TX_OPTION_ACK;
323  p0 = Create<Packet> (6);
324 
325  Simulator::ScheduleWithContext (1, Seconds (0.0),
326  &LrWpanMac::McpsDataRequest,
327  dev0->GetMac (), params, p0);
328 
329 
330  Simulator::Run ();
331 
332  // MPDU = MAC header (11 bytes) + MSDU (6 bytes)+ MAC trailer (2 bytes) = 19)
333  // MPDU (19 bytes) > 18 bytes therefore IFS = LIFS
334  // LIFS = 40 symbols (640 Microseconds on a 2.4Ghz O-QPSK PHY)
335  ifsSize = m_endIfs - m_ackRxTime;
336  NS_TEST_EXPECT_MSG_EQ (ifsSize, Time (MicroSeconds (640)), "Wrong Long InterFrame Space (LIFS) Size after ACK Rx");
337  std::cout << "----------------------------------\n";
338 
340 
341  // A packet is broadcasted and the receiving device respond with another broadcast.
342  // The devices are configured to not have any backoff delays in their CSMA/CA.
343  // In most cases, a device receive a packet after its IFS, however in this test,
344  // the receiving device of the reply broadcast will still be in its IFS when the
345  // broadcast is received (i.e. a PHY StartRX () occur before the end of IFS).
346  // This demonstrates that a device can start receiving a frame even during an IFS.
347 
348  // Makes the backoff delay period = 0 in the CSMA/CA
349  dev0->GetCsmaCa ()->SetMacMinBE (0);
350  dev1->GetCsmaCa ()->SetMacMinBE (0);
351 
352  p0 = Create<Packet> (50); // 50 bytes of dummy data
353  params.m_dstPanId = 0;
354  params.m_srcAddrMode = SHORT_ADDR;
355  params.m_dstAddrMode = SHORT_ADDR;
356  params.m_dstAddr = Mac16Address ("ff:ff");
357  params.m_msduHandle = 0;
358 
359  Simulator::ScheduleWithContext (1, Seconds (0.0),
360  &LrWpanMac::McpsDataRequest,
361  dev0->GetMac (), params, p0);
362 
363  Simulator::Run ();
364 
365  NS_TEST_ASSERT_MSG_GT (m_endIfs, m_phyStartRx, "Error, IFS end time should be greater than PHY start Rx time");
366 
368 
369  Simulator::Destroy ();
370 
371 }
372 
373 
382 {
383 public:
385 };
386 
388  : TestSuite ("lr-wpan-ifs-test", UNIT)
389 {
390  AddTestCase (new LrWpanDataIfsTestCase, TestCase::QUICK);
391 }
392 
394 
395 
396 
397 
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:280
uint16_t m_dstPanId
Destination PAN identifier.
Definition: lr-wpan-mac.h:248
bool IsBroadcast(void) const
Checks if the address is a broadcast address according to 802.15.4 scheme (i.e., 0xFFFF).
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
Mac16Address GetShortDstAddr(void) const
Get the Destination Short address.
A suite of tests to run.
Definition: test.h:1343
Callback< R > MakeBoundCallback(R(*fnPtr)(TX), ARG a1)
Make Callbacks with one bound argument.
Definition: callback.h:1703
double GetSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:380
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#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
Represent the Mac Header with the Frame Control and Sequence Number fields.
encapsulates test code
Definition: test.h:1153
Time m_phyStartRx
The time the phy start receiving a packet.
channel
Definition: third.py:92
virtual void SetAddress(Address address)
This method indirects to LrWpanMac::SetShortAddress ()
static void DataReceivedDev0(LrWpanDataIfsTestCase *testcase, Ptr< LrWpanNetDevice > dev, Ptr< const Packet > p)
Function called when DataReceived is hit.
static void DataConfirm(LrWpanDataIfsTestCase *testcase, Ptr< LrWpanNetDevice > dev, McpsDataConfirmParams params)
Function called when DataConfirm is hit.
TX_OPTION_ACK.
Definition: lr-wpan-mac.h:59
void LogComponentEnable(char const *name, enum LogLevel level)
Enable the logging output associated with that log component.
Definition: log.cc:361
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
MCPS-DATA.confirm params.
Definition: lr-wpan-mac.h:260
bool IsAcknowledgment(void) const
Returns true if the header is an ack.
void LogComponentEnableAll(enum LogLevel level)
Enable the logging output for all registered log components.
Definition: log.cc:385
Prefix all trace prints with simulation time.
Definition: log.h:119
static LrWpanIfsTestSuite lrWpanIfsTestSuite
Static variable for test initialization.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
LrWpan Dataframe transmission with Interframe Space.
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:121
This class can contain 16 bit addresses.
Definition: mac16-address.h:41
void SetPosition(const Vector &position)
LOG_DEBUG and above.
Definition: log.h:104
uint32_t AddDevice(Ptr< NetDevice > device)
Associate a NetDevice to this node.
Definition: node.cc:130
Prefix all trace prints with function.
Definition: log.h:118
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1289
virtual void DoRun(void)
Implementation to actually run this TestCase.
Time m_ackRxTime
The time of the received acknowledgment.
static void PhyDataRxStart(LrWpanDataIfsTestCase *testcase, Ptr< LrWpanNetDevice > dev, Ptr< const Packet > p)
Function called when PhyDataRxStart is hit.
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1305
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:287
MCPS-DATA.request params.
Definition: lr-wpan-mac.h:236
static void DataReceivedDev1(LrWpanDataIfsTestCase *testcase, Ptr< LrWpanNetDevice > dev, Ptr< const Packet >)
Function called when DataConfirm is hit.
Ptr< LrWpanMac > GetMac(void) const
Get the MAC used by this NetDevice.
Time m_endIfs
The time where the Interframe Space ended.
#define NS_TEST_ASSERT_MSG_GT(actual, limit, msg)
Test that an actual value is greater than a limit and report and abort if not.
Definition: test.h:995
LrWpan IFS TestSuite.
static void DataConfirm(McpsDataConfirmParams params)
Function called when a Data confirm is invoked.
Definition: lr-wpan-data.cc:56
Time m_lastTxTime
The time of the last transmitted packet.
static void IfsEnd(LrWpanDataIfsTestCase *testcase, Ptr< LrWpanNetDevice > dev, Time IfsTime)
Function called when the IFS ends.