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 
LrWpan Dataframe transmission with Interframe Space.
static void IfsEnd(LrWpanDataIfsTestCase *testcase, Ptr< LrWpanNetDevice > dev, Time IfsTime)
Function called when the IFS ends.
Time m_endIfs
The time where the Interframe Space ended.
static void DataReceivedDev1(LrWpanDataIfsTestCase *testcase, Ptr< LrWpanNetDevice > dev, Ptr< const Packet >)
Function called when DataConfirm is hit.
Time m_phyStartRx
The time the phy start receiving a packet.
Time m_lastTxTime
The time of the last transmitted packet.
static void DataReceivedDev0(LrWpanDataIfsTestCase *testcase, Ptr< LrWpanNetDevice > dev, Ptr< const Packet > p)
Function called when DataReceived is hit.
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.
static void DataConfirm(LrWpanDataIfsTestCase *testcase, Ptr< LrWpanNetDevice > dev, McpsDataConfirmParams params)
Function called when DataConfirm is hit.
LrWpan IFS TestSuite.
Represent the Mac Header with the Frame Control and Sequence Number fields.
Mac16Address GetShortDstAddr(void) const
Get the Destination Short address.
bool IsAcknowledgment(void) const
Returns true if the header is an ack.
virtual void SetAddress(Address address)
This method indirects to LrWpanMac::SetShortAddress ()
void SetChannel(Ptr< SpectrumChannel > channel)
Set the channel to which the NetDevice, and therefore the PHY, should be attached to.
Ptr< LrWpanPhy > GetPhy(void) const
Get the PHY used by this NetDevice.
Ptr< LrWpanMac > GetMac(void) const
Get the MAC used by this NetDevice.
Ptr< LrWpanCsmaCa > GetCsmaCa(void) const
Get the CSMA/CA implementation used by this NetDevice.
This class can contain 16 bit addresses.
Definition: mac16-address.h:42
bool IsBroadcast(void) const
Checks if the address is a broadcast address according to 802.15.4 scheme (i.e., 0xFFFF).
uint32_t AddDevice(Ptr< NetDevice > device)
Associate a NetDevice to this node.
Definition: node.cc:130
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:280
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:121
encapsulates test code
Definition: test.h:994
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
A suite of tests to run.
Definition: test.h:1188
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
double GetSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:379
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
@ TX_OPTION_ACK
TX_OPTION_ACK.
Definition: lr-wpan-mac.h:59
@ SHORT_ADDR
Definition: lr-wpan-mac.h:141
Callback< R > MakeBoundCallback(R(*fnPtr)(TX), ARG a1)
Make Callbacks with one bound argument.
Definition: callback.h:1709
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:287
#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:240
#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:825
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1260
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1244
static void DataConfirm(McpsDataConfirmParams params)
Function called when a Data confirm is invoked.
Definition: lr-wpan-data.cc:56
static LrWpanIfsTestSuite lrWpanIfsTestSuite
Static variable for test initialization.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
@ LOG_PREFIX_FUNC
Prefix all trace prints with function.
Definition: log.h:118
@ LOG_PREFIX_TIME
Prefix all trace prints with simulation time.
Definition: log.h:119
@ LOG_LEVEL_DEBUG
LOG_DEBUG and above.
Definition: log.h:104
void LogComponentEnable(char const *name, enum LogLevel level)
Enable the logging output associated with that log component.
Definition: log.cc:361
void LogComponentEnableAll(enum LogLevel level)
Enable the logging output for all registered log components.
Definition: log.cc:385
channel
Definition: third.py:92
MCPS-DATA.confirm params.
Definition: lr-wpan-mac.h:261
MCPS-DATA.request params.
Definition: lr-wpan-mac.h:237
LrWpanAddressMode m_srcAddrMode
Source address mode.
Definition: lr-wpan-mac.h:246
LrWpanAddressMode m_dstAddrMode
Destination address mode.
Definition: lr-wpan-mac.h:247
uint16_t m_dstPanId
Destination PAN identifier.
Definition: lr-wpan-mac.h:248
Mac16Address m_dstAddr
Destination address.
Definition: lr-wpan-mac.h:249
uint8_t m_msduHandle
MSDU handle.
Definition: lr-wpan-mac.h:251
uint8_t m_txOptions
Tx Options (bitfield)
Definition: lr-wpan-mac.h:252