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{
40
41NS_LOG_COMPONENT_DEFINE("LrWpanCsmaCa");
42
43NS_OBJECT_ENSURE_REGISTERED(LrWpanCsmaCa);
44
45TypeId
47{
48 static TypeId tid = TypeId("ns3::LrWpanCsmaCa")
50 .SetGroupName("LrWpan")
51 .AddConstructor<LrWpanCsmaCa>();
52 return tid;
53}
54
56{
57 // TODO-- make these into ns-3 attributes
58
59 m_isSlotted = false;
60 m_NB = 0;
61 m_CW = 2;
62 m_macBattLifeExt = false;
63 m_macMinBE = 3;
64 m_macMaxBE = 5;
66 m_random = CreateObject<UniformRandomVariable>();
68 m_ccaRequestRunning = false;
70 m_coorDest = false;
71}
72
74{
75 m_mac = nullptr;
76}
77
78void
80{
81 m_lrWpanMacStateCallback = MakeNullCallback<void, LrWpanMacState>();
82 m_lrWpanMacTransCostCallback = MakeNullCallback<void, uint32_t>();
83
84 Cancel();
85 m_mac = nullptr;
86}
87
88void
90{
91 m_mac = mac;
92}
93
96{
97 return m_mac;
98}
99
100void
102{
103 NS_LOG_FUNCTION(this);
104 m_isSlotted = true;
105}
106
107void
109{
110 NS_LOG_FUNCTION(this);
111 m_isSlotted = false;
112}
113
114bool
116{
117 NS_LOG_FUNCTION(this);
118 return m_isSlotted;
119}
120
121bool
123{
124 NS_LOG_FUNCTION(this);
125 return !m_isSlotted;
126}
127
128void
130{
131 NS_LOG_FUNCTION(this << macMinBE);
133 "MacMinBE (" << macMinBE << ") should be <= MacMaxBE (" << m_macMaxBE << ")");
135}
136
137uint8_t
139{
140 NS_LOG_FUNCTION(this);
141 return m_macMinBE;
142}
143
144void
146{
147 NS_LOG_FUNCTION(this << macMaxBE);
148 NS_ASSERT_MSG(macMaxBE >= 3 && macMaxBE <= 8,
149 "MacMaxBE (" << macMaxBE << ") should be >= 3 and <= 8");
150 m_macMaxBE = macMaxBE;
151}
152
153uint8_t
155{
156 NS_LOG_FUNCTION(this);
157 return m_macMaxBE;
158}
159
160void
161LrWpanCsmaCa::SetMacMaxCSMABackoffs(uint8_t macMaxCSMABackoffs)
162{
163 NS_LOG_FUNCTION(this << macMaxCSMABackoffs);
164 NS_ASSERT_MSG(macMaxCSMABackoffs <= 5, "MacMaxCSMABackoffs should be <= 5");
165 m_macMaxCSMABackoffs = macMaxCSMABackoffs;
166}
167
168uint8_t
170{
171 NS_LOG_FUNCTION(this);
173}
174
175Time
177{
178 NS_LOG_FUNCTION(this);
179
180 // The reference for the beginning of the SUPERFRAME (the active period) changes depending
181 // on the data packet being sent from the Coordinator/outgoing frame (Tx beacon time reference)
182 // or other device/incoming frame (Rx beacon time reference ).
183
184 Time elapsedSuperframe; // (i.e The beacon + the elapsed CAP)
185 Time currentTime = Simulator::Now();
186 double symbolsToBoundary;
187 Time nextBoundary;
188 uint64_t elapsedSuperframeSymbols;
189 uint64_t symbolRate =
190 (uint64_t)m_mac->GetPhy()->GetDataOrSymbolRate(false); // symbols per second
191 Time timeAtBoundary;
192
193 if (m_coorDest)
194 {
195 // Take the Incoming Frame Reference
196 elapsedSuperframe = currentTime - m_mac->m_macBeaconRxTime;
197
198 Time beaconTime [[maybe_unused]] = Seconds((double)m_mac->m_rxBeaconSymbols / symbolRate);
199 Time elapsedCap [[maybe_unused]] = elapsedSuperframe - beaconTime;
200 NS_LOG_DEBUG("Elapsed incoming CAP symbols: " << (elapsedCap.GetSeconds() * symbolRate)
201 << " (" << elapsedCap.As(Time::S) << ")");
202 }
203 else
204 {
205 // Take the Outgoing Frame Reference
206 elapsedSuperframe = currentTime - m_mac->m_macBeaconTxTime;
207 }
208
209 // get a close value to the the boundary in symbols
210 elapsedSuperframeSymbols = elapsedSuperframe.GetSeconds() * symbolRate;
211 symbolsToBoundary = lrwpan::aUnitBackoffPeriod -
212 std::fmod((double)elapsedSuperframeSymbols, lrwpan::aUnitBackoffPeriod);
213
214 timeAtBoundary = Seconds((double)(elapsedSuperframeSymbols + symbolsToBoundary) / symbolRate);
215
216 // get the exact time boundary
217 nextBoundary = timeAtBoundary - elapsedSuperframe;
218
219 NS_LOG_DEBUG("Elapsed Superframe symbols: " << elapsedSuperframeSymbols << " ("
220 << elapsedSuperframe.As(Time::S) << ")");
221
222 NS_LOG_DEBUG("Next backoff period boundary in approx. "
223 << nextBoundary.GetSeconds() * symbolRate << " symbols ("
224 << nextBoundary.As(Time::S) << ")");
225
226 return nextBoundary;
227}
228
229void
231{
232 NS_LOG_FUNCTION(this);
233 m_NB = 0;
234 if (IsSlottedCsmaCa())
235 {
236 // TODO: Check if the current PHY is using the Japanese band 950 Mhz:
237 // (IEEE_802_15_4_950MHZ_BPSK and IEEE_802_15_4_950MHZ_2GFSK)
238 // if in use, m_CW = 1.
239 // Currently 950 Mhz band PHYs are not supported in ns-3.
240 // To know the current used PHY, making the method for GetPhy()->GetMyPhyOption()
241 // public is necessary. Alternatively, the current PHY used
242 // can be known using phyCurrentPage variable.
243
244 m_CW = 2;
245
247 {
248 m_BE = std::min(static_cast<uint8_t>(2), m_macMinBE);
249 }
250 else
251 {
253 }
254
255 // m_coorDest to decide between incoming and outgoing superframes times
256 m_coorDest = m_mac->isCoordDest();
257
258 // Locate backoff period boundary. (i.e. a time delay to align with the next backoff period
259 // boundary)
260 Time backoffBoundary = GetTimeToNextSlot();
263 }
264 else
265 {
268 }
269}
270
271void
273{
277 m_mac->GetPhy()->CcaCancel();
278}
279
280void
282{
283 NS_LOG_FUNCTION(this);
284
285 uint64_t upperBound = (uint64_t)pow(2, m_BE) - 1;
286 Time randomBackoff;
287 uint64_t symbolRate;
288 Time timeLeftInCap;
289
290 symbolRate = (uint64_t)m_mac->GetPhy()->GetDataOrSymbolRate(false); // symbols per second
291
292 // We should not recalculate the random backoffPeriods if we are in a slotted CSMA-CA and the
293 // transmission was previously deferred (m_randomBackoffPeriods != 0)
295 {
296 m_randomBackoffPeriodsLeft = (uint64_t)m_random->GetValue(0, upperBound + 1);
297 }
298
299 randomBackoff =
301
302 if (IsUnSlottedCsmaCa())
303 {
304 NS_LOG_DEBUG("Unslotted CSMA-CA: requesting CCA after backoff of "
305 << m_randomBackoffPeriodsLeft << " periods (" << randomBackoff.As(Time::S)
306 << ")");
308 }
309 else
310 {
311 // We must make sure there is enough time left in the CAP, otherwise we continue in
312 // the CAP of the next superframe after the transmission/reception of the beacon (and the
313 // IFS)
314 timeLeftInCap = GetTimeLeftInCap();
315
316 NS_LOG_DEBUG("Slotted CSMA-CA: proceeding after random backoff of "
317 << m_randomBackoffPeriodsLeft << " periods ("
318 << (randomBackoff.GetSeconds() * symbolRate) << " symbols or "
319 << randomBackoff.As(Time::S) << ")");
320
321 NS_LOG_DEBUG("Backoff periods left in CAP: "
322 << ((timeLeftInCap.GetSeconds() * symbolRate) / lrwpan::aUnitBackoffPeriod)
323 << " (" << (timeLeftInCap.GetSeconds() * symbolRate) << " symbols or "
324 << timeLeftInCap.As(Time::S) << ")");
325
326 if (randomBackoff >= timeLeftInCap)
327 {
328 uint64_t usedBackoffs =
329 (double)(timeLeftInCap.GetSeconds() * symbolRate) / lrwpan::aUnitBackoffPeriod;
330 m_randomBackoffPeriodsLeft -= usedBackoffs;
331 NS_LOG_DEBUG("No time in CAP to complete backoff delay, deferring to the next CAP");
334 }
335 else
336 {
338 }
339 }
340}
341
342Time
344{
345 Time currentTime;
346 uint64_t capSymbols;
347 Time endCapTime;
348 uint64_t activeSlot;
349 uint64_t symbolRate;
350 Time rxBeaconTime;
351
352 // At this point, the currentTime should be aligned on a backoff period boundary
353 currentTime = Simulator::Now();
354 symbolRate = (uint64_t)m_mac->GetPhy()->GetDataOrSymbolRate(false); // symbols per second
355
356 if (m_coorDest)
357 { // Take Incoming frame reference
358 activeSlot = m_mac->m_incomingSuperframeDuration / 16;
359 capSymbols = activeSlot * (m_mac->m_incomingFnlCapSlot + 1);
360 endCapTime = m_mac->m_macBeaconRxTime + Seconds((double)capSymbols / symbolRate);
361 }
362 else
363 { // Take Outgoing frame reference
364 activeSlot = m_mac->m_superframeDuration / 16;
365 capSymbols = activeSlot * (m_mac->m_fnlCapSlot + 1);
366 endCapTime = m_mac->m_macBeaconTxTime + Seconds((double)capSymbols / symbolRate);
367 }
368
369 return (endCapTime - currentTime);
370}
371
372void
374{
375 NS_LOG_FUNCTION(this);
376
377 Time timeLeftInCap;
378 uint16_t ccaSymbols;
379 uint32_t transactionSymbols;
380 Time transactionTime;
381 uint64_t symbolRate;
382
383 ccaSymbols = 0;
385 symbolRate = (uint64_t)m_mac->GetPhy()->GetDataOrSymbolRate(false);
386 timeLeftInCap = GetTimeLeftInCap();
387
388 // TODO: On the 950 Mhz Band (Japanese Band)
389 // only a single CCA check is performed;
390 // the CCA check duration time is:
391 //
392 // CCA symbols = phyCCADuration * m_CW (1)
393 // other PHYs:
394 // CCA symbols = 8 * m_CW(2)
395 //
396 // note: phyCCADuration & 950Mhz band PHYs are
397 // not currently implemented in ns-3.
398 ccaSymbols += 8 * m_CW;
399
400 // The MAC sublayer shall proceed if the remaining CSMA-CA algorithm steps
401 // can be completed before the end of the CAP.
402 // See IEEE 802.15.4-2011 (Sections 5.1.1.1 and 5.1.1.4)
403 // Transaction = 2 CCA + frame transmission (SHR+PHR+PPDU) + turnaroudtime*2 (Rx->Tx & Tx->Rx) +
404 // IFS (LIFS or SIFS) and Ack time (if ack flag true)
405
406 transactionSymbols = ccaSymbols + m_mac->GetTxPacketSymbols();
407
408 if (m_mac->isTxAckReq())
409 {
410 NS_LOG_DEBUG("ACK duration symbols: " << m_mac->GetMacAckWaitDuration());
411 transactionSymbols += m_mac->GetMacAckWaitDuration();
412 }
413 else
414 {
415 // time the PHY takes to switch from Rx to Tx and Tx to Rx
416 transactionSymbols += (lrwpan::aTurnaroundTime * 2);
417 }
418 transactionSymbols += m_mac->GetIfsSize();
419
420 // Report the transaction cost
422 {
423 m_lrWpanMacTransCostCallback(transactionSymbols);
424 }
425
426 transactionTime = Seconds((double)transactionSymbols / symbolRate);
427 NS_LOG_DEBUG("Total required transaction: " << transactionSymbols << " symbols ("
428 << transactionTime.As(Time::S) << ")");
429
430 if (transactionTime > timeLeftInCap)
431 {
432 NS_LOG_DEBUG("Transaction of "
433 << transactionSymbols << " symbols "
434 << "cannot be completed in CAP, deferring transmission to the next CAP");
435
436 NS_LOG_DEBUG("Symbols left in CAP: " << (timeLeftInCap.GetSeconds() * symbolRate) << " ("
437 << timeLeftInCap.As(Time::S) << ")");
438
440 }
441 else
442 {
444 }
445}
446
447void
449{
450 NS_LOG_FUNCTION(this);
451 m_ccaRequestRunning = true;
452 m_mac->GetPhy()->PlmeCcaRequest();
453}
454
455void
457{
458 NS_LOG_FUNCTION(this);
460}
461
462void
464{
465 NS_LOG_FUNCTION(this << status);
466
467 // Only react on this event, if we are actually waiting for a CCA.
468 // If the CSMA algorithm was canceled, we could still receive this event from
469 // the PHY. In this case we ignore the event.
471 {
472 m_ccaRequestRunning = false;
473 if (status == IEEE_802_15_4_PHY_IDLE)
474 {
475 if (IsSlottedCsmaCa())
476 {
477 m_CW--;
478 if (m_CW == 0)
479 {
480 // inform MAC channel is idle
482 {
483 NS_LOG_LOGIC("Notifying MAC of idle channel");
485 }
486 }
487 else
488 {
489 NS_LOG_LOGIC("Perform CCA again, m_CW = " << m_CW);
491 this); // Perform CCA again
492 }
493 }
494 else
495 {
496 // inform MAC, channel is idle
498 {
499 NS_LOG_LOGIC("Notifying MAC of idle channel");
501 }
502 }
503 }
504 else
505 {
506 if (IsSlottedCsmaCa())
507 {
508 m_CW = 2;
509 }
510 m_BE = std::min(static_cast<uint16_t>(m_BE + 1), static_cast<uint16_t>(m_macMaxBE));
511 m_NB++;
513 {
514 // no channel found so cannot send pkt
515 NS_LOG_DEBUG("Channel access failure");
517 {
518 NS_LOG_LOGIC("Notifying MAC of Channel access failure");
520 }
521 return;
522 }
523 else
524 {
525 NS_LOG_DEBUG("Perform another backoff; m_NB = " << static_cast<uint16_t>(m_NB));
528 this); // Perform another backoff (step 2)
529 }
530 }
531 }
532}
533
534void
536{
537 NS_LOG_FUNCTION(this);
539}
540
541void
543{
544 NS_LOG_FUNCTION(this);
546}
547
548void
550{
551 m_macBattLifeExt = batteryLifeExtension;
552}
553
554int64_t
556{
557 NS_LOG_FUNCTION(this);
558 m_random->SetStream(stream);
559 return 1;
560}
561
562uint8_t
564{
565 return m_NB;
566}
567
568bool
570{
571 return m_macBattLifeExt;
572}
573
574} // namespace ns3
bool IsNull() const
Check for null implementation.
Definition: callback.h:569
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:55
This class is a helper for the LrWpanMac to manage the Csma/CA state machine according to IEEE 802....
Ptr< LrWpanMac > m_mac
The MAC instance for which this CSMA/CA implementation is configured.
void SetBatteryLifeExtension(bool batteryLifeExtension)
Set the value of the Battery Life Extension.
void PlmeCcaConfirm(LrWpanPhyEnumeration status)
IEEE 802.15.4-2006 section 6.2.2.2 PLME-CCA.confirm status.
LrWpanCsmaCa()
Default constructor.
void RequestCCA()
Request the Phy to perform CCA (Step 3)
uint8_t GetMacMinBE() const
Get the minimum backoff exponent value.
bool m_isSlotted
Beacon-enabled slotted or nonbeacon-enabled unslotted CSMA-CA.
uint8_t m_BE
Backoff exponent.
EventId m_canProceedEvent
Scheduler event for checking if we can complete the transmission before the end of the CAP.
static TypeId GetTypeId()
Get the type ID.
EventId m_randomBackoffEvent
Scheduler event for the start of the next random backoff/slot.
void SetUnSlottedCsmaCa()
Configure for the use of the unslotted CSMA/CA version.
void DeferCsmaTimeout()
The CSMA algorithm call this function at the end of the CAP to return the MAC state back to to IDLE a...
bool IsUnSlottedCsmaCa() const
Check if the unslotted CSMA/CA version is being used.
void SetMac(Ptr< LrWpanMac > mac)
Set the MAC to which this CSMA/CA implementation is attached to.
uint8_t GetNB() const
Get the number of CSMA retries.
LrWpanMacStateCallback m_lrWpanMacStateCallback
The callback to inform the configured MAC of the CSMA/CA result.
Ptr< LrWpanMac > GetMac() const
Get the MAC to which this CSMA/CA implementation is attached to.
LrWpanMacTransCostCallback m_lrWpanMacTransCostCallback
The callback to inform the cost of a transaction in slotted CSMA-CA.
void Cancel()
Cancel CSMA-CA algorithm.
EventId m_requestCcaEvent
Scheduler event when to start the CCA after a random backoff.
bool m_coorDest
Indicates whether the CSMA procedure is targeted for a message to be sent to the coordinator.
bool IsSlottedCsmaCa() const
Check if the slotted CSMA/CA version is being used.
void SetLrWpanMacTransCostCallback(LrWpanMacTransCostCallback trans)
Set the callback function to report a transaction cost in slotted CSMA-CA.
void SetMacMaxBE(uint8_t macMaxBE)
Set the maximum backoff exponent value.
void RandomBackoffDelay()
In step 2 of the CSMA-CA, perform a random backoff in the range of 0 to 2^BE -1.
uint8_t m_macMaxBE
Maximum backoff exponent.
void SetMacMinBE(uint8_t macMinBE)
Set the minimum backoff exponent value.
bool GetBatteryLifeExtension() const
Get the value of the Battery Life Extension.
uint8_t m_CW
Contention window length (used in slotted ver only).
uint8_t m_macMinBE
Minimum backoff exponent.
uint8_t GetMacMaxCSMABackoffs() const
Get the maximum number of backoffs.
bool m_macBattLifeExt
Battery Life Extension.
Time GetTimeToNextSlot() const
Locates the time to the next backoff period boundary in the SUPERFRAME and returns the amount of time...
uint8_t GetMacMaxBE() const
Get the maximum backoff exponent value.
void SetSlottedCsmaCa()
Configure for the use of the slotted CSMA/CA version.
EventId m_endCapEvent
Scheduler event for the end of the current CAP.
void CanProceed()
In the slotted CSMA-CA, after random backoff, determine if the remaining CSMA-CA operation can procee...
uint64_t m_randomBackoffPeriodsLeft
Count the number of remaining random backoff periods left to delay.
Time GetTimeLeftInCap()
Get the time left in the CAP portion of the Outgoing or Incoming superframe.
~LrWpanCsmaCa() override
bool m_ccaRequestRunning
Flag indicating that the PHY is currently running a CCA.
void SetLrWpanMacStateCallback(LrWpanMacStateCallback macState)
Set the callback function to the MAC.
void DoDispose() override
Destructor implementation.
void Start()
Start CSMA-CA algorithm (step 1), initialize NB, BE for both slotted and unslotted CSMA-CA.
uint8_t m_NB
Number of backoffs for the current transmission.
Ptr< UniformRandomVariable > m_random
Uniform random variable stream.
void SetMacMaxCSMABackoffs(uint8_t macMaxCSMABackoffs)
Set the maximum number of backoffs.
int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model.
uint8_t m_macMaxCSMABackoffs
Maximum number of backoffs.
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.
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 ",...
LrWpanPhyEnumeration
IEEE802.15.4-2006 PHY Emumerations Table 18 in section 6.2.3.
Definition: lr-wpan-phy.h:111
@ CHANNEL_ACCESS_FAILURE
CHANNEL_ACCESS_FAILURE.
Definition: lr-wpan-mac.h:77
@ MAC_CSMA_DEFERRED
MAC_CSMA_DEFERRED.
Definition: lr-wpan-mac.h:82
@ CHANNEL_IDLE
CHANNEL_IDLE.
Definition: lr-wpan-mac.h:78
@ IEEE_802_15_4_PHY_IDLE
Definition: lr-wpan-phy.h:116
@ macMinBE
The minimum value of the backoff exponent (BE) in the CSMA-CA algorithm.
#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:1326
Every class exported by the ns3 library is enclosed in the ns3 namespace.