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 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author:
7 * kwong yin <kwong-sang.yin@boeing.com>
8 * Sascha Alexander Jopen <jopen@cs.uni-bonn.de>
9 * Alberto Gallegos Ramonet <ramonet@fc.ritsumei.ac.jp>
10 */
11
12#include "lr-wpan-csmaca.h"
13
14#include "lr-wpan-constants.h"
15
16#include <ns3/log.h>
17#include <ns3/random-variable-stream.h>
18#include <ns3/simulator.h>
19
20#include <algorithm>
21
22#undef NS_LOG_APPEND_CONTEXT
23#define NS_LOG_APPEND_CONTEXT \
24 std::clog << "[" << m_mac->GetShortAddress() << " | " << m_mac->GetExtendedAddress() << "] ";
25
26namespace ns3
27{
28namespace lrwpan
29{
30
31NS_LOG_COMPONENT_DEFINE("LrWpanCsmaCa");
32NS_OBJECT_ENSURE_REGISTERED(LrWpanCsmaCa);
33
34TypeId
36{
37 static TypeId tid = TypeId("ns3::lrwpan::LrWpanCsmaCa")
38 .AddDeprecatedName("ns3::LrWpanCsmaCa")
40 .SetGroupName("LrWpan")
41 .AddConstructor<LrWpanCsmaCa>();
42 return tid;
43}
44
46{
47 // TODO-- make these into ns-3 attributes
48
49 m_isSlotted = false;
50 m_NB = 0;
51 m_CW = 2;
52 m_macBattLifeExt = false;
53 m_macMinBE = 3;
54 m_macMaxBE = 5;
58 m_ccaRequestRunning = false;
60 m_coorDest = false;
61}
62
64{
65 m_mac = nullptr;
66}
67
68void
77
78void
83
86{
87 return m_mac;
88}
89
90void
95
96void
101
102bool
104{
105 return m_isSlotted;
106}
107
108bool
110{
111 return !m_isSlotted;
112}
113
114void
116{
117 NS_LOG_FUNCTION(this << macMinBE);
119 "MacMinBE (" << macMinBE << ") should be <= MacMaxBE (" << m_macMaxBE << ")");
121}
122
123uint8_t
125{
126 NS_LOG_FUNCTION(this);
127 return m_macMinBE;
128}
129
130void
132{
133 NS_LOG_FUNCTION(this << macMaxBE);
134 NS_ASSERT_MSG(macMaxBE >= 3 && macMaxBE <= 8,
135 "MacMaxBE (" << macMaxBE << ") should be >= 3 and <= 8");
136 m_macMaxBE = macMaxBE;
137}
138
139uint8_t
141{
142 NS_LOG_FUNCTION(this);
143 return m_macMaxBE;
144}
145
146void
147LrWpanCsmaCa::SetMacMaxCSMABackoffs(uint8_t macMaxCSMABackoffs)
148{
149 NS_LOG_FUNCTION(this << macMaxCSMABackoffs);
150 NS_ASSERT_MSG(macMaxCSMABackoffs <= 5, "MacMaxCSMABackoffs should be <= 5");
151 m_macMaxCSMABackoffs = macMaxCSMABackoffs;
152}
153
154uint8_t
160
161Time
163{
164 NS_LOG_FUNCTION(this);
165
166 // The reference for the beginning of the SUPERFRAME (the active period) changes depending
167 // on the data packet being sent from the Coordinator/outgoing frame (Tx beacon time reference)
168 // or other device/incoming frame (Rx beacon time reference ).
169
170 Time elapsedSuperframe; // (i.e The beacon + the elapsed CAP)
171 Time currentTime = Simulator::Now();
172 double symbolsToBoundary;
173 Time nextBoundary;
174 uint64_t elapsedSuperframeSymbols;
175 uint64_t symbolRate =
176 (uint64_t)m_mac->GetPhy()->GetDataOrSymbolRate(false); // symbols per second
177 Time timeAtBoundary;
178
179 if (m_coorDest)
180 {
181 // Take the Incoming Frame Reference
182 elapsedSuperframe = currentTime - m_mac->m_macBeaconRxTime;
183
184 Time beaconTime [[maybe_unused]] = Seconds((double)m_mac->m_rxBeaconSymbols / symbolRate);
185 Time elapsedCap [[maybe_unused]] = elapsedSuperframe - beaconTime;
186 NS_LOG_DEBUG("Elapsed incoming CAP symbols: " << (elapsedCap.GetSeconds() * symbolRate)
187 << " (" << elapsedCap.As(Time::S) << ")");
188 }
189 else
190 {
191 // Take the Outgoing Frame Reference
192 elapsedSuperframe = currentTime - m_mac->m_macBeaconTxTime;
193 }
194
195 // get a close value to the the boundary in symbols
196 elapsedSuperframeSymbols = elapsedSuperframe.GetSeconds() * symbolRate;
197 symbolsToBoundary = lrwpan::aUnitBackoffPeriod -
198 std::fmod((double)elapsedSuperframeSymbols, lrwpan::aUnitBackoffPeriod);
199
200 timeAtBoundary = Seconds((double)(elapsedSuperframeSymbols + symbolsToBoundary) / symbolRate);
201
202 // get the exact time boundary
203 nextBoundary = timeAtBoundary - elapsedSuperframe;
204
205 NS_LOG_DEBUG("Elapsed Superframe symbols: " << elapsedSuperframeSymbols << " ("
206 << elapsedSuperframe.As(Time::S) << ")");
207
208 NS_LOG_DEBUG("Next backoff period boundary in approx. "
209 << nextBoundary.GetSeconds() * symbolRate << " symbols ("
210 << nextBoundary.As(Time::S) << ")");
211
212 return nextBoundary;
213}
214
215void
217{
218 NS_LOG_FUNCTION(this);
219 m_NB = 0;
220 if (IsSlottedCsmaCa())
221 {
222 NS_LOG_DEBUG("Using Slotted CSMA-CA");
223
224 // TODO: Check if the current PHY is using the Japanese band 950 Mhz:
225 // (IEEE_802_15_4_950MHZ_BPSK and IEEE_802_15_4_950MHZ_2GFSK)
226 // if in use, m_CW = 1.
227 // Currently 950 Mhz band PHYs are not supported in ns-3.
228 // To know the current used PHY, making the method for GetPhy()->GetMyPhyOption()
229 // public is necessary. Alternatively, the current PHY used
230 // can be known using phyCurrentPage variable.
231
232 m_CW = 2;
233
235 {
236 m_BE = std::min(static_cast<uint8_t>(2), m_macMinBE);
237 }
238 else
239 {
241 }
242
243 // m_coorDest to decide between incoming and outgoing superframes times
244 m_coorDest = m_mac->IsCoordDest();
245
246 // Locate backoff period boundary. (i.e. a time delay to align with the next backoff period
247 // boundary)
248 Time backoffBoundary = GetTimeToNextSlot();
251 }
252 else
253 {
254 NS_LOG_DEBUG("Using Unslotted CSMA-CA");
257 }
258}
259
260void
262{
266 m_mac->GetPhy()->CcaCancel();
267}
268
269void
271{
272 NS_LOG_FUNCTION(this);
273
274 uint64_t upperBound = (uint64_t)pow(2, m_BE) - 1;
275 Time randomBackoff;
276 uint64_t symbolRate;
277 Time timeLeftInCap;
278
279 symbolRate = (uint64_t)m_mac->GetPhy()->GetDataOrSymbolRate(false); // symbols per second
280
281 // We should not recalculate the random backoffPeriods if we are in a slotted CSMA-CA and the
282 // transmission was previously deferred (m_randomBackoffPeriods != 0)
284 {
285 m_randomBackoffPeriodsLeft = (uint64_t)m_random->GetValue(0, upperBound + 1);
286 }
287
288 randomBackoff =
290
291 if (IsUnSlottedCsmaCa())
292 {
293 NS_LOG_DEBUG("Unslotted CSMA-CA: requesting CCA after backoff of "
294 << m_randomBackoffPeriodsLeft << " periods (" << randomBackoff.As(Time::S)
295 << ")");
297 }
298 else
299 {
300 // We must make sure there is enough time left in the CAP, otherwise we continue in
301 // the CAP of the next superframe after the transmission/reception of the beacon (and the
302 // IFS)
303 timeLeftInCap = GetTimeLeftInCap();
304
305 NS_LOG_DEBUG("Slotted CSMA-CA: proceeding after random backoff of "
306 << m_randomBackoffPeriodsLeft << " periods ("
307 << (randomBackoff.GetSeconds() * symbolRate) << " symbols or "
308 << randomBackoff.As(Time::S) << ")");
309
310 NS_LOG_DEBUG("Backoff periods left in CAP: "
311 << ((timeLeftInCap.GetSeconds() * symbolRate) / lrwpan::aUnitBackoffPeriod)
312 << " (" << (timeLeftInCap.GetSeconds() * symbolRate) << " symbols or "
313 << timeLeftInCap.As(Time::S) << ")");
314
315 if (randomBackoff >= timeLeftInCap)
316 {
317 uint64_t usedBackoffs =
318 (double)(timeLeftInCap.GetSeconds() * symbolRate) / lrwpan::aUnitBackoffPeriod;
319 m_randomBackoffPeriodsLeft -= usedBackoffs;
320 NS_LOG_DEBUG("No time in CAP to complete backoff delay, deferring to the next CAP");
323 }
324 else
325 {
327 }
328 }
329}
330
331Time
333{
334 Time currentTime;
335 uint64_t capSymbols;
336 Time endCapTime;
337 uint64_t activeSlot;
338 uint64_t symbolRate;
339 Time rxBeaconTime;
340
341 // At this point, the currentTime should be aligned on a backoff period boundary
342 currentTime = Simulator::Now();
343 symbolRate = (uint64_t)m_mac->GetPhy()->GetDataOrSymbolRate(false); // symbols per second
344
345 if (m_coorDest)
346 { // Take Incoming frame reference
347 activeSlot = m_mac->m_incomingSuperframeDuration / 16;
348 capSymbols = activeSlot * (m_mac->m_incomingFnlCapSlot + 1);
349 endCapTime = m_mac->m_macBeaconRxTime + Seconds((double)capSymbols / symbolRate);
350 }
351 else
352 { // Take Outgoing frame reference
353 activeSlot = m_mac->m_superframeDuration / 16;
354 capSymbols = activeSlot * (m_mac->m_fnlCapSlot + 1);
355 endCapTime = m_mac->m_macBeaconTxTime + Seconds((double)capSymbols / symbolRate);
356 }
357
358 return (endCapTime - currentTime);
359}
360
361void
363{
364 NS_LOG_FUNCTION(this);
365
366 Time timeLeftInCap;
367 uint16_t ccaSymbols;
368 uint32_t transactionSymbols;
369 Time transactionTime;
370 uint64_t symbolRate;
371
372 ccaSymbols = 0;
374 symbolRate = (uint64_t)m_mac->GetPhy()->GetDataOrSymbolRate(false);
375 timeLeftInCap = GetTimeLeftInCap();
376
377 // TODO: On the 950 Mhz Band (Japanese Band)
378 // only a single CCA check is performed;
379 // the CCA check duration time is:
380 //
381 // CCA symbols = phyCCADuration * m_CW (1)
382 // other PHYs:
383 // CCA symbols = 8 * m_CW(2)
384 //
385 // note: phyCCADuration & 950Mhz band PHYs are
386 // not currently implemented in ns-3.
387 ccaSymbols += 8 * m_CW;
388
389 // The MAC sublayer shall proceed if the remaining CSMA-CA algorithm steps
390 // can be completed before the end of the CAP.
391 // See IEEE 802.15.4-2011 (Sections 5.1.1.1 and 5.1.1.4)
392 // Transaction = 2 CCA + frame transmission (SHR+PHR+PPDU) + turnaroudtime*2 (Rx->Tx & Tx->Rx) +
393 // IFS (LIFS or SIFS) and Ack time (if ack flag true)
394
395 transactionSymbols = ccaSymbols + m_mac->GetTxPacketSymbols();
396
397 if (m_mac->IsTxAckReq())
398 {
399 NS_LOG_DEBUG("ACK duration symbols: " << m_mac->GetMacAckWaitDuration());
400 transactionSymbols += m_mac->GetMacAckWaitDuration();
401 }
402 else
403 {
404 // time the PHY takes to switch from Rx to Tx and Tx to Rx
405 transactionSymbols += (lrwpan::aTurnaroundTime * 2);
406 }
407 transactionSymbols += m_mac->GetIfsSize();
408
409 // Report the transaction cost
411 {
412 m_lrWpanMacTransCostCallback(transactionSymbols);
413 }
414
415 transactionTime = Seconds((double)transactionSymbols / symbolRate);
416 NS_LOG_DEBUG("Total required transaction: " << transactionSymbols << " symbols ("
417 << transactionTime.As(Time::S) << ")");
418
419 if (transactionTime > timeLeftInCap)
420 {
421 NS_LOG_DEBUG("Transaction of "
422 << transactionSymbols << " symbols "
423 << "cannot be completed in CAP, deferring transmission to the next CAP");
424
425 NS_LOG_DEBUG("Symbols left in CAP: " << (timeLeftInCap.GetSeconds() * symbolRate) << " ("
426 << timeLeftInCap.As(Time::S) << ")");
427
429 }
430 else
431 {
433 }
434}
435
436void
438{
439 NS_LOG_FUNCTION(this);
440 m_ccaRequestRunning = true;
441 m_mac->GetPhy()->PlmeCcaRequest();
442}
443
444void
450
451void
453{
454 NS_LOG_FUNCTION(this << status);
455
456 // Only react on this event, if we are actually waiting for a CCA.
457 // If the CSMA algorithm was canceled, we could still receive this event from
458 // the PHY. In this case we ignore the event.
460 {
461 m_ccaRequestRunning = false;
462 if (status == IEEE_802_15_4_PHY_IDLE)
463 {
464 if (IsSlottedCsmaCa())
465 {
466 m_CW--;
467 if (m_CW == 0)
468 {
469 // inform MAC channel is idle
471 {
472 NS_LOG_LOGIC("Notifying MAC of idle channel");
474 }
475 }
476 else
477 {
478 NS_LOG_LOGIC("Perform CCA again, m_CW = " << m_CW);
480 this); // Perform CCA again
481 }
482 }
483 else
484 {
485 // inform MAC, channel is idle
487 {
488 NS_LOG_LOGIC("Notifying MAC of idle channel");
490 }
491 }
492 }
493 else
494 {
495 if (IsSlottedCsmaCa())
496 {
497 m_CW = 2;
498 }
499 m_BE = std::min(static_cast<uint16_t>(m_BE + 1), static_cast<uint16_t>(m_macMaxBE));
500 m_NB++;
502 {
503 // no channel found so cannot send pkt
504 NS_LOG_DEBUG("Channel access failure");
506 {
507 NS_LOG_LOGIC("Notifying MAC of Channel access failure");
509 }
510 return;
511 }
512 else
513 {
514 NS_LOG_DEBUG("Perform another backoff; m_NB = " << static_cast<uint16_t>(m_NB));
517 this); // Perform another backoff (step 2)
518 }
519 }
520 }
521}
522
523void
529
530void
536
537void
539{
540 m_macBattLifeExt = batteryLifeExtension;
541}
542
543int64_t
545{
546 NS_LOG_FUNCTION(this);
547 m_random->SetStream(stream);
548 return 1;
549}
550
551uint8_t
553{
554 return m_NB;
555}
556
557bool
562
563} // namespace lrwpan
564} // namespace ns3
bool IsNull() const
Check for null implementation.
Definition callback.h:555
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition event-id.cc:44
A base class which provides memory management and object aggregation.
Definition object.h:78
Smart pointer class similar to boost::intrusive_ptr.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:560
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:197
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
Definition simulator.h:594
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition time.cc:404
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition nstime.h:392
@ S
second
Definition nstime.h:105
a unique identifier for an interface.
Definition type-id.h:48
TypeId AddDeprecatedName(const std::string &name)
Add an deprecated name for a TypeId.
Definition type-id.cc:862
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
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:75
Callback< R, Args... > MakeNullCallback()
Definition callback.h:727
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition log.h:271
#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.
@ 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:69
@ CHANNEL_IDLE
CHANNEL_IDLE.
Definition lr-wpan-mac.h:70
@ MAC_CSMA_DEFERRED
MAC_CSMA_DEFERRED.
Definition lr-wpan-mac.h:74
@ IEEE_802_15_4_PHY_IDLE
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition object-base.h:35
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1308
Every class exported by the ns3 library is enclosed in the ns3 namespace.