A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
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
35using namespace ns3;
36using namespace ns3::lrwpan;
37
38NS_LOG_COMPONENT_DEFINE("lr-wpan-ifs-test");
39
40/**
41 * \ingroup lr-wpan-test
42 * \ingroup tests
43 *
44 * \brief LrWpan Dataframe transmission with Interframe Space
45 */
47{
48 public:
50 ~LrWpanDataIfsTestCase() override;
51
52 private:
53 /**
54 * \brief Function called when DataConfirm is hit.
55 * \param testcase pointer to the testcase
56 * \param dev originating NetDevice
57 * \param params the MCPS params
58 */
59 static void DataConfirm(LrWpanDataIfsTestCase* testcase,
62
63 /**
64 * \brief Function called when DataReceived is hit.
65 * \param testcase pointer to the testcase
66 * \param dev originating NetDevice
67 * \param p packet
68 */
69 static void DataReceivedDev0(LrWpanDataIfsTestCase* testcase,
72
73 /**
74 * \brief Function called when PhyDataRxStart is hit.
75 * \param testcase pointer to the testcase
76 * \param dev originating NetDevice
77 * \param p packet
78 */
79 static void PhyDataRxStart(LrWpanDataIfsTestCase* testcase,
82
83 /**
84 * \brief Function called when DataConfirm is hit.
85 * \param testcase pointer to the testcase
86 * \param dev originating NetDevice
87 * \param p packet
88 */
89 static void DataReceivedDev1(LrWpanDataIfsTestCase* testcase,
92
93 /**
94 * \brief Function called when the IFS ends.
95 * \param testcase pointer to the testcase
96 * \param dev originating NetDevice
97 * \param IfsTime the IFS time
98 */
99 static void IfsEnd(LrWpanDataIfsTestCase* testcase, Ptr<LrWpanNetDevice> dev, Time IfsTime);
100
101 void DoRun() override;
102 Time m_lastTxTime; //!< The time of the last transmitted packet
103 Time m_ackRxTime; //!< The time of the received acknowledgment.
104 Time m_endIfs; //!< The time where the Interframe Space ended.
105 Time m_phyStartRx; //!< The time the phy start receiving a packet.
106};
107
109 : TestCase("Lrwpan: IFS tests")
110{
111}
112
114{
115}
116
117void
121{
122 // get the end time of transmission
123 testcase->m_lastTxTime = Simulator::Now();
124}
125
126void
130{
131 // Callback for Data received in the Dev0
132 Ptr<Packet> RxPacket = p->Copy();
133 LrWpanMacHeader receivedMacHdr;
134 RxPacket->RemoveHeader(receivedMacHdr);
135
136 if (receivedMacHdr.IsAcknowledgment())
137 {
138 testcase->m_ackRxTime = Simulator::Now();
139 std::cout << Simulator::Now().GetSeconds() << " | Dev0 (Node 0) received Acknowledgment.\n";
140 }
141 else if (receivedMacHdr.GetShortDstAddr().IsBroadcast())
142 {
143 std::cout << Simulator::Now().GetSeconds() << " | Dev0 (Node 0) received Broadcast. \n";
144 }
145}
146
147void
151{
152 // get the start time the phy in dev 0 ( Node 0) start receiving a frame
153 testcase->m_phyStartRx = Simulator::Now();
154}
155
156void
160{
161 // Callback for Data received in the Dev1
162 Ptr<Packet> RxPacket = p->Copy();
163 LrWpanMacHeader receivedMacHdr;
164 RxPacket->RemoveHeader(receivedMacHdr);
165
166 if (receivedMacHdr.GetShortDstAddr().IsBroadcast())
167 {
168 std::cout << Simulator::Now().GetSeconds() << " | Dev1 (Node 1) received Broadcast. \n";
169
170 // Bcst received, respond with another bcst
171
172 Ptr<Packet> p0 = Create<Packet>(50); // 50 bytes of dummy data
173 McpsDataRequestParams params1;
174 params1.m_dstPanId = 0;
175 params1.m_srcAddrMode = SHORT_ADDR;
176 params1.m_dstAddrMode = SHORT_ADDR;
177 params1.m_dstAddr = Mac16Address("ff:ff");
178 params1.m_msduHandle = 0;
179
180 Simulator::ScheduleNow(&LrWpanMac::McpsDataRequest, dev->GetMac(), params1, p0);
181 }
182}
183
184void
187 Time IfsTime)
188{
189 // take the time of the end of the IFS
190 testcase->m_endIfs = Simulator::Now();
191}
192
193void
195{
196 // Test of Interframe Spaces (IFS)
197
198 // The MAC layer needs a finite amount of time to process the data received from the PHY.
199 // To allow this, to successive transmitted frames must be separated for at least one IFS.
200 // The IFS size depends on the transmitted frame. This test verifies that the IFS is correctly
201 // implemented and its size correspond to the situations described by the standard.
202 // For more info see IEEE 802.15.4-2011 Section 5.1.1.3
203
208 LogComponentEnable("LrWpanCsmaCa", LOG_LEVEL_DEBUG);
209
210 // Create 2 nodes, and a NetDevice for each one
211 Ptr<Node> n0 = CreateObject<Node>();
212 Ptr<Node> n1 = CreateObject<Node>();
213
214 Ptr<LrWpanNetDevice> dev0 = CreateObject<LrWpanNetDevice>();
215 Ptr<LrWpanNetDevice> dev1 = CreateObject<LrWpanNetDevice>();
216
217 dev0->SetAddress(Mac16Address("00:01"));
218 dev1->SetAddress(Mac16Address("00:02"));
219
220 // Each device must be attached to the same channel
221 Ptr<SingleModelSpectrumChannel> channel = CreateObject<SingleModelSpectrumChannel>();
223 CreateObject<LogDistancePropagationLossModel>();
225 CreateObject<ConstantSpeedPropagationDelayModel>();
226 channel->AddPropagationLossModel(propModel);
227 channel->SetPropagationDelayModel(delayModel);
228
229 dev0->SetChannel(channel);
230 dev1->SetChannel(channel);
231
232 // To complete configuration, a LrWpanNetDevice must be added to a node
233 n0->AddDevice(dev0);
234 n1->AddDevice(dev1);
235
236 // Connect to trace files in the MAC layer
237 dev0->GetMac()->TraceConnectWithoutContext(
238 "IfsEnd",
240 dev0->GetMac()->TraceConnectWithoutContext(
241 "MacRx",
243 dev0->GetPhy()->TraceConnectWithoutContext(
244 "PhyRxBegin",
246 dev1->GetMac()->TraceConnectWithoutContext(
247 "MacRx",
249
250 Ptr<ConstantPositionMobilityModel> sender0Mobility =
251 CreateObject<ConstantPositionMobilityModel>();
252 sender0Mobility->SetPosition(Vector(0, 0, 0));
253 dev0->GetPhy()->SetMobility(sender0Mobility);
254 Ptr<ConstantPositionMobilityModel> sender1Mobility =
255 CreateObject<ConstantPositionMobilityModel>();
256 // Configure position 10 m distance
257 sender1Mobility->SetPosition(Vector(0, 10, 0));
258 dev1->GetPhy()->SetMobility(sender1Mobility);
259
262 dev0->GetMac()->SetMcpsDataConfirmCallback(cb0);
263
266 dev1->GetMac()->SetMcpsDataConfirmCallback(cb1);
267
268 Ptr<Packet> p0 = Create<Packet>(2);
270 params.m_dstPanId = 0;
271
272 params.m_srcAddrMode = SHORT_ADDR;
273 params.m_dstAddrMode = SHORT_ADDR;
274 params.m_dstAddr = Mac16Address("00:02");
275 params.m_msduHandle = 0;
276
277 Time ifsSize;
278
279 // NOTE: // For all the test , PAN SRC and DST are the same (PAN compression is ON) therefore
280 // MAC header is 2 bytes smaller than the usual 11 bytes (see IEEE 802.15.4 Section 7.5.6.1)
281
282 //////////////////////// SIFS ///////////////////////////
283
285 Seconds(0.0),
287 dev0->GetMac(),
288 params,
289 p0);
290
292
293 // MPDU = MAC header (9 bytes) + MSDU (2 bytes)+ MAC trailer (2 bytes) = 13)
294 // MPDU (13 bytes) < 18 bytes therefore IFS = SIFS
295 // SIFS = 12 symbols (192 Microseconds on a 2.4Ghz O-QPSK PHY)
296 ifsSize = m_endIfs - m_lastTxTime;
297 NS_TEST_EXPECT_MSG_EQ(ifsSize,
298 Time(MicroSeconds(192)),
299 "Wrong Short InterFrame Space (SIFS) Size after dataframe Tx");
300 std::cout << "----------------------------------\n";
301
302 //////////////////////// LIFS ///////////////////////////
303
304 p0 = Create<Packet>(8);
305
307 Seconds(0.0),
309 dev0->GetMac(),
310 params,
311 p0);
312
314
315 // MPDU = MAC header (9 bytes) + MSDU (8 bytes)+ MAC trailer (2 bytes) = 19)
316 // MPDU (19 bytes) > 18 bytes therefore IFS = LIFS
317 // LIFS = 40 symbols (640 Microseconds on a 2.4Ghz O-QPSK PHY)
318 ifsSize = m_endIfs - m_lastTxTime;
319 NS_TEST_EXPECT_MSG_EQ(ifsSize,
320 Time(MicroSeconds(640)),
321 "Wrong Long InterFrame Space (LIFS) Size after dataframe Tx");
322 std::cout << "----------------------------------\n";
323
324 //////////////////////// SIFS after ACK //////////////////
325
326 params.m_txOptions = TX_OPTION_ACK;
327 p0 = Create<Packet>(2);
328
330 Seconds(0.0),
332 dev0->GetMac(),
333 params,
334 p0);
335
337
338 // MPDU = MAC header (9 bytes) + MSDU (2 bytes)+ MAC trailer (2 bytes) = 13)
339 // MPDU (13 bytes) < 18 bytes therefore IFS = SIFS
340 // SIFS = 12 symbols (192 Microseconds on a 2.4Ghz O-QPSK PHY)
341 ifsSize = m_endIfs - m_ackRxTime;
342 NS_TEST_EXPECT_MSG_EQ(ifsSize,
343 Time(MicroSeconds(192)),
344 "Wrong Short InterFrame Space (SIFS) Size after ACK Rx");
345 std::cout << "----------------------------------\n";
346
347 //////////////////////// LIFS after ACK //////////////////
348
349 params.m_txOptions = TX_OPTION_ACK;
350 p0 = Create<Packet>(8);
351
353 Seconds(0.0),
355 dev0->GetMac(),
356 params,
357 p0);
358
360
361 // MPDU = MAC header (9 bytes) + MSDU (8 bytes)+ MAC trailer (2 bytes) = 19)
362 // MPDU (19 bytes) > 18 bytes therefore IFS = LIFS
363 // LIFS = 40 symbols (640 Microseconds on a 2.4Ghz O-QPSK PHY)
364 ifsSize = m_endIfs - m_ackRxTime;
365 NS_TEST_EXPECT_MSG_EQ(ifsSize,
366 Time(MicroSeconds(640)),
367 "Wrong Long InterFrame Space (LIFS) Size after ACK Rx");
368 std::cout << "----------------------------------\n";
369
370 /////////////////////// BCST frame with immediate BCST response //////////////////
371
372 // A packet is broadcasted and the receiving device respond with another broadcast.
373 // The devices are configured to not have any backoff delays in their CSMA/CA.
374 // In most cases, a device receive a packet after its IFS, however in this test,
375 // the receiving device of the reply broadcast will still be in its IFS when the
376 // broadcast is received (i.e. a PHY StartRX () occur before the end of IFS).
377 // This demonstrates that a device can start receiving a frame even during an IFS.
378
379 // Makes the backoff delay period = 0 in the CSMA/CA
380 dev0->GetCsmaCa()->SetMacMinBE(0);
381 dev1->GetCsmaCa()->SetMacMinBE(0);
382
383 p0 = Create<Packet>(50); // 50 bytes of dummy data
384 params.m_dstPanId = 0;
385 params.m_srcAddrMode = SHORT_ADDR;
386 params.m_dstAddrMode = SHORT_ADDR;
387 params.m_dstAddr = Mac16Address("ff:ff");
388 params.m_msduHandle = 0;
389
391 Seconds(0.0),
393 dev0->GetMac(),
394 params,
395 p0);
396
398
401 "Error, IFS end time should be greater than PHY start Rx time");
402
403 //////////////////////////////////////////////////////////////////////////////////
404
406}
407
408/**
409 * \ingroup lr-wpan-test
410 * \ingroup tests
411 *
412 * \brief LrWpan IFS TestSuite
413 */
414
416{
417 public:
419};
420
422 : TestSuite("lr-wpan-ifs-test", Type::UNIT)
423{
424 AddTestCase(new LrWpanDataIfsTestCase, TestCase::Duration::QUICK);
425}
426
427static LrWpanIfsTestSuite lrWpanIfsTestSuite; //!< Static variable for test initialization
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.
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).
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition: simulator.cc:142
static void ScheduleWithContext(uint32_t context, const Time &delay, FUNC f, Ts &&... args)
Schedule an event with the given context.
Definition: simulator.h:588
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:208
static void Run()
Run the simulation.
Definition: simulator.cc:178
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
Definition: simulator.h:605
encapsulates test code
Definition: test.h:1061
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:301
A suite of tests to run.
Definition: test.h:1268
Type
Type of test.
Definition: test.h:1275
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
Represent the Mac Header with the Frame Control and Sequence Number fields.
Mac16Address GetShortDstAddr() const
Get the Destination Short address.
bool IsAcknowledgment() const
Returns true if the header is an ack.
void McpsDataRequest(McpsDataRequestParams params, Ptr< Packet > p) override
IEEE 802.15.4-2006, section 7.1.1.1 MCPS-DATA.request Request to transfer a MSDU.
Definition: lr-wpan-mac.cc:386
#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:64
auto MakeBoundCallback(R(*fnPtr)(Args...), BArgs &&... bargs)
Make Callbacks with varying number of bound arguments.
Definition: callback.h:767
#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:252
#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:875
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1343
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1319
static LrWpanIfsTestSuite lrWpanIfsTestSuite
Static variable for test initialization.
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
AddressMode m_dstAddrMode
Destination address mode.
Mac16Address m_dstAddr
Destination address.
uint16_t m_dstPanId
Destination PAN identifier.
AddressMode m_srcAddrMode
Source address mode.