lr-wpan: Beacon Enabled Mode Direct transmissions

This commit is contained in:
Alberto Gallegos Ramonet
2020-03-06 00:33:44 +01:00
committed by Tommaso Pecorella
parent 2fde925da7
commit c2054cb25b
20 changed files with 4001 additions and 331 deletions

View File

@@ -83,7 +83,6 @@ Tom Henderson (tomhend@u.washington.edu)
Christopher Hepner (hepner@hs-ulm.de)
Budiarto Herman (budiarto.herman@magister.fi)
Tom Hewer (tomhewer@mac.com)
Jack Higgins (shattered.feelings@gmail.com)
Kristian A. Hiorth (kristahi@ifi.uio.no)
Kim Højgaard-Hansen (kimrhh@gmail.com)
Chris Hood (chood8@gatech.edu)

View File

@@ -0,0 +1,211 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2019 Ritsumeikan University, Shiga, Japan.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Alberto Gallegos Ramonet <ramonet@fc.ritsumei.ac.jp>
*/
/*
* Coordinator End Device
* N0 <---------------- N1
* (dev0) (dev1)
*
* This example demonstrate the usage of the MAC primitives involved in
* direct transmissions for the beacon enabled mode of IEEE 802.15.4-2011.
* A single packet is sent from an end device to the coordinator during the CAP
* of the first incoming superframe.
*
* This example do not demonstrate a full protocol stack usage.
* For full protocol stack usage refer to 6lowpan examples.
*
*/
#include <ns3/log.h>
#include <ns3/core-module.h>
#include <ns3/lr-wpan-module.h>
#include <ns3/propagation-loss-model.h>
#include <ns3/propagation-delay-model.h>
#include <ns3/simulator.h>
#include <ns3/single-model-spectrum-channel.h>
#include <ns3/constant-position-mobility-model.h>
#include <ns3/packet.h>
#include <iostream>
using namespace ns3;
static void BeaconIndication (MlmeBeaconNotifyIndicationParams params, Ptr<Packet> p)
{
NS_LOG_UNCOND (Simulator::Now ().GetSeconds () << " secs | Received BEACON packet of size " << p->GetSize ());
}
static void DataIndication (McpsDataIndicationParams params, Ptr<Packet> p)
{
NS_LOG_UNCOND (Simulator::Now ().GetSeconds () << " secs | Received DATA packet of size " << p->GetSize ());
}
static void TransEndIndication (McpsDataConfirmParams params)
{
// In the case of transmissions with the Ack flag activated, the transaction is only
// successful if the Ack was received.
if (params.m_status == LrWpanMcpsDataConfirmStatus::IEEE_802_15_4_SUCCESS)
{
NS_LOG_UNCOND (Simulator::Now ().GetSeconds () << " secs | Transmission successfully sent");
}
}
static void DataIndicationCoordinator (McpsDataIndicationParams params, Ptr<Packet> p)
{
NS_LOG_UNCOND (Simulator::Now ().GetSeconds () << "s Coordinator Received DATA packet (size " << p->GetSize () << " bytes)");
}
static void StartConfirm (MlmeStartConfirmParams params)
{
if (params.m_status == MLMESTART_SUCCESS)
{
NS_LOG_UNCOND (Simulator::Now ().GetSeconds () << "Beacon status SUCESSFUL");
}
}
int main (int argc, char *argv[])
{
LogComponentEnableAll (LOG_PREFIX_TIME);
LogComponentEnableAll (LOG_PREFIX_FUNC);
LogComponentEnable ("LrWpanMac", LOG_LEVEL_INFO);
LogComponentEnable ("LrWpanCsmaCa", LOG_LEVEL_INFO);
LrWpanHelper lrWpanHelper;
// Create 2 nodes, and a NetDevice for each one
Ptr<Node> n0 = CreateObject <Node> ();
Ptr<Node> n1 = CreateObject <Node> ();
Ptr<LrWpanNetDevice> dev0 = CreateObject<LrWpanNetDevice> ();
Ptr<LrWpanNetDevice> dev1 = CreateObject<LrWpanNetDevice> ();
dev0->SetAddress (Mac16Address ("00:01"));
dev1->SetAddress (Mac16Address ("00:02"));
Ptr<SingleModelSpectrumChannel> channel = CreateObject<SingleModelSpectrumChannel> ();
Ptr<LogDistancePropagationLossModel> propModel = CreateObject<LogDistancePropagationLossModel> ();
Ptr<ConstantSpeedPropagationDelayModel> delayModel = CreateObject<ConstantSpeedPropagationDelayModel> ();
channel->AddPropagationLossModel (propModel);
channel->SetPropagationDelayModel (delayModel);
dev0->SetChannel (channel);
dev1->SetChannel (channel);
n0->AddDevice (dev0);
n1->AddDevice (dev1);
///////////////// Mobility ///////////////////////
Ptr<ConstantPositionMobilityModel> sender0Mobility = CreateObject<ConstantPositionMobilityModel> ();
sender0Mobility->SetPosition (Vector (0,0,0));
dev0->GetPhy ()->SetMobility (sender0Mobility);
Ptr<ConstantPositionMobilityModel> sender1Mobility = CreateObject<ConstantPositionMobilityModel> ();
sender1Mobility->SetPosition (Vector (0,10,0)); //10 m distance
dev1->GetPhy ()->SetMobility (sender1Mobility);
/////// MAC layer Callbacks hooks/////////////
MlmeStartConfirmCallback cb0;
cb0 = MakeCallback (&StartConfirm);
dev0->GetMac ()->SetMlmeStartConfirmCallback (cb0);
McpsDataConfirmCallback cb1;
cb1 = MakeCallback (&TransEndIndication);
dev1->GetMac ()->SetMcpsDataConfirmCallback (cb1);
MlmeBeaconNotifyIndicationCallback cb3;
cb3 = MakeCallback (&BeaconIndication);
dev1->GetMac ()->SetMlmeBeaconNotifyIndicationCallback (cb3);
McpsDataIndicationCallback cb4;
cb4 = MakeCallback (&DataIndication);
dev1->GetMac ()->SetMcpsDataIndicationCallback (cb4);
McpsDataIndicationCallback cb5;
cb5 = MakeCallback (&DataIndicationCoordinator);
dev0->GetMac ()->SetMcpsDataIndicationCallback (cb5);
//////////// Manual device association ////////////////////
// Note: We manually associate the devices to a PAN coordinator
// because currently there is no automatic association behavior (bootstrap);
// The PAN COORDINATOR does not need to associate or set its
// PAN Id or its own coordinator id, these are set
// by the MLME-start.request primitive when used.
dev1->GetMac ()->SetPanId (5);
dev1->GetMac ()->SetAssociatedCoor (Mac16Address ("00:01"));
///////////////////// Start transmitting beacons from coordinator ////////////////////////
MlmeStartRequestParams params;
params.m_panCoor = true;
params.m_PanId = 5;
params.m_bcnOrd = 14;
params.m_sfrmOrd = 6;
Simulator::ScheduleWithContext (1, Seconds (2.0),
&LrWpanMac::MlmeStartRequest,
dev0->GetMac (), params);
///////////////////// Transmission of data Packets from end device //////////////////////
Ptr<Packet> p1 = Create<Packet> (5);
McpsDataRequestParams params2;
params2.m_dstPanId = 5;
params2.m_srcAddrMode = SHORT_ADDR;
params2.m_dstAddrMode = SHORT_ADDR;
params2.m_dstAddr = Mac16Address ("00:01");
params2.m_msduHandle = 0;
// params2.m_txOptions = TX_OPTION_ACK; // Enable direct transmission with Ack
/////////////////////////////////////////////////////////////////////////////////////
// Examples of time parameters for transmissions in the first incoming superframe. //
/////////////////////////////////////////////////////////////////////////////////////
// 2.981 sec No time to finish CCA in CAP, the transmission at this time will cause
// the packet to be deferred to the next superframe.
// 2.98272 sec No time to finish random backoff delay in CAP, the transmission at this
// time will cause the packet to be deferred to the next superframe.
// 2.93 sec Enough time, the packet can be transmitted within the CAP of the first superframe
// MCPS-DATA.request Beacon enabled Direct Transmission (dev1)
// Frame transmission from End Device to Coordinator (Direct transmission)
Simulator::ScheduleWithContext (1, Seconds (2.93),
&LrWpanMac::McpsDataRequest,
dev1->GetMac (), params2, p1);
Simulator::Stop (Seconds (600));
Simulator::Run ();
Simulator::Destroy ();
return 0;
}

View File

@@ -15,3 +15,6 @@ def build(bld):
obj = bld.create_ns3_program('lr-wpan-error-distance-plot', ['lr-wpan', 'stats'])
obj.source = 'lr-wpan-error-distance-plot.cc'
obj = bld.create_ns3_program('lr-wpan-mlme', ['lr-wpan'])
obj.source = 'lr-wpan-mlme.cc'

View File

@@ -254,6 +254,63 @@ LrWpanHelper::AssociateToPan (NetDeviceContainer c, uint16_t panId)
return;
}
void
LrWpanHelper::AssociateToBeaconPan (NetDeviceContainer c, uint16_t panId, Mac16Address coor, uint8_t bcnOrd, uint8_t sfrmOrd)
{
NetDeviceContainer devices;
uint16_t id = 1;
uint8_t idBuf[2];
Mac16Address address;
if (bcnOrd > 14)
{
NS_LOG_DEBUG("The Beacon Order must be an int between 0 and 14");
return;
}
if ((sfrmOrd > 14) || (sfrmOrd > bcnOrd))
{
NS_LOG_DEBUG("The Superframe Order must be an int between 0 and 14, and less or equal to Beacon Order");
return;
}
for (NetDeviceContainer::Iterator i = c.Begin (); i != c.End (); i++)
{
Ptr<LrWpanNetDevice> device = DynamicCast<LrWpanNetDevice> (*i);
if (device)
{
idBuf[0] = (id >> 8) & 0xff;
idBuf[1] = (id >> 0) & 0xff;
address.CopyFrom (idBuf);
device->GetMac ()->SetShortAddress (address);
if (address == coor)
{
MlmeStartRequestParams params;
params.m_panCoor = true;
params.m_PanId = panId;
params.m_bcnOrd = bcnOrd;
params.m_sfrmOrd = sfrmOrd;
Ptr<UniformRandomVariable> uniformRandomVariable = CreateObject<UniformRandomVariable> ();;
Time jitter = Time (MilliSeconds (uniformRandomVariable->GetInteger (0, 10)));
Simulator::Schedule (jitter, &LrWpanMac::MlmeStartRequest,
device->GetMac (), params);
}
else
{
device->GetMac ()->SetPanId (panId);
device->GetMac ()->SetAssociatedCoor(coor);
}
id++;
}
}
return;
}
/**
* @brief Write a packet in a PCAP file
* @param file the output file

View File

@@ -112,6 +112,19 @@ public:
*/
void AssociateToPan (NetDeviceContainer c, uint16_t panId);
/**
* \brief Associate the nodes to the same PAN and initiate beacon enabled mode.
*
* \param c a set of nodes
* \param panID the PAN id
* \param coor the address of the PAN coordinator
* \param bcnOrd indicates the interval between beacons.
* The value must be an int between 0 and 14.
* \param sfrmOrd indicates the length of the superframe.
* The value must be an int between 0 and 14 and less or equal to the bcnOrd
*/
void AssociateToBeaconPan (NetDeviceContainer c, uint16_t panId, Mac16Address coor, uint8_t bcnOrd, uint8_t sfrmOrd);
/**
* Helper to enable all LrWpan log components with one statement
*/

View File

@@ -18,6 +18,7 @@
* Author:
* kwong yin <kwong-sang.yin@boeing.com>
* Sascha Alexander Jopen <jopen@cs.uni-bonn.de>
* Alberto Gallegos Ramonet <ramonet@fc.ritsumei.ac.jp>
*/
#include "lr-wpan-csmaca.h"
@@ -26,6 +27,10 @@
#include <ns3/log.h>
#include <algorithm>
#undef NS_LOG_APPEND_CONTEXT
#define NS_LOG_APPEND_CONTEXT \
std::clog << "[address " << m_mac->GetShortAddress () << "] ";
namespace ns3 {
NS_LOG_COMPONENT_DEFINE ("LrWpanCsmaCa");
@@ -50,14 +55,16 @@ LrWpanCsmaCa::LrWpanCsmaCa ()
m_isSlotted = false;
m_NB = 0;
m_CW = 2;
m_BLE = false;
m_macBattLifeExt = false;
m_macMinBE = 3;
m_macMaxBE = 5;
m_macMaxCSMABackoffs = 4;
m_aUnitBackoffPeriod = 20; //20 symbols
m_aUnitBackoffPeriod = 20; // symbols
m_random = CreateObject<UniformRandomVariable> ();
m_BE = m_macMinBE;
m_ccaRequestRunning = false;
m_randomBackoffPeriodsLeft = 0;
m_coorDest = false;
}
LrWpanCsmaCa::~LrWpanCsmaCa ()
@@ -68,7 +75,9 @@ LrWpanCsmaCa::~LrWpanCsmaCa ()
void
LrWpanCsmaCa::DoDispose ()
{
m_lrWpanMacStateCallback = MakeNullCallback< void, LrWpanMacState> ();
m_lrWpanMacStateCallback = MakeNullCallback <void, LrWpanMacState> ();
m_lrWpanMacTransCostCallback = MakeNullCallback <void, uint32_t> ();
Cancel ();
m_mac = 0;
}
@@ -169,26 +178,66 @@ LrWpanCsmaCa::GetUnitBackoffPeriod (void) const
return m_aUnitBackoffPeriod;
}
Time
LrWpanCsmaCa::GetTimeToNextSlot (void) const
{
NS_LOG_FUNCTION (this);
// TODO: Calculate the offset to the next slot.
// The reference for the beginning of the CAP changes depending
// on the data packet being sent from the Coordinator/outgoing frame (Tx beacon time reference)
// or other device/incoming frame (Rx beacon time reference).
return Seconds (0);
uint32_t elapsedSuperframe;
uint64_t currentTimeSymbols;
uint32_t symbolsToBoundary;
Time nextBoundary;
currentTimeSymbols = Simulator::Now ().GetSeconds () * m_mac->GetPhy ()->GetDataOrSymbolRate (false);
if (m_coorDest)
{
// Take the Incoming Frame Reference
elapsedSuperframe = currentTimeSymbols - m_mac->m_beaconRxTime;
}
else
{
// Take the Outgoing Frame Reference
elapsedSuperframe = currentTimeSymbols - m_mac->m_macBeaconTxTime;
}
symbolsToBoundary = m_aUnitBackoffPeriod - std::fmod (elapsedSuperframe,m_aUnitBackoffPeriod);
nextBoundary = MicroSeconds (symbolsToBoundary * 1000 * 1000 / m_mac->GetPhy ()->GetDataOrSymbolRate (false));
NS_LOG_DEBUG ("Elapsed symbols in CAP: " << elapsedSuperframe << "(" << elapsedSuperframe / m_aUnitBackoffPeriod << " backoff periods)");
NS_LOG_DEBUG ("Next backoff period boundary in " << symbolsToBoundary << " symbols ("
<< nextBoundary.GetSeconds () << " s)");
return nextBoundary;
}
void
LrWpanCsmaCa::Start ()
{
NS_LOG_FUNCTION (this);
m_NB = 0;
if (IsSlottedCsmaCa ())
{
// TODO: Check if the current PHY is using the Japanese band 950 Mhz:
// (IEEE_802_15_4_950MHZ_BPSK and IEEE_802_15_4_950MHZ_2GFSK)
// if in use, m_CW = 1.
// Currently 950 Mhz band PHYs are not supported in ns-3.
// To know the current used PHY, making the method for GetPhy()->GetMyPhyOption()
// public is necessary. Alternatively, the current PHY used
// can be known using phyCurrentPage variable.
m_CW = 2;
if (m_BLE)
if (m_macBattLifeExt)
{
m_BE = std::min (static_cast<uint8_t> (2), m_macMinBE);
}
@@ -196,23 +245,20 @@ LrWpanCsmaCa::Start ()
{
m_BE = m_macMinBE;
}
//TODO: for slotted, locate backoff period boundary. i.e. delay to the next slot boundary
// m_coorDest to decide between incoming and outgoing superframes times
m_coorDest = m_mac->isCoordDest ();
// Locate backoff period boundary. (i.e. a time delay to align with the next backoff period boundary)
Time backoffBoundary = GetTimeToNextSlot ();
m_randomBackoffEvent = Simulator::Schedule (backoffBoundary, &LrWpanCsmaCa::RandomBackoffDelay, this);
}
else
{
m_BE = m_macMinBE;
m_randomBackoffEvent = Simulator::ScheduleNow (&LrWpanCsmaCa::RandomBackoffDelay, this);
}
/*
* TODO: If using Backoff.cc (will need to modify Backoff::GetBackoffTime)
* Backoff.m_minSlots = 0;
* Backoff.m_ceiling = m_BE;
* Backoff.ResetBackoffTime(); //m_NB is same as m_numBackoffRetries in Backoff.h
* Backoff.m_maxRetries = macMaxCSMABackoffs;
* Backoff.m_slotTime = m_backoffPeriod;
*/
}
void
@@ -223,65 +269,166 @@ LrWpanCsmaCa::Cancel ()
m_canProceedEvent.Cancel ();
}
/*
* Delay for backoff period in the range 0 to 2^BE -1 units
* TODO: If using Backoff.cc (Backoff::GetBackoffTime) will need to be slightly modified
*/
void
LrWpanCsmaCa::RandomBackoffDelay ()
{
NS_LOG_FUNCTION (this);
uint64_t upperBound = (uint64_t) pow (2, m_BE) - 1;
uint64_t backoffPeriod;
Time randomBackoff;
uint64_t symbolRate;
bool isData = false;
uint32_t backoffPeriodsLeftInCap;
symbolRate = (uint64_t) m_mac->GetPhy ()->GetDataOrSymbolRate (false); //symbols per second
symbolRate = (uint64_t) m_mac->GetPhy ()->GetDataOrSymbolRate (isData); //symbols per second
backoffPeriod = (uint64_t)m_random->GetValue (0, upperBound+1); // num backoff periods
randomBackoff = MicroSeconds (backoffPeriod * GetUnitBackoffPeriod () * 1000 * 1000 / symbolRate);
// We should not recalculate the random backoffPeriods if we are in a slotted CSMA-CA and the
// transmission was previously deferred (m_randomBackoffPeriods != 0)
if (m_randomBackoffPeriodsLeft == 0 || IsUnSlottedCsmaCa ())
{
m_randomBackoffPeriodsLeft = (uint64_t)m_random->GetValue (0, upperBound + 1);
}
randomBackoff = MicroSeconds (m_randomBackoffPeriodsLeft * GetUnitBackoffPeriod () * 1000 * 1000 / symbolRate);
if (IsUnSlottedCsmaCa ())
{
NS_LOG_LOGIC ("Unslotted: requesting CCA after backoff of " << randomBackoff.GetMicroSeconds () << " us");
NS_LOG_DEBUG ("Unslotted CSMA-CA: requesting CCA after backoff of " << m_randomBackoffPeriodsLeft <<
" periods (" << randomBackoff.GetSeconds () << " s)");
m_requestCcaEvent = Simulator::Schedule (randomBackoff, &LrWpanCsmaCa::RequestCCA, this);
}
else
{
NS_LOG_LOGIC ("Slotted: proceeding after backoff of " << randomBackoff.GetMicroSeconds () << " us");
m_canProceedEvent = Simulator::Schedule (randomBackoff, &LrWpanCsmaCa::CanProceed, this);
// We must make sure there are enough backoff periods left in the CAP, otherwise we continue in
// the CAP of the next superframe after the transmission/reception of the beacon (and the IFS)
backoffPeriodsLeftInCap = GetBackoffPeriodsLeftInCap ();
NS_LOG_DEBUG ("Slotted CSMA-CA: proceeding after backoff of " << m_randomBackoffPeriodsLeft <<
" periods (" << randomBackoff.GetSeconds () << " s)");
Time rmnCapTime = MicroSeconds (backoffPeriodsLeftInCap * GetUnitBackoffPeriod () * 1000 * 1000 / symbolRate);
NS_LOG_DEBUG ("Backoff periods left in CAP: " << backoffPeriodsLeftInCap << " (" << rmnCapTime.GetSeconds () << " s)");
if (m_randomBackoffPeriodsLeft > backoffPeriodsLeftInCap)
{
m_randomBackoffPeriodsLeft = m_randomBackoffPeriodsLeft - backoffPeriodsLeftInCap;
NS_LOG_DEBUG ("No time in CAP to complete backoff delay, deferring to the next CAP");
m_endCapEvent = Simulator::Schedule (rmnCapTime, &LrWpanCsmaCa::DeferCsmaTimeout, this);
}
else
{
m_canProceedEvent = Simulator::Schedule (randomBackoff, &LrWpanCsmaCa::CanProceed, this);
}
}
}
// TODO : Determine if transmission can be completed before end of CAP for the slotted csmaca
// If not delay to the next CAP
uint32_t
LrWpanCsmaCa::GetBackoffPeriodsLeftInCap ()
{
uint64_t currentTimeSymbols;
uint16_t capSymbols;
uint64_t endCapSymbols;
uint64_t activeSlot;
//At this point, the currentTime should be aligned on a backoff period boundary
currentTimeSymbols = Simulator::Now ().GetMicroSeconds () * 1000 * 1000 *
m_mac->GetPhy ()->GetDataOrSymbolRate (false);
if (m_coorDest)
{ // Take Incoming frame reference
activeSlot = m_mac->m_incomingSuperframeDuration / 16;
capSymbols = activeSlot * (m_mac->m_incomingFnlCapSlot + 1);
endCapSymbols = m_mac->m_beaconRxTime + capSymbols;
}
else
{ // Take Outgoing frame reference
activeSlot = m_mac->m_superframeDuration / 16;
capSymbols = activeSlot * (m_mac->m_fnlCapSlot + 1);
endCapSymbols = m_mac->m_macBeaconTxTime + capSymbols;
}
return ((endCapSymbols - currentTimeSymbols) / m_aUnitBackoffPeriod);
}
void
LrWpanCsmaCa::CanProceed ()
{
NS_LOG_FUNCTION (this);
bool canProceed = true;
uint32_t backoffPeriodsLeftInCap;
uint16_t ccaSymbols;
uint32_t transactionSymbols;
uint64_t symbolRate;
if (m_BLE)
ccaSymbols = 0;
m_randomBackoffPeriodsLeft = 0;
symbolRate = (uint64_t) m_mac->GetPhy ()->GetDataOrSymbolRate (false);
backoffPeriodsLeftInCap = GetBackoffPeriodsLeftInCap ();
// TODO: On the 950 Mhz Band (Japanese Band)
// only a single CCA check is performed;
// the CCA check duration time is:
//
// CCA symbols = phyCCADuration * m_CW (1)
// other PHYs:
// CCA symbols = 8 * m_CW(2)
//
// note: phyCCADuration & 950Mhz band PHYs are
// not currently implemented in ns-3.
ccaSymbols += 8 * m_CW;
// The MAC sublayer shall proceed if the remaining CSMA-CA algorithm steps
// can be completed before the end of the CAP.
// See IEEE 802.15.4-2011 (Sections 5.1.1.1 and 5.1.1.4)
// Transaction = 2 CCA + frame transmission (PPDU) + turnaroudtime or Ack time (optional) + IFS
transactionSymbols = ccaSymbols + m_mac->GetTxPacketSymbols ();
if (m_mac->isTxAckReq ())
{
NS_LOG_DEBUG ("ACK duration symbols: " << m_mac->GetMacAckWaitDuration ());
transactionSymbols += m_mac->GetMacAckWaitDuration ();
}
else
{
//time the PHY takes to switch from TX to Rx or Rx to Tx
transactionSymbols += m_mac->GetPhy ()->aTurnaroundTime;
}
transactionSymbols += m_mac->GetIfsSize ();
// Report the transaction cost
if (!m_lrWpanMacTransCostCallback.IsNull ())
{
m_lrWpanMacTransCostCallback (transactionSymbols);
}
if (canProceed)
NS_LOG_DEBUG ("Total required transaction symbols: " << transactionSymbols);
if (transactionSymbols > (backoffPeriodsLeftInCap * GetUnitBackoffPeriod ()))
{
// TODO: For slotted, Perform CCA on backoff period boundary i.e. delay to next slot boundary
Time backoffBoundary = GetTimeToNextSlot ();
m_requestCcaEvent = Simulator::Schedule (backoffBoundary, &LrWpanCsmaCa::RequestCCA, this);
NS_LOG_DEBUG ("Transaction of " << transactionSymbols << " symbols " <<
"cannot be completed in CAP, deferring transmission to the next CAP");
Time waitTime = MicroSeconds (backoffPeriodsLeftInCap * GetUnitBackoffPeriod () * 1000 * 10000 / symbolRate);
NS_LOG_DEBUG ("Symbols left in CAP: " << backoffPeriodsLeftInCap * GetUnitBackoffPeriod () <<
" (" << waitTime.GetSeconds () << "s)");
m_endCapEvent = Simulator::Schedule (waitTime, &LrWpanCsmaCa::DeferCsmaTimeout, this);
}
else
{
Time nextCap = Seconds (0);
m_randomBackoffEvent = Simulator::Schedule (nextCap, &LrWpanCsmaCa::RandomBackoffDelay, this);
m_requestCcaEvent = Simulator::ScheduleNow (&LrWpanCsmaCa::RequestCCA,this);
}
}
void
@@ -292,9 +439,13 @@ LrWpanCsmaCa::RequestCCA ()
m_mac->GetPhy ()->PlmeCcaRequest ();
}
/*
* This function is called when the phy calls back after completing a PlmeCcaRequest
*/
void
LrWpanCsmaCa::DeferCsmaTimeout ()
{
NS_LOG_FUNCTION (this);
m_lrWpanMacStateCallback (MAC_CSMA_DEFERRED);
}
void
LrWpanCsmaCa::PlmeCcaConfirm (LrWpanPhyEnumeration status)
{
@@ -364,6 +515,15 @@ LrWpanCsmaCa::PlmeCcaConfirm (LrWpanPhyEnumeration status)
}
}
void
LrWpanCsmaCa::SetLrWpanMacTransCostCallback (LrWpanMacTransCostCallback c)
{
NS_LOG_FUNCTION (this);
m_lrWpanMacTransCostCallback = c;
}
void
LrWpanCsmaCa::SetLrWpanMacStateCallback (LrWpanMacStateCallback c)
{
@@ -371,6 +531,13 @@ LrWpanCsmaCa::SetLrWpanMacStateCallback (LrWpanMacStateCallback c)
m_lrWpanMacStateCallback = c;
}
void
LrWpanCsmaCa::SetBatteryLifeExtension (bool batteryLifeExtension)
{
m_macBattLifeExt = batteryLifeExtension;
}
int64_t
LrWpanCsmaCa::AssignStreams (int64_t stream)
{
@@ -385,4 +552,10 @@ LrWpanCsmaCa::GetNB (void)
return m_NB;
}
bool
LrWpanCsmaCa::GetBatteryLifeExtension (void)
{
return m_macBattLifeExt;
}
} //namespace ns3

View File

@@ -18,6 +18,7 @@
* Author:
* kwong yin <kwong-sang.yin@boeing.com>
* Sascha Alexander Jopen <jopen@cs.uni-bonn.de>
* Alberto Gallegos Ramonet <ramonet@fc.ritsumei.ac.jp>
*/
#ifndef LR_WPAN_CSMACA_H
@@ -34,10 +35,18 @@ class UniformRandomVariable;
/**
* \ingroup lr-wpan
*
* This method informs the MAC whether the channel is idle or busy.
* This method informs the MAC whether the channel is idle or busy.
*/
typedef Callback<void, LrWpanMacState> LrWpanMacStateCallback;
/**
* \ingroup lr-wpan
*
* This method informs the transaction cost in a slotted CSMA-CA data transmission.
* i.e. Reports number of symbols (time) it would take slotted CSMA-CA to process the current transaction.
* 1 Transaction = 2 CCA + frame transmission (PPDU) + turnaroudtime or Ack time (optional) + IFS
* See IEEE 802.15.4-2011 (Sections 5.1.1.1 and 5.1.1.4)
*/
typedef Callback<void, uint32_t> LrWpanMacTransCostCallback;
/**
* \ingroup lr-wpan
*
@@ -54,20 +63,17 @@ public:
* \return the object TypeId
*/
static TypeId GetTypeId (void);
/**
* Default constructor.
*/
LrWpanCsmaCa (void);
virtual ~LrWpanCsmaCa (void);
/**
* Set the MAC to which this CSMA/CA implementation is attached to.
*
* \param mac the used MAC
*/
void SetMac (Ptr<LrWpanMac> mac);
/**
* Get the MAC to which this CSMA/CA implementation is attached to.
*
@@ -79,26 +85,22 @@ public:
* Configure for the use of the slotted CSMA/CA version.
*/
void SetSlottedCsmaCa (void);
/**
* Configure for the use of the unslotted CSMA/CA version.
*/
void SetUnSlottedCsmaCa (void);
/**
* Check if the slotted CSMA/CA version is being used.
*
* \return true, if slotted CSMA/CA is used, false otherwise.
*/
bool IsSlottedCsmaCa (void) const;
/**
* Check if the unslotted CSMA/CA version is being used.
*
* \return true, if unslotted CSMA/CA is used, false otherwise.
*/
bool IsUnSlottedCsmaCa (void) const;
/**
* Set the minimum backoff exponent value.
* See IEEE 802.15.4-2006, section 7.4.2, Table 86.
@@ -106,7 +108,6 @@ public:
* \param macMinBE the minimum backoff exponent value
*/
void SetMacMinBE (uint8_t macMinBE);
/**
* Get the minimum backoff exponent value.
* See IEEE 802.15.4-2006, section 7.4.2, Table 86.
@@ -114,7 +115,6 @@ public:
* \return the minimum backoff exponent value
*/
uint8_t GetMacMinBE (void) const;
/**
* Set the maximum backoff exponent value.
* See IEEE 802.15.4-2006, section 7.4.2, Table 86.
@@ -122,7 +122,6 @@ public:
* \param macMaxBE the maximum backoff exponent value
*/
void SetMacMaxBE (uint8_t macMaxBE);
/**
* Get the maximum backoff exponent value.
* See IEEE 802.15.4-2006, section 7.4.2, Table 86.
@@ -130,7 +129,6 @@ public:
* \return the maximum backoff exponent value
*/
uint8_t GetMacMaxBE (void) const;
/**
* Set the maximum number of backoffs.
* See IEEE 802.15.4-2006, section 7.4.2, Table 86.
@@ -146,7 +144,6 @@ public:
* \return the maximum number of backoffs
*/
uint8_t GetMacMaxCSMABackoffs (void) const;
/**
* Set the number of symbols forming the basic time period used by the
* CSMA-CA algorithm.
@@ -155,7 +152,6 @@ public:
* \param unitBackoffPeriod the period length in symbols
*/
void SetUnitBackoffPeriod (uint64_t unitBackoffPeriod);
/**
* Get the number of symbols forming the basic time period used by the
* CSMA-CA algorithm.
@@ -164,30 +160,26 @@ public:
* \return the period length in symbols
*/
uint64_t GetUnitBackoffPeriod (void) const;
/**
* Get the amount of time from now to the beginning of the next slot.
* Locates the time to the next backoff period boundary and returns the
* amount of time left (in symbols).
*
* \return time offset to the next slot
*/
Time GetTimeToNextSlot (void) const;
/**
* Start CSMA-CA algorithm (step 1), initialize NB, BE for both slotted and unslotted
* CSMA-CA. For the slotted initialize CW plus also start on the backoff boundary
* CSMA-CA. For slotted CSMA-CA initializes CW and starts the backoff slot count.
*/
void Start (void);
/**
* Cancel CSMA-CA algorithm.
*/
void Cancel (void);
/**
* In step 2 of the CSMA-CA, perform a random backoff in the range of 0 to 2^BE -1
*/
void RandomBackoffDelay (void);
/**
* In the slotted CSMA-CA, after random backoff, determine if the remaining
* CSMA-CA operation can proceed, i.e. can the entire transactions can be
@@ -196,12 +188,15 @@ public:
* proceed function RequestCCA() is called.
*/
void CanProceed (void);
/**
* Request the Phy to perform CCA (Step 3)
*/
void RequestCCA (void);
/**
* The CSMA algorithm call this function at the end of the CAP to return the MAC state
* back to to IDLE after a transmission was deferred due to the lack of time in the CAP.
*/
void DeferCsmaTimeout (void);
/**
* IEEE 802.15.4-2006 section 6.2.2.2
* PLME-CCA.confirm status
@@ -214,7 +209,14 @@ public:
* treat as channel access failure (step 4).
*/
void PlmeCcaConfirm (LrWpanPhyEnumeration status);
/**
* Set the callback function to report a transaction cost in slotted CSMA-CA. The callback is
* triggered in CanProceed() after calculating the transaction cost (2 CCA checks,transmission cost, turnAroundTime, ifs)
* in the boundary of an Active Period.
*
* \param trans the transaction cost callback
*/
void SetLrWpanMacTransCostCallback (LrWpanMacTransCostCallback trans);
/**
* Set the callback function to the MAC. Used at the end of a Channel Assessment, as part of the
* interconnections between the CSMA-CA and the MAC. The callback
@@ -223,7 +225,12 @@ public:
* \param macState the mac state callback
*/
void SetLrWpanMacStateCallback (LrWpanMacStateCallback macState);
/**
* Set the value of the Battery Life Extension
*
* \param batteryLifeExtension the Battery Life Extension value active or inactive
*/
void SetBatteryLifeExtension (bool batteryLifeExtension);
/**
* Assign a fixed random variable stream number to the random variables
* used by this model. Return the number of streams that have been assigned.
@@ -232,13 +239,18 @@ public:
* \return the number of stream indices assigned by this model
*/
int64_t AssignStreams (int64_t stream);
/**
* Get the number of CSMA retries
*
* \returns the number of CSMA retries
*/
uint8_t GetNB (void);
/**
* Get the value of the Battery Life Extension
*
* \returns true or false to Battery Life Extension support
*/
bool GetBatteryLifeExtension (void);
private:
// Disable implicit copy constructors
@@ -251,90 +263,98 @@ private:
* \returns
*/
LrWpanCsmaCa& operator= (LrWpanCsmaCa const &);
virtual void DoDispose (void);
virtual void DoDispose (void);
/**
* \brief Get the periods left in the CAP portion of the Outgoing or Incoming frame.
* \return num of backoff periods left in the CAP
*/
uint32_t GetBackoffPeriodsLeftInCap ();
/**
* The callback to inform the cost of a transaction in slotted CSMA-CA.
*/
LrWpanMacTransCostCallback m_lrWpanMacTransCostCallback;
/**
* The callback to inform the configured MAC of the CSMA/CA result.
*/
LrWpanMacStateCallback m_lrWpanMacStateCallback;
/**
* Beacon-enabled slotted or nonbeacon-enabled unslotted CSMA-CA.
*/
bool m_isSlotted;
/**
* The MAC instance for which this CSMAÄ/CA implementation is configured.
* The MAC instance for which this CSMA/CA implemenation is configured.
*/
Ptr<LrWpanMac> m_mac;
/**
* Number of backoffs for the current transmission.
*/
uint8_t m_NB;
/**
* Contention window length (used in slotted ver only).
*/
uint8_t m_CW;
/**
* Backoff exponent.
*/
uint8_t m_BE;
/**
* Battery Life Extension.
*/
bool m_BLE;
bool m_macBattLifeExt;
/**
* Minimum backoff exponent. 0 - macMaxBE, default 3
*/
uint8_t m_macMinBE; //
/**
* Maximum backoff exponent. 3 - 8, default 5
*/
uint8_t m_macMaxBE;
/**
* Maximum number of backoffs. 0 - 5, default 4
*/
uint8_t m_macMaxCSMABackoffs;
/**
* Number of symbols per CSMA/CA time unit, default 20 symbols.
*/
uint64_t m_aUnitBackoffPeriod;
/**
* Count the number of remaining random backoff periods left to delay.
*/
uint64_t m_randomBackoffPeriodsLeft;
/**
* Uniform random variable stream.
*/
Ptr<UniformRandomVariable> m_random;
/**
* Scheduler event for the start of the next random backoff/slot.
*/
EventId m_randomBackoffEvent;
/**
* Scheduler event for the end of the current CAP
*/
EventId m_endCapEvent;
/**
* Scheduler event when to start the CCA after a random backoff.
*/
EventId m_requestCcaEvent;
/**
* Scheduler event for checking if we can complete the transmission before the
* end of the CAP.
*/
EventId m_canProceedEvent;
/**
* Flag indicating that the PHY is currently running a CCA. Used to prevent
* reporting the channel status to the MAC while canceling the CSMA algorithm.
*/
bool m_ccaRequestRunning;
/**
* Indicates whether the CSMA procedure is targeted for a message to be sent to the coordinator.
* Used to run slotted CSMA/CA on the incoming or outgoing superframe
* according to the target.
*/
bool m_coorDest;
};
}

View File

@@ -0,0 +1,491 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2019 Ritsumeikan University, Shiga, Japan.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Alberto Gallegos Ramonet <ramonet@fc.ritsumei.ac.jp>
*/
#include "lr-wpan-fields.h"
#include <ns3/log.h>
#include <ns3/address-utils.h>
namespace ns3 {
SuperframeField::SuperframeField ()
{
SetBeaconOrder (15);
SetSuperframeOrder (15);
SetFinalCapSlot (0);
SetBattLifeExt (false);
SetPanCoor (false);
SetAssocPermit (false);
}
void
SuperframeField::SetSuperframe (uint16_t superFrmSpec)
{
m_sspecBcnOrder = (superFrmSpec) & (0x0F); //Bits 0-3
m_sspecSprFrmOrder = (superFrmSpec >> 4) & (0x0F); //Bits 4-7
m_sspecFnlCapSlot = (superFrmSpec >> 8) & (0x0F); //Bits 8-11
m_sspecBatLifeExt = (superFrmSpec >> 12) & (0x01); //Bit 12
//Bit 13 (Reserved)
m_sspecPanCoor = (superFrmSpec >> 14) & (0x01); //Bit 14
m_sspecAssocPermit = (superFrmSpec >> 15) & (0x01); //Bit 15
}
void
SuperframeField::SetBeaconOrder (uint8_t bcnOrder)
{
if (bcnOrder > 15)
{
std::cout << "SuperframeField Beacon Order value must be 15 or less\n";
}
else
{
m_sspecBcnOrder = bcnOrder;
}
}
void
SuperframeField::SetSuperframeOrder (uint8_t frmOrder)
{
if (frmOrder > 15)
{
std::cout << "SuperframeField Frame Order value must be 15 or less\n";
}
else
{
m_sspecSprFrmOrder = frmOrder;
}
}
void
SuperframeField::SetFinalCapSlot (uint8_t capSlot)
{
if (capSlot > 15)
{
std::cout << "The final slot cannot greater than the slots in a CAP (15)\n";
}
else
{
m_sspecFnlCapSlot = capSlot;
}
}
void
SuperframeField::SetBattLifeExt (bool battLifeExt)
{
m_sspecBatLifeExt = battLifeExt;
}
void
SuperframeField::SetPanCoor (bool panCoor)
{
m_sspecPanCoor = panCoor;
}
void
SuperframeField::SetAssocPermit (bool assocPermit)
{
m_sspecAssocPermit = assocPermit;
}
uint8_t
SuperframeField::GetBeaconOrder (void) const
{
return m_sspecBcnOrder;
}
uint8_t
SuperframeField::GetFrameOrder (void) const
{
return m_sspecSprFrmOrder;
}
uint8_t
SuperframeField::GetFinalCapSlot (void) const
{
return m_sspecFnlCapSlot;
}
bool
SuperframeField::IsBattLifeExt (void) const
{
return m_sspecBatLifeExt;
}
bool
SuperframeField::IsPanCoor (void) const
{
return m_sspecPanCoor;
}
bool
SuperframeField::IsAssocPermit (void) const
{
return m_sspecAssocPermit;
}
uint16_t
SuperframeField::GetSuperframe (void) const
{
uint16_t superframe;
superframe = m_sspecBcnOrder & (0x0F); // Bits 0-3
superframe |= (m_sspecSprFrmOrder << 4) & (0x0F << 4); // Bits 4-7
superframe |= (m_sspecFnlCapSlot << 8) & (0x0F << 8); // Bits 8-11
superframe |= (m_sspecBatLifeExt << 12) & (0x01 << 12); // Bit 12
// Bit 13 (Reserved)
superframe |= (m_sspecPanCoor << 14) & (0x01 << 14); // Bit 14
superframe |= (m_sspecAssocPermit << 15) & (0x01 << 15); // Bit 15
return superframe;
}
uint32_t
SuperframeField::GetSerializedSize (void) const
{
return 2; // 2 Octets (superframeSpec)
}
Buffer::Iterator
SuperframeField::Serialize (Buffer::Iterator i) const
{
i.WriteHtolsbU16 (GetSuperframe ());
return i;
}
Buffer::Iterator
SuperframeField::Deserialize (Buffer::Iterator i)
{
uint16_t superframe = i.ReadLsbtohU16 ();
SetSuperframe (superframe);
return i;
}
/**
* output stream output operator
*
* \param os output stream
* \param superframeField The Superframe Specification Field
*
* \returns output stream
*/
std::ostream &
operator << (std::ostream &os, const SuperframeField &superframeField)
{
os << " Beacon Order = " << uint32_t (superframeField.GetBeaconOrder ())
<< ", Frame Order = " << uint32_t (superframeField.GetFrameOrder ())
<< ", Final CAP slot = " << uint32_t (superframeField.GetFinalCapSlot ())
<< ", Battery Life Ext = " << bool (superframeField.IsBattLifeExt ())
<< ", PAN Coordinator = " << bool (superframeField.IsPanCoor ())
<< ", Association Permit = " << bool (superframeField.IsAssocPermit ());
return os;
}
/***********************************************************
* Guaranteed Time Slots (GTS) Fields
***********************************************************/
GtsFields::GtsFields ()
{
// GTS Specification Field
m_gtsSpecDescCount = 0;
m_gtsSpecPermit = 0;
// GTS Direction Field
m_gtsDirMask = 0;
}
uint8_t
GtsFields::GetGtsSpecField (void) const
{
uint8_t gtsSpecField;
gtsSpecField = m_gtsSpecDescCount & (0x07); // Bits 0-2
// Bits 3-6 (Reserved)
gtsSpecField |= (m_gtsSpecPermit << 7) & (0x01 << 7); // Bit 7
return gtsSpecField;
}
uint8_t
GtsFields::GetGtsDirectionField (void) const
{
uint8_t gtsDirectionField;
gtsDirectionField = m_gtsDirMask & (0x7F); // Bit 0-6
// Bit 7 (Reserved)
return gtsDirectionField;
}
void
GtsFields::SetGtsSpecField (uint8_t gtsSpec)
{
m_gtsSpecDescCount = (gtsSpec) & (0x07); // Bits 0-2
// Bits 3-6 (Reserved)
m_gtsSpecPermit = (gtsSpec >> 7) & (0x01); // Bit 7
}
void
GtsFields::SetGtsDirectionField (uint8_t gtsDir)
{
m_gtsDirMask = (gtsDir) & (0x7F); // Bits 0-6
// Bit 7 (Reserved)
}
uint32_t
GtsFields::GetSerializedSize (void) const
{
uint32_t size;
size = 1; // 1 octet GTS Specification Field
if (m_gtsSpecDescCount > 0)
{
size += 1; // 1 octet GTS Direction Field
size += (m_gtsSpecDescCount * 3); // 3 octets per GTS descriptor
}
return size;
}
Buffer::Iterator
GtsFields::Serialize (Buffer::Iterator i) const
{
i.WriteU8 (GetGtsSpecField ());
if (m_gtsSpecDescCount > 0)
{
uint8_t gtsDescStartAndLenght;
i.WriteU8 (GetGtsDirectionField ());
for (int j = 0; j < m_gtsSpecDescCount; j++)
{
WriteTo (i,m_gtsList[j].m_gtsDescDevShortAddr);
gtsDescStartAndLenght = m_gtsList[j].m_gtsDescStartSlot & (0x0F);
gtsDescStartAndLenght = (m_gtsList[j].m_gtsDescLength << 4) & (0x0F);
i.WriteU8 (gtsDescStartAndLenght);
}
}
return i;
}
Buffer::Iterator
GtsFields::Deserialize (Buffer::Iterator i)
{
uint8_t gtsSpecField = i.ReadU8 ();
SetGtsSpecField (gtsSpecField);
if (m_gtsSpecDescCount > 0)
{
uint8_t gtsDirectionField = i.ReadU8 ();
SetGtsDirectionField (gtsDirectionField);
uint8_t gtsDescStartAndLenght;
for (int j = 0; j < m_gtsSpecDescCount; j++)
{
ReadFrom (i, m_gtsList[j].m_gtsDescDevShortAddr);
gtsDescStartAndLenght = i.ReadU8 ();
m_gtsList[j].m_gtsDescStartSlot = (gtsDescStartAndLenght) & (0x0F);
m_gtsList[j].m_gtsDescLength = (gtsDescStartAndLenght >> 4) & (0x0F);
}
}
return i;
}
/***********************************************************
* Pending Address Fields
***********************************************************/
PendingAddrFields::PendingAddrFields ()
{
m_pndAddrSpecNumShortAddr = 0;
m_pndAddrSpecNumExtAddr = 0;
}
uint8_t
PendingAddrFields::GetNumShortAddr (void) const
{
return m_pndAddrSpecNumShortAddr;
}
uint8_t
PendingAddrFields::GetNumExtAddr (void) const
{
return m_pndAddrSpecNumExtAddr;
}
uint8_t
PendingAddrFields::GetPndAddrSpecField (void) const
{
uint8_t pndAddrSpecField;
pndAddrSpecField = m_pndAddrSpecNumShortAddr & (0x07); // Bits 0-2
// Bit 3 (Reserved)
pndAddrSpecField |= (m_pndAddrSpecNumExtAddr << 4) & (0x07 << 4); // Bits 4-6
// Bit 7 (Reserved)
return pndAddrSpecField;
}
void
PendingAddrFields::AddAddress (Mac16Address shortAddr)
{
uint8_t totalPendAddr = m_pndAddrSpecNumShortAddr + m_pndAddrSpecNumExtAddr;
if (totalPendAddr == 7)
{
return;
}
else
{
m_shortAddrList[m_pndAddrSpecNumShortAddr] = shortAddr;
m_pndAddrSpecNumShortAddr++;
}
}
void
PendingAddrFields::AddAddress (Mac64Address extAddr)
{
uint8_t totalPendAddr = m_pndAddrSpecNumShortAddr + m_pndAddrSpecNumExtAddr;
if (totalPendAddr == 7)
{
return;
}
else
{
m_extAddrList[m_pndAddrSpecNumExtAddr] = extAddr;
m_pndAddrSpecNumExtAddr++;
}
}
bool
PendingAddrFields::SearchAddress (Mac16Address shortAddr)
{
for (int j = 0; j <= m_pndAddrSpecNumShortAddr; j++)
{
if (shortAddr == m_shortAddrList[j])
{
return true;
}
}
return false;
}
bool
PendingAddrFields::SearchAddress (Mac64Address extAddr)
{
for (int j = 0; j <= m_pndAddrSpecNumExtAddr; j++)
{
if (extAddr == m_extAddrList[j])
{
return true;
}
}
return false;
}
void
PendingAddrFields::SetPndAddrSpecField (uint8_t pndAddrSpecField)
{
m_pndAddrSpecNumShortAddr = (pndAddrSpecField) & (0x07); // Bit 0-2
// Bit 3
m_pndAddrSpecNumExtAddr = (pndAddrSpecField >> 4) & (0x07); // Bit 4-6
// Bit 7
}
uint32_t
PendingAddrFields::GetSerializedSize (void) const
{
uint32_t size;
size = 1; // 1 octet (Pending Address Specification Field)
size = size + (m_pndAddrSpecNumShortAddr * 2); // X octets (Short Pending Address List)
size = size + (m_pndAddrSpecNumExtAddr * 8); // X octets (Extended Pending Address List)
return size;
}
Buffer::Iterator
PendingAddrFields::Serialize (Buffer::Iterator i) const
{
i.WriteU8 (GetPndAddrSpecField ());
for (int j = 0; j < m_pndAddrSpecNumShortAddr; j++)
{
WriteTo (i,m_shortAddrList[j]);
}
for (int k = 0; k < m_pndAddrSpecNumExtAddr; k++ )
{
WriteTo (i,m_extAddrList[k]);
}
return i;
}
Buffer::Iterator
PendingAddrFields::Deserialize (Buffer::Iterator i)
{
uint8_t pndAddrSpecField = i.ReadU8 ();
SetPndAddrSpecField (pndAddrSpecField);
for (int j = 0; j < m_pndAddrSpecNumShortAddr; j++)
{
ReadFrom (i, m_shortAddrList[j]);
}
for (int k = 0; k < m_pndAddrSpecNumExtAddr; k++)
{
ReadFrom (i, m_extAddrList[k]);
}
return i;
}
/**
* output stream output operator
*
* \param os output stream
* \param PendingAddrField the Pending Address Specification Field
*
* \returns output stream
*/
std::ostream &
operator << (std::ostream &os, const PendingAddrFields &pendingAddrFields)
{
os << " Num. Short Addr = " << uint32_t (pendingAddrFields.GetNumShortAddr ())
<< ", Num. Ext Addr = " << uint32_t (pendingAddrFields.GetNumExtAddr ());
return os;
}
} // ns-3 namespace

View File

@@ -0,0 +1,314 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2019 Ritsumeikan University, Shiga, Japan.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Alberto Gallegos Ramonet <ramonet@fc.ritsumei.ac.jp>
*
* This file implements Information Fields present in IEEE 802.15.4-2011.
* Information Fields are in practice similar to the Information Elements(IE)
* introduced in later revisions of the standard, however, they lack
* descriptors and common format unlike the IEs. To keep this implementation
* consistent with the IEEE 802.15.4-2011 std. the present file implements
* Information Fields not Information Elements.
*/
#ifndef LR_WPAN_FIELDS_H
#define LR_WPAN_FIELDS_H
#include <ns3/mac16-address.h>
#include <ns3/mac64-address.h>
#include "ns3/buffer.h"
#include <array>
namespace ns3 {
/**
* The device Capabilities.
*/
enum DeviceType
{
RFD = 0, //!< Reduced Functional Device (RFD)
FFD = 1 //!< Full Functional Device (FFD)
};
/**
* \ingroup lr-wpan
* Represent the Superframe Specification information field.
* See IEEE 802.15.4-2011 Section 5.2.2.1.2 Figure 41
*/
class SuperframeField
{
public:
SuperframeField ();
/**
* Set the whole Superframe Specification Information field.
* \param superFrm The Superframe Specification information field.
*/
void SetSuperframe (uint16_t superFrm);
/**
* Set the superframe specification Beacon Order field.
* \param bcnOrder The beacon order value to set in the superframe.
*/
void SetBeaconOrder (uint8_t bcnOrder);
/**
* Set the superframe specification Superframe Order field.
* \param frmOrder The frame Order value to set on the superframe.
*/
void SetSuperframeOrder (uint8_t frmOrder);
/**
* Set the superframe specification Final CAP slot field.
* \param capSlot Set the final slot of the Contention Access Period (CAP).
*/
void SetFinalCapSlot (uint8_t capSlot);
/**
* Set the Superframe Specification Battery Life Extension (BLE).
* \param battLifeExt Sets true or false the value of the Battery Life Extension flag of the superframe field.
*/
void SetBattLifeExt (bool battLifeExt);
/**
* Set the Superframe Specification PAN coordinator field.
* \param panCoor set true or false the value for the PAN Coordinator flag of the superframe field.
*/
void SetPanCoor (bool panCoor);
/**
* Set the Superframe Specification Association Permit field.
* \param assocPermit set true or false the value of the Association Permit flag of the superframe field.
*/
void SetAssocPermit (bool assocPermit);
/**
* Get the Superframe Specification Beacon Order field.
*/
uint8_t GetBeaconOrder (void) const;
/**
* Get the Superframe Specification Frame Order field.
*/
uint8_t GetFrameOrder (void) const;
/**
* Check if the Final CAP Slot bit is enabled.
*/
uint8_t GetFinalCapSlot (void) const;
/**
* Check if the Battery Life Extension bit is enabled.
*/
bool IsBattLifeExt (void) const;
/**
* Check if the PAN Coordinator bit is enabled.
*/
bool IsPanCoor (void) const;
/**
* Check if the Association Permit bit is enabled.
*/
bool IsAssocPermit (void) const;
/**
* Get the Superframe specification information field.
* \return the Superframe Specification Information field bits.
*/
uint16_t GetSuperframe (void) const;
/**
* Get the size of the serialized Superframe specification information field.
* \return the size of the serialized field.
*/
uint32_t GetSerializedSize (void) const;
/**
* Serialize the entire superframe specification field.
* \param i an iterator which points to where the superframe specification field should be written.
* \return an iterator.
*/
Buffer::Iterator Serialize (Buffer::Iterator i) const;
/**
* Deserialize the entire superframe specification field.
* \param i an iterator which points to where the superframe specification field should be read.
* \return an iterator.
*/
Buffer::Iterator Deserialize (Buffer::Iterator i);
private:
// Superframe Specification field
// See IEEE 802.14.15-2011 5.2.2.1.2
uint8_t m_sspecBcnOrder; //!< Superframe Specification field Beacon Order (Bit 0-3)
uint8_t m_sspecSprFrmOrder; //!< Superframe Specification field Superframe Order (Bit 4-7)
uint8_t m_sspecFnlCapSlot; //!< Superframe Specification field Final CAP slot (Bit 8-11)
bool m_sspecBatLifeExt; //!< Superframe Specification field Battery Life Extension (Bit 12)
//!< Superframe Specification field Reserved (not necessary) (Bit 13)
bool m_sspecPanCoor; //!< Superframe Specification field PAN Coordinator (Bit 14)
bool m_sspecAssocPermit; //!< Superframe Specification field Association Permit (Bit 15)
};
std::ostream &operator << (std::ostream &os, const SuperframeField &superframeField);
/**
* \ingroup lr-wpan
* Represent the GTS information fields.
* See IEEE 802.15.4-2011 Section 5.2.2 Figure 39
*/
class GtsFields
{
public:
GtsFields ();
/**
* Get the GTS Specification Field from the GTS Fields
* \return The GTS Spcecification Field
*/
uint8_t GetGtsSpecField (void) const;
/**
* Get the GTS Direction Field from the GTS Fields
* \return The GTS Direction Field
*/
uint8_t GetGtsDirectionField (void) const;
/**
* Set the GTS Specification Field to the GTS Fields
* gtsSpec The GTS Specification Field to set.
*/
void SetGtsSpecField (uint8_t gtsSpec);
/**
* Set the GTS direction field to the GTS Fields
* gtsDir The GTS Direction Field to set
*/
void SetGtsDirectionField (uint8_t gtsDir);
/**
* Get the size of the serialized GTS fields.
* \return the size of the serialized fields.
*/
uint32_t GetSerializedSize (void) const;
/**
* Serialize the entire GTS fields.
* \param i an iterator which points to where the superframe specification field should be written.
* \return an iterator.
*/
Buffer::Iterator Serialize (Buffer::Iterator i) const;
/**
* Deserialize the entire GTS fields.
* \param i an iterator which points to where the superframe specification field should be read.
* \return an iterator.
*/
Buffer::Iterator Deserialize (Buffer::Iterator i);
private:
//GTS Descriptor
struct gtsDescriptor
{
Mac16Address m_gtsDescDevShortAddr; //!< GTS Descriptor Device Short Address (Bit 0-15)
u_int8_t m_gtsDescStartSlot; //!< GTS Descriptor GTS Starting Slot(Bit 16-19)
u_int8_t m_gtsDescLength; //!< GTS Descriptor GTS Length (Bit 20-23)
};
//GTS specification field
u_int8_t m_gtsSpecDescCount; //!< GTS specification field Descriptor Count (Bit 0-2)
//!< GTS specification field Reserved (Not necessary) (Bit 3-6)
u_int8_t m_gtsSpecPermit; //!< GTS specification field GTS Permit (Bit 7)
//GTS Direction field
u_int8_t m_gtsDirMask; //!< GTS Direction field Directions Mask (Bit 0-6)
//!< GTS Direction field Reserved (Not Necessary) (Bit 7)
//GTS List
gtsDescriptor m_gtsList[6]; //!< GTS List field (maximum descriptors stored == 7)
};
std::ostream &operator << (std::ostream &os, const GtsFields &gtsFields);
/**
* \ingroup lr-wpan
* Represent the Pending Address Specification field.
* See IEEE 802.15.4-2011 Section 5.2.2.1.6. Figure 45
*/
class PendingAddrFields
{
public:
PendingAddrFields ();
/**
* Add a short Pending Address to the Address List.
* \param shortAddr The extended Pending Address List.
*/
void AddAddress (Mac16Address shortAddr);
/**
* Add a extended Pending Address to the Address List.
* \param extAddr The extended Pending Address List.
*/
void AddAddress (Mac64Address extAddr);
/**
* Search for the short Pending Address in the Address List.
* \param shortAddr The extended Address to look in the Address List.
* \return True if the address exist in the extended Address List.
*/
bool SearchAddress (Mac16Address shortAddr);
/**
* Search for the extended Pending Address in the Address List.
* \param extAddr The extended Address to look in the Address List.
* \return True if the address exist in the extended Address List.
*/
bool SearchAddress (Mac64Address extAddr);
/**
* Get the whole Pending Address Specification Field from the Pending Address Fields.
* \return The Pending Address Specification Field.
*/
uint8_t GetPndAddrSpecField (void) const;
/**
* Get the number of Short Pending Address indicated in the Pending Address Specification Field.
* \return The number Short Pending Address.
*/
uint8_t GetNumShortAddr (void) const;
/**
* Get the number of Extended Pending Address indicated in the Pending Address Specification Field.
* \return The number Short Pending Address.
*/
uint8_t GetNumExtAddr (void) const;
/**
* Set the whole Pending Address Specification field. This field is part of the
* Pending Address Fields header.
* \param pndAddrSpecField The Pending Address Specification Field
*/
void SetPndAddrSpecField (uint8_t pndAddrSpecField);
/**
* Get the size of the serialized Pending Address Fields.
* \return the size of the serialized fields.
*/
uint32_t GetSerializedSize (void) const;
/**
* Serialize the entire Pending Address Fields.
* \param i an iterator which points to where the Pending Address Fields should be written.
* \return an iterator.
*/
Buffer::Iterator Serialize (Buffer::Iterator i) const;
/**
* Deserialize the all the Pending Address Fields.
* \param start an iterator which points to where the Pending Address Fields should be read.
* \return an iterator.
*/
Buffer::Iterator Deserialize (Buffer::Iterator i);
private:
// Pending Address Specification Field
uint8_t m_pndAddrSpecNumShortAddr; //!< Pending Address Specification field Number of Short Address (Bits 0-2)
//!< Pending Address Specification field Reserved (Not Necessary)(Bit 3)
uint8_t m_pndAddrSpecNumExtAddr; //!< Pending Address Specification field Number of Extended Address (Bits 4-6)
//!< Pending Address Specification field Reserved (Not Necessary) (Bit 7)
// Address List
std::array <Mac16Address,7> m_shortAddrList; //!< Pending Short Address List
std::array<Mac64Address,7> m_extAddrList; //!< Pending Extended Address List
};
std::ostream &operator << (std::ostream &os, const PendingAddrFields &pendingAddrFields);
} //end namespace ns3
#endif /* LR_WPAN_FIELDS_H */

View File

@@ -252,31 +252,24 @@ LrWpanMacHeader::GetKeyIdIndex (void) const
return(m_auxKeyIdKeyIndex);
}
bool
LrWpanMacHeader::IsBeacon (void) const
{
return(m_fctrlFrmType == LRWPAN_MAC_BEACON);
}
bool
LrWpanMacHeader::IsData (void) const
{
return(m_fctrlFrmType == LRWPAN_MAC_DATA);
}
bool
LrWpanMacHeader::IsAcknowledgment (void) const
{
return(m_fctrlFrmType == LRWPAN_MAC_ACKNOWLEDGMENT);
}
bool
LrWpanMacHeader::IsCommand (void) const
{
@@ -787,9 +780,6 @@ LrWpanMacHeader::Deserialize (Buffer::Iterator start)
return i.GetDistanceFrom (start);
}
// ----------------------------------------------------------------------------------------------------------
} //namespace ns3

View File

@@ -54,17 +54,16 @@ class LrWpanMacHeader : public Header
{
public:
/**
* The possible MAC types, see IEEE 802.15.4-2006, Table 79.
*/
enum LrWpanMacType
{
LRWPAN_MAC_BEACON = 0, //!< LRWPAN_MAC_BEACON
LRWPAN_MAC_DATA = 1, //!< LRWPAN_MAC_DATA
LRWPAN_MAC_ACKNOWLEDGMENT = 2,//!< LRWPAN_MAC_ACKNOWLEDGMENT
LRWPAN_MAC_COMMAND = 3, //!< LRWPAN_MAC_COMMAND
LRWPAN_MAC_RESERVED //!< LRWPAN_MAC_RESERVED
LRWPAN_MAC_BEACON = 0, //!< LRWPAN_MAC_BEACON
LRWPAN_MAC_DATA = 1, //!< LRWPAN_MAC_DATA
LRWPAN_MAC_ACKNOWLEDGMENT = 2, //!< LRWPAN_MAC_ACKNOWLEDGMENT
LRWPAN_MAC_COMMAND = 3, //!< LRWPAN_MAC_COMMAND
LRWPAN_MAC_RESERVED //!< LRWPAN_MAC_RESERVED
};
/**
@@ -113,37 +112,31 @@ public:
* \return the Frame control field
*/
uint16_t GetFrameControl (void) const;
/**
* Check if Security Enabled bit of Frame Control is enabled
* \return true if Security Enabled bit is enabled
*/
bool IsSecEnable (void) const;
/**
* Check if Frame Pending bit of Frame Control is enabled
* \return true if Frame Pending bit is enabled
*/
bool IsFrmPend (void) const;
/**
* Check if Ack. Request bit of Frame Control is enabled
* \return true if Ack. Request bit is enabled
*/
bool IsAckReq (void) const;
/**
* Check if PAN ID Compression bit of Frame Control is enabled
* \return true if PAN ID Compression bit is enabled
*/
bool IsPanIdComp (void) const;
/**
* Get the Reserved bits of Frame control field
* \return the Reserved bits
*/
uint8_t GetFrmCtrlRes (void) const;
/**
* Get the Dest. Addressing Mode of Frame control field
* \return the Dest. Addressing Mode bits
@@ -159,13 +152,11 @@ public:
* \return the Source Addressing Mode bits
*/
uint8_t GetSrcAddrMode (void) const;
/**
* Get the frame Sequence number
* \return the sequence number
*/
uint8_t GetSeqNum (void) const;
/**
* Get the Destination PAN ID
* \return the Destination PAN ID
@@ -196,7 +187,6 @@ public:
* \return the Source Extended address
*/
Mac64Address GetExtSrcAddr (void) const;
/**
* Get the Auxiliary Security Header - Security Control Octect
* \return the Auxiliary Security Header - Security Control Octect
@@ -223,7 +213,6 @@ public:
* \return the Auxiliary Security Header - Security Control - Reserved bits
*/
uint8_t GetSecCtrlReserved (void) const;
/**
* Get the Auxiliary Security Header - Key Identifier - Key Source (2 Octects)
* \return the Auxiliary Security Header - Key Identifier - Key Source (2 Octects)
@@ -239,7 +228,6 @@ public:
* \return the Auxiliary Security Header - Key Identifier - Key Index
*/
uint8_t GetKeyIdIndex (void) const;
/**
* Returns true if the header is a beacon
* \return true if the header is a beacon
@@ -260,59 +248,48 @@ public:
* \return true if the header is a command
*/
bool IsCommand (void) const;
/**
* Set the Frame Control field "Frame Type" bits
* \param wpanMacType the frame type
*/
void SetType (enum LrWpanMacType wpanMacType);
/**
* Set the whole Frame Control field
* \param frameControl the Frame Control field
*/
void SetFrameControl (uint16_t frameControl);
/**
* Set the Frame Control field "Security Enabled" bit to true
*/
void SetSecEnable (void);
/**
* Set the Frame Control field "Security Enabled" bit to false
*/
void SetSecDisable (void);
/**
* Set the Frame Control field "Frame Pending" bit to true
*/
void SetFrmPend (void);
/**
* Set the Frame Control field "Frame Pending" bit to false
*/
void SetNoFrmPend (void);
/**
* Set the Frame Control field "Ack. Request" bit to true
*/
void SetAckReq (void);
/**
* Set the Frame Control field "Ack. Request" bit to false
*/
void SetNoAckReq (void);
/**
* Set the Frame Control field "PAN ID Compression" bit to true
*/
void SetPanIdComp (void);
/**
* Set the Frame Control field "PAN ID Compression" bit to false
*/
void SetNoPanIdComp (void);
/**
* Set the Frame Control field "Reserved" bits
* \param res reserved bits
@@ -333,13 +310,11 @@ public:
* \param addrMode Source address mode
*/
void SetSrcAddrMode (uint8_t addrMode);
/**
* Set the Sequence number
* \param seqNum sequence number
*/
void SetSeqNum (uint8_t seqNum);
/* The Source/Destination Addressing fields are only set if SrcAddrMode/DstAddrMode are set */
/**
* Set Source address fields
@@ -377,7 +352,6 @@ public:
* \param frmCntr the "Frame Counter" octect
*/
void SetFrmCounter (uint32_t frmCntr);
/**
* Set the Security Control field "Security Level" bits (3 bits)
* \param secLevel the "Security Level" bits
@@ -388,13 +362,11 @@ public:
* \param keyIdMode the "Key Identifier Mode" bits
*/
void SetKeyIdMode (uint8_t keyIdMode);
/**
* Set the Security Control field "Reserved" bits (3 bits)
* \param res the "Reserved" bits
*/
void SetSecCtrlReserved (uint8_t res);
/* Variable length will be dependent on Key Id Mode*/
/**
* Set the Key Index
@@ -413,7 +385,6 @@ public:
* \param keyIndex the Key index
*/
void SetKeyId (uint64_t keySrc, uint8_t keyIndex);
/**
* \brief Get the type ID.
* \return the object TypeId

View File

@@ -0,0 +1,240 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2020 Ritsumeikan University, Shiga, Japan.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Alberto Gallegos Ramonet <ramonet@fc.ritsumei.ac.jp>
*/
#include "lr-wpan-mac-pl-headers.h"
#include <ns3/simulator.h>
namespace ns3 {
/***********************************************************
* Beacon MAC Payload
***********************************************************/
BeaconPayloadHeader::BeaconPayloadHeader ()
{
}
NS_OBJECT_ENSURE_REGISTERED (BeaconPayloadHeader);
TypeId
BeaconPayloadHeader::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::BeaconPayloadHeader")
.SetParent<Header> ()
.SetGroupName ("LrWpan")
.AddConstructor<BeaconPayloadHeader> ()
;
return tid;
}
TypeId
BeaconPayloadHeader::GetInstanceTypeId (void) const
{
return GetTypeId ();
}
uint32_t
BeaconPayloadHeader::GetSerializedSize (void) const
{
uint32_t size = 0;
size += m_superframeField.GetSerializedSize ();
size += m_gtsFields.GetSerializedSize ();
size += m_pndAddrFields.GetSerializedSize ();
return size;
}
void
BeaconPayloadHeader::Serialize (Buffer::Iterator start) const
{
Buffer::Iterator i = start;
i = m_superframeField.Serialize (i);
i = m_gtsFields.Serialize (i);
i = m_pndAddrFields.Serialize (i);
}
uint32_t
BeaconPayloadHeader::Deserialize (Buffer::Iterator start)
{
Buffer::Iterator i = start;
i = m_superframeField.Deserialize (i);
i = m_gtsFields.Deserialize (i);
i = m_pndAddrFields.Deserialize (i);
return i.GetDistanceFrom (start);
}
void
BeaconPayloadHeader::Print (std::ostream &os) const
{
os << "| Superframe Spec Field | = " << m_superframeField
<< "| GTS Spec Field | = " << m_gtsFields.GetGtsSpecField ()
<< "| Pending Spec Field| =" << m_pndAddrFields.GetPndAddrSpecField ();
}
void
BeaconPayloadHeader::SetSuperframeSpecField (SuperframeField sf)
{
m_superframeField = sf;
}
void
BeaconPayloadHeader::SetGtsFields (GtsFields gtsFields)
{
m_gtsFields = gtsFields;
}
void
BeaconPayloadHeader::SetPndAddrFields (PendingAddrFields pndAddrFields)
{
m_pndAddrFields = pndAddrFields;
}
SuperframeField
BeaconPayloadHeader::GetSuperframeSpecField (void) const
{
return m_superframeField;
}
GtsFields
BeaconPayloadHeader::GetGtsFields (void) const
{
return m_gtsFields;
}
PendingAddrFields
BeaconPayloadHeader::GetPndAddrFields (void) const
{
return m_pndAddrFields;
}
/***********************************************************
* Command MAC Payload
***********************************************************/
CommandPayloadHeader::CommandPayloadHeader ()
{
SetCommandFrameType (CMD_RESERVED);
}
CommandPayloadHeader::CommandPayloadHeader (enum MacCommand macCmd)
{
SetCommandFrameType (macCmd);
}
NS_OBJECT_ENSURE_REGISTERED (CommandPayloadHeader);
TypeId
CommandPayloadHeader::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::CommandPayloadHeader")
.SetParent<Header> ()
.SetGroupName ("LrWpan")
.AddConstructor<CommandPayloadHeader> ()
;
return tid;
}
TypeId
CommandPayloadHeader::GetInstanceTypeId (void) const
{
return GetTypeId ();
}
uint32_t
CommandPayloadHeader::GetSerializedSize (void) const
{
uint32_t size = 1;
return size;
}
void
CommandPayloadHeader::Serialize (Buffer::Iterator start) const
{
Buffer::Iterator i = start;
i.WriteU8 (m_cmdFrameId);
}
uint32_t
CommandPayloadHeader::Deserialize (Buffer::Iterator start)
{
Buffer::Iterator i = start;
m_cmdFrameId = i.ReadU8 ();
return i.GetDistanceFrom (start);
}
void
CommandPayloadHeader::Print (std::ostream &os) const
{
os << "| MAC Command Frame ID | = " << (uint32_t) m_cmdFrameId;
}
void
CommandPayloadHeader::SetCommandFrameType (MacCommand macCommand)
{
m_cmdFrameId = macCommand;
}
CommandPayloadHeader::MacCommand
CommandPayloadHeader::GetCommandFrameType (void) const
{
switch (m_cmdFrameId)
{
case 0x01:
return ASSOCIATION_REQ;
break;
case 0x02:
return ASSOCIATION_RESP;
break;
case 0x03:
return DISASSOCIATION_NOTIF;
break;
case 0x04:
return DATA_REQ;
break;
case 0x05:
return PANID_CONFLICT;
break;
case 0x06:
return ORPHAN_NOTIF;
break;
case 0x07:
return BEACON_REQ;
break;
case 0x08:
return COOR_REALIGN;
break;
case 0x09:
return GTS_REQ;
break;
default:
return CMD_RESERVED;
}
}
} // ns3 namespace

View File

@@ -0,0 +1,165 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2019 Ritsumeikan University, Shiga, Japan.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Alberto Gallegos Ramonet <ramonet@fc.ritsumei.ac.jp>
*/
#ifndef LR_WPAN_MAC_PL_HEADERS_H
#define LR_WPAN_MAC_PL_HEADERS_H
#include <ns3/header.h>
#include <ns3/mac16-address.h>
#include <ns3/mac64-address.h>
#include "lr-wpan-fields.h"
namespace ns3 {
/**
* \ingroup lr-wpan
* Implements the header for the MAC payload beacon frame according to
* the IEEE 802.15.4-2011 Std.
*/
class BeaconPayloadHeader : public Header
{
public:
BeaconPayloadHeader ();
/**
* \brief Get the type ID.
* \return the object TypeId
*/
static TypeId GetTypeId (void);
TypeId GetInstanceTypeId (void) const;
uint32_t GetSerializedSize (void) const;
virtual void Serialize (Buffer::Iterator start) const;
uint32_t Deserialize (Buffer::Iterator start);
void Print (std::ostream &os) const;
/**
* Set the superframe specification field to the beacon payload header.
* \param sfrmField The superframe specification field
*/
void SetSuperframeSpecField (SuperframeField sfrmField);
/**
* Set the superframe Guaranteed Time Slot (GTS) fields to the beacon payload header.
* \param gtsFields The GTS fields.
*/
void SetGtsFields (GtsFields gtsFields);
/**
* Set the superframe Pending Address fields to the beacon payload header.
* \param pndAddrFields The Pending Address fields.
*/
void SetPndAddrFields (PendingAddrFields pndAddrFields);
/**
* Get the superframe specification field from the beacon payload header.
* \return The superframe specification field
*/
SuperframeField GetSuperframeSpecField (void) const;
/**
* Get the Guaranteed Time Slots (GTS) fields from the beacon payload header.
* \return The GTS fields.
*/
GtsFields GetGtsFields (void) const;
/***
* Get the pending address fields from the beacon payload header.
* \return The Pending Address fields.
*/
PendingAddrFields GetPndAddrFields (void) const;
private:
/**
* Superframe Specification Field
*/
SuperframeField m_superframeField;
/**
* GTS Fields
*/
GtsFields m_gtsFields;
/**
* Pending Address Fields
*/
PendingAddrFields m_pndAddrFields;
};
/**
* \ingroup lr-wpan
* Implements the header for the MAC payload command frame according to
* the IEEE 802.15.4-2011 Std.
*/
class CommandPayloadHeader : public Header
{
public:
/**
* The MAC command frames.
* See IEEE 802.15.4-2011, Table 5
*/
enum MacCommand
{
ASSOCIATION_REQ = 0x01, //!< Association request (RFD true: Tx)
ASSOCIATION_RESP = 0x02, //!< Association response (RFD true: Rx)
DISASSOCIATION_NOTIF = 0x03, //!< Disassociation notification (RFD true: TX, Rx)
DATA_REQ = 0x04, //!< Data Request (RFD true: Tx)
PANID_CONFLICT = 0x05, //!< Pan ID conflict notification (RFD true: Tx)
ORPHAN_NOTIF = 0x06, //!< Orphan Notification (RFD true: Tx)
BEACON_REQ = 0x07, //!< Beacon Request (RFD true: none )
COOR_REALIGN = 0x08, //!< Coordinator Realignment (RFD true: Rx)
GTS_REQ = 0x09, //!< GTS Request (RFD true: none)
CMD_RESERVED = 0xff //!< Reserved
};
CommandPayloadHeader (void);
/**
* Constructor
* \param macCmd the command type of this command header
*/
CommandPayloadHeader (enum MacCommand macCmd);
/**
* \brief Get the type ID.
* \return the object TypeId
*/
static TypeId GetTypeId (void);
TypeId GetInstanceTypeId (void) const;
uint32_t GetSerializedSize (void) const;
virtual void Serialize (Buffer::Iterator start) const;
uint32_t Deserialize (Buffer::Iterator start);
void Print (std::ostream &os) const;
/**
* Set the command frame type
*/
void SetCommandFrameType (MacCommand macCmd);
/**
* Get the command frame type
*/
MacCommand GetCommandFrameType (void) const;
private:
/** The command Frame Identifier*/
uint8_t m_cmdFrameId;
};
} // namespace ns3
#endif /* LR_WPAN_MAC_PL_HEADERS_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,283 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2019 Ritsumeikan University, Shiga, Japan
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author:
* Alberto Gallegos Ramonet <ramonet@fc.ritsumei.ac.jp>
*/
#include <ns3/log.h>
#include <ns3/core-module.h>
#include <ns3/lr-wpan-module.h>
#include <ns3/propagation-loss-model.h>
#include <ns3/propagation-delay-model.h>
#include <ns3/simulator.h>
#include <ns3/single-model-spectrum-channel.h>
#include <ns3/constant-position-mobility-model.h>
#include <ns3/packet.h>
#include "ns3/rng-seed-manager.h"
#include <iostream>
#include <iomanip>
using namespace ns3;
NS_LOG_COMPONENT_DEFINE ("lr-wpan-ifs-test");
/**
* \ingroup lr-wpan-test
* \ingroup tests
*
* \brief LrWpan Dataframe transmission with Interframe Space
*/
class LrWpanDataIfsTestCase : public TestCase
{
public:
LrWpanDataIfsTestCase ();
virtual ~LrWpanDataIfsTestCase ();
private:
static void DataConfirm (LrWpanDataIfsTestCase *testcase,
Ptr<LrWpanNetDevice> dev,
McpsDataConfirmParams params);
static void DataReceived (LrWpanDataIfsTestCase *testcase,
Ptr<LrWpanNetDevice> dev,
Ptr<const Packet>);
static void MacState (LrWpanDataIfsTestCase *testcase,
Ptr<LrWpanNetDevice> dev,
LrWpanMacState oldValue,
LrWpanMacState newValue);
virtual void DoRun (void);
Time m_lastTxTime; //!< The time of the last transmitted packet
Time m_ackRxTime; //!< The time of the received acknoledgment.
Time m_endIfs; //!< The time where the Interframe Space ended.
};
LrWpanDataIfsTestCase::LrWpanDataIfsTestCase ()
: TestCase ("Lrwpan: IFS with and without ACK")
{
}
LrWpanDataIfsTestCase::~LrWpanDataIfsTestCase ()
{
}
void
LrWpanDataIfsTestCase::DataConfirm (LrWpanDataIfsTestCase *testcase, Ptr<LrWpanNetDevice> dev, McpsDataConfirmParams params)
{
std::cout << Simulator::Now ().GetSeconds () << " | Dataframe Sent\n";
testcase->m_lastTxTime = Simulator::Now ();
}
void
LrWpanDataIfsTestCase::DataReceived (LrWpanDataIfsTestCase *testcase,Ptr<LrWpanNetDevice> dev, Ptr<const Packet> p)
{
Ptr<Packet> RxPacket = p->Copy ();
LrWpanMacHeader receivedMacHdr;
RxPacket->RemoveHeader (receivedMacHdr);
NS_ASSERT (receivedMacHdr.IsAcknowledgment ());
testcase->m_ackRxTime = Simulator::Now ();
std::cout << Simulator::Now ().GetSeconds () << " | ACK received\n";
}
void
LrWpanDataIfsTestCase::MacState (LrWpanDataIfsTestCase *testcase, Ptr<LrWpanNetDevice> dev,LrWpanMacState oldValue, LrWpanMacState newValue)
{
// Check the time after the MAC layer go back to IDLE state
// (i.e. after the packet has been sent and the IFS is finished)
if (newValue == LrWpanMacState::MAC_IDLE)
{
testcase->m_endIfs = Simulator::Now ();
std::cout << Simulator::Now ().GetSeconds () << " | MAC layer is free\n";
}
}
void
LrWpanDataIfsTestCase::DoRun ()
{
// Test of Interframe Spaces (IFS)
// The MAC layer needs a finite amount of time to process the data received from the PHY.
// To allow this, to successive transmitted frames must be separated for at least one IFS.
// The IFS size depends on the transmitted frame. This test verifies that the IFS is correctly
// implemented and its size correspond to the situations described by the standard.
// For more info see IEEE 802.15.4-2011 Section 5.1.1.3
// Create 2 nodes, and a NetDevice for each one
Ptr<Node> n0 = CreateObject <Node> ();
Ptr<Node> n1 = CreateObject <Node> ();
Ptr<LrWpanNetDevice> dev0 = CreateObject<LrWpanNetDevice> ();
Ptr<LrWpanNetDevice> dev1 = CreateObject<LrWpanNetDevice> ();
dev0->SetAddress (Mac16Address ("00:01"));
dev1->SetAddress (Mac16Address ("00:02"));
// Each device must be attached to the same channel
Ptr<SingleModelSpectrumChannel> channel = CreateObject<SingleModelSpectrumChannel> ();
Ptr<LogDistancePropagationLossModel> propModel = CreateObject<LogDistancePropagationLossModel> ();
Ptr<ConstantSpeedPropagationDelayModel> delayModel = CreateObject<ConstantSpeedPropagationDelayModel> ();
channel->AddPropagationLossModel (propModel);
channel->SetPropagationDelayModel (delayModel);
dev0->SetChannel (channel);
dev1->SetChannel (channel);
// To complete configuration, a LrWpanNetDevice must be added to a node
n0->AddDevice (dev0);
n1->AddDevice (dev1);
// Connect to trace files in the MAC layer
dev0->GetMac ()->TraceConnectWithoutContext ("MacStateValue", MakeBoundCallback (&LrWpanDataIfsTestCase::MacState, this, dev0));
dev0->GetMac ()->TraceConnectWithoutContext ("MacRx", MakeBoundCallback (&LrWpanDataIfsTestCase::DataReceived, this, dev0));
Ptr<ConstantPositionMobilityModel> sender0Mobility = CreateObject<ConstantPositionMobilityModel> ();
sender0Mobility->SetPosition (Vector (0,0,0));
dev0->GetPhy ()->SetMobility (sender0Mobility);
Ptr<ConstantPositionMobilityModel> sender1Mobility = CreateObject<ConstantPositionMobilityModel> ();
// Configure position 10 m distance
sender1Mobility->SetPosition (Vector (0,10,0));
dev1->GetPhy ()->SetMobility (sender1Mobility);
McpsDataConfirmCallback cb0;
cb0 = MakeBoundCallback (&LrWpanDataIfsTestCase::DataConfirm, this, dev0);
dev0->GetMac ()->SetMcpsDataConfirmCallback (cb0);
Ptr<Packet> p0 = Create<Packet> (2);
McpsDataRequestParams params;
params.m_dstPanId = 0;
params.m_srcAddrMode = SHORT_ADDR;
params.m_dstAddrMode = SHORT_ADDR;
params.m_dstAddr = Mac16Address ("00:02");
params.m_msduHandle = 0;
Time ifsSize;
//////////////////////// SIFS ///////////////////////////
Simulator::ScheduleWithContext (1, Seconds (0.0),
&LrWpanMac::McpsDataRequest,
dev0->GetMac (), params, p0);
Simulator::Run ();
// MPDU = MAC header (11 bytes) + MSDU (2 bytes)+ MAC trailer (2 bytes) = 15)
// MPDU (15 bytes) < 18 bytes therefore IFS = SIFS
// SIFS = 12 symbols (192 Microseconds on a 2.4Ghz O-QPSK PHY)
ifsSize = m_endIfs - m_lastTxTime;
NS_TEST_EXPECT_MSG_EQ (ifsSize, Time (MicroSeconds (192)), "Wrong Short InterFrame Space (SIFS) Size after dataframe Tx");
//////////////////////// LIFS ///////////////////////////
p0 = Create<Packet> (6);
Simulator::ScheduleWithContext (1, Seconds (0.0),
&LrWpanMac::McpsDataRequest,
dev0->GetMac (), params, p0);
Simulator::Run ();
// MPDU = MAC header (11 bytes) + MSDU (6 bytes)+ MAC trailer (2 bytes) = 19)
// MPDU (19 bytes) > 18 bytes therefore IFS = LIFS
// LIFS = 20 symbols (640 Microseconds on a 2.4Ghz O-QPSK PHY)
ifsSize = m_endIfs - m_lastTxTime;
NS_TEST_EXPECT_MSG_EQ (ifsSize, Time (MicroSeconds (640)), "Wrong Long InterFrame Space (LIFS) Size after dataframe Tx");
//////////////////////// SIFS after ACK //////////////////
params.m_txOptions = TX_OPTION_ACK;
p0 = Create<Packet> (2);
Simulator::ScheduleWithContext (1, Seconds (0.0),
&LrWpanMac::McpsDataRequest,
dev0->GetMac (), params, p0);
Simulator::Run ();
// MPDU = MAC header (11 bytes) + MSDU (2 bytes)+ MAC trailer (2 bytes) = 15)
// MPDU (15 bytes) < 18 bytes therefore IFS = SIFS
// SIFS = 12 symbols (192 Microseconds on a 2.4Ghz O-QPSK PHY)
ifsSize = m_endIfs - m_ackRxTime;
NS_TEST_EXPECT_MSG_EQ (ifsSize, Time (MicroSeconds (192)), "Wrong Short InterFrame Space (SIFS) Size after ACK Rx");
//////////////////////// LIFS after ACK //////////////////
params.m_txOptions = TX_OPTION_ACK;
p0 = Create<Packet> (6);
Simulator::ScheduleWithContext (1, Seconds (0.0),
&LrWpanMac::McpsDataRequest,
dev0->GetMac (), params, p0);
Simulator::Run ();
// MPDU = MAC header (11 bytes) + MSDU (6 bytes)+ MAC trailer (2 bytes) = 19)
// MPDU (19 bytes) > 18 bytes therefore IFS = LIFS
// LIFS = 20 symbols (640 Microseconds on a 2.4Ghz O-QPSK PHY)
ifsSize = m_endIfs - m_ackRxTime;
NS_TEST_EXPECT_MSG_EQ (ifsSize, Time (MicroSeconds (640)), "Wrong Long InterFrame Space (LIFS) Size after ACK Rx");
Simulator::Destroy ();
}
/**
* \ingroup lr-wpan-test
* \ingroup tests
*
* \brief LrWpan IFS TestSuite
*/
class LrWpanIfsTestSuite : public TestSuite
{
public:
LrWpanIfsTestSuite ();
};
LrWpanIfsTestSuite::LrWpanIfsTestSuite ()
: TestSuite ("lr-wpan-ifs-test", UNIT)
{
AddTestCase (new LrWpanDataIfsTestCase, TestCase::QUICK);
}
static LrWpanIfsTestSuite lrWpanIfsTestSuite; //!< Static variable for test initialization

View File

@@ -0,0 +1,342 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2019 Ritsumeikan University, Shiga, Japan
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author:
* Alberto Gallegos Ramonet <ramonet@fc.ritsumei.ac.jp>
*/
#include <ns3/log.h>
#include <ns3/core-module.h>
#include <ns3/lr-wpan-module.h>
#include <ns3/propagation-loss-model.h>
#include <ns3/propagation-delay-model.h>
#include <ns3/simulator.h>
#include <ns3/single-model-spectrum-channel.h>
#include <ns3/constant-position-mobility-model.h>
#include <ns3/packet.h>
using namespace ns3;
NS_LOG_COMPONENT_DEFINE ("lr-wpan-slotted-csma-test");
/**
* \ingroup lr-wpan-test
* \ingroup tests
*
* \brief Test the correct allocation of DIRECT transmissions in the
* contention access period (CAP) of the superframe
* (Slotted CSMA-CA algorithm).
*/
class LrWpanSlottedCsmacaTestCase : public TestCase
{
public:
LrWpanSlottedCsmacaTestCase ();
virtual ~LrWpanSlottedCsmacaTestCase ();
private:
/**
* \brief Function called when McpsDataConfirm is hit.
* \param testcase The TestCase.
* \param dev The LrWpanNetDevice.
* \param params The McpsDataConfirm parameters.
*/
static void TransEndIndication (LrWpanSlottedCsmacaTestCase *testcase,
Ptr<LrWpanNetDevice> dev,
McpsDataConfirmParams params);
/**
* \brief Function called when McpsDataIndication is hit.
* \param testcase The TestCase.
* \param dev The LrWpanNetDevice.
* \param params The McpsDataIndication parameters.
* \param p The received packet.
*/
static void DataIndicationCoordinator (LrWpanSlottedCsmacaTestCase *testcase,
Ptr<LrWpanNetDevice> dev,
McpsDataIndicationParams params,
Ptr<Packet> p);
/**
* \brief Function called when MlmeStartConfirm is hit.
* \param testcase The TestCase.
* \param dev The LrWpanNetDevice.
* \param params The MlmeStartConfirm parameters.
*/
static void StartConfirm (LrWpanSlottedCsmacaTestCase *testcase,
Ptr<LrWpanNetDevice> dev,
MlmeStartConfirmParams params);
/**
* \brief Function called on each Superframe status change (CAP|CFP|INACTIVE).
* \param testcase The TestCase.
* \param dev The LrWpanNetDevice.
* \param oldValue The previous superframe status.
* \param newValue THe new superframe status.
*/
static void IncomingSuperframeStatus (LrWpanSlottedCsmacaTestCase *testcase,
Ptr<LrWpanNetDevice> dev,
SuperframeStatus oldValue,
SuperframeStatus newValue);
/**
* \brief Function called to indicated the calculated transaction cost in slotted CSMA-CA
* \param testcase The TestCase.
* \param dev The LrWpanNetDevice.
* \param trans The transaction cost in symbols.
*/
static void TransactionCost (LrWpanSlottedCsmacaTestCase *testcase,
Ptr<LrWpanNetDevice> dev,
uint32_t trans);
virtual void DoRun (void);
Time m_startCap; //!< The time of the start of the Contention Access Period (CAP).
Time m_apBoundary; //!< Indicates the time after the calculation of the transaction cost (A boundary of an Active Period in the CAP)
Time m_sentTime; //!< Indicates the time after a successful transmission.
uint32_t m_transCost; //!< The current transaction cost in symbols.
};
LrWpanSlottedCsmacaTestCase::LrWpanSlottedCsmacaTestCase ()
: TestCase ("Lrwpan: Slotted CSMA-CA test")
{
m_transCost = 0;
}
LrWpanSlottedCsmacaTestCase::~LrWpanSlottedCsmacaTestCase ()
{
}
void
LrWpanSlottedCsmacaTestCase::TransEndIndication (LrWpanSlottedCsmacaTestCase *testcase, Ptr<LrWpanNetDevice> dev, McpsDataConfirmParams params)
{
// In the case of transmissions with the acknowledgment flag activated, the transmission is only
// successful if the acknowledgment was received.
if (params.m_status == LrWpanMcpsDataConfirmStatus::IEEE_802_15_4_SUCCESS)
{
NS_LOG_UNCOND (Simulator::Now ().GetSeconds () << "s Transmission successfully sent");
testcase->m_sentTime = Simulator::Now ();
}
}
void
LrWpanSlottedCsmacaTestCase::DataIndicationCoordinator (LrWpanSlottedCsmacaTestCase *testcase, Ptr<LrWpanNetDevice> dev, McpsDataIndicationParams params, Ptr<Packet> p)
{
NS_LOG_UNCOND (Simulator::Now ().GetSeconds () << "s Coordinator Received DATA packet (size " << p->GetSize () << " bytes)");
}
void
LrWpanSlottedCsmacaTestCase::StartConfirm (LrWpanSlottedCsmacaTestCase *testcase, Ptr<LrWpanNetDevice> dev, MlmeStartConfirmParams params)
{
NS_LOG_UNCOND (Simulator::Now ().GetSeconds () << "s Beacon Sent");
}
void
LrWpanSlottedCsmacaTestCase::IncomingSuperframeStatus (LrWpanSlottedCsmacaTestCase *testcase, Ptr<LrWpanNetDevice> dev,SuperframeStatus oldValue, SuperframeStatus newValue)
{
if (newValue == SuperframeStatus::CAP)
{
testcase->m_startCap = Simulator::Now ();
NS_LOG_UNCOND (Simulator::Now ().GetSeconds () << "s Incoming superframe CAP starts");
}
}
void
LrWpanSlottedCsmacaTestCase::TransactionCost (LrWpanSlottedCsmacaTestCase *testcase, Ptr<LrWpanNetDevice> dev, uint32_t trans)
{
testcase->m_apBoundary = Simulator::Now ();
testcase->m_transCost = trans;
NS_LOG_UNCOND (Simulator::Now ().GetSeconds () << "s Transaction Cost is:" << trans);
}
void
LrWpanSlottedCsmacaTestCase::DoRun ()
{
// Create 2 nodes, and a NetDevice for each one
Ptr<Node> n0 = CreateObject <Node> ();
Ptr<Node> n1 = CreateObject <Node> ();
Ptr<LrWpanNetDevice> dev0 = CreateObject<LrWpanNetDevice> ();
Ptr<LrWpanNetDevice> dev1 = CreateObject<LrWpanNetDevice> ();
dev0->SetAddress (Mac16Address ("00:01"));
dev1->SetAddress (Mac16Address ("00:02"));
// Each device must be attached to the same channel
Ptr<SingleModelSpectrumChannel> channel = CreateObject<SingleModelSpectrumChannel> ();
Ptr<LogDistancePropagationLossModel> propModel = CreateObject<LogDistancePropagationLossModel> ();
Ptr<ConstantSpeedPropagationDelayModel> delayModel = CreateObject<ConstantSpeedPropagationDelayModel> ();
channel->AddPropagationLossModel (propModel);
channel->SetPropagationDelayModel (delayModel);
dev0->SetChannel (channel);
dev1->SetChannel (channel);
// To complete configuration, a LrWpanNetDevice must be added to a node
n0->AddDevice (dev0);
n1->AddDevice (dev1);
// Set mobility
Ptr<ConstantPositionMobilityModel> sender0Mobility = CreateObject<ConstantPositionMobilityModel> ();
sender0Mobility->SetPosition (Vector (0,0,0));
dev0->GetPhy ()->SetMobility (sender0Mobility);
Ptr<ConstantPositionMobilityModel> sender1Mobility = CreateObject<ConstantPositionMobilityModel> ();
sender1Mobility->SetPosition (Vector (0,10,0));
dev1->GetPhy ()->SetMobility (sender1Mobility);
// MAC layer and CSMA-CA callback hooks
MlmeStartConfirmCallback cb0;
cb0 = MakeBoundCallback (&LrWpanSlottedCsmacaTestCase::StartConfirm, this, dev0);
dev0->GetMac ()->SetMlmeStartConfirmCallback (cb0);
McpsDataConfirmCallback cb1;
cb1 = MakeBoundCallback (&LrWpanSlottedCsmacaTestCase::TransEndIndication, this, dev1);
dev1->GetMac ()->SetMcpsDataConfirmCallback (cb1);
LrWpanMacTransCostCallback cb2;
cb2 = MakeBoundCallback (&LrWpanSlottedCsmacaTestCase::TransactionCost, this, dev1);
dev1->GetCsmaCa ()->SetLrWpanMacTransCostCallback (cb2);
McpsDataIndicationCallback cb5;
cb5 = MakeBoundCallback (&LrWpanSlottedCsmacaTestCase::DataIndicationCoordinator, this, dev0);
dev0->GetMac ()->SetMcpsDataIndicationCallback (cb5);
// Connect to trace in the MAC layer
dev1->GetMac ()->TraceConnectWithoutContext ("MacIncSuperframeStatus",
MakeBoundCallback (&LrWpanSlottedCsmacaTestCase::IncomingSuperframeStatus, this, dev1));
// Manual Device Association
// Note: We manually associate dev1 device to a PAN coordinator
// because currently there is no automatic association behavior;
// The PAN COORDINATOR does not need to associate, set
// PAN Id or its own coordinator id, these are set
// by the MLME-start.request primitive when used.
dev1->GetMac ()->SetPanId (5);
dev1->GetMac ()->SetAssociatedCoor (Mac16Address ("00:01"));
// Dev0 sets the start time for beacons
MlmeStartRequestParams params;
params.m_panCoor = true;
params.m_PanId = 5;
params.m_bcnOrd = 14;
params.m_sfrmOrd = 6;
Simulator::ScheduleWithContext (1, Seconds (2.0),
&LrWpanMac::MlmeStartRequest,
dev0->GetMac (), params);
// Dev1 sets the transmission of data packet
Ptr<Packet> p1 = Create<Packet> (5); // 5 bytes of dummy data
McpsDataRequestParams params2;
params2.m_dstPanId = 5;
params2.m_srcAddrMode = SHORT_ADDR;
params2.m_dstAddrMode = SHORT_ADDR;
params2.m_dstAddr = Mac16Address ("00:01");
params2.m_msduHandle = 0;
// Beacon-enabled | Device to Coordinator | Direct transmission
Simulator::ScheduleWithContext (1, Seconds (2.93),
&LrWpanMac::McpsDataRequest,
dev1->GetMac (), params2, p1);
Simulator::Stop (Seconds (4));
Simulator::Run ();
Time activePeriodsSum;
Time transactionTime;
uint64_t symbolRate;
u_int32_t activePeriodSize = 20;
double boundary;
// Verifies that the CCA checks and the rest of the transaction runs
// on a boundary of an Active Period in the slotted CSMA-CA.
symbolRate = (uint64_t) dev1->GetMac ()->GetPhy ()->GetDataOrSymbolRate (false);
activePeriodsSum = m_apBoundary - m_startCap;
boundary = (activePeriodsSum.GetMicroSeconds () * 1000 * 1000 * symbolRate) % activePeriodSize;
NS_TEST_EXPECT_MSG_EQ (boundary, 0, "Error, the transaction is not calculated on a boundary of an Active Period in the CAP");
// Slotted CSMA-CA needs to precalculate the cost of the transaction to ensure there
// is enough time in the CAP to complete the transmission. The following checks that such
// pre-calculation matches the time it took to complete the transmission.
// The calculated transaction includes the IFS time, so we need to subtract its value to compare it.
// MPDU = MAC Header + MSDU (payload)
// Mac Header = 13 bytes
// If the MPDU is > aMaxSIFSFrameSize (18 bytes) then IFS = LIFS (40 symbols), else IFS = SIFS (12 symbols)
uint32_t ifsSize;
if (p1->GetSize () > 18)
{
ifsSize = 40;
}
else
{
ifsSize = 12;
}
transactionTime = MicroSeconds ((m_transCost - ifsSize) * 1000 * 1000 / symbolRate);
NS_TEST_EXPECT_MSG_EQ (m_sentTime,(m_apBoundary + transactionTime),"Error, the transaction time is not the expected value");
Simulator::Destroy ();
}
/**
* \ingroup lr-wpan-test
* \ingroup tests
*
* \brief LrWpan Slotted CSMA-CA TestSuite
*/
class LrWpanSlottedCsmacaTestSuite : public TestSuite
{
public:
LrWpanSlottedCsmacaTestSuite ();
};
LrWpanSlottedCsmacaTestSuite::LrWpanSlottedCsmacaTestSuite ()
: TestSuite ("lr-wpan-slotted-csmaca", UNIT)
{
AddTestCase (new LrWpanSlottedCsmacaTestCase, TestCase::QUICK);
}
static LrWpanSlottedCsmacaTestSuite lrWpanSlottedCsmacaTestSuite; //!< Static variable for test initialization

View File

@@ -8,6 +8,8 @@ def build(bld):
'model/lr-wpan-phy.cc',
'model/lr-wpan-mac.cc',
'model/lr-wpan-mac-header.cc',
'model/lr-wpan-mac-pl-headers.cc',
'model/lr-wpan-fields.cc',
'model/lr-wpan-mac-trailer.cc',
'model/lr-wpan-csmaca.cc',
'model/lr-wpan-net-device.cc',
@@ -27,6 +29,8 @@ def build(bld):
'test/lr-wpan-packet-test.cc',
'test/lr-wpan-pd-plme-sap-test.cc',
'test/lr-wpan-spectrum-value-helper-test.cc',
'test/lr-wpan-ifs-test.cc',
'test/lr-wpan-slotted-csmaca-test.cc',
]
headers = bld(features='ns3header')
@@ -37,6 +41,8 @@ def build(bld):
'model/lr-wpan-phy.h',
'model/lr-wpan-mac.h',
'model/lr-wpan-mac-header.h',
'model/lr-wpan-mac-pl-headers.h',
'model/lr-wpan-fields.h',
'model/lr-wpan-mac-trailer.h',
'model/lr-wpan-csmaca.h',
'model/lr-wpan-net-device.h',

View File

@@ -0,0 +1,181 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2020 Ritsumeikan University, Shiga, Japan
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Alberto Gallegos Ramonet <ramonet@fc.ritsumei.ac.jp>
*/
#include <fstream>
#include "ns3/core-module.h"
#include "ns3/internet-module.h"
#include "ns3/internet-apps-module.h"
#include "ns3/mobility-module.h"
#include "ns3/spectrum-module.h"
#include "ns3/propagation-module.h"
#include "ns3/sixlowpan-module.h"
#include "ns3/lr-wpan-module.h"
using namespace ns3;
static void dataSentMacConfirm (McpsDataConfirmParams params)
{
// In the case of transmissions with the Ack flag activated, the transaction is only
// successful if the Ack was received.
if (params.m_status == LrWpanMcpsDataConfirmStatus::IEEE_802_15_4_SUCCESS)
{
NS_LOG_UNCOND ("**********" << Simulator::Now ().GetSeconds () << " secs | Transmission successfully sent");
}
}
int main (int argc, char** argv)
{
bool verbose = false;
CommandLine cmd;
cmd.AddValue ("verbose", "turn on log components", verbose);
cmd.Parse (argc, argv);
if (verbose)
{
LogComponentEnableAll (LOG_PREFIX_TIME);
LogComponentEnableAll (LOG_PREFIX_FUNC);
LogComponentEnable ("LrWpanMac", LOG_LEVEL_INFO);
LogComponentEnable ("LrWpanCsmaCa", LOG_LEVEL_INFO);
LogComponentEnable ("LrWpanHelper", LOG_LEVEL_ALL);
LogComponentEnable ("Ping6Application", LOG_LEVEL_INFO);
}
NodeContainer nodes;
nodes.Create (2);
MobilityHelper mobility;
mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
mobility.SetPositionAllocator ("ns3::GridPositionAllocator",
"MinX", DoubleValue (0.0),
"MinY", DoubleValue (0.0),
"DeltaX", DoubleValue (20),
"DeltaY", DoubleValue (20),
"GridWidth", UintegerValue (3),
"LayoutType", StringValue ("RowFirst"));
mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
mobility.Install (nodes);
LrWpanHelper lrWpanHelper;
// Add and install the LrWpanNetDevice for each node
NetDeviceContainer lrwpanDevices = lrWpanHelper.Install (nodes);
Ptr<LrWpanNetDevice> dev1 = lrwpanDevices.Get (0)->GetObject<LrWpanNetDevice> ();
Ptr<LrWpanNetDevice> dev2 = lrwpanDevices.Get (1)->GetObject<LrWpanNetDevice> ();
McpsDataConfirmCallback cb1;
cb1 = MakeCallback (&dataSentMacConfirm);
dev1->GetMac ()->SetMcpsDataConfirmCallback (cb1);
dev2->GetMac ()->SetMcpsDataConfirmCallback (cb1);
// Fake PAN association, coordinator assignment, short address assignment and initialization
// of beacon-enabled mode in 802.15.4-2011.
// This is needed because the lr-wpan module does not provide (yet)
// a full PAN association procedure.
// AssociateToBeaconPan (devices, PAN ID, Coordinator Address, Beacon Order, Superframe Order)
// Must be careful not setting the beacon order (BO) and the superframe order (SO) too far apart
// or the ping reply (ICMPV6 echo reply) can time out during the inactive period of the superframe.
// A full time table of the BO/SO time equivalence can be found at the end of this document.
// The current configuration is BO = 14, SO = 13 :
// Contention Access Period (CAP) Inactive
// (125.82912 secs) (125.82088)
// |---------------------------------------------|-------------------------------------------|
// Beacon Beacon
// Beacon Interval = 251.65 secs
// |-----------------------------------------------------------------------------------------|
lrWpanHelper.AssociateToBeaconPan (lrwpanDevices, 0, Mac16Address ("00:01"), 14,13);
InternetStackHelper internetv6;
internetv6.Install (nodes);
SixLowPanHelper sixlowpan;
NetDeviceContainer devices = sixlowpan.Install (lrwpanDevices);
Ipv6AddressHelper ipv6;
ipv6.SetBase (Ipv6Address ("2001:2::"), Ipv6Prefix (64));
Ipv6InterfaceContainer deviceInterfaces;
deviceInterfaces = ipv6.Assign (devices);
// Send ping packets after the 2nd second of the simulation during the
// first 8 seconds of the CAP in the incoming superframe
uint32_t packetSize = 10;
uint32_t maxPacketCount = 5;
Time interPacketInterval = Seconds (1);
Ping6Helper ping6;
ping6.SetLocal (deviceInterfaces.GetAddress (0, 1));
ping6.SetRemote (deviceInterfaces.GetAddress (1, 1));
ping6.SetAttribute ("MaxPackets", UintegerValue (maxPacketCount));
ping6.SetAttribute ("Interval", TimeValue (interPacketInterval));
ping6.SetAttribute ("PacketSize", UintegerValue (packetSize));
ApplicationContainer apps = ping6.Install (nodes.Get (0));
apps.Start (Seconds (2.0));
apps.Stop (Seconds (10.0));
AsciiTraceHelper ascii;
lrWpanHelper.EnableAsciiAll (ascii.CreateFileStream ("Ping-6LoW-lr-wpan-beacon.tr"));
lrWpanHelper.EnablePcapAll (std::string ("Ping-6LoW-lr-wpan-beacon"), true);
Simulator::Stop (Seconds (600));
Simulator::Run ();
Simulator::Destroy ();
}
// BO/SO values to time equivalence
// These times are only valid for a 250kbps O-QPSK modulation,
// times differ with other modulation configurations.
// +------------------------+
// | BO/SO | Time (secs) |
// +------------------------+
// | 0 | 0.01536 secs |
// | 1 | 0.03072 secs |
// | 2 | 0.06144 secs |
// | 3 | 0.12288 secs |
// | 4 | 0.24576 secs |
// | 5 | 0.49152 secs |
// | 6 | 0.98304 secs |
// | 7 | 1.96608 secs |
// | 8 | 3.93216 secs |
// | 9 | 7.86432 secs |
// | 10 | 15.72864 secs |
// | 11 | 31.45728 secs |
// | 12 | 62.91456 secs |
// | 13 | 125.82912 secs |
// | 14 | 251.65 secs |
// +------------------------+

View File

@@ -11,6 +11,10 @@ def build(bld):
obj = bld.create_ns3_program('example-ping-lr-wpan',
['network', 'sixlowpan', 'internet', 'lr-wpan', 'internet-apps'])
obj.source = 'example-ping-lr-wpan.cc'
obj = bld.create_ns3_program('example-ping-lr-wpan-beacon',
['network', 'sixlowpan', 'internet', 'lr-wpan', 'internet-apps'])
obj.source = 'example-ping-lr-wpan-beacon.cc'
obj = bld.create_ns3_program('example-ping-lr-wpan-mesh-under',
['network', 'sixlowpan', 'internet', 'lr-wpan', 'internet-apps', 'csma'])