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
36using namespace ns3;
37
38NS_LOG_COMPONENT_DEFINE ("lr-wpan-ifs-test");
39
40
48{
49public:
51 virtual ~LrWpanDataIfsTestCase ();
52
53private:
60 static void DataConfirm (LrWpanDataIfsTestCase *testcase,
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
123void
125{
126 // get the end time of transmission
127 testcase->m_lastTxTime = Simulator::Now ();
128}
129
130void
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
150void
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
157void
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
186void
188{
189 // take the time of the end of the IFS
190 testcase->m_endIfs = Simulator::Now ();
191}
192
193
194void
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);
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
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
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
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
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
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{
383public:
385};
386
388 : TestSuite ("lr-wpan-ifs-test", UNIT)
389{
390 AddTestCase (new LrWpanDataIfsTestCase, TestCase::QUICK);
391}
392
394
395
396
397
void Run(ObjectFactory &factory, uint32_t pop, uint32_t total, uint32_t runs, Ptr< RandomVariableStream > eventStream, bool calRev)
Perform the runs for a single scheduler type.
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:104
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
@ TX_OPTION_ACK
TX_OPTION_ACK.
Definition: lr-wpan-mac.h:61
@ SHORT_ADDR
Definition: lr-wpan-mac.h:156
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:1261
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1245
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:83
MCPS-DATA.confirm params.
Definition: lr-wpan-mac.h:353
MCPS-DATA.request params.
Definition: lr-wpan-mac.h:337
LrWpanAddressMode m_srcAddrMode
Source address mode.
Definition: lr-wpan-mac.h:338
LrWpanAddressMode m_dstAddrMode
Destination address mode.
Definition: lr-wpan-mac.h:339
uint16_t m_dstPanId
Destination PAN identifier.
Definition: lr-wpan-mac.h:340
Mac16Address m_dstAddr
Destination address.
Definition: lr-wpan-mac.h:341
uint8_t m_msduHandle
MSDU handle.
Definition: lr-wpan-mac.h:343
uint8_t m_txOptions
Tx Options (bitfield)
Definition: lr-wpan-mac.h:344