A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
lr-wpan-csmaca.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2011 The Boeing Company
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 * kwong yin <kwong-sang.yin@boeing.com>
19 * Sascha Alexander Jopen <jopen@cs.uni-bonn.de>
20 * Alberto Gallegos Ramonet <ramonet@fc.ritsumei.ac.jp>
21 */
22
23#include "lr-wpan-csmaca.h"
24
25#include "lr-wpan-constants.h"
26
27#include <ns3/log.h>
28#include <ns3/random-variable-stream.h>
29#include <ns3/simulator.h>
30
31#include <algorithm>
32
33#undef NS_LOG_APPEND_CONTEXT
34#define NS_LOG_APPEND_CONTEXT \
35 std::clog << "[address " << m_mac->GetShortAddress() << " | " << m_mac->GetExtendedAddress() \
36 << "] ";
37
38namespace ns3
39{
40namespace lrwpan
41{
42
43NS_LOG_COMPONENT_DEFINE("LrWpanCsmaCa");
45
46TypeId
48{
49 static TypeId tid = TypeId("ns3::LrWpanCsmaCa")
51 .SetGroupName("LrWpan")
52 .AddConstructor<LrWpanCsmaCa>();
53 return tid;
54}
55
57{
58 // TODO-- make these into ns-3 attributes
59
60 m_isSlotted = false;
61 m_NB = 0;
62 m_CW = 2;
63 m_macBattLifeExt = false;
64 m_macMinBE = 3;
65 m_macMaxBE = 5;
67 m_random = CreateObject<UniformRandomVariable>();
69 m_ccaRequestRunning = false;
71 m_coorDest = false;
72}
73
75{
76 m_mac = nullptr;
77}
78
79void
81{
82 m_lrWpanMacStateCallback = MakeNullCallback<void, MacState>();
83 m_lrWpanMacTransCostCallback = MakeNullCallback<void, uint32_t>();
84
85 Cancel();
86 m_mac = nullptr;
87}
88
89void
91{
92 m_mac = mac;
93}
94
97{
98 return m_mac;
99}
100
101void
103{
104 NS_LOG_FUNCTION(this);
105 m_isSlotted = true;
106}
107
108void
110{
111 NS_LOG_FUNCTION(this);
112 m_isSlotted = false;
113}
114
115bool
117{
118 NS_LOG_FUNCTION(this);
119 return m_isSlotted;
120}
121
122bool
124{
125 NS_LOG_FUNCTION(this);
126 return !m_isSlotted;
127}
128
129void
131{
132 NS_LOG_FUNCTION(this << macMinBE);
134 "MacMinBE (" << macMinBE << ") should be <= MacMaxBE (" << m_macMaxBE << ")");
136}
137
138uint8_t
140{
141 NS_LOG_FUNCTION(this);
142 return m_macMinBE;
143}
144
145void
147{
148 NS_LOG_FUNCTION(this << macMaxBE);
149 NS_ASSERT_MSG(macMaxBE >= 3 && macMaxBE <= 8,
150 "MacMaxBE (" << macMaxBE << ") should be >= 3 and <= 8");
151 m_macMaxBE = macMaxBE;
152}
153
154uint8_t
156{
157 NS_LOG_FUNCTION(this);
158 return m_macMaxBE;
159}
160
161void
162LrWpanCsmaCa::SetMacMaxCSMABackoffs(uint8_t macMaxCSMABackoffs)
163{
164 NS_LOG_FUNCTION(this << macMaxCSMABackoffs);
165 NS_ASSERT_MSG(macMaxCSMABackoffs <= 5, "MacMaxCSMABackoffs should be <= 5");
166 m_macMaxCSMABackoffs = macMaxCSMABackoffs;
167}
168
169uint8_t
171{
172 NS_LOG_FUNCTION(this);
174}
175
176Time
178{
179 NS_LOG_FUNCTION(this);
180
181 // The reference for the beginning of the SUPERFRAME (the active period) changes depending
182 // on the data packet being sent from the Coordinator/outgoing frame (Tx beacon time reference)
183 // or other device/incoming frame (Rx beacon time reference ).
184
185 Time elapsedSuperframe; // (i.e The beacon + the elapsed CAP)
186 Time currentTime = Simulator::Now();
187 double symbolsToBoundary;
188 Time nextBoundary;
189 uint64_t elapsedSuperframeSymbols;
190 uint64_t symbolRate =
191 (uint64_t)m_mac->GetPhy()->GetDataOrSymbolRate(false); // symbols per second
192 Time timeAtBoundary;
193
194 if (m_coorDest)
195 {
196 // Take the Incoming Frame Reference
197 elapsedSuperframe = currentTime - m_mac->m_macBeaconRxTime;
198
199 Time beaconTime [[maybe_unused]] = Seconds((double)m_mac->m_rxBeaconSymbols / symbolRate);
200 Time elapsedCap [[maybe_unused]] = elapsedSuperframe - beaconTime;
201 NS_LOG_DEBUG("Elapsed incoming CAP symbols: " << (elapsedCap.GetSeconds() * symbolRate)
202 << " (" << elapsedCap.As(Time::S) << ")");
203 }
204 else
205 {
206 // Take the Outgoing Frame Reference
207 elapsedSuperframe = currentTime - m_mac->m_macBeaconTxTime;
208 }
209
210 // get a close value to the the boundary in symbols
211 elapsedSuperframeSymbols = elapsedSuperframe.GetSeconds() * symbolRate;
212 symbolsToBoundary = lrwpan::aUnitBackoffPeriod -
213 std::fmod((double)elapsedSuperframeSymbols, lrwpan::aUnitBackoffPeriod);
214
215 timeAtBoundary = Seconds((double)(elapsedSuperframeSymbols + symbolsToBoundary) / symbolRate);
216
217 // get the exact time boundary
218 nextBoundary = timeAtBoundary - elapsedSuperframe;
219
220 NS_LOG_DEBUG("Elapsed Superframe symbols: " << elapsedSuperframeSymbols << " ("
221 << elapsedSuperframe.As(Time::S) << ")");
222
223 NS_LOG_DEBUG("Next backoff period boundary in approx. "
224 << nextBoundary.GetSeconds() * symbolRate << " symbols ("
225 << nextBoundary.As(Time::S) << ")");
226
227 return nextBoundary;
228}
229
230void
232{
233 NS_LOG_FUNCTION(this);
234 m_NB = 0;
235 if (IsSlottedCsmaCa())
236 {
237 // TODO: Check if the current PHY is using the Japanese band 950 Mhz:
238 // (IEEE_802_15_4_950MHZ_BPSK and IEEE_802_15_4_950MHZ_2GFSK)
239 // if in use, m_CW = 1.
240 // Currently 950 Mhz band PHYs are not supported in ns-3.
241 // To know the current used PHY, making the method for GetPhy()->GetMyPhyOption()
242 // public is necessary. Alternatively, the current PHY used
243 // can be known using phyCurrentPage variable.
244
245 m_CW = 2;
246
248 {
249 m_BE = std::min(static_cast<uint8_t>(2), m_macMinBE);
250 }
251 else
252 {
254 }
255
256 // m_coorDest to decide between incoming and outgoing superframes times
257 m_coorDest = m_mac->IsCoordDest();
258
259 // Locate backoff period boundary. (i.e. a time delay to align with the next backoff period
260 // boundary)
261 Time backoffBoundary = GetTimeToNextSlot();
264 }
265 else
266 {
269 }
270}
271
272void
274{
278 m_mac->GetPhy()->CcaCancel();
279}
280
281void
283{
284 NS_LOG_FUNCTION(this);
285
286 uint64_t upperBound = (uint64_t)pow(2, m_BE) - 1;
287 Time randomBackoff;
288 uint64_t symbolRate;
289 Time timeLeftInCap;
290
291 symbolRate = (uint64_t)m_mac->GetPhy()->GetDataOrSymbolRate(false); // symbols per second
292
293 // We should not recalculate the random backoffPeriods if we are in a slotted CSMA-CA and the
294 // transmission was previously deferred (m_randomBackoffPeriods != 0)
296 {
297 m_randomBackoffPeriodsLeft = (uint64_t)m_random->GetValue(0, upperBound + 1);
298 }
299
300 randomBackoff =
302
303 if (IsUnSlottedCsmaCa())
304 {
305 NS_LOG_DEBUG("Unslotted CSMA-CA: requesting CCA after backoff of "
306 << m_randomBackoffPeriodsLeft << " periods (" << randomBackoff.As(Time::S)
307 << ")");
309 }
310 else
311 {
312 // We must make sure there is enough time left in the CAP, otherwise we continue in
313 // the CAP of the next superframe after the transmission/reception of the beacon (and the
314 // IFS)
315 timeLeftInCap = GetTimeLeftInCap();
316
317 NS_LOG_DEBUG("Slotted CSMA-CA: proceeding after random backoff of "
318 << m_randomBackoffPeriodsLeft << " periods ("
319 << (randomBackoff.GetSeconds() * symbolRate) << " symbols or "
320 << randomBackoff.As(Time::S) << ")");
321
322 NS_LOG_DEBUG("Backoff periods left in CAP: "
323 << ((timeLeftInCap.GetSeconds() * symbolRate) / lrwpan::aUnitBackoffPeriod)
324 << " (" << (timeLeftInCap.GetSeconds() * symbolRate) << " symbols or "
325 << timeLeftInCap.As(Time::S) << ")");
326
327 if (randomBackoff >= timeLeftInCap)
328 {
329 uint64_t usedBackoffs =
330 (double)(timeLeftInCap.GetSeconds() * symbolRate) / lrwpan::aUnitBackoffPeriod;
331 m_randomBackoffPeriodsLeft -= usedBackoffs;
332 NS_LOG_DEBUG("No time in CAP to complete backoff delay, deferring to the next CAP");
335 }
336 else
337 {
339 }
340 }
341}
342
343Time
345{
346 Time currentTime;
347 uint64_t capSymbols;
348 Time endCapTime;
349 uint64_t activeSlot;
350 uint64_t symbolRate;
351 Time rxBeaconTime;
352
353 // At this point, the currentTime should be aligned on a backoff period boundary
354 currentTime = Simulator::Now();
355 symbolRate = (uint64_t)m_mac->GetPhy()->GetDataOrSymbolRate(false); // symbols per second
356
357 if (m_coorDest)
358 { // Take Incoming frame reference
359 activeSlot = m_mac->m_incomingSuperframeDuration / 16;
360 capSymbols = activeSlot * (m_mac->m_incomingFnlCapSlot + 1);
361 endCapTime = m_mac->m_macBeaconRxTime + Seconds((double)capSymbols / symbolRate);
362 }
363 else
364 { // Take Outgoing frame reference
365 activeSlot = m_mac->m_superframeDuration / 16;
366 capSymbols = activeSlot * (m_mac->m_fnlCapSlot + 1);
367 endCapTime = m_mac->m_macBeaconTxTime + Seconds((double)capSymbols / symbolRate);
368 }
369
370 return (endCapTime - currentTime);
371}
372
373void
375{
376 NS_LOG_FUNCTION(this);
377
378 Time timeLeftInCap;
379 uint16_t ccaSymbols;
380 uint32_t transactionSymbols;
381 Time transactionTime;
382 uint64_t symbolRate;
383
384 ccaSymbols = 0;
386 symbolRate = (uint64_t)m_mac->GetPhy()->GetDataOrSymbolRate(false);
387 timeLeftInCap = GetTimeLeftInCap();
388
389 // TODO: On the 950 Mhz Band (Japanese Band)
390 // only a single CCA check is performed;
391 // the CCA check duration time is:
392 //
393 // CCA symbols = phyCCADuration * m_CW (1)
394 // other PHYs:
395 // CCA symbols = 8 * m_CW(2)
396 //
397 // note: phyCCADuration & 950Mhz band PHYs are
398 // not currently implemented in ns-3.
399 ccaSymbols += 8 * m_CW;
400
401 // The MAC sublayer shall proceed if the remaining CSMA-CA algorithm steps
402 // can be completed before the end of the CAP.
403 // See IEEE 802.15.4-2011 (Sections 5.1.1.1 and 5.1.1.4)
404 // Transaction = 2 CCA + frame transmission (SHR+PHR+PPDU) + turnaroudtime*2 (Rx->Tx & Tx->Rx) +
405 // IFS (LIFS or SIFS) and Ack time (if ack flag true)
406
407 transactionSymbols = ccaSymbols + m_mac->GetTxPacketSymbols();
408
409 if (m_mac->IsTxAckReq())
410 {
411 NS_LOG_DEBUG("ACK duration symbols: " << m_mac->GetMacAckWaitDuration());
412 transactionSymbols += m_mac->GetMacAckWaitDuration();
413 }
414 else
415 {
416 // time the PHY takes to switch from Rx to Tx and Tx to Rx
417 transactionSymbols += (lrwpan::aTurnaroundTime * 2);
418 }
419 transactionSymbols += m_mac->GetIfsSize();
420
421 // Report the transaction cost
423 {
424 m_lrWpanMacTransCostCallback(transactionSymbols);
425 }
426
427 transactionTime = Seconds((double)transactionSymbols / symbolRate);
428 NS_LOG_DEBUG("Total required transaction: " << transactionSymbols << " symbols ("
429 << transactionTime.As(Time::S) << ")");
430
431 if (transactionTime > timeLeftInCap)
432 {
433 NS_LOG_DEBUG("Transaction of "
434 << transactionSymbols << " symbols "
435 << "cannot be completed in CAP, deferring transmission to the next CAP");
436
437 NS_LOG_DEBUG("Symbols left in CAP: " << (timeLeftInCap.GetSeconds() * symbolRate) << " ("
438 << timeLeftInCap.As(Time::S) << ")");
439
441 }
442 else
443 {
445 }
446}
447
448void
450{
451 NS_LOG_FUNCTION(this);
452 m_ccaRequestRunning = true;
453 m_mac->GetPhy()->PlmeCcaRequest();
454}
455
456void
458{
459 NS_LOG_FUNCTION(this);
461}
462
463void
465{
466 NS_LOG_FUNCTION(this << status);
467
468 // Only react on this event, if we are actually waiting for a CCA.
469 // If the CSMA algorithm was canceled, we could still receive this event from
470 // the PHY. In this case we ignore the event.
472 {
473 m_ccaRequestRunning = false;
474 if (status == IEEE_802_15_4_PHY_IDLE)
475 {
476 if (IsSlottedCsmaCa())
477 {
478 m_CW--;
479 if (m_CW == 0)
480 {
481 // inform MAC channel is idle
483 {
484 NS_LOG_LOGIC("Notifying MAC of idle channel");
486 }
487 }
488 else
489 {
490 NS_LOG_LOGIC("Perform CCA again, m_CW = " << m_CW);
492 this); // Perform CCA again
493 }
494 }
495 else
496 {
497 // inform MAC, channel is idle
499 {
500 NS_LOG_LOGIC("Notifying MAC of idle channel");
502 }
503 }
504 }
505 else
506 {
507 if (IsSlottedCsmaCa())
508 {
509 m_CW = 2;
510 }
511 m_BE = std::min(static_cast<uint16_t>(m_BE + 1), static_cast<uint16_t>(m_macMaxBE));
512 m_NB++;
514 {
515 // no channel found so cannot send pkt
516 NS_LOG_DEBUG("Channel access failure");
518 {
519 NS_LOG_LOGIC("Notifying MAC of Channel access failure");
521 }
522 return;
523 }
524 else
525 {
526 NS_LOG_DEBUG("Perform another backoff; m_NB = " << static_cast<uint16_t>(m_NB));
529 this); // Perform another backoff (step 2)
530 }
531 }
532 }
533}
534
535void
537{
538 NS_LOG_FUNCTION(this);
540}
541
542void
544{
545 NS_LOG_FUNCTION(this);
547}
548
549void
551{
552 m_macBattLifeExt = batteryLifeExtension;
553}
554
555int64_t
557{
558 NS_LOG_FUNCTION(this);
559 m_random->SetStream(stream);
560 return 1;
561}
562
563uint8_t
565{
566 return m_NB;
567}
568
569bool
571{
572 return m_macBattLifeExt;
573}
574
575} // namespace lrwpan
576} // namespace ns3
bool IsNull() const
Check for null implementation.
Definition: callback.h:571
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:55
Introspection did not find any typical Config paths.
A base class which provides memory management and object aggregation.
Definition: object.h:89
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
void SetStream(int64_t stream)
Specifies the stream number for the RngStream.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:571
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:208
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
Definition: simulator.h:605
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition: time.cc:415
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:403
@ S
second
Definition: nstime.h:116
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:932
double GetValue(double min, double max)
Get the next random value drawn from the distribution.
This class is a helper for the LrWpanMac to manage the Csma/CA state machine according to IEEE 802....
uint8_t m_macMaxCSMABackoffs
Maximum number of backoffs.
bool m_coorDest
Indicates whether the CSMA procedure is targeted for a message to be sent to the coordinator.
EventId m_randomBackoffEvent
Scheduler event for the start of the next random backoff/slot.
LrWpanMacStateCallback m_lrWpanMacStateCallback
The callback to inform the configured MAC of the CSMA/CA result.
LrWpanMacTransCostCallback m_lrWpanMacTransCostCallback
The callback to inform the cost of a transaction in slotted CSMA-CA.
uint8_t m_CW
Contention window length (used in slotted ver only).
void SetUnSlottedCsmaCa()
Configure for the use of the unslotted CSMA/CA version.
void SetMacMaxCSMABackoffs(uint8_t macMaxCSMABackoffs)
Set the maximum number of backoffs.
void Cancel()
Cancel CSMA-CA algorithm.
void Start()
Start CSMA-CA algorithm (step 1), initialize NB, BE for both slotted and unslotted CSMA-CA.
static TypeId GetTypeId()
Get the type ID.
EventId m_canProceedEvent
Scheduler event for checking if we can complete the transmission before the end of the CAP.
EventId m_requestCcaEvent
Scheduler event when to start the CCA after a random backoff.
Ptr< LrWpanMac > GetMac() const
Get the MAC to which this CSMA/CA implementation is attached to.
void RandomBackoffDelay()
In step 2 of the CSMA-CA, perform a random backoff in the range of 0 to 2^BE -1.
void CanProceed()
In the slotted CSMA-CA, after random backoff, determine if the remaining CSMA-CA operation can procee...
uint8_t GetNB() const
Get the number of CSMA retries.
bool IsUnSlottedCsmaCa() const
Check if the unslotted CSMA/CA version is being used.
uint8_t m_BE
Backoff exponent.
Time GetTimeToNextSlot() const
Locates the time to the next backoff period boundary in the SUPERFRAME and returns the amount of time...
void PlmeCcaConfirm(PhyEnumeration status)
IEEE 802.15.4-2006 section 6.2.2.2 PLME-CCA.confirm status.
bool GetBatteryLifeExtension() const
Get the value of the Battery Life Extension.
int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model.
uint64_t m_randomBackoffPeriodsLeft
Count the number of remaining random backoff periods left to delay.
uint8_t GetMacMaxBE() const
Get the maximum backoff exponent value.
uint8_t GetMacMaxCSMABackoffs() const
Get the maximum number of backoffs.
uint8_t GetMacMinBE() const
Get the minimum backoff exponent value.
void SetLrWpanMacTransCostCallback(LrWpanMacTransCostCallback trans)
Set the callback function to report a transaction cost in slotted CSMA-CA.
uint8_t m_macMaxBE
Maximum backoff exponent.
void SetSlottedCsmaCa()
Configure for the use of the slotted CSMA/CA version.
bool m_ccaRequestRunning
Flag indicating that the PHY is currently running a CCA.
bool m_macBattLifeExt
Battery Life Extension.
bool IsSlottedCsmaCa() const
Check if the slotted CSMA/CA version is being used.
Ptr< UniformRandomVariable > m_random
Uniform random variable stream.
bool m_isSlotted
Beacon-enabled slotted or nonbeacon-enabled unslotted CSMA-CA.
void SetMacMinBE(uint8_t macMinBE)
Set the minimum backoff exponent value.
uint8_t m_NB
Number of backoffs for the current transmission.
EventId m_endCapEvent
Scheduler event for the end of the current CAP.
void SetMac(Ptr< LrWpanMac > mac)
Set the MAC to which this CSMA/CA implementation is attached to.
Time GetTimeLeftInCap()
Get the time left in the CAP portion of the Outgoing or Incoming superframe.
void SetBatteryLifeExtension(bool batteryLifeExtension)
Set the value of the Battery Life Extension.
void SetMacMaxBE(uint8_t macMaxBE)
Set the maximum backoff exponent value.
void DoDispose() override
Destructor implementation.
void RequestCCA()
Request the Phy to perform CCA (Step 3)
void DeferCsmaTimeout()
The CSMA algorithm call this function at the end of the CAP to return the MAC state back to to IDLE a...
uint8_t m_macMinBE
Minimum backoff exponent.
Ptr< LrWpanMac > m_mac
The MAC instance for which this CSMA/CA implementation is configured.
LrWpanCsmaCa()
Default constructor.
void SetLrWpanMacStateCallback(LrWpanMacStateCallback macState)
Set the callback function to the MAC.
constexpr uint32_t aUnitBackoffPeriod
Number of symbols per CSMA/CA time unit, default 20 symbols.
constexpr uint32_t aTurnaroundTime
The turnaround time in symbol periods for switching the transceiver from RX to TX or vice-versa.
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:86
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:282
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
PhyEnumeration
IEEE802.15.4-2006 PHY Emumerations Table 18 in section 6.2.3.
Definition: lr-wpan-phy.h:115
@ macMinBE
The minimum value of the backoff exponent (BE) in the CSMA-CA algorithm.
@ CHANNEL_ACCESS_FAILURE
CHANNEL_ACCESS_FAILURE.
Definition: lr-wpan-mac.h:80
@ CHANNEL_IDLE
CHANNEL_IDLE.
Definition: lr-wpan-mac.h:81
@ MAC_CSMA_DEFERRED
MAC_CSMA_DEFERRED.
Definition: lr-wpan-mac.h:85
@ IEEE_802_15_4_PHY_IDLE
Definition: lr-wpan-phy.h:120
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1319
Every class exported by the ns3 library is enclosed in the ns3 namespace.