A Discrete-Event Network Simulator
API
lr-wpan-ifs-test.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2019 Ritsumeikan University, Shiga, Japan
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Author:
18  * Alberto Gallegos Ramonet <ramonet@fc.ritsumei.ac.jp>
19  */
20 
21 #include "ns3/rng-seed-manager.h"
22 #include <ns3/constant-position-mobility-model.h>
23 #include <ns3/core-module.h>
24 #include <ns3/log.h>
25 #include <ns3/lr-wpan-module.h>
26 #include <ns3/packet.h>
27 #include <ns3/propagation-delay-model.h>
28 #include <ns3/propagation-loss-model.h>
29 #include <ns3/simulator.h>
30 #include <ns3/single-model-spectrum-channel.h>
31 
32 #include <iomanip>
33 #include <iostream>
34 
35 using namespace ns3;
36 
37 NS_LOG_COMPONENT_DEFINE("lr-wpan-ifs-test");
38 
46 {
47  public:
49  ~LrWpanDataIfsTestCase() override;
50 
51  private:
58  static void DataConfirm(LrWpanDataIfsTestCase* testcase,
61 
68  static void DataReceivedDev0(LrWpanDataIfsTestCase* testcase,
71 
78  static void PhyDataRxStart(LrWpanDataIfsTestCase* testcase,
81 
88  static void DataReceivedDev1(LrWpanDataIfsTestCase* testcase,
91 
98  static void IfsEnd(LrWpanDataIfsTestCase* testcase, Ptr<LrWpanNetDevice> dev, Time IfsTime);
99 
100  void DoRun() override;
105 };
106 
108  : TestCase("Lrwpan: IFS tests")
109 {
110 }
111 
113 {
114 }
115 
116 void
120 {
121  // get the end time of transmission
122  testcase->m_lastTxTime = Simulator::Now();
123 }
124 
125 void
129 {
130  // Callback for Data received in the Dev0
131  Ptr<Packet> RxPacket = p->Copy();
132  LrWpanMacHeader receivedMacHdr;
133  RxPacket->RemoveHeader(receivedMacHdr);
134 
135  if (receivedMacHdr.IsAcknowledgment())
136  {
137  testcase->m_ackRxTime = Simulator::Now();
138  std::cout << Simulator::Now().GetSeconds() << " | Dev0 (Node 0) received Acknowledgment.\n";
139  }
140  else if (receivedMacHdr.GetShortDstAddr().IsBroadcast())
141  {
142  std::cout << Simulator::Now().GetSeconds() << " | Dev0 (Node 0) received Broadcast. \n";
143  }
144 }
145 
146 void
150 {
151  // get the start time the phy in dev 0 ( Node 0) start receiving a frame
152  testcase->m_phyStartRx = Simulator::Now();
153 }
154 
155 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, dev->GetMac(), params1, p0);
180  }
181 }
182 
183 void
186  Time IfsTime)
187 {
188  // take the time of the end of the IFS
189  testcase->m_endIfs = Simulator::Now();
190 }
191 
192 void
194 {
195  // Test of Interframe Spaces (IFS)
196 
197  // The MAC layer needs a finite amount of time to process the data received from the PHY.
198  // To allow this, to successive transmitted frames must be separated for at least one IFS.
199  // The IFS size depends on the transmitted frame. This test verifies that the IFS is correctly
200  // implemented and its size correspond to the situations described by the standard.
201  // For more info see IEEE 802.15.4-2011 Section 5.1.1.3
202 
205  LogComponentEnable("LrWpanPhy", LOG_LEVEL_DEBUG);
206  LogComponentEnable("LrWpanMac", LOG_LEVEL_DEBUG);
207  LogComponentEnable("LrWpanCsmaCa", LOG_LEVEL_DEBUG);
208 
209  // Create 2 nodes, and a NetDevice for each one
210  Ptr<Node> n0 = CreateObject<Node>();
211  Ptr<Node> n1 = CreateObject<Node>();
212 
213  Ptr<LrWpanNetDevice> dev0 = CreateObject<LrWpanNetDevice>();
214  Ptr<LrWpanNetDevice> dev1 = CreateObject<LrWpanNetDevice>();
215 
216  dev0->SetAddress(Mac16Address("00:01"));
217  dev1->SetAddress(Mac16Address("00:02"));
218 
219  // Each device must be attached to the same channel
220  Ptr<SingleModelSpectrumChannel> channel = CreateObject<SingleModelSpectrumChannel>();
222  CreateObject<LogDistancePropagationLossModel>();
224  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(
237  "IfsEnd",
239  dev0->GetMac()->TraceConnectWithoutContext(
240  "MacRx",
242  dev0->GetPhy()->TraceConnectWithoutContext(
243  "PhyRxBegin",
245  dev1->GetMac()->TraceConnectWithoutContext(
246  "MacRx",
248 
249  Ptr<ConstantPositionMobilityModel> sender0Mobility =
250  CreateObject<ConstantPositionMobilityModel>();
251  sender0Mobility->SetPosition(Vector(0, 0, 0));
252  dev0->GetPhy()->SetMobility(sender0Mobility);
253  Ptr<ConstantPositionMobilityModel> sender1Mobility =
254  CreateObject<ConstantPositionMobilityModel>();
255  // Configure position 10 m distance
256  sender1Mobility->SetPosition(Vector(0, 10, 0));
257  dev1->GetPhy()->SetMobility(sender1Mobility);
258 
261  dev0->GetMac()->SetMcpsDataConfirmCallback(cb0);
262 
265  dev1->GetMac()->SetMcpsDataConfirmCallback(cb1);
266 
267  Ptr<Packet> p0 = Create<Packet>(2);
269  params.m_dstPanId = 0;
270 
271  params.m_srcAddrMode = SHORT_ADDR;
272  params.m_dstAddrMode = SHORT_ADDR;
273  params.m_dstAddr = Mac16Address("00:02");
274  params.m_msduHandle = 0;
275 
276  Time ifsSize;
277 
278  // NOTE: // For all the test , PAN SRC and DST are the same (PAN compression is ON) therefore
279  // MAC header is 2 bytes smaller than the usual 11 bytes (see IEEE 802.15.4 Section 7.5.6.1)
280 
282 
283  Simulator::ScheduleWithContext(1,
284  Seconds(0.0),
285  &LrWpanMac::McpsDataRequest,
286  dev0->GetMac(),
287  params,
288  p0);
289 
290  Simulator::Run();
291 
292  // MPDU = MAC header (9 bytes) + MSDU (2 bytes)+ MAC trailer (2 bytes) = 13)
293  // MPDU (13 bytes) < 18 bytes therefore IFS = SIFS
294  // SIFS = 12 symbols (192 Microseconds on a 2.4Ghz O-QPSK PHY)
295  ifsSize = m_endIfs - m_lastTxTime;
296  NS_TEST_EXPECT_MSG_EQ(ifsSize,
297  Time(MicroSeconds(192)),
298  "Wrong Short InterFrame Space (SIFS) Size after dataframe Tx");
299  std::cout << "----------------------------------\n";
300 
302 
303  p0 = Create<Packet>(8);
304 
305  Simulator::ScheduleWithContext(1,
306  Seconds(0.0),
307  &LrWpanMac::McpsDataRequest,
308  dev0->GetMac(),
309  params,
310  p0);
311 
312  Simulator::Run();
313 
314  // MPDU = MAC header (9 bytes) + MSDU (8 bytes)+ MAC trailer (2 bytes) = 19)
315  // MPDU (19 bytes) > 18 bytes therefore IFS = LIFS
316  // LIFS = 40 symbols (640 Microseconds on a 2.4Ghz O-QPSK PHY)
317  ifsSize = m_endIfs - m_lastTxTime;
318  NS_TEST_EXPECT_MSG_EQ(ifsSize,
319  Time(MicroSeconds(640)),
320  "Wrong Long InterFrame Space (LIFS) Size after dataframe Tx");
321  std::cout << "----------------------------------\n";
322 
324 
325  params.m_txOptions = TX_OPTION_ACK;
326  p0 = Create<Packet>(2);
327 
328  Simulator::ScheduleWithContext(1,
329  Seconds(0.0),
330  &LrWpanMac::McpsDataRequest,
331  dev0->GetMac(),
332  params,
333  p0);
334 
335  Simulator::Run();
336 
337  // MPDU = MAC header (9 bytes) + MSDU (2 bytes)+ MAC trailer (2 bytes) = 13)
338  // MPDU (13 bytes) < 18 bytes therefore IFS = SIFS
339  // SIFS = 12 symbols (192 Microseconds on a 2.4Ghz O-QPSK PHY)
340  ifsSize = m_endIfs - m_ackRxTime;
341  NS_TEST_EXPECT_MSG_EQ(ifsSize,
342  Time(MicroSeconds(192)),
343  "Wrong Short InterFrame Space (SIFS) Size after ACK Rx");
344  std::cout << "----------------------------------\n";
345 
347 
348  params.m_txOptions = TX_OPTION_ACK;
349  p0 = Create<Packet>(8);
350 
351  Simulator::ScheduleWithContext(1,
352  Seconds(0.0),
353  &LrWpanMac::McpsDataRequest,
354  dev0->GetMac(),
355  params,
356  p0);
357 
358  Simulator::Run();
359 
360  // MPDU = MAC header (9 bytes) + MSDU (8 bytes)+ MAC trailer (2 bytes) = 19)
361  // MPDU (19 bytes) > 18 bytes therefore IFS = LIFS
362  // LIFS = 40 symbols (640 Microseconds on a 2.4Ghz O-QPSK PHY)
363  ifsSize = m_endIfs - m_ackRxTime;
364  NS_TEST_EXPECT_MSG_EQ(ifsSize,
365  Time(MicroSeconds(640)),
366  "Wrong Long InterFrame Space (LIFS) Size after ACK Rx");
367  std::cout << "----------------------------------\n";
368 
370 
371  // A packet is broadcasted and the receiving device respond with another broadcast.
372  // The devices are configured to not have any backoff delays in their CSMA/CA.
373  // In most cases, a device receive a packet after its IFS, however in this test,
374  // the receiving device of the reply broadcast will still be in its IFS when the
375  // broadcast is received (i.e. a PHY StartRX () occur before the end of IFS).
376  // This demonstrates that a device can start receiving a frame even during an IFS.
377 
378  // Makes the backoff delay period = 0 in the CSMA/CA
379  dev0->GetCsmaCa()->SetMacMinBE(0);
380  dev1->GetCsmaCa()->SetMacMinBE(0);
381 
382  p0 = Create<Packet>(50); // 50 bytes of dummy data
383  params.m_dstPanId = 0;
384  params.m_srcAddrMode = SHORT_ADDR;
385  params.m_dstAddrMode = SHORT_ADDR;
386  params.m_dstAddr = Mac16Address("ff:ff");
387  params.m_msduHandle = 0;
388 
389  Simulator::ScheduleWithContext(1,
390  Seconds(0.0),
391  &LrWpanMac::McpsDataRequest,
392  dev0->GetMac(),
393  params,
394  p0);
395 
396  Simulator::Run();
397 
399  m_phyStartRx,
400  "Error, IFS end time should be greater than PHY start Rx time");
401 
403 
404  Simulator::Destroy();
405 }
406 
415 {
416  public:
418 };
419 
421  : TestSuite("lr-wpan-ifs-test", UNIT)
422 {
423  AddTestCase(new LrWpanDataIfsTestCase, TestCase::QUICK);
424 }
425 
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.
void DoRun() override
Implementation to actually run this TestCase.
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.
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.
bool IsAcknowledgment() const
Returns true if the header is an ack.
Mac16Address GetShortDstAddr() const
Get the Destination Short address.
void SetChannel(Ptr< SpectrumChannel > channel)
Set the channel to which the NetDevice, and therefore the PHY, should be attached to.
Ptr< LrWpanMac > GetMac() const
Get the MAC used by this NetDevice.
Ptr< LrWpanPhy > GetPhy() const
Get the PHY used by this NetDevice.
void SetAddress(Address address) override
This method indirects to LrWpanMac::SetShortAddress ()
Ptr< LrWpanCsmaCa > GetCsmaCa() const
Get the CSMA/CA implementation used by this NetDevice.
This class can contain 16 bit addresses.
Definition: mac16-address.h:44
bool IsBroadcast() 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:138
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:294
Ptr< Packet > Copy() const
performs a COW copy of the packet.
Definition: packet.cc:131
encapsulates test code
Definition: test.h:1060
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:301
A suite of tests to run.
Definition: test.h:1256
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:403
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
@ TX_OPTION_ACK
TX_OPTION_ACK.
Definition: lr-wpan-mac.h:61
@ SHORT_ADDR
auto MakeBoundCallback(R(*fnPtr)(Args...), BArgs &&... bargs)
Make Callbacks with varying number of bound arguments.
Definition: callback.h:765
Time Now()
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:305
#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:251
#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:874
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1350
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1326
static void DataConfirm(McpsDataConfirmParams params)
Function called when a Data confirm is invoked.
Definition: lr-wpan-data.cc:57
static LrWpanIfsTestSuite lrWpanIfsTestSuite
Static variable for test initialization.
void(* Time)(Time oldValue, Time newValue)
TracedValue callback signature for Time.
Definition: nstime.h:839
Every class exported by the ns3 library is enclosed in the ns3 namespace.
void LogComponentEnable(const std::string &name, LogLevel level)
Enable the logging output associated with that log component.
Definition: log.cc:302
@ 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:113
void LogComponentEnableAll(LogLevel level)
Enable the logging output for all registered log components.
Definition: log.cc:320
channel
Definition: third.py:88
params
Fit Fluctuating Two Ray model to the 3GPP TR 38.901 using the Anderson-Darling goodness-of-fit ##.
MCPS-DATA.confirm params.
MCPS-DATA.request params.
LrWpanAddressMode m_srcAddrMode
Source address mode.
LrWpanAddressMode m_dstAddrMode
Destination address mode.
uint16_t m_dstPanId
Destination PAN identifier.
Mac16Address m_dstAddr
Destination address.
uint8_t m_msduHandle
MSDU handle.