ACK (Sascha Jopen), NetDevice (Tommaso Pecorella and Margherita Filippetti), FCS changes (Erwan Livolant), and clang compliance

This commit is contained in:
Tommaso Pecorella
2014-02-23 16:24:11 +01:00
parent b5d3e81f81
commit 131f31f56a
38 changed files with 1543 additions and 1040 deletions

View File

@@ -25,13 +25,15 @@
* Trace Phy state changes, and Mac DataIndication and DataConfirm events
* to stdout
*/
#include "ns3/log.h"
#include "ns3/core-module.h"
#include "ns3/lr-wpan-module.h"
#include "ns3/propagation-loss-model.h"
#include "ns3/simulator.h"
#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>
@@ -83,7 +85,9 @@ int main (int argc, char *argv[])
// 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);
@@ -128,21 +132,24 @@ int main (int argc, char *argv[])
// The below should trigger two callbacks when end-to-end data is working
// 1) DataConfirm callback is called
// 2) DataIndication callback is called with value of 20
Ptr<Packet> p0 = Create<Packet> (50); // 20 bytes of dummy data
// 2) DataIndication callback is called with value of 50
Ptr<Packet> p0 = Create<Packet> (50); // 50 bytes of dummy data
McpsDataRequestParams params;
params.m_srcAddrMode = 2;
params.m_dstAddrMode = 2;
params.m_srcAddrMode = SHORT_ADDR;
params.m_dstAddrMode = SHORT_ADDR;
params.m_dstPanId = 0;
params.m_dstAddr = Mac16Address ("00:02");
params.m_msduHandle = 0;
params.m_txOptions = 0;
dev0->GetMac ()->McpsDataRequest (params, p0);
params.m_txOptions = TX_OPTION_ACK;
// dev0->GetMac ()->McpsDataRequest (params, p0);
Simulator::ScheduleWithContext (1, Seconds (0.0),
&LrWpanMac::McpsDataRequest,
dev0->GetMac (), params, p0);
// Send a packet back at time 2 seconds
Ptr<Packet> p2 = Create<Packet> (60); // 20 bytes of dummy data
Ptr<Packet> p2 = Create<Packet> (60); // 60 bytes of dummy data
params.m_dstAddr = Mac16Address ("00:01");
Simulator::Schedule (MilliSeconds (2.0),
Simulator::ScheduleWithContext (2, Seconds (2.0),
&LrWpanMac::McpsDataRequest,
dev1->GetMac (), params, p2);

View File

@@ -23,28 +23,26 @@
// LogDistance propagation loss model, the 2.4 GHz OQPSK error model, a
// default transmit power of 0 dBm, and a default packet size of 20 bytes of
// 802.15.4 payload.
#include "ns3/test.h"
#include "ns3/log.h"
#include "ns3/callback.h"
#include "ns3/packet.h"
#include "ns3/simulator.h"
#include "ns3/lr-wpan-error-model.h"
#include "ns3/propagation-loss-model.h"
#include "ns3/lr-wpan-net-device.h"
#include "ns3/lr-wpan-spectrum-value-helper.h"
#include "ns3/lr-wpan-mac.h"
#include "ns3/node.h"
#include "ns3/net-device.h"
#include "ns3/single-model-spectrum-channel.h"
#include "ns3/mac16-address.h"
#include "ns3/constant-position-mobility-model.h"
#include "ns3/uinteger.h"
#include "ns3/nstime.h"
#include "ns3/abort.h"
#include "ns3/command-line.h"
#include "ns3/gnuplot.h"
#include <ns3/test.h>
#include <ns3/log.h>
#include <ns3/callback.h>
#include <ns3/packet.h>
#include <ns3/simulator.h>
#include <ns3/lr-wpan-error-model.h>
#include <ns3/propagation-loss-model.h>
#include <ns3/lr-wpan-net-device.h>
#include <ns3/lr-wpan-spectrum-value-helper.h>
#include <ns3/lr-wpan-mac.h>
#include <ns3/node.h>
#include <ns3/net-device.h>
#include <ns3/single-model-spectrum-channel.h>
#include <ns3/mac16-address.h>
#include <ns3/constant-position-mobility-model.h>
#include <ns3/uinteger.h>
#include <ns3/nstime.h>
#include <ns3/abort.h>
#include <ns3/command-line.h>
#include <ns3/gnuplot.h>
#include <fstream>
#include <iostream>

View File

@@ -17,15 +17,15 @@
*
* Author: Gary Pei <guangyu.pei@boeing.com>
*/
#include "ns3/packet.h"
#include "ns3/uinteger.h"
#include "ns3/simulator.h"
#include "ns3/nstime.h"
#include "ns3/log.h"
#include "ns3/abort.h"
#include "ns3/command-line.h"
#include "ns3/gnuplot.h"
#include "ns3/lr-wpan-error-model.h"
#include <ns3/packet.h>
#include <ns3/uinteger.h>
#include <ns3/simulator.h>
#include <ns3/nstime.h>
#include <ns3/log.h>
#include <ns3/abort.h>
#include <ns3/command-line.h>
#include <ns3/gnuplot.h>
#include <ns3/lr-wpan-error-model.h>
#include <fstream>
#include <iostream>

View File

@@ -17,9 +17,8 @@
*
* Author: Tom Henderson <thomas.r.henderson@boeing.com>
*/
#include "ns3/core-module.h"
#include "ns3/lr-wpan-module.h"
#include <ns3/core-module.h>
#include <ns3/lr-wpan-module.h>
#include <iostream>

View File

@@ -17,9 +17,9 @@
*
* Author: Gary Pei <guangyu.pei@boeing.com>
*/
#include <ns3/log.h>
#include <ns3/test.h>
#include <ns3/packet.h>
#include <ns3/lr-wpan-phy.h>
#include <ns3/lr-wpan-mac.h>
#include <ns3/simulator.h>
@@ -37,7 +37,7 @@ void GetSetTRXStateConfirm (LrWpanPhyEnumeration status)
void
ReceivePdDataIndication (uint32_t psduLength,
Ptr<Packet> p,
uint32_t lqi)
uint8_t lqi)
{
NS_LOG_UNCOND ("At: " << Simulator::Now ()
<< " Received frame size: " << psduLength << " LQI: " <<

View File

@@ -19,13 +19,14 @@
* Gary Pei <guangyu.pei@boeing.com>
* Tom Henderson <thomas.r.henderson@boeing.com>
*/
#include "lr-wpan-helper.h"
#include "ns3/lr-wpan-phy.h"
#include "ns3/lr-wpan-net-device.h"
#include "ns3/propagation-loss-model.h"
#include "ns3/log.h"
#include "ns3/config.h"
#include <ns3/lr-wpan-csmaca.h>
#include <ns3/lr-wpan-error-model.h>
#include <ns3/lr-wpan-net-device.h>
#include <ns3/mobility-model.h>
#include <ns3/single-model-spectrum-channel.h>
#include <ns3/propagation-loss-model.h>
#include <ns3/log.h>
NS_LOG_COMPONENT_DEFINE ("LrWpanHelper");

View File

@@ -22,17 +22,16 @@
#ifndef LR_WPAN_HELPER_H
#define LR_WPAN_HELPER_H
#include "ns3/node-container.h"
#include "ns3/net-device-container.h"
#include "ns3/lr-wpan-phy.h"
#include "ns3/lr-wpan-mac.h"
#include "ns3/lr-wpan-csmaca.h"
#include "ns3/trace-helper.h"
#include "ns3/lr-wpan-error-model.h"
#include "ns3/single-model-spectrum-channel.h"
#include <ns3/node-container.h>
#include <ns3/lr-wpan-phy.h>
#include <ns3/lr-wpan-mac.h>
#include <ns3/trace-helper.h>
namespace ns3 {
class SingleModelSpectrumChannel;
class MobilityModel;
/**
* \ingroup lr-wpan
*
@@ -51,7 +50,7 @@ public:
* \brief Create a LrWpan helper in an empty state.
*/
LrWpanHelper (void);
~LrWpanHelper (void);
virtual ~LrWpanHelper (void);
/**
* \brief Add mobility model to a physical device

View File

@@ -15,13 +15,14 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: kwong yin <kwong-sang.yin@boeing.com>
* Author:
* kwong yin <kwong-sang.yin@boeing.com>
* Sascha Alexander Jopen <jopen@cs.uni-bonn.de>
*/
#include "ns3/simulator.h"
#include "ns3/lr-wpan-csmaca.h"
#include "ns3/lr-wpan-mac.h"
#include "ns3/log.h"
#include "lr-wpan-csmaca.h"
#include <ns3/simulator.h>
#include <ns3/log.h>
NS_LOG_COMPONENT_DEFINE ("LrWpanCsmaCa");
@@ -52,10 +53,16 @@ LrWpanCsmaCa::LrWpanCsmaCa ()
// TODO-- make these into ns-3 attributes
m_isSlotted = false;
m_NB = 0;
m_CW = 2;
m_BLE = false;
m_macMinBE = 3;
m_macMaxBE = 5;
m_macMaxCSMABackoffs = 4;
m_aUnitBackoffPeriod = 20; //20 symbols
m_random = UniformVariable ();
m_BE = m_macMinBE;
m_ccaRequestRunning = false;
}
LrWpanCsmaCa::~LrWpanCsmaCa ()
@@ -67,6 +74,7 @@ void
LrWpanCsmaCa::DoDispose ()
{
m_lrWpanMacStateCallback = MakeNullCallback< void, LrWpanMacState> ();
Cancel ();
m_mac = 0;
}
@@ -197,12 +205,12 @@ LrWpanCsmaCa::Start ()
}
//TODO: for slotted, locate backoff period boundary. i.e. delay to the next slot boundary
backoffBoundary = getTimeToNextSlot ();
Simulator::Schedule (Seconds (backoffBoundary),&LrWpanCsmaCa::RandomBackoffDelay,this);
m_randomBackoffEvent = Simulator::Schedule (Seconds (backoffBoundary), &LrWpanCsmaCa::RandomBackoffDelay, this);
}
else
{
m_BE = m_macMinBE;
Simulator::ScheduleNow (&LrWpanCsmaCa::RandomBackoffDelay,this);
m_randomBackoffEvent = Simulator::ScheduleNow (&LrWpanCsmaCa::RandomBackoffDelay, this);
}
/*
* TODO: If using Backoff.cc (will need to modify Backoff::GetBackoffTime)
@@ -217,9 +225,11 @@ LrWpanCsmaCa::Start ()
void
LrWpanCsmaCa::Cancel ()
{
m_randomBackoffEvent.Cancel ();
m_requestCcaEvent.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
@@ -229,8 +239,6 @@ LrWpanCsmaCa::RandomBackoffDelay ()
{
NS_LOG_FUNCTION (this);
SeedManager::SetSeed (100);
UniformVariable uniformVar;
uint64_t upperBound = (uint64_t) pow (2, m_BE) - 1;
uint64_t backoffPeriod;
Time randomBackoff;
@@ -239,19 +247,18 @@ LrWpanCsmaCa::RandomBackoffDelay ()
symbolRate = (uint64_t) m_mac->GetPhy ()->GetDataOrSymbolRate (isData); //symbols per second
uniformVar = UniformVariable (0, upperBound);
backoffPeriod = (uint64_t)uniformVar.GetValue (); //num backoff periods
backoffPeriod = (uint64_t)m_random.GetValue (0, upperBound); //num backoff periods
randomBackoff = MicroSeconds (backoffPeriod * getUnitBackoffPeriod () * 1000 * 1000 / symbolRate);
if (isUnSlottedCsmaCa ())
{
NS_LOG_LOGIC ("Unslotted: requesting CCA after backoff of " << randomBackoff.GetMicroSeconds () << " us");
Simulator::Schedule (randomBackoff,&LrWpanCsmaCa::RequestCCA,this);
m_requestCcaEvent = Simulator::Schedule (randomBackoff, &LrWpanCsmaCa::RequestCCA, this);
}
else
{
NS_LOG_LOGIC ("Slotted: proceeding after backoff of " << randomBackoff.GetMicroSeconds () << " us");
Simulator::Schedule (randomBackoff,&LrWpanCsmaCa::CanProceed,this);
m_canProceedEvent = Simulator::Schedule (randomBackoff, &LrWpanCsmaCa::CanProceed, this);
}
}
@@ -276,11 +283,11 @@ LrWpanCsmaCa::CanProceed ()
{
// TODO: For slotted, Perform CCA on backoff period boundary i.e. delay to next slot boundary
backoffBoundary = getTimeToNextSlot ();
Simulator::Schedule (Seconds (backoffBoundary),&LrWpanCsmaCa::RequestCCA,this);
m_requestCcaEvent = Simulator::Schedule (Seconds (backoffBoundary), &LrWpanCsmaCa::RequestCCA, this);
}
else
{
Simulator::Schedule (Seconds (nextCap),&LrWpanCsmaCa::RandomBackoffDelay,this);
m_randomBackoffEvent = Simulator::Schedule (Seconds (nextCap), &LrWpanCsmaCa::RandomBackoffDelay, this);
}
}
@@ -288,6 +295,7 @@ void
LrWpanCsmaCa::RequestCCA ()
{
NS_LOG_FUNCTION (this);
m_ccaRequestRunning = true;
m_mac->GetPhy ()->PlmeCcaRequest ();
}
@@ -299,60 +307,67 @@ LrWpanCsmaCa::PlmeCcaConfirm (LrWpanPhyEnumeration status)
{
NS_LOG_FUNCTION (this << status);
if (status == IEEE_802_15_4_PHY_IDLE)
// Only react on this event, if we are actually waiting for a CCA.
// If the CSMA algorithm was canceled, we could still receive this event from
// the PHY. In this case we ignore the event.
if (m_ccaRequestRunning)
{
if (isSlottedCsmaCa ())
m_ccaRequestRunning = false;
if (status == IEEE_802_15_4_PHY_IDLE)
{
m_CW--;
if (m_CW == 0)
if (isSlottedCsmaCa ())
{
// inform MAC channel is idle
m_CW--;
if (m_CW == 0)
{
// inform MAC channel is idle
if (!m_lrWpanMacStateCallback.IsNull ())
{
NS_LOG_LOGIC ("Notifying MAC of idle channel");
m_lrWpanMacStateCallback (CHANNEL_IDLE);
}
}
else
{
NS_LOG_LOGIC ("Perform CCA again, m_CW = " << m_CW);
m_requestCcaEvent = Simulator::ScheduleNow (&LrWpanCsmaCa::RequestCCA, this); // Perform CCA again
}
}
else
{
// inform MAC, channel is idle
if (!m_lrWpanMacStateCallback.IsNull ())
{
NS_LOG_LOGIC ("Notifying MAC of idle channel");
m_lrWpanMacStateCallback (CHANNEL_IDLE);
}
}
}
else
{
if (isSlottedCsmaCa ())
{
m_CW = 2;
}
m_BE = MIN (m_BE + 1, m_macMaxBE);
m_NB++;
if (m_NB > m_macMaxCSMABackoffs)
{
// no channel found so cannot send pkt
NS_LOG_DEBUG ("Channel access failure");
if (!m_lrWpanMacStateCallback.IsNull ())
{
NS_LOG_LOGIC ("Notifying MAC of Channel access failure");
m_lrWpanMacStateCallback (CHANNEL_ACCESS_FAILURE);
}
return;
}
else
{
NS_LOG_LOGIC ("Perform CCA again, m_CW = " << m_CW);
Simulator::ScheduleNow (&LrWpanCsmaCa::RequestCCA,this); // Perform CCA again
NS_LOG_DEBUG ("Perform another backoff; m_NB = " << static_cast<uint16_t> (m_NB));
m_randomBackoffEvent = Simulator::ScheduleNow (&LrWpanCsmaCa::RandomBackoffDelay, this); //Perform another backoff (step 2)
}
}
else
{
// inform MAC, channel is idle
if (!m_lrWpanMacStateCallback.IsNull ())
{
NS_LOG_LOGIC ("Notifying MAC of idle channel");
m_lrWpanMacStateCallback (CHANNEL_IDLE);
}
}
}
else
{
if (isSlottedCsmaCa ())
{
m_CW = 2;
}
m_BE = MIN (m_BE + 1, m_macMaxBE);
m_NB++;
if (m_NB > m_macMaxCSMABackoffs)
{
// no channel found so cannot send pkt
NS_LOG_DEBUG ("Channel access failure");
if (!m_lrWpanMacStateCallback.IsNull ())
{
NS_LOG_LOGIC ("Notifying MAC of Channel access failure");
m_lrWpanMacStateCallback (CHANNEL_ACCESS_FAILURE);
}
return;
}
else
{
NS_LOG_DEBUG ("Perform another backoff; m_NB = " << static_cast<uint16_t> (m_NB));
Simulator::ScheduleNow (&LrWpanCsmaCa::RandomBackoffDelay,this); //Perform another backoff (step 2)
}
}
}

View File

@@ -15,24 +15,23 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: kwong yin <kwong-sang.yin@boeing.com>
* Author:
* kwong yin <kwong-sang.yin@boeing.com>
* Sascha Alexander Jopen <jopen@cs.uni-bonn.de>
*/
#ifndef LRWPANCSMACA_H
#define LRWPANCSMACA_H
#ifndef LR_WPAN_CSMACA_H
#define LR_WPAN_CSMACA_H
#include <stdint.h>
#include "ns3/object.h"
#include "ns3/nstime.h"
#include "ns3/random-variable.h"
#include "ns3/packet.h"
#include "ns3/lr-wpan-phy.h"
#include "ns3/lr-wpan-mac.h"
#include <ns3/object.h>
#include <ns3/random-variable.h>
#include <ns3/event-id.h>
#include <ns3/lr-wpan-mac.h>
namespace ns3 {
/* This method informs MAC that channel is idle or busy */
typedef Callback< void, LrWpanMacState> LrWpanMacStateCallback;
typedef Callback<void, LrWpanMacState> LrWpanMacStateCallback;
/**
* \ingroup lr-wpan
@@ -44,10 +43,10 @@ class LrWpanCsmaCa : public Object
{
public:
static TypeId GetTypeId ();
static TypeId GetTypeId (void);
LrWpanCsmaCa ();
~LrWpanCsmaCa ();
LrWpanCsmaCa (void);
virtual ~LrWpanCsmaCa (void);
void SetMac (Ptr<LrWpanMac> mac);
Ptr<LrWpanMac> GetMac (void) const;
@@ -80,12 +79,12 @@ public:
/*
* cancel CSMA-CA algorithm
*/
void Cancel ();
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 RandomBackoffDelay (void);
/*
* In the slotted CSMA-CA, after random backoff, Determine if the remaining
@@ -94,13 +93,13 @@ public:
* This step is NOT performed for the unslotted CSMA-CA. If it can proceed
* function CCAconfirmed() is called.
*/
void CanProceed ();
void CanProceed (void);
/*
* Request the Phy to perform CCA (Step 3)
*
*/
void RequestCCA ();
void RequestCCA (void);
/**
* IEEE 802.15.4-2006 section 6.2.2.2
@@ -123,7 +122,7 @@ public:
void SetLrWpanMacStateCallback (LrWpanMacStateCallback macState);
private:
virtual void DoDispose ();
virtual void DoDispose (void);
LrWpanMacStateCallback m_lrWpanMacStateCallback;
bool m_isSlotted; // beacon-enabled slotted or nonbeacon-enabled unslotted CSMA-CA
// beacon order == 15 means nonbeacon-enabled
@@ -138,11 +137,16 @@ private:
uint8_t m_macMaxBE; //3-8 default 5
uint8_t m_macMaxCSMABackoffs; //0-5 default 4
uint64_t m_aUnitBackoffPeriod; // 20 symbols in each backoff periods
UniformVariable m_random;
EventId m_randomBackoffEvent;
EventId m_requestCcaEvent;
EventId m_canProceedEvent;
bool m_ccaRequestRunning;
};
}
// namespace ns-3
#endif /* LRWPANCSMACA_H */
#endif /* LR_WPAN_CSMACA_H */

View File

@@ -17,8 +17,10 @@
*
* Author: Gary Pei <guangyu.pei@boeing.com>
*/
#include "ns3/lr-wpan-error-model.h"
#include "ns3/log.h"
#include "lr-wpan-error-model.h"
#include <ns3/log.h>
#include <cmath>
NS_LOG_COMPONENT_DEFINE ("LrWpanErrorModel");
@@ -36,8 +38,25 @@ LrWpanErrorModel::GetTypeId (void)
return tid;
}
LrWpanErrorModel::LrWpanErrorModel ()
LrWpanErrorModel::LrWpanErrorModel (void)
{
m_binomialCoefficients[0] = 1;
m_binomialCoefficients[1] = -16;
m_binomialCoefficients[2] = 120;
m_binomialCoefficients[3] = -560;
m_binomialCoefficients[4] = 1820;
m_binomialCoefficients[5] = -4368;
m_binomialCoefficients[6] = 8008;
m_binomialCoefficients[7] = -11440;
m_binomialCoefficients[8] = 12870;
m_binomialCoefficients[9] = -11440;
m_binomialCoefficients[10] = 8008;
m_binomialCoefficients[11] = -4368;
m_binomialCoefficients[12] = 1820;
m_binomialCoefficients[13] = -560;
m_binomialCoefficients[14] = 120;
m_binomialCoefficients[15] = -16;
m_binomialCoefficients[16] = 1;
}
double
@@ -47,7 +66,7 @@ LrWpanErrorModel::GetChunkSuccessRate (double snr, uint32_t nbits) const
for (uint32_t k = 2; k <= 16; k++)
{
ber += pow (-1.0, (double) k) * BinomialCoefficient (k,16) * exp (20.0 * snr * (1.0 / k - 1.0));
ber += m_binomialCoefficients[k] * exp (20.0 * snr * (1.0 / k - 1.0));
}
ber = ber * 8.0 / 15.0 / 16.0;
@@ -57,23 +76,4 @@ LrWpanErrorModel::GetChunkSuccessRate (double snr, uint32_t nbits) const
return retval;
}
uint64_t
LrWpanErrorModel::Factorial (uint32_t k) const
{
uint64_t fact = 1;
while (k > 0)
{
fact *= k;
k--;
}
return fact;
}
uint32_t LrWpanErrorModel::BinomialCoefficient (uint32_t k, uint32_t n) const
{
uint32_t retval = Factorial (n) / Factorial (k) / Factorial (n - k);
return retval;
}
} // namespace ns3

View File

@@ -20,9 +20,7 @@
#ifndef LR_WPAN_ERROR_MODEL_H
#define LR_WPAN_ERROR_MODEL_H
#include <stdint.h>
#include <math.h>
#include "ns3/object.h"
#include <ns3/object.h>
namespace ns3 {
@@ -38,7 +36,7 @@ class LrWpanErrorModel : public Object
public:
static TypeId GetTypeId (void);
LrWpanErrorModel ();
LrWpanErrorModel (void);
/**
* return chunk success rate for given SNR
@@ -49,8 +47,8 @@ public:
double GetChunkSuccessRate (double snr, uint32_t nbits) const;
private:
uint64_t Factorial (uint32_t k) const;
uint32_t BinomialCoefficient (uint32_t k, uint32_t n) const;
double m_binomialCoefficients[17];
};

View File

@@ -1,79 +0,0 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2011 The Boeing Company
*
* 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: Gary Pei <guangyu.pei@boeing.com>
*/
#include "ns3/lr-wpan-error-rate-model.h"
#include "ns3/log.h"
NS_LOG_COMPONENT_DEFINE ("LrWpanErrorRateModel");
namespace ns3 {
NS_OBJECT_ENSURE_REGISTERED (LrWpanErrorRateModel);
TypeId
LrWpanErrorRateModel::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::LrWpanErrorRateModel")
.SetParent<Object> ()
.AddConstructor<LrWpanErrorRateModel> ()
;
return tid;
}
LrWpanErrorRateModel::LrWpanErrorRateModel ()
{
}
double
LrWpanErrorRateModel::GetChunkSuccessRate (double snr, uint32_t nbits) const
{
double ber = 0.0;
for (uint32_t k = 2; k <= 16; k++)
{
ber += pow (-1.0, (double) k) * BinomialCoefficient (k,16) * exp (20.0 * snr * (1.0 / k - 1.0));
}
ber = ber * 8.0 / 15.0 / 16.0;
ber = std::min (ber, 1.0);
double retval = pow (1.0 - ber, nbits);
return retval;
}
uint64_t
LrWpanErrorRateModel::Factorial (uint32_t k) const
{
uint64_t fact = 1;
while (k > 0)
{
fact *= k;
k--;
}
return fact;
}
uint32_t LrWpanErrorRateModel::BinomialCoefficient (uint32_t k, uint32_t n) const
{
uint32_t retval = Factorial (n) / Factorial (k) / Factorial (n - k);
return retval;
}
} // namespace ns3

View File

@@ -1,51 +0,0 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2011 The Boeing Company
*
* 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: Gary Pei <guangyu.pei@boeing.com>
*/
#ifndef LR_WPAN_ERROR_RATE_MODEL_H
#define LR_WPAN_ERROR_RATE_MODEL_H
#include <stdint.h>
#include <math.h>
#include "ns3/object.h"
namespace ns3 {
/**
* Model the error rate for IEEE 802.15.4 2.4 GHz AWGN channel for OQPSK
* the model description can be found in IEEE Std 802.15.4-2006, section
* E.4.1.7
*/
class LrWpanErrorRateModel : public Object
{
public:
static TypeId GetTypeId (void);
LrWpanErrorRateModel ();
double GetChunkSuccessRate (double snr, uint32_t nbits) const;
private:
uint64_t Factorial (uint32_t k) const;
uint32_t BinomialCoefficient (uint32_t k, uint32_t n) const;
};
} // namespace ns3
#endif /* LR_WPAN_ERROR_RATE_MODEL_H */

View File

@@ -0,0 +1,94 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2013 Fraunhofer FKIE
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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, see <http://www.gnu.org/licenses/>.
*
* Author:
* Sascha Alexander Jopen <jopen@cs.uni-bonn.de>
*/
#include "lr-wpan-lqi-tag.h"
#include <ns3/integer.h>
namespace ns3 {
NS_OBJECT_ENSURE_REGISTERED (LrWpanLqiTag);
TypeId
LrWpanLqiTag::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::LrWpanLqiTag")
.SetParent<Tag> ()
.AddConstructor<LrWpanLqiTag> ()
.AddAttribute ("Lqi", "The lqi of the last packet received",
IntegerValue (0),
MakeIntegerAccessor (&LrWpanLqiTag::Get),
MakeIntegerChecker<uint8_t> ())
;
return tid;
}
TypeId
LrWpanLqiTag::GetInstanceTypeId (void) const
{
return GetTypeId ();
}
LrWpanLqiTag::LrWpanLqiTag (void)
: m_lqi (0)
{
}
LrWpanLqiTag::LrWpanLqiTag (uint8_t lqi)
: m_lqi (lqi)
{
}
uint32_t
LrWpanLqiTag::GetSerializedSize (void) const
{
return sizeof (uint8_t);
}
void
LrWpanLqiTag::Serialize (TagBuffer i) const
{
i.WriteU8 (m_lqi);
}
void
LrWpanLqiTag::Deserialize (TagBuffer i)
{
m_lqi = i.ReadU8 ();
}
void
LrWpanLqiTag::Print (std::ostream &os) const
{
os << "Lqi = " << m_lqi;
}
void
LrWpanLqiTag::Set (uint8_t lqi)
{
m_lqi = lqi;
}
uint8_t
LrWpanLqiTag::Get (void) const
{
return m_lqi;
}
}

View File

@@ -0,0 +1,69 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2013 Fraunhofer FKIE
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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, see <http://www.gnu.org/licenses/>.
*
* Author:
* Sascha Alexander Jopen <jopen@cs.uni-bonn.de>
*/
#ifndef LR_WPAN_LQI_TAG_H
#define LR_WPAN_LQI_TAG_H
#include <ns3/tag.h>
namespace ns3 {
class Tag;
class LrWpanLqiTag : public Tag
{
public:
static TypeId GetTypeId (void);
virtual TypeId GetInstanceTypeId (void) const;
/**
* Create a LrWpanLqiTag with the default LQI 0 .
*/
LrWpanLqiTag (void);
/**
* Create a LrWpanLqiTag with the given LQI value.
*/
LrWpanLqiTag (uint8_t lqi);
virtual uint32_t GetSerializedSize (void) const;
virtual void Serialize (TagBuffer i) const;
virtual void Deserialize (TagBuffer i);
virtual void Print (std::ostream &os) const;
/**
* Set the LQI to the given value.
*
* @param lqi the value of the LQI to set
*/
void Set (uint8_t lqi);
/**
* Get the LQI value.
*
* @return the LQI value
*/
uint8_t Get (void) const;
private:
uint8_t m_lqi;
};
}
#endif /* LR_WPAN_LQI_TAG_H */

View File

@@ -17,11 +17,8 @@
*
* Author: kwong yin <kwong-sang.yin@boeing.com>
*/
#include "ns3/lr-wpan-mac-header.h"
#include "ns3/mac16-address.h"
#include "ns3/mac64-address.h"
#include "ns3/address-utils.h"
#include "lr-wpan-mac-header.h"
#include <ns3/address-utils.h>
namespace ns3 {

View File

@@ -35,14 +35,12 @@
* ++ - These fields are optional and of variable size
*/
#ifndef LRWPAN_MAC_HEADER_H
#define LRWPAN_MAC_HEADER_H
#ifndef LR_WPAN_MAC_HEADER_H
#define LR_WPAN_MAC_HEADER_H
#include <stdint.h>
#include "ns3/header.h"
#include "ns3/nstime.h"
#include "ns3/mac16-address.h"
#include "ns3/mac64-address.h"
#include <ns3/header.h>
#include <ns3/mac16-address.h>
#include <ns3/mac64-address.h>
namespace ns3 {
@@ -211,7 +209,7 @@ private:
Mac64Address m_addrExtSrcAddr; // 0 or 8 Octet
/* Auxiliary Security Header // 0, 5, 6, 10 or 14 Octets */
uint8_t m_auxSecCtrl; // 1 Octet see below
// uint8_t m_auxSecCtrl; // 1 Octet see below
uint32_t m_auxFrmCntr; // 4 Octet
/* Security Control fields */
@@ -235,7 +233,7 @@ private:
}; //LrWpanMacHeader
}; // namespace ns-3
#endif /* LRWPAN_MAC_HEADER_H */
#endif /* LR_WPAN_MAC_HEADER_H */
// ----------------------------------------------------------------------------------------------------------

View File

@@ -15,27 +15,25 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: kwong yin <kwong-sang.yin@boeing.com>
* Author:
* kwong yin <kwong-sang.yin@boeing.com>
* Sascha Alexander Jopen <jopen@cs.uni-bonn.de>
* Erwan Livolant <erwan.livolant@inria.fr>
*/
#include "lr-wpan-mac-trailer.h"
#include "ns3/object.h"
#include <ns3/packet.h>
namespace ns3 {
NS_OBJECT_ENSURE_REGISTERED (LrWpanMacTrailer);
LrWpanMacTrailer::LrWpanMacTrailer ()
LrWpanMacTrailer::LrWpanMacTrailer () :
m_fcs (0), m_calcFcs (false)
{
}
LrWpanMacTrailer::~LrWpanMacTrailer ()
{
}
TypeId LrWpanMacTrailer::GetTypeId (void)
TypeId
LrWpanMacTrailer::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::LrWpanMacTrailer")
.SetParent<Trailer> ()
@@ -44,30 +42,108 @@ TypeId LrWpanMacTrailer::GetTypeId (void)
return tid;
}
TypeId LrWpanMacTrailer::GetInstanceTypeId (void) const
TypeId
LrWpanMacTrailer::GetInstanceTypeId (void) const
{
return GetTypeId ();
}
void LrWpanMacTrailer::Print (std::ostream &os) const
void
LrWpanMacTrailer::Print (std::ostream &os) const
{
os << " FCS = " << m_fcs;
}
uint32_t LrWpanMacTrailer::GetSerializedSize (void) const
uint32_t
LrWpanMacTrailer::GetSerializedSize (void) const
{
return LRWPAN_MAC_FCS_LENGTH;
}
void LrWpanMacTrailer::Serialize (Buffer::Iterator start) const
void
LrWpanMacTrailer::Serialize (Buffer::Iterator start) const
{
start.Prev (LRWPAN_MAC_FCS_LENGTH);
start.WriteU16 (0);
start.WriteU16 (m_fcs);
}
uint32_t LrWpanMacTrailer::Deserialize (Buffer::Iterator start)
uint32_t
LrWpanMacTrailer::Deserialize (Buffer::Iterator start)
{
start.Prev (LRWPAN_MAC_FCS_LENGTH);
m_fcs = start.ReadU16 ();
return LRWPAN_MAC_FCS_LENGTH;
}
uint16_t
LrWpanMacTrailer::GetFcs (void) const
{
return m_fcs;
}
void
LrWpanMacTrailer::SetFcs (Ptr<const Packet> p)
{
if (m_calcFcs)
{
uint16_t size = p->GetSize ();
uint8_t *serial_packet = new uint8_t[size];
p->CopyData(serial_packet, size);
m_fcs = GenerateCrc16(serial_packet, size);
delete[] serial_packet;
}
}
/* Be sure to have removed the trailer and only the trailer
* from the packet before to use CheckFcs */
bool
LrWpanMacTrailer::CheckFcs (Ptr<const Packet> p)
{
if (!m_calcFcs)
{
return true;
}
else
{
uint16_t checkFcs;
uint16_t size = p->GetSize ();
uint8_t *serial_packet = new uint8_t[size];
p->CopyData(serial_packet, size);
checkFcs = GenerateCrc16(serial_packet, size);
delete[] serial_packet;
return (checkFcs == GetFcs ());
}
}
void
LrWpanMacTrailer::EnableFcs (bool enable)
{
m_calcFcs = enable;
}
/* CRC16-CCITT with a generator polynomial = ^16 + ^12 + ^5 + 1,
* LSB first and initial value = 0x0000 */
uint16_t
LrWpanMacTrailer::GenerateCrc16 (uint8_t *data, int length)
{
int i;
uint16_t accumulator = 0;
for(i = 0; i < length; ++i)
{
accumulator ^= *data;
accumulator = (accumulator >> 8) | (accumulator << 8);
accumulator ^= (accumulator & 0xff00) << 4;
accumulator ^= (accumulator >> 8) >> 4;
accumulator ^= (accumulator & 0xff00) >> 5;
++data;
}
return accumulator;
}
} //namespace ns3

View File

@@ -15,17 +15,21 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: kwong yin <kwong-sang.yin@boeing.com>
* Author:
* kwong yin <kwong-sang.yin@boeing.com>
* Sascha Alexander Jopen <jopen@cs.uni-bonn.de>
* Erwan Livolant <erwan.livolant@inria.fr>
*/
#ifndef LRWPANMACTRAILER_H_
#define LRWPANMACTRAILER_H_
#ifndef LR_WPAN_MAC_TRAILER_H
#define LR_WPAN_MAC_TRAILER_H
#include "ns3/trailer.h"
#include <stdint.h>
#include <ns3/trailer.h>
namespace ns3 {
class Packet;
/**
* The length in octets of the IEEE 802.15.4 MAC FCS field
*/
@@ -36,7 +40,6 @@ class LrWpanMacTrailer : public Trailer
{
public:
LrWpanMacTrailer ();
~LrWpanMacTrailer ();
static TypeId GetTypeId (void);
virtual TypeId GetInstanceTypeId (void) const;
@@ -44,6 +47,16 @@ public:
virtual uint32_t GetSerializedSize (void) const;
virtual void Serialize (Buffer::Iterator start) const;
virtual uint32_t Deserialize (Buffer::Iterator start);
uint16_t GetFcs (void) const;
void SetFcs (Ptr<const Packet> p);
bool CheckFcs (Ptr<const Packet> p);
void EnableFcs (bool enable);
private:
uint16_t m_fcs;
bool m_calcFcs;
uint16_t GenerateCrc16 (uint8_t *data, int length);
};
} // namespace ns3
#endif /* LRWPANMACTRAILER_H_ */
#endif /* LR_WPAN_MAC_TRAILER_H */

View File

@@ -19,16 +19,18 @@
* Gary Pei <guangyu.pei@boeing.com>
* kwong yin <kwong-sang.yin@boeing.com>
* Tom Henderson <thomas.r.henderson@boeing.com>
* Sascha Alexander Jopen <jopen@cs.uni-bonn.de>
* Erwan Livolant <erwan.livolant@inria.fr>
*/
#include "ns3/simulator.h"
#include "ns3/lr-wpan-mac.h"
#include "ns3/log.h"
#include "ns3/uinteger.h"
#include "ns3/trace-source-accessor.h"
#include "ns3/lr-wpan-csmaca.h"
#include "ns3/lr-wpan-phy.h"
#include "ns3/mac16-address.h"
#include "ns3/mac64-address.h"
#include "lr-wpan-mac.h"
#include "lr-wpan-csmaca.h"
#include "lr-wpan-mac-header.h"
#include "lr-wpan-mac-trailer.h"
#include <ns3/simulator.h>
#include <ns3/log.h>
#include <ns3/uinteger.h>
#include <ns3/node.h>
#include <ns3/packet.h>
NS_LOG_COMPONENT_DEFINE ("LrWpanMac");
@@ -52,11 +54,14 @@ LrWpanMac::GetTypeId (void)
UintegerValue (),
MakeUintegerAccessor (&LrWpanMac::m_macPanId),
MakeUintegerChecker<uint16_t> ())
.AddTraceSource ("MacTxQueue",
"Trace source indicating a packet has was enqueued or dequeued to/from the transaction queue",
MakeTraceSourceAccessor (&LrWpanMac::m_macTxQueueTrace))
.AddTraceSource ("MacTx",
"Trace source indicating a packet has arrived for transmission by this device",
MakeTraceSourceAccessor (&LrWpanMac::m_macTxTrace))
.AddTraceSource ("MacTxDrop",
"Trace source indicating a packet has been dropped by the device before transmission",
"Trace source indicating a packet has been dropped during transmission",
MakeTraceSourceAccessor (&LrWpanMac::m_macTxDropTrace))
.AddTraceSource ("MacPromiscRx",
"A packet has been received by this device, has been passed up from the physical layer "
@@ -85,13 +90,19 @@ LrWpanMac::GetTypeId (void)
LrWpanMac::LrWpanMac ()
{
// First set the state to a known value, call ChangeMacState to fire trace source.
m_lrWpanMacState = MAC_IDLE;
ChangeMacState (MAC_IDLE);
m_macRxOnWhenIdle = true;
m_macPanId = 0;
m_associationStatus = ASSOCIATED;
m_selfExt = Mac64Address::Allocate ();
m_macPromiscuousMode = false;
m_macMaxFrameRetries = 3;
m_retransmission = 0;
m_txPkt = 0;
SeedManager::SetSeed (100);
UniformVariable uniformVar;
uniformVar = UniformVariable (0, 255);
m_macDsn = SequenceNumber16 (uniformVar.GetValue ());
@@ -102,6 +113,21 @@ LrWpanMac::~LrWpanMac ()
{
}
void
LrWpanMac::DoInitialize ()
{
if (m_macRxOnWhenIdle)
{
m_phy->PlmeSetTRXStateRequest (IEEE_802_15_4_PHY_RX_ON);
}
else
{
m_phy->PlmeSetTRXStateRequest (IEEE_802_15_4_PHY_TRX_OFF);
}
Object::DoInitialize ();
}
void
LrWpanMac::DoDispose ()
{
@@ -120,8 +146,34 @@ LrWpanMac::DoDispose ()
m_phy = 0;
m_mcpsDataIndicationCallback = MakeNullCallback< void, McpsDataIndicationParams, Ptr<Packet> > ();
m_mcpsDataConfirmCallback = MakeNullCallback< void, McpsDataConfirmParams > ();
Object::DoDispose ();
}
bool
LrWpanMac::GetRxOnWhenIdle ()
{
return m_macRxOnWhenIdle;
}
void
LrWpanMac::SetRxOnWhenIdle (bool rxOnWhenIdle)
{
NS_LOG_FUNCTION (this << rxOnWhenIdle);
m_macRxOnWhenIdle = rxOnWhenIdle;
if (m_lrWpanMacState == MAC_IDLE)
{
if (m_macRxOnWhenIdle)
{
m_phy->PlmeSetTRXStateRequest (IEEE_802_15_4_PHY_RX_ON);
}
else
{
m_phy->PlmeSetTRXStateRequest (IEEE_802_15_4_PHY_TRX_OFF);
}
}
}
void
LrWpanMac::SetShortAddress (Mac16Address address)
@@ -158,6 +210,10 @@ LrWpanMac::McpsDataRequest (McpsDataRequestParams params, Ptr<Packet> p)
McpsDataConfirmParams confirmParams;
confirmParams.m_msduHandle = params.m_msduHandle;
// TODO: We need a drop trace for the case that the packet is too large or the request parameters are maleformed.
// The current tx drop trace is not suitable, because packets dropped using this trace carry the mac header
// and footer, while packets being dropped here do not have them.
LrWpanMacHeader macHdr (LrWpanMacHeader::LRWPAN_MAC_DATA, (uint8_t)m_macDsn.GetValue ());
m_macDsn++;
if (m_macDsn > SequenceNumber16 (255))
@@ -218,15 +274,20 @@ LrWpanMac::McpsDataRequest (McpsDataRequestParams params, Ptr<Packet> p)
}
macHdr.SetDstAddrMode (params.m_dstAddrMode);
// TODO: Add field for EXT_ADDR destination address (and use it here).
macHdr.SetDstAddrFields (params.m_dstPanId, params.m_dstAddr);
macHdr.SetSecDisable ();
//extract the last 3 bits in TxOptions and map to macHdr
int b0 = params.m_txOptions & 1;
int b1 = params.m_txOptions & 2;
int b2 = params.m_txOptions & 4;
if (b0 == 1)
int b0 = params.m_txOptions & TX_OPTION_ACK;
int b1 = params.m_txOptions & TX_OPTION_GTS;
int b2 = params.m_txOptions & TX_OPTION_INDIRECT;
if (b0 == TX_OPTION_ACK)
{
macHdr.SetAckReq ();
// Set AckReq bit only if the destination is not the broadcast address.
if (!(macHdr.GetDstAddrMode () == SHORT_ADDR && macHdr.GetShortDstAddr() == "ff:ff"))
{
macHdr.SetAckReq ();
}
}
else if (b0 == 0)
{
@@ -246,7 +307,7 @@ LrWpanMac::McpsDataRequest (McpsDataRequestParams params, Ptr<Packet> p)
//if is Slotted CSMA means its beacon enabled
if (m_csmaCa->isSlottedCsmaCa ())
{
if (b1 == 2)
if (b1 == TX_OPTION_GTS)
{
//TODO:GTS Transmission
}
@@ -279,7 +340,7 @@ LrWpanMac::McpsDataRequest (McpsDataRequestParams params, Ptr<Packet> p)
}
}
if (b2 == 4)
if (b2 == TX_OPTION_INDIRECT)
{
//TODO :indirect tx
}
@@ -301,43 +362,50 @@ LrWpanMac::McpsDataRequest (McpsDataRequestParams params, Ptr<Packet> p)
p->AddHeader (macHdr);
LrWpanMacTrailer macTrailer;
// Calculate FCS if the global attribute ChecksumEnable is set.
if (Node::ChecksumEnabled ())
{
macTrailer.EnableFcs (true);
macTrailer.SetFcs (p);
}
p->AddTrailer (macTrailer);
m_macTxTrace (p);
confirmParams.m_status = IEEE_802_15_4_SUCCESS;
if (!m_mcpsDataConfirmCallback.IsNull ())
{
m_mcpsDataConfirmCallback (confirmParams);
}
m_macTxQueueTrace (p, true);
TxQueueElement *txQElement = new TxQueueElement;
txQElement->txQMsduHandle = params.m_msduHandle;
txQElement->txQPkt = p;
if (m_txQueue.empty ())
m_txQueue.push_back (txQElement);
CheckQueue ();
}
void
LrWpanMac::CheckQueue ()
{
// Pull a packet from the queue and start sending, if we are not already sending.
if (m_lrWpanMacState == MAC_IDLE && !m_txQueue.empty () && m_txPkt == 0)
{
m_txPkt = txQElement->txQPkt->Copy ();
m_txQueue.push_front (txQElement); // the first packet in the queue is currently worked on
// Start CCA process for this packet
Simulator::ScheduleNow (&LrWpanCsmaCa::Start, m_csmaCa);
}
else
{
// if queue is not empty put this packet at the end of Tx queue
m_txQueue.push_back (txQElement);
TxQueueElement *txQElement = m_txQueue.front ();
m_txPkt = txQElement->txQPkt;
Simulator::ScheduleNow (&LrWpanMac::SetLrWpanMacState, this, MAC_CSMA);
}
}
void LrWpanMac::SetCsmaCa (Ptr<LrWpanCsmaCa> csmaCa)
void
LrWpanMac::SetCsmaCa (Ptr<LrWpanCsmaCa> csmaCa)
{
m_csmaCa = csmaCa;
}
void LrWpanMac::SetPhy (Ptr<LrWpanPhy> phy)
void
LrWpanMac::SetPhy (Ptr<LrWpanPhy> phy)
{
m_phy = phy;
}
Ptr<LrWpanPhy> LrWpanMac::GetPhy (void)
Ptr<LrWpanPhy>
LrWpanMac::GetPhy (void)
{
return m_phy;
}
@@ -355,38 +423,14 @@ LrWpanMac::SetMcpsDataConfirmCallback (McpsDataConfirmCallback c)
}
void
LrWpanMac::PdDataIndication (uint32_t psduLength, Ptr<Packet> p, uint32_t lqi)
LrWpanMac::PdDataIndication (uint32_t psduLength, Ptr<Packet> p, uint8_t lqi)
{
NS_ASSERT (m_lrWpanMacState == MAC_IDLE || m_lrWpanMacState == MAC_ACK_PENDING || m_lrWpanMacState == MAC_CSMA);
NS_LOG_FUNCTION (this << psduLength << p << lqi);
bool acceptFrame;
Ptr<Packet> originalPkt = p->Copy (); // because we will strip headers
LrWpanMacHeader receivedMacHdr;
p->RemoveHeader (receivedMacHdr);
LrWpanMacTrailer receivedMacTrailer;
p->RemoveTrailer (receivedMacTrailer);
m_promiscSnifferTrace (originalPkt);
McpsDataIndicationParams params;
params.m_dsn = receivedMacHdr.GetSeqNum ();
params.m_mpduLinkQuality = lqi;
params.m_srcPanId = receivedMacHdr.GetSrcPanId ();
params.m_srcAddrMode = receivedMacHdr.GetSrcAddrMode ();
if (params.m_srcAddrMode == SHORT_ADDR)
{
params.m_srcAddr = receivedMacHdr.GetShortSrcAddr ();
}
params.m_dstPanId = receivedMacHdr.GetDstPanId ();
params.m_dstAddrMode = receivedMacHdr.GetDstAddrMode ();
if (params.m_dstAddrMode == SHORT_ADDR)
{
params.m_dstAddr = receivedMacHdr.GetShortDstAddr ();
}
NS_LOG_DEBUG ("Packet from " << params.m_srcAddr << " to " << params.m_dstAddr);
// from sec 7.5.6.2 Reception and rejection, Std802.15.4-2006
// level 1 filtering, test FCS field and reject if frame fails
// level 2 filtering if promiscuous mode pass frame to higher layer otherwise perform level 3 filtering
@@ -397,79 +441,56 @@ LrWpanMac::PdDataIndication (uint32_t psduLength, Ptr<Packet> p, uint32_t lqi)
// if beacon frame then srcPanId = m_macPanId
// if only srcAddr field in Data or Command frame,accept frame if srcPanId=m_macPanId
Ptr<Packet> originalPkt = p->Copy (); // because we will strip headers
m_promiscSnifferTrace (originalPkt);
m_macPromiscRxTrace (originalPkt);
// XXX no rejection tracing (to macRxDropTrace) being performed below
if (m_macPromiscuousMode)
LrWpanMacTrailer receivedMacTrailer;
p->RemoveTrailer (receivedMacTrailer);
if (Node::ChecksumEnabled ())
{
//level 2 filtering
if (!m_mcpsDataIndicationCallback.IsNull ())
{
NS_LOG_DEBUG ("promiscuous mode, forwarding up");
m_mcpsDataIndicationCallback (params, p);
}
else
{
NS_LOG_ERROR (this << " Data Indication Callback not initialised");
}
receivedMacTrailer.EnableFcs (true);
}
// level 1 filtering
if(!receivedMacTrailer.CheckFcs (p))
{
m_macRxDropTrace (originalPkt);
}
else
{
//level 3 frame filtering
acceptFrame = (receivedMacHdr.GetType () != LrWpanMacHeader::LRWPAN_MAC_RESERVED);
LrWpanMacHeader receivedMacHdr;
p->RemoveHeader (receivedMacHdr);
if (acceptFrame)
McpsDataIndicationParams params;
params.m_dsn = receivedMacHdr.GetSeqNum ();
params.m_mpduLinkQuality = lqi;
params.m_srcPanId = receivedMacHdr.GetSrcPanId ();
params.m_srcAddrMode = receivedMacHdr.GetSrcAddrMode ();
// TODO: Add field for EXT_ADDR source address.
if (params.m_srcAddrMode == SHORT_ADDR)
{
acceptFrame = (receivedMacHdr.GetFrameVer () <= 1);
params.m_srcAddr = receivedMacHdr.GetShortSrcAddr ();
}
params.m_dstPanId = receivedMacHdr.GetDstPanId ();
params.m_dstAddrMode = receivedMacHdr.GetDstAddrMode ();
// TODO: Add field for EXT_ADDR destination address.
if (params.m_dstAddrMode == SHORT_ADDR)
{
params.m_dstAddr = receivedMacHdr.GetShortDstAddr ();
}
if (acceptFrame
&& (receivedMacHdr.GetDstAddrMode () > 1))
{
acceptFrame = receivedMacHdr.GetDstPanId () == m_macPanId
|| receivedMacHdr.GetDstPanId () == 0xffff;
}
NS_LOG_DEBUG ("Packet from " << params.m_srcAddr << " to " << params.m_dstAddr);
if (acceptFrame
&& (receivedMacHdr.GetDstAddrMode () == 2))
if (m_macPromiscuousMode)
{
acceptFrame = receivedMacHdr.GetShortDstAddr () == m_shortAddress
|| receivedMacHdr.GetShortDstAddr () == Mac16Address ("ff:ff"); // check for broadcast addrs
}
if (acceptFrame
&& (receivedMacHdr.GetDstAddrMode () == 3))
{
acceptFrame = (receivedMacHdr.GetExtDstAddr () == m_selfExt);
}
if (acceptFrame
&& (receivedMacHdr.GetType () == LrWpanMacHeader::LRWPAN_MAC_BEACON))
{
if (m_macPanId == 0xffff)
{
acceptFrame = true;
}
else
{
acceptFrame = receivedMacHdr.GetSrcPanId () == m_macPanId;
}
}
if (acceptFrame
&& ((receivedMacHdr.GetType () == LrWpanMacHeader::LRWPAN_MAC_DATA)
|| (receivedMacHdr.GetType () == LrWpanMacHeader::LRWPAN_MAC_COMMAND))
&& (receivedMacHdr.GetSrcAddrMode () > 1))
{
acceptFrame = receivedMacHdr.GetSrcPanId () == m_macPanId; //TODO need to check if PAN coord
}
if (acceptFrame)
{
m_macRxTrace (originalPkt);
//level 2 filtering
if (!m_mcpsDataIndicationCallback.IsNull ())
{
NS_LOG_DEBUG ("PdDataIndication(): Packet is for me; forwarding up");
NS_LOG_DEBUG ("promiscuous mode, forwarding up");
m_mcpsDataIndicationCallback (params, p);
}
else
@@ -479,36 +500,288 @@ LrWpanMac::PdDataIndication (uint32_t psduLength, Ptr<Packet> p, uint32_t lqi)
}
else
{
m_macRxDropTrace (originalPkt);
p = 0;
//level 3 frame filtering
acceptFrame = (receivedMacHdr.GetType () != LrWpanMacHeader::LRWPAN_MAC_RESERVED);
if (acceptFrame)
{
acceptFrame = (receivedMacHdr.GetFrameVer () <= 1);
}
if (acceptFrame
&& (receivedMacHdr.GetDstAddrMode () > 1))
{
acceptFrame = receivedMacHdr.GetDstPanId () == m_macPanId
|| receivedMacHdr.GetDstPanId () == 0xffff;
}
if (acceptFrame
&& (receivedMacHdr.GetDstAddrMode () == 2))
{
acceptFrame = receivedMacHdr.GetShortDstAddr () == m_shortAddress
|| receivedMacHdr.GetShortDstAddr () == Mac16Address ("ff:ff"); // check for broadcast addrs
}
if (acceptFrame
&& (receivedMacHdr.GetDstAddrMode () == 3))
{
acceptFrame = (receivedMacHdr.GetExtDstAddr () == m_selfExt);
}
if (acceptFrame
&& (receivedMacHdr.GetType () == LrWpanMacHeader::LRWPAN_MAC_BEACON))
{
if (m_macPanId == 0xffff)
{
// TODO: Accept only if the frame version field is valid
acceptFrame = true;
}
else
{
acceptFrame = receivedMacHdr.GetSrcPanId () == m_macPanId;
}
}
if (acceptFrame
&& ((receivedMacHdr.GetType () == LrWpanMacHeader::LRWPAN_MAC_DATA)
|| (receivedMacHdr.GetType () == LrWpanMacHeader::LRWPAN_MAC_COMMAND))
&& (receivedMacHdr.GetSrcAddrMode () > 1))
{
acceptFrame = receivedMacHdr.GetSrcPanId () == m_macPanId; //TODO need to check if PAN coord
}
if (acceptFrame)
{
m_macRxTrace (originalPkt);
// TODO: What should we do if we receive a frame while waiting for an ACK?
// Especially if this frame has the ACK request bit set, should we reply with an ACK, possibly missing the pending ACK?
// If the received frame is a frame with the ACK request bit set, we immediately send back an ACK.
// If we are currently waiting for a pending ACK, we assume the ACK was lost and trigger a retransmission after sending the ACK.
if ((receivedMacHdr.IsData () || receivedMacHdr.IsCommand ()) && receivedMacHdr.IsAckReq ()
&& !(receivedMacHdr.GetDstAddrMode () == SHORT_ADDR && receivedMacHdr.GetShortDstAddr () == "ff:ff"))
{
// If this is a data or mac command frame, which is not a broadcast,
// with ack req set, generate and send an ack frame.
// If there is a CSMA medium access in progress we cancel the medium access
// for sending the ACK frame. A new transmission attempt will be started
// after the ACK was send.
if (m_lrWpanMacState == MAC_ACK_PENDING)
{
m_ackWaitTimeout.Cancel ();
PrepareRetransmission ();
}
else if (m_lrWpanMacState == MAC_CSMA)
{
// TODO: If we receive a packet while doing CSMA/CA, should we drop the packet because of channel busy,
// or should we restart CSMA/CA for the packet after sending the ACK?
// Currently we simply restart CSMA/CA after sending the ACK.
m_csmaCa->Cancel ();
}
ChangeMacState (MAC_IDLE);
Simulator::ScheduleNow (&LrWpanMac::SendAck, this, receivedMacHdr.GetSeqNum ());
}
if (receivedMacHdr.IsData () && !m_mcpsDataIndicationCallback.IsNull ())
{
// If it is a data frame, push it up the stack.
NS_LOG_DEBUG ("PdDataIndication(): Packet is for me; forwarding up");
m_mcpsDataIndicationCallback (params, p);
}
else if (receivedMacHdr.IsAcknowledgment () && m_txPkt && m_lrWpanMacState == MAC_ACK_PENDING)
{
LrWpanMacHeader macHdr;;
m_txPkt->PeekHeader (macHdr);
if (receivedMacHdr.GetSeqNum () == macHdr.GetSeqNum ())
{
// If it is an ACK with the expected sequence number, finish the transmission
// and notify the upper layer.
m_ackWaitTimeout.Cancel ();
if (!m_mcpsDataConfirmCallback.IsNull ())
{
TxQueueElement *txQElement = m_txQueue.front ();
McpsDataConfirmParams confirmParams;
confirmParams.m_msduHandle = txQElement->txQMsduHandle;
confirmParams.m_status = IEEE_802_15_4_SUCCESS;
m_mcpsDataConfirmCallback (confirmParams);
}
RemoveFirstTxQElement ();
Simulator::ScheduleNow (&LrWpanMac::SetLrWpanMacState, this, MAC_IDLE);
}
else
{
// If it is an ACK with an unexpected sequence number, mark the current transmission as failed and start a retransmit. (cf 7.5.6.4.3)
m_ackWaitTimeout.Cancel ();
if (!PrepareRetransmission ())
{
Simulator::ScheduleNow (&LrWpanMac::SetLrWpanMacState, this, MAC_IDLE);
}
else
{
Simulator::ScheduleNow (&LrWpanMac::SetLrWpanMacState, this, MAC_CSMA);
}
}
}
}
else
{
m_macRxDropTrace (originalPkt);
}
}
}
}
void
LrWpanMac::SendAck (uint8_t seqno)
{
NS_ASSERT (m_lrWpanMacState == MAC_IDLE);
// Generate a corresponding ACK Frame.
LrWpanMacHeader macHdr (LrWpanMacHeader::LRWPAN_MAC_ACKNOWLEDGMENT, seqno);
LrWpanMacTrailer macTrailer;
Ptr<Packet> ackPacket = Create<Packet> (0);
ackPacket->AddHeader (macHdr);
ackPacket->AddTrailer (macTrailer);
// Enqueue the ACK packet for further processing
// when the transmitter is activated.
m_txPkt = ackPacket;
// Switch transceiver to TX mode. Proceed sending the Ack on confirm.
ChangeMacState (MAC_SENDING);
m_phy->PlmeSetTRXStateRequest (IEEE_802_15_4_PHY_TX_ON);
}
void
LrWpanMac::RemoveFirstTxQElement (void)
{
TxQueueElement *txQElement = m_txQueue.front ();
Ptr<const Packet> p = txQElement->txQPkt;
txQElement->txQPkt = 0;
delete txQElement;
m_txQueue.pop_front ();
m_txPkt = 0;
m_retransmission = 0;
m_macTxQueueTrace (p, false);
}
void
LrWpanMac::AckWaitTimeout (void)
{
// TODO: If we are a PAN coordinator and this was an indirect transmission,
// we will not initiate a retransmission. Instead we wait for the data
// being extracted after a new data request command.
if (!PrepareRetransmission ())
{
SetLrWpanMacState (MAC_IDLE);
}
else
{
SetLrWpanMacState (MAC_CSMA);
}
}
bool
LrWpanMac::PrepareRetransmission (void)
{
if (m_retransmission >= m_macMaxFrameRetries)
{
// Maximum number of retransmissions has been reached.
// remove the copy of the packet that was just sent
TxQueueElement *txQElement = m_txQueue.front ();
m_macTxDropTrace (txQElement->txQPkt);
if (!m_mcpsDataConfirmCallback.IsNull ())
{
McpsDataConfirmParams confirmParams;
confirmParams.m_msduHandle = txQElement->txQMsduHandle;
confirmParams.m_status = IEEE_802_15_4_NO_ACK;
m_mcpsDataConfirmCallback (confirmParams);
}
RemoveFirstTxQElement ();
return false;
}
else
{
m_retransmission++;
// Start next CCA process for this packet.
return true;
}
}
void
LrWpanMac::PdDataConfirm (LrWpanPhyEnumeration status)
{
NS_LOG_FUNCTION (this << status << m_txQueue.empty () ? 0 : m_txQueue.size ());
m_phy->PlmeSetTRXStateRequest (IEEE_802_15_4_PHY_RX_ON);
NS_ASSERT (m_lrWpanMacState == MAC_SENDING);
if (status == IEEE_802_15_4_PHY_SUCCESS || status == IEEE_802_15_4_PHY_UNSPECIFIED)
NS_LOG_FUNCTION (this << status << (m_txQueue.empty () ? 0 : m_txQueue.size ()));
TxQueueElement *txQElement = m_txQueue.front ();
LrWpanMacHeader macHdr;
m_txPkt->PeekHeader (macHdr);
if (status == IEEE_802_15_4_PHY_SUCCESS)
{
// remove the copy of the packet that was just sent
TxQueueElement *txQElement = m_txQueue.front ();
txQElement->txQPkt = 0;
delete txQElement;
m_txQueue.pop_front ();
ChangeMacState (CHANNEL_IDLE);
if (!m_txQueue.empty ())
if (!macHdr.IsAcknowledgment ())
{
NS_LOG_FUNCTION ("PdDataConfirm: start CCA process for next packet");
// Start CCA process for next packet in the tx queue
m_txPkt = m_txQueue.front ()->txQPkt->Copy ();
Simulator::ScheduleNow (&LrWpanCsmaCa::Start, m_csmaCa);
// We have just send a regular data packet, check if we have to wait
// for an ACK.
if (macHdr.IsAckReq ())
{
// wait for the ack or the next retransmission timeout
// start retransmission timer
Time waitTime = MicroSeconds (GetMacAckWaitDuration () * 1000 * 1000 / m_phy->GetDataOrSymbolRate (false));
NS_ASSERT (m_ackWaitTimeout.IsExpired());
m_ackWaitTimeout = Simulator::Schedule (waitTime, &LrWpanMac::AckWaitTimeout, this);
Simulator::ScheduleNow (&LrWpanMac::SetLrWpanMacState, this, MAC_ACK_PENDING);
return;
}
else
{
// remove the copy of the packet that was just sent
if (!m_mcpsDataConfirmCallback.IsNull ())
{
McpsDataConfirmParams confirmParams;
confirmParams.m_msduHandle = txQElement->txQMsduHandle;
confirmParams.m_status = IEEE_802_15_4_SUCCESS;
m_mcpsDataConfirmCallback (confirmParams);
}
RemoveFirstTxQElement ();
}
}
else
{
// We have send an ACK. Clear the packet buffer.
m_txPkt = 0;
}
}
else if (status == IEEE_802_15_4_PHY_UNSPECIFIED)
{
if (!macHdr.IsAcknowledgment ())
{
m_macTxDropTrace (txQElement->txQPkt);
if (!m_mcpsDataConfirmCallback.IsNull ())
{
McpsDataConfirmParams confirmParams;
confirmParams.m_msduHandle = txQElement->txQMsduHandle;
confirmParams.m_status = IEEE_802_15_4_FRAME_TOO_LONG;
m_mcpsDataConfirmCallback (confirmParams);
}
RemoveFirstTxQElement ();
}
else
{
NS_LOG_ERROR ("Unable to send ACK");
}
}
else
{
// Something went really wrong. The PHY is not in the correct state for
// data transmission.
NS_FATAL_ERROR ("Transmission attempt failed with PHY status " << status);
}
Simulator::ScheduleNow (&LrWpanMac::SetLrWpanMacState, this, MAC_IDLE);
}
void
@@ -529,7 +802,7 @@ LrWpanMac::PlmeEdConfirm (LrWpanPhyEnumeration status, uint8_t energyLevel)
void
LrWpanMac::PlmeGetAttributeConfirm (LrWpanPhyEnumeration status,
LrWpanPibAttributeIdentifier id,
LrWpanPhyPIBAttributes* attribute)
LrWpanPhyPibAttributes* attribute)
{
NS_LOG_FUNCTION (this << status << id << attribute);
}
@@ -538,14 +811,36 @@ void
LrWpanMac::PlmeSetTRXStateConfirm (LrWpanPhyEnumeration status)
{
NS_LOG_FUNCTION (this << status);
if (status == IEEE_802_15_4_PHY_TX_ON || status == IEEE_802_15_4_PHY_SUCCESS)
if (m_lrWpanMacState == MAC_SENDING && (status == IEEE_802_15_4_PHY_TX_ON || status == IEEE_802_15_4_PHY_SUCCESS))
{
if ((m_txPkt) && (m_lrWpanMacState == SET_PHY_TX_ON))
{
m_promiscSnifferTrace (m_txPkt);
m_snifferTrace (m_txPkt);
m_phy->PdDataRequest (m_txPkt->GetSize (), m_txPkt);
}
NS_ASSERT (m_txPkt);
// Start sending if we are in state SENDING and the PHY transmitter was enabled.
m_promiscSnifferTrace (m_txPkt);
m_snifferTrace (m_txPkt);
m_phy->PdDataRequest (m_txPkt->GetSize (), m_txPkt);
}
else if (m_lrWpanMacState == MAC_CSMA && (status == IEEE_802_15_4_PHY_RX_ON || status == IEEE_802_15_4_PHY_SUCCESS))
{
// Start the CSMA algorithm as soon as the receiver is enabled.
m_csmaCa->Start ();
}
else if (m_lrWpanMacState == MAC_IDLE)
{
NS_ASSERT (status == IEEE_802_15_4_PHY_RX_ON || status == IEEE_802_15_4_PHY_SUCCESS || status == IEEE_802_15_4_PHY_TRX_OFF);
// Do nothing special when going idle.
}
else if (m_lrWpanMacState == MAC_ACK_PENDING)
{
NS_ASSERT (status == IEEE_802_15_4_PHY_RX_ON || status == IEEE_802_15_4_PHY_SUCCESS);
}
else
{
// TODO: What to do when we receive an error?
// If we want to transmit a packet, but switching the transceiver on results
// in an error, we have to recover somehow (and start sending again).
NS_FATAL_ERROR ("Error changing transceiver state");
}
}
@@ -563,39 +858,57 @@ LrWpanMac::SetLrWpanMacState (LrWpanMacState macState)
McpsDataConfirmParams confirmParams;
ChangeMacState (macState);
if ((m_lrWpanMacState == CHANNEL_IDLE) && (m_txPkt))
if (macState == MAC_IDLE)
{
ChangeMacState (MAC_IDLE);
if (m_macRxOnWhenIdle)
{
m_phy->PlmeSetTRXStateRequest (IEEE_802_15_4_PHY_RX_ON);
}
else
{
m_phy->PlmeSetTRXStateRequest (IEEE_802_15_4_PHY_TRX_OFF);
}
CheckQueue ();
}
else if (macState == MAC_ACK_PENDING)
{
ChangeMacState (MAC_ACK_PENDING);
m_phy->PlmeSetTRXStateRequest (IEEE_802_15_4_PHY_RX_ON);
}
else if (macState == MAC_CSMA)
{
NS_ASSERT (m_lrWpanMacState == MAC_IDLE);
ChangeMacState (MAC_CSMA);
m_phy->PlmeSetTRXStateRequest (IEEE_802_15_4_PHY_RX_ON);
}
else if (m_lrWpanMacState == MAC_CSMA && macState == CHANNEL_IDLE)
{
// Channel is idle, set transmitter to TX_ON
NS_LOG_DEBUG ( this << " channel idle");
ChangeMacState (SET_PHY_TX_ON);
ChangeMacState (MAC_SENDING);
m_phy->PlmeSetTRXStateRequest (IEEE_802_15_4_PHY_TX_ON);
}
else if ((m_lrWpanMacState == CHANNEL_ACCESS_FAILURE) && (m_txPkt))
else if (m_lrWpanMacState == MAC_CSMA && macState == CHANNEL_ACCESS_FAILURE)
{
NS_ASSERT (m_txPkt);
// cannot find a clear channel, drop the current packet.
NS_LOG_DEBUG ( this << " cannot find clear channel");
confirmParams.m_msduHandle = m_txQueue.front ()->txQMsduHandle;
confirmParams.m_status = IEEE_802_15_4_CHANNEL_ACCESS_FAILURE;
m_macTxDropTrace (m_txPkt);
// remove the copy of the packet that was just sent
TxQueueElement *txQElement = m_txQueue.front ();
txQElement->txQPkt = 0;
delete txQElement;
m_txQueue.pop_front ();
if (!m_mcpsDataConfirmCallback.IsNull ())
{
m_mcpsDataConfirmCallback (confirmParams);
}
// if there are more packets waiting to be sent
if (!m_txQueue.empty ())
{
// Start CCA process for next packet in the tx queue
m_txPkt = m_txQueue.front ()->txQPkt->Copy ();
Simulator::ScheduleNow (&LrWpanCsmaCa::Start, m_csmaCa);
}
}
// remove the copy of the packet that was just sent
RemoveFirstTxQElement ();
Simulator::ScheduleNow (&LrWpanMac::SetLrWpanMacState, this, MAC_IDLE);
}
}
LrWpanAssociationStatus
@@ -631,4 +944,24 @@ LrWpanMac::ChangeMacState (LrWpanMacState newState)
m_macStateLogger (Simulator::Now (), m_lrWpanMacState, newState);
m_lrWpanMacState = newState;
}
uint64_t
LrWpanMac::GetMacAckWaitDuration (void) const
{
return m_csmaCa->getUnitBackoffPeriod () + m_phy->aTurnaroundTime + m_phy->GetPhySHRDuration ()
+ ceil (6 * m_phy->GetPhySymbolsPerOctet ());
}
uint8_t
LrWpanMac::GetMacMaxFrameRetries (void) const
{
return m_macMaxFrameRetries;
}
void
LrWpanMac::SetMacMaxFrameRetries (uint8_t retries)
{
m_macMaxFrameRetries = retries;
}
} // namespace ns3

View File

@@ -19,35 +19,44 @@
* Gary Pei <guangyu.pei@boeing.com>
* kwong yin <kwong-sang.yin@boeing.com>
* Tom Henderson <thomas.r.henderson@boeing.com>
* Sascha Alexander Jopen <jopen@cs.uni-bonn.de>
*/
#ifndef LR_WPAN_MAC_H
#define LR_WPAN_MAC_H
#include <stdint.h>
#include <math.h>
#include "ns3/object.h"
#include "ns3/callback.h"
#include "ns3/mac16-address.h"
#include "lr-wpan-phy.h"
#include "lr-wpan-mac-header.h"
#include "lr-wpan-mac-trailer.h"
#include "ns3/mac16-address.h"
#include "ns3/mac64-address.h"
#include <ns3/object.h>
#include <ns3/traced-callback.h>
#include <ns3/mac16-address.h>
#include <ns3/mac64-address.h>
#include <ns3/sequence-number.h>
#include <ns3/lr-wpan-phy.h>
#include <ns3/event-id.h>
#include <deque>
#include "ns3/sequence-number.h"
namespace ns3 {
class Packet;
class LrWpanCsmaCa;
/**
* \defgroup lr-wpan LR-WPAN models
*
* This section documents the API of the IEEE 802.15.4-related models. For a generic functional description, please refer to the ns-3 manual.
*/
typedef enum
{
TX_OPTION_ACK = 1,
TX_OPTION_GTS = 2,
TX_OPTION_INDIRECT = 4
} LrWpanTxOption;
typedef enum
{
MAC_IDLE,
MAC_CSMA,
MAC_SENDING,
MAC_ACK_PENDING,
CHANNEL_ACCESS_FAILURE,
CHANNEL_IDLE,
SET_PHY_TX_ON
@@ -97,8 +106,12 @@ typedef enum
struct McpsDataRequestParams
{
uint8_t m_srcAddrMode;
uint8_t m_dstAddrMode;
McpsDataRequestParams () :
m_srcAddrMode (SHORT_ADDR), m_dstAddrMode (SHORT_ADDR), m_dstPanId (0),
m_dstAddr (), m_msduHandle (0), m_txOptions (0)
{ };
LrWpanAddressMode m_srcAddrMode;
LrWpanAddressMode m_dstAddrMode;
uint16_t m_dstPanId;
Mac16Address m_dstAddr;
uint8_t m_msduHandle;
@@ -126,16 +139,15 @@ struct McpsDataIndicationParams
// This callback is called after a McpsDataRequest has been called from
// the higher layer. It returns a status of the outcome of the
// transmission request
typedef Callback< void, McpsDataConfirmParams > McpsDataConfirmCallback;
typedef Callback<void, McpsDataConfirmParams> McpsDataConfirmCallback;
// This callback is called after a Mcps has successfully received a
// frame and wants to deliver it to the higher layer.
//
// XXX for now, we do not deliver all of the parameters in section
// 7.1.1.3.1 but just send up the packet.
typedef Callback< void, McpsDataIndicationParams, Ptr<Packet> > McpsDataIndicationCallback;
typedef Callback<void, McpsDataIndicationParams, Ptr<Packet> > McpsDataIndicationCallback;
class LrWpanCsmaCa;
/**
* \ingroup lr-wpan
@@ -153,6 +165,9 @@ public:
LrWpanMac ();
virtual ~LrWpanMac ();
bool GetRxOnWhenIdle ();
void SetRxOnWhenIdle (bool rxOnWhenIdle);
// XXX these setters will become obsolete if we use the attribute system
void SetShortAddress (Mac16Address address);
Mac16Address GetShortAddress (void) const;
@@ -188,7 +203,7 @@ public:
* @param p the packet to be transmitted
* @param lqi Link quality (LQI) value measured during reception of the PPDU
*/
void PdDataIndication (uint32_t psduLength, Ptr<Packet> p, uint32_t lqi);
void PdDataIndication (uint32_t psduLength, Ptr<Packet> p, uint8_t lqi);
/**
* IEEE 802.15.4-2006 section 6.2.1.2
@@ -223,7 +238,7 @@ public:
*/
void PlmeGetAttributeConfirm (LrWpanPhyEnumeration status,
LrWpanPibAttributeIdentifier id,
LrWpanPhyPIBAttributes* attribute);
LrWpanPhyPibAttributes* attribute);
/**
* IEEE 802.15.4-2006 section 6.2.2.8
@@ -263,7 +278,7 @@ public:
uint64_t m_aBaseSlotDuration; // 60 symbols in each superframe slot
uint64_t m_aNumSuperframeSlots; // 16 slots in each superframe
uint64_t m_aBaseSuperframeDuration; // aBaseSlotDuration * aNumSuperframeSlots in symbols
//MAC PIB attributes
uint64_t m_macBeaconTxTime; // time the device tx last beacon frame in symbols, only 24 bits used
uint64_t m_macSyncSymbolOffset; // symbol boundary is same as m_macBeaconTxTime
@@ -271,11 +286,33 @@ public:
uint64_t m_macSuperframeOrder; // 0..14 and 15 means superframe shall not remain active after beacon
bool m_macPromiscuousMode; // Indicates if MAC sublayer is in receive all mode. True mean accept all frames from PHY.
uint16_t m_macPanId; // 16bits id of PAN on which this device is operating. 0xffff means not asscoiated
SequenceNumber16 m_macDsn; //Seq num added to transmitted data or MAC command frame 00-ff
SequenceNumber16 m_macDsn; // Seq num added to transmitted data or MAC command frame 00-ff
uint8_t m_macMaxFrameRetries; // The maximum number of retries allowed after a transmission failure
uint64_t GetMacAckWaitDuration (void) const;
uint8_t GetMacMaxFrameRetries (void) const;
void SetMacMaxFrameRetries (uint8_t retries);
protected:
virtual void DoInitialize (void);
virtual void DoDispose (void);
private:
virtual void DoDispose (void);
struct TxQueueElement
{
uint8_t txQMsduHandle;
Ptr<Packet> txQPkt;
};
void SendAck (uint8_t seqno);
void RemoveFirstTxQElement (void);
void ChangeMacState (LrWpanMacState newState);
void AckWaitTimeout (void);
bool PrepareRetransmission (void);
void CheckQueue (void);
TracedCallback<Ptr<const Packet>, bool> m_macTxQueueTrace;
/**
* The trace source fired when packets come into the "top" of the device
* at the L3/L2 transition, before being queued for transmission.
@@ -373,13 +410,10 @@ private:
Ptr<Packet> m_txPkt; // XXX need packet buffer instead of single packet
Mac16Address m_shortAddress;
Mac64Address m_selfExt;
struct TxQueueElement
{
uint8_t txQMsduHandle;
Ptr<Packet> txQPkt;
};
std::deque<TxQueueElement*> m_txQueue;
uint8_t m_retransmission;
EventId m_ackWaitTimeout;
bool m_macRxOnWhenIdle;
};

View File

@@ -15,18 +15,24 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Tom Henderson <thomas.r.henderson@boeing.com>
* Author:
* Tom Henderson <thomas.r.henderson@boeing.com>
* Tommaso Pecorella <tommaso.pecorella@unifi.it>
* Margherita Filippetti <morag87@gmail.com>
*/
#include "ns3/abort.h"
#include "ns3/node.h"
#include "lr-wpan-net-device.h"
#include "ns3/log.h"
#include "ns3/lr-wpan-mac.h"
#include "ns3/lr-wpan-phy.h"
#include "ns3/lr-wpan-csmaca.h"
#include "ns3/spectrum-channel.h"
#include "ns3/pointer.h"
#include "lr-wpan-phy.h"
#include "lr-wpan-csmaca.h"
#include "lr-wpan-error-model.h"
#include <ns3/abort.h>
#include <ns3/node.h>
#include <ns3/log.h>
#include <ns3/spectrum-channel.h>
#include <ns3/pointer.h>
#include <ns3/boolean.h>
#include <ns3/mobility-model.h>
#include <ns3/packet.h>
NS_LOG_COMPONENT_DEFINE ("LrWpanNetDevice");
@@ -54,6 +60,10 @@ LrWpanNetDevice::GetTypeId (void)
MakePointerAccessor (&LrWpanNetDevice::GetMac,
&LrWpanNetDevice::SetMac),
MakePointerChecker<LrWpanMac> ())
.AddAttribute ("UseAcks", "Request acknowledgments for data frames.",
BooleanValue (true),
MakeBooleanAccessor (&LrWpanNetDevice::m_useAcks),
MakeBooleanChecker ())
;
return tid;
}
@@ -114,11 +124,13 @@ LrWpanNetDevice::CompleteConfig (void)
}
m_mac->SetPhy (m_phy);
m_mac->SetCsmaCa (m_csmaca);
m_mac->SetMcpsDataIndicationCallback (MakeCallback (&LrWpanNetDevice::McpsDataIndication, this));
m_csmaca->SetMac (m_mac);
m_phy->SetMobility (m_node->GetObject<MobilityModel> ());
Ptr<LrWpanErrorModel> model = CreateObject<LrWpanErrorModel> ();
m_phy->SetErrorModel (model);
m_phy->SetDevice (this);
m_phy->SetPdDataIndicationCallback (MakeCallback (&LrWpanMac::PdDataIndication, m_mac));
m_phy->SetPdDataConfirmCallback (MakeCallback (&LrWpanMac::PdDataConfirm, m_mac));
@@ -252,8 +264,12 @@ LrWpanNetDevice::SetMtu (const uint16_t mtu)
uint16_t
LrWpanNetDevice::GetMtu (void) const
{
NS_ABORT_MSG ("Unsupported");
return 0;
NS_LOG_FUNCTION (this);
// Maximum payload size is: max psdu - frame control - seqno - addressing - security - fcs
// = 127 - 2 - 1 - (2+2+2+2) - 0 - 2
// = 114
// assuming no security and addressing with only 16 bit addresses without pan id compression.
return 114;
}
bool
@@ -280,15 +296,15 @@ LrWpanNetDevice::IsBroadcast (void) const
Address
LrWpanNetDevice::GetBroadcast (void) const
{
NS_ABORT_MSG ("Unsupported; add me");
return Address ();
NS_LOG_FUNCTION (this);
return Mac16Address ("ff:ff");
}
bool
LrWpanNetDevice::IsMulticast (void) const
{
NS_LOG_FUNCTION (this);
return false;
return true;
}
Address
@@ -301,8 +317,34 @@ LrWpanNetDevice::GetMulticast (Ipv4Address multicastGroup) const
Address
LrWpanNetDevice::GetMulticast (Ipv6Address addr) const
{
NS_ABORT_MSG ("Unsupported");
return Address ();
NS_LOG_FUNCTION (this);
/* Implementation based on RFC 4944 Section 9.
* An IPv6 packet with a multicast destination address (DST),
* consisting of the sixteen octets DST[1] through DST[16], is
* transmitted to the following 802.15.4 16-bit multicast address:
* 0 1
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |1 0 0|DST[15]* | DST[16] |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* Here, DST[15]* refers to the last 5 bits in octet DST[15], that is,
* bits 3-7 within DST[15]. The initial 3-bit pattern of "100" follows
* the 16-bit address format for multicast addresses (Section 12). */
// \todo re-add this once Lr-Wpan will be able to accept these multicast addresses
// uint8_t buf[16];
// uint8_t buf2[2];
//
// addr.GetBytes(buf);
//
// buf2[0] = 0x80 | (buf[14] & 0x1F);
// buf2[1] = buf[15];
//
// Mac16Address newaddr = Mac16Address();
// newaddr.CopyFrom(buf2);
// return newaddr;
return Mac16Address ("ff:ff");
}
bool
@@ -327,14 +369,35 @@ LrWpanNetDevice::Send (Ptr<Packet> packet, const Address& dest, uint16_t protoco
// McpsDataRequest parameters.
// For further study: how to support these methods somehow, such as
// inventing a fake ethertype and packet tag for McpsDataRequest
NS_ABORT_MSG ("Unsupported; use McpsDataRequest instead");
return false;
NS_LOG_FUNCTION (this << packet << dest << protocolNumber);
if (packet->GetSize () > GetMtu ())
{
NS_LOG_ERROR ("Fragmentation is needed for this packet, drop the packet ");
return false;
}
McpsDataRequestParams m_mcpsDataRequestParams;
m_mcpsDataRequestParams.m_dstAddr = Mac16Address::ConvertFrom (dest);
m_mcpsDataRequestParams.m_dstAddrMode = SHORT_ADDR;
m_mcpsDataRequestParams.m_dstPanId = m_mac->GetPanId ();
m_mcpsDataRequestParams.m_srcAddrMode = SHORT_ADDR;
// Using ACK requests for broadcast destinations is ok here. They are disabled
// by the MAC.
if (m_useAcks)
{
m_mcpsDataRequestParams.m_txOptions = TX_OPTION_ACK;
}
m_mcpsDataRequestParams.m_msduHandle = 0;
m_mac->McpsDataRequest (m_mcpsDataRequestParams, packet);
return true;
}
bool
LrWpanNetDevice::SendFrom (Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber)
{
NS_ABORT_MSG ("Unsupported; use McpsDataRequest instead");
NS_ABORT_MSG ("Unsupported");
// TODO: To support SendFrom, the MACs McpsDataRequest has to use the provided source address, instead of to local one.
return false;
}
@@ -356,19 +419,15 @@ LrWpanNetDevice::SetNode (Ptr<Node> node)
bool
LrWpanNetDevice::NeedsArp (void) const
{
NS_ABORT_MSG ("Unsupported");
return false;
NS_LOG_FUNCTION (this);
return true;
}
void
LrWpanNetDevice::SetReceiveCallback (ReceiveCallback cb)
{
// This method basically assumes an 802.3-compliant device, but a raw
// 802.15.4 device does not have an ethertype, and requires specific
// McpsDataIndication parameters.
// For further study: how to support these methods somehow, such as
// inventing a fake ethertype and packet tag for McpsDataRequest
NS_LOG_WARN ("Unsupported; use LrWpan MAC APIs instead");
NS_LOG_FUNCTION (this);
m_receiveCallback = cb;
}
void
@@ -382,6 +441,14 @@ LrWpanNetDevice::SetPromiscReceiveCallback (PromiscReceiveCallback cb)
NS_LOG_WARN ("Unsupported; use LrWpan MAC APIs instead");
}
void
LrWpanNetDevice::McpsDataIndication (McpsDataIndicationParams params, Ptr<Packet> pkt)
{
NS_LOG_FUNCTION (this);
// TODO: Use the PromiscReceiveCallback if the MAC is in promiscuous mode.
m_receiveCallback (this, pkt, 0, params.m_srcAddr);
}
bool
LrWpanNetDevice::SupportsSendFrom (void) const
{

View File

@@ -15,20 +15,20 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Tom Henderson <thomas.r.henderson@boeing.com>
* Author:
* Tom Henderson <thomas.r.henderson@boeing.com>
* Tommaso Pecorella <tommaso.pecorella@unifi.it>
* Margherita Filippetti <morag87@gmail.com>
*/
#ifndef LR_WPAN_NET_DEVICE_H
#define LR_WPAN_NET_DEVICE_H
#include <string>
#include <stdint.h>
#include "ns3/net-device.h"
#include "ns3/traced-callback.h"
#include <ns3/net-device.h>
#include <ns3/traced-callback.h>
#include <ns3/lr-wpan-mac.h>
namespace ns3 {
class LrWpanMac;
class LrWpanPhy;
class LrWpanCsmaCa;
class SingleModelSpectrumChannel;
@@ -52,8 +52,8 @@ class LrWpanNetDevice : public NetDevice
public:
static TypeId GetTypeId (void);
LrWpanNetDevice ();
virtual ~LrWpanNetDevice ();
LrWpanNetDevice (void);
virtual ~LrWpanNetDevice (void);
void SetMac (Ptr<LrWpanMac> mac);
void SetPhy (Ptr<LrWpanPhy> phy);
@@ -103,6 +103,8 @@ public:
virtual void SetPromiscReceiveCallback (PromiscReceiveCallback cb);
virtual bool SupportsSendFrom (void) const;
void McpsDataIndication (McpsDataIndicationParams params, Ptr<Packet> pkt);
private:
virtual void DoDispose (void);
virtual void DoStart (void);
@@ -116,13 +118,15 @@ private:
Ptr<LrWpanCsmaCa> m_csmaca;
Ptr<Node> m_node;
bool m_configComplete;
bool m_useAcks;
bool m_linkUp;
uint32_t m_ifIndex;
TracedCallback<> m_linkChanges;
ReceiveCallback m_receiveCallback;
};
} // namespace ns3
#endif /* NET_DEVICE_H */
#endif /* LR_WPAN_NET_DEVICE_H */

View File

@@ -15,14 +15,25 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Gary Pei <guangyu.pei@boeing.com>
* Author:
* Gary Pei <guangyu.pei@boeing.com>
* Sascha Alexander Jopen <jopen@cs.uni-bonn.de>
*/
#include "ns3/log.h"
#include "ns3/abort.h"
#include <math.h>
#include "ns3/simulator.h"
#include "ns3/lr-wpan-phy.h"
#include "ns3/trace-source-accessor.h"
#include "lr-wpan-phy.h"
#include "lr-wpan-lqi-tag.h"
#include "lr-wpan-spectrum-signal-parameters.h"
#include "lr-wpan-spectrum-value-helper.h"
#include "lr-wpan-error-model.h"
#include <ns3/log.h>
#include <ns3/abort.h>
#include <ns3/simulator.h>
#include <ns3/spectrum-value.h>
#include <ns3/antenna-model.h>
#include <ns3/mobility-model.h>
#include <ns3/spectrum-channel.h>
#include <ns3/packet.h>
#include <ns3/packet-burst.h>
#include <ns3/net-device.h>
NS_LOG_COMPONENT_DEFINE ("LrWpanPhy");
@@ -91,8 +102,7 @@ LrWpanPhy::LrWpanPhy ()
: m_edRequest (),
m_setTRXState ()
{
m_trxState = IEEE_802_15_4_PHY_IDLE;
ChangeTrxState (IEEE_802_15_4_PHY_RX_ON);
m_trxState = IEEE_802_15_4_PHY_TRX_OFF;
m_trxStatePending = IEEE_802_15_4_PHY_IDLE;
// default PHY PIB attributes
@@ -121,6 +131,8 @@ LrWpanPhy::LrWpanPhy ()
m_currentRxPacket = std::make_pair (none, true);
m_currentTxPacket = std::make_pair (none, true);
m_errorModel = 0;
ChangeTrxState (IEEE_802_15_4_PHY_TRX_OFF);
}
LrWpanPhy::~LrWpanPhy ()
@@ -131,6 +143,12 @@ void
LrWpanPhy::DoDispose ()
{
NS_LOG_FUNCTION (this);
// Cancel pending transceiver state change, if one is in progress.
m_setTRXState.Cancel ();
m_trxState = IEEE_802_15_4_PHY_TRX_OFF;
m_trxStatePending = IEEE_802_15_4_PHY_IDLE;
m_mobility = 0;
m_device = 0;
m_channel = 0;
@@ -138,11 +156,11 @@ LrWpanPhy::DoDispose ()
m_rxPsd = 0;
m_noise = 0;
m_errorModel = 0;
m_pdDataIndicationCallback = MakeNullCallback< void, uint32_t, Ptr<Packet>, uint32_t > ();
m_pdDataIndicationCallback = MakeNullCallback< void, uint32_t, Ptr<Packet>, uint8_t > ();
m_pdDataConfirmCallback = MakeNullCallback< void, LrWpanPhyEnumeration > ();
m_plmeCcaConfirmCallback = MakeNullCallback< void, LrWpanPhyEnumeration > ();
m_plmeEdConfirmCallback = MakeNullCallback< void, LrWpanPhyEnumeration,uint8_t > ();
m_plmeGetAttributeConfirmCallback = MakeNullCallback< void, LrWpanPhyEnumeration, LrWpanPibAttributeIdentifier, LrWpanPhyPIBAttributes* > ();
m_plmeGetAttributeConfirmCallback = MakeNullCallback< void, LrWpanPhyEnumeration, LrWpanPibAttributeIdentifier, LrWpanPhyPibAttributes* > ();
m_plmeSetTRXStateConfirmCallback = MakeNullCallback< void, LrWpanPhyEnumeration > ();
m_plmeSetAttributeConfirmCallback = MakeNullCallback< void, LrWpanPhyEnumeration, LrWpanPibAttributeIdentifier > ();
@@ -192,6 +210,7 @@ LrWpanPhy::SetChannel (Ptr<SpectrumChannel> c)
Ptr<SpectrumChannel>
LrWpanPhy::GetChannel (void)
{
NS_LOG_FUNCTION (this);
return m_channel;
}
@@ -199,6 +218,7 @@ LrWpanPhy::GetChannel (void)
Ptr<const SpectrumModel>
LrWpanPhy::GetRxSpectrumModel () const
{
NS_LOG_FUNCTION (this);
if (m_txPsd)
{
return m_txPsd->GetSpectrumModel ();
@@ -212,6 +232,7 @@ LrWpanPhy::GetRxSpectrumModel () const
Ptr<AntennaModel>
LrWpanPhy::GetRxAntenna ()
{
NS_LOG_FUNCTION (this);
return m_antenna;
}
@@ -233,25 +254,53 @@ LrWpanPhy::StartRx (Ptr<SpectrumSignalParameters> spectrumRxParams)
Ptr<LrWpanSpectrumSignalParameters> lrWpanRxParams = DynamicCast<LrWpanSpectrumSignalParameters> (spectrumRxParams);
if (lrWpanRxParams != 0)
if (m_trxState == IEEE_802_15_4_PHY_RX_ON)
{
// The specification doesn't seem to refer to BUSY_RX, but vendor
// data sheets suggest that this is a substate of the RX_ON state
// that is entered after preamble detection when the digital receiver
// is enabled. Here, for now, we use BUSY_RX to mark the period between
// StartRx() and EndRx() states.
ChangeTrxState (IEEE_802_15_4_PHY_BUSY_RX);
if (lrWpanRxParams != 0)
{
// The specification doesn't seem to refer to BUSY_RX, but vendor
// data sheets suggest that this is a substate of the RX_ON state
// that is entered after preamble detection when the digital receiver
// is enabled. Here, for now, we use BUSY_RX to mark the period between
// StartRx() and EndRx() states.
Ptr<Packet> p = (lrWpanRxParams->packetBurst->GetPackets ()).front ();
NS_ASSERT(p != 0);
m_rxPsd = lrWpanRxParams->psd;
m_rxTotalPower = psdHelper.TotalAvgPower (m_rxPsd);
Time duration = lrWpanRxParams->duration;
if (m_rxTotalPower >= m_rxSensitivity)
{
ChangeTrxState (IEEE_802_15_4_PHY_BUSY_RX);
Time duration = lrWpanRxParams->duration;
m_currentRxPacket = std::make_pair (p, false);
Ptr<Packet> p = (lrWpanRxParams->packetBurst->GetPackets ()).front ();
m_currentRxPacket = std::make_pair (p, false);
m_rxPsd = lrWpanRxParams->psd;
m_rxTotalPower = psdHelper.TotalAvgPower (*m_rxPsd);
Simulator::Schedule (duration, &LrWpanPhy::EndRx, this);
m_phyRxBeginTrace (p);
Simulator::Schedule (duration, &LrWpanPhy::EndRx, this);
m_phyRxBeginTrace (p);
}
else
{
// We are below our receiver sensitivity, the packet cannot be received.
// TODO: Add the power somehow to the interference.
m_phyRxDropTrace (p);
}
}
NS_LOG_LOGIC (this << " state: " << m_trxState << " m_rxTotalPower: " << m_rxTotalPower);
}
else if (m_trxState == IEEE_802_15_4_PHY_BUSY_RX)
{
// TODO: Drop the second packet and add the signal power to the interference of
// the currently received packet. Consider the received signal power
// during CCA/ED, too.
NS_LOG_DEBUG (this << " packet collision");
Ptr<Packet> p = (lrWpanRxParams->packetBurst->GetPackets ()).front ();
m_phyRxDropTrace (p);
}
else
{
NS_LOG_DEBUG (this << " transceiver not in RX state");
Ptr<Packet> p = (lrWpanRxParams->packetBurst->GetPackets ()).front ();
m_phyRxDropTrace (p);
}
NS_LOG_LOGIC (this << " state: " << m_trxState << " m_rxTotalPower: " << m_rxTotalPower);
}
void LrWpanPhy::EndRx ()
@@ -261,62 +310,84 @@ void LrWpanPhy::EndRx ()
// Calculate whether packet was lost
if (m_currentRxPacket.second == true)
{
NS_LOG_DEBUG ("Reception was previously terminated; dropping packet");
m_phyRxDropTrace (m_currentRxPacket.first);
}
else if (m_errorModel != 0)
{
double sinr = psdHelper.TotalAvgPower (*m_rxPsd) / psdHelper.TotalAvgPower (*m_noise);
Ptr<Packet> p = m_currentRxPacket.first;
// Simplified calculation; the chunk is the whole packet
double per = 1.0 - m_errorModel->GetChunkSuccessRate (sinr, p->GetSize () * 8);
if (m_random.GetValue () > per)
if (m_currentRxPacket.first != 0)
{
NS_LOG_DEBUG ("Reception success for packet: per " << per << " sinr " << sinr);
m_phyRxEndTrace (p, sinr);
if (!m_pdDataIndicationCallback.IsNull ())
NS_LOG_DEBUG ("Reception was previously terminated; dropping packet");
m_phyRxDropTrace (m_currentRxPacket.first);
m_currentRxPacket.first = 0;
}
else
{
// TODO: This should never happen, but it does!
NS_LOG_UNCOND (this << " Finishing receive of NULL packet!");
}
}
else
{
if (m_errorModel != 0)
{
double sinr = psdHelper.TotalAvgPower (m_rxPsd) / psdHelper.TotalAvgPower (m_noise);
Ptr<Packet> p = m_currentRxPacket.first;
NS_ASSERT (p != 0);
p->AddPacketTag (LrWpanLqiTag (sinr));
// Simplified calculation; the chunk is the whole packet
double per = 1.0 - m_errorModel->GetChunkSuccessRate (sinr, p->GetSize () * 8);
if (m_random.GetValue () > per)
{
m_pdDataIndicationCallback (p->GetSize (), p, (uint32_t)sinr);
NS_LOG_DEBUG ("Reception success for packet: per " << per << " sinr " << sinr);
m_phyRxEndTrace (p, sinr);
if (!m_pdDataIndicationCallback.IsNull ())
{
m_pdDataIndicationCallback (p->GetSize (), p, (uint8_t)sinr);
}
}
else
{
/* Failure */
NS_LOG_DEBUG ("Reception failure for packet per" << per << " sinr " << sinr);
m_phyRxEndTrace (p, sinr);
m_phyRxDropTrace (p);
}
}
else
{
/* Failure */
NS_LOG_DEBUG ("Reception failure for packet per" << per << " sinr " << sinr);
m_phyRxEndTrace (p, sinr);
m_phyRxDropTrace (p);
NS_LOG_WARN ("Missing ErrorModel");
Ptr<Packet> p = m_currentRxPacket.first;
p->AddPacketTag (LrWpanLqiTag ());
m_phyRxEndTrace (p, 0);
if (!m_pdDataIndicationCallback.IsNull ())
{
m_pdDataIndicationCallback (p->GetSize (), p, 0);
}
}
}
else
{
NS_LOG_WARN ("Missing ErrorModel");
Ptr<Packet> p = m_currentRxPacket.first;
m_phyRxEndTrace (p, 0);
if (!m_pdDataIndicationCallback.IsNull ())
{
m_pdDataIndicationCallback (p->GetSize (), p, 0);
}
}
m_rxTotalPower = 0;
m_currentRxPacket.first = 0;
m_currentRxPacket.second = false;
// We may be waiting to apply a pending state change
if (m_trxStatePending != IEEE_802_15_4_PHY_IDLE)
{
NS_LOG_LOGIC ("Apply pending state change to " << m_trxStatePending);
ChangeTrxState (m_trxStatePending);
m_trxStatePending = IEEE_802_15_4_PHY_IDLE;
if (!m_plmeSetTRXStateConfirmCallback.IsNull ())
m_rxTotalPower = 0;
Ptr<Packet> none = 0;
m_currentRxPacket = std::make_pair (none, true);
// We may be waiting to apply a pending state change.
if (m_trxStatePending != IEEE_802_15_4_PHY_IDLE)
{
m_plmeSetTRXStateConfirmCallback (IEEE_802_15_4_PHY_SUCCESS);
// Only change the state immediately, if the transceiver is not already
// switching the state.
if (!m_setTRXState.IsRunning ())
{
NS_LOG_LOGIC ("Apply pending state change to " << m_trxStatePending);
ChangeTrxState (m_trxStatePending);
m_trxStatePending = IEEE_802_15_4_PHY_IDLE;
if (!m_plmeSetTRXStateConfirmCallback.IsNull ())
{
m_plmeSetTRXStateConfirmCallback (IEEE_802_15_4_PHY_SUCCESS);
}
}
}
}
else
{
if (m_trxState != IEEE_802_15_4_PHY_TRX_OFF)
else
{
ChangeTrxState (IEEE_802_15_4_PHY_RX_ON);
if (m_trxState != IEEE_802_15_4_PHY_TRX_OFF)
{
ChangeTrxState (IEEE_802_15_4_PHY_RX_ON);
}
}
}
}
@@ -341,6 +412,10 @@ LrWpanPhy::PdDataRequest (const uint32_t psduLength, Ptr<Packet> p)
//send down
NS_ASSERT (m_channel);
// Remove a possible LQI tag from a previous transmission of the packet.
LrWpanLqiTag lqiTag;
p->RemovePacketTag (lqiTag);
Ptr<LrWpanSpectrumSignalParameters> txParams = Create<LrWpanSpectrumSignalParameters> ();
txParams->duration = CalculateTxTime (p);
txParams->txPhy = GetObject<SpectrumPhy> ();
@@ -379,17 +454,24 @@ void
LrWpanPhy::PlmeCcaRequest (void)
{
NS_LOG_FUNCTION (this);
if (m_trxState == IEEE_802_15_4_PHY_RX_ON)
if (m_trxState == IEEE_802_15_4_PHY_RX_ON || m_trxState == IEEE_802_15_4_PHY_BUSY_RX)
{
//call StartRx or ED and then get updated m_rxTotalPower in EndCCA?
Time ccaTime = Seconds (8.0 / GetDataOrSymbolRate (false));
Simulator::Schedule (ccaTime, &LrWpanPhy::EndCca, this);
m_ccaRequest = Simulator::Schedule (ccaTime, &LrWpanPhy::EndCca, this);
}
else
{
if (!m_plmeCcaConfirmCallback.IsNull ())
{
m_plmeCcaConfirmCallback (m_trxState);
if (m_trxState == IEEE_802_15_4_PHY_TRX_OFF)
{
m_plmeCcaConfirmCallback (IEEE_802_15_4_PHY_TRX_OFF);
}
else
{
m_plmeCcaConfirmCallback (IEEE_802_15_4_PHY_BUSY);
}
}
}
}
@@ -441,8 +523,8 @@ LrWpanPhy::PlmeGetAttributeRequest (LrWpanPibAttributeIdentifier id)
}
if (!m_plmeGetAttributeConfirmCallback.IsNull ())
{
LrWpanPhyPIBAttributes retValue;
memcpy (&retValue, &m_phyPIBAttributes, sizeof(LrWpanPhyPIBAttributes));
LrWpanPhyPibAttributes retValue;
memcpy (&retValue, &m_phyPIBAttributes, sizeof(LrWpanPhyPibAttributes));
m_plmeGetAttributeConfirmCallback (status,id,&retValue);
}
}
@@ -460,17 +542,24 @@ LrWpanPhy::PlmeSetTRXStateRequest (LrWpanPhyEnumeration state)
&& (state != IEEE_802_15_4_PHY_TX_ON) );
NS_LOG_LOGIC ("Trying to set m_trxState from " << m_trxState << " to " << state);
// this method always overrides previous state setting attempts
if (!m_setTRXState.IsExpired ())
{
if (m_trxStatePending == state)
{
// Simply wait for the ongoing state switch.
return;
}
else
{
NS_LOG_DEBUG ("Cancel m_setTRXState");
m_setTRXState.Cancel();
}
}
if (m_trxStatePending != IEEE_802_15_4_PHY_IDLE)
{
m_trxStatePending = IEEE_802_15_4_PHY_IDLE;
}
if (m_setTRXState.IsRunning ())
{
NS_LOG_DEBUG ("Cancel m_setTRXState");
m_setTRXState.Cancel ();
}
if (state == m_trxState)
{
@@ -494,19 +583,29 @@ LrWpanPhy::PlmeSetTRXStateRequest (LrWpanPhyEnumeration state)
// a valid SFD. Here, we are not modelling at that level of
// granularity, so we just test for BUSY_RX state (any part of
// a packet being actively received)
if ((state == IEEE_802_15_4_PHY_TRX_OFF)
&& (m_trxState == IEEE_802_15_4_PHY_BUSY_RX)
&& (m_currentRxPacket.first) && (!m_currentRxPacket.second))
if (state == IEEE_802_15_4_PHY_TRX_OFF)
{
NS_LOG_DEBUG ("Receiver has valid SFD; defer state change");
m_trxStatePending = state;
return; // Send PlmeSetTRXStateConfirm later
if ((m_trxState == IEEE_802_15_4_PHY_BUSY_RX)
&& (m_currentRxPacket.first) && (!m_currentRxPacket.second))
{
NS_LOG_DEBUG ("Receiver has valid SFD; defer state change");
m_trxStatePending = state;
return; // Send PlmeSetTRXStateConfirm later
}
else if (m_trxState == IEEE_802_15_4_PHY_RX_ON || m_trxState == IEEE_802_15_4_PHY_TX_ON)
{
ChangeTrxState (IEEE_802_15_4_PHY_TRX_OFF);
if (!m_plmeSetTRXStateConfirmCallback.IsNull ())
{
m_plmeSetTRXStateConfirmCallback (state);
}
return;
}
}
if (state == IEEE_802_15_4_PHY_TX_ON)
{
NS_LOG_DEBUG ("turn on PHY_TX_ON");
ChangeTrxState (IEEE_802_15_4_PHY_TX_ON);
if ((m_trxState == IEEE_802_15_4_PHY_BUSY_RX) || (m_trxState == IEEE_802_15_4_PHY_RX_ON))
{
if (m_currentRxPacket.first)
@@ -516,16 +615,44 @@ LrWpanPhy::PlmeSetTRXStateRequest (LrWpanPhyEnumeration state)
NS_LOG_DEBUG ("force TX_ON, terminate reception");
m_currentRxPacket.second = true;
}
// If CCA is in progress, cancel CCA and return BUSY.
if (!m_ccaRequest.IsExpired ())
{
m_ccaRequest.Cancel ();
if (!m_plmeCcaConfirmCallback.IsNull ())
{
m_plmeCcaConfirmCallback (IEEE_802_15_4_PHY_BUSY);
}
}
m_trxStatePending = IEEE_802_15_4_PHY_TX_ON;
// Prevent PHY from receiving another packet while switching.
ChangeTrxState (IEEE_802_15_4_PHY_IDLE);
// Delay for turnaround time
// TODO: Does it also take aTurnaroundTime to switch the transceiver state,
// even when the receiver is not busy? (6.9.2)
Time setTime = Seconds ( (double) aTurnaroundTime / GetDataOrSymbolRate (false));
m_setTRXState = Simulator::Schedule (setTime, &LrWpanPhy::EndSetTRXState, this);
return;
}
else
else if (m_trxState == IEEE_802_15_4_PHY_BUSY_TX || m_trxState == IEEE_802_15_4_PHY_TX_ON)
{
// We do NOT change the transceiver state here. We only report that
// the transceiver is already in TX_ON state.
if (!m_plmeSetTRXStateConfirmCallback.IsNull ())
{
m_plmeSetTRXStateConfirmCallback (IEEE_802_15_4_PHY_SUCCESS);
m_plmeSetTRXStateConfirmCallback (IEEE_802_15_4_PHY_TX_ON);
}
return;
}
else if (m_trxState == IEEE_802_15_4_PHY_TRX_OFF)
{
ChangeTrxState (IEEE_802_15_4_PHY_TX_ON);
if (!m_plmeSetTRXStateConfirmCallback.IsNull ())
{
m_plmeSetTRXStateConfirmCallback (IEEE_802_15_4_PHY_TX_ON);
}
return;
}
@@ -550,7 +677,6 @@ LrWpanPhy::PlmeSetTRXStateRequest (LrWpanPhyEnumeration state)
{
NS_LOG_DEBUG ("force TRX_OFF, terminate transmission");
m_currentTxPacket.second = true;
m_currentTxPacket.first = 0;
}
ChangeTrxState (IEEE_802_15_4_PHY_TRX_OFF);
// Clear any other state
@@ -563,15 +689,33 @@ LrWpanPhy::PlmeSetTRXStateRequest (LrWpanPhyEnumeration state)
return;
}
if ((state == IEEE_802_15_4_PHY_RX_ON) && (m_trxState == IEEE_802_15_4_PHY_TX_ON))
if (state == IEEE_802_15_4_PHY_RX_ON)
{
// Turnaround delay
m_trxStatePending = IEEE_802_15_4_PHY_RX_ON;
Time setTime = Seconds ( (double) aTurnaroundTime / GetDataOrSymbolRate (false));
m_setTRXState = Simulator::Schedule (setTime, &LrWpanPhy::EndSetTRXState, this);
return;
if (m_trxState == IEEE_802_15_4_PHY_TX_ON || m_trxState == IEEE_802_15_4_PHY_TRX_OFF)
{
// Turnaround delay
// TODO: Does it really take aTurnaroundTime to switch the transceiver state,
// even when the transmitter is not busy? (6.9.1)
m_trxStatePending = IEEE_802_15_4_PHY_RX_ON;
// Prevent PHY from sending another packet while switching.
ChangeTrxState (IEEE_802_15_4_PHY_IDLE);
Time setTime = Seconds ( (double) aTurnaroundTime / GetDataOrSymbolRate (false));
m_setTRXState = Simulator::Schedule (setTime, &LrWpanPhy::EndSetTRXState, this);
return;
}
else if (m_trxState == IEEE_802_15_4_PHY_BUSY_RX)
{
if (!m_plmeSetTRXStateConfirmCallback.IsNull ())
{
m_plmeSetTRXStateConfirmCallback (IEEE_802_15_4_PHY_RX_ON);
}
return;
}
}
NS_FATAL_ERROR ("Catch other transitions");
NS_FATAL_ERROR ("Unexpected transition from state " << m_trxState << " to state " << state);
}
bool
@@ -594,10 +738,10 @@ LrWpanPhy::ChannelSupported (uint8_t channel)
void
LrWpanPhy::PlmeSetAttributeRequest (LrWpanPibAttributeIdentifier id,
LrWpanPhyPIBAttributes* attribute)
LrWpanPhyPibAttributes* attribute)
{
NS_ASSERT (attribute);
NS_LOG_FUNCTION (this << id << attribute);
NS_ASSERT (attribute);
LrWpanPhyEnumeration status = IEEE_802_15_4_PHY_SUCCESS;
switch (id)
@@ -609,7 +753,22 @@ LrWpanPhy::PlmeSetAttributeRequest (LrWpanPibAttributeIdentifier id,
status = IEEE_802_15_4_PHY_INVALID_PARAMETER;
}
if (m_phyPIBAttributes.phyCurrentChannel != attribute->phyCurrentChannel)
{ //any packet in transmission or reception will be corrupted
{
// Cancel a pending tranceiver state change.
// Switch off the transceiver.
// TODO: Is switching off the transceiver the right choice?
m_trxState = IEEE_802_15_4_PHY_TRX_OFF;
if (m_trxStatePending != IEEE_802_15_4_PHY_IDLE)
{
m_trxStatePending = IEEE_802_15_4_PHY_IDLE;
m_setTRXState.Cancel ();
if (!m_plmeSetTRXStateConfirmCallback.IsNull ())
{
m_plmeSetTRXStateConfirmCallback (IEEE_802_15_4_PHY_TRX_OFF);
}
}
// Any packet in transmission or reception will be corrupted.
if (m_currentRxPacket.first)
{
m_currentRxPacket.second = true;
@@ -623,11 +782,6 @@ LrWpanPhy::PlmeSetAttributeRequest (LrWpanPibAttributeIdentifier id,
{
m_pdDataConfirmCallback (IEEE_802_15_4_PHY_TRX_OFF);
}
if (m_trxStatePending != IEEE_802_15_4_PHY_IDLE)
{
m_trxStatePending = IEEE_802_15_4_PHY_IDLE;
}
}
m_phyPIBAttributes.phyCurrentChannel = attribute->phyCurrentChannel;
}
@@ -744,6 +898,7 @@ LrWpanPhy::ChangeTrxState (LrWpanPhyEnumeration newState)
bool
LrWpanPhy::PhyIsBusy (void) const
{
NS_LOG_FUNCTION (this << m_trxState);
return ((m_trxState == IEEE_802_15_4_PHY_BUSY_TX)
|| (m_trxState == IEEE_802_15_4_PHY_BUSY_RX)
|| (m_trxState == IEEE_802_15_4_PHY_BUSY));
@@ -782,7 +937,7 @@ void
LrWpanPhy::EndCca ()
{
NS_LOG_FUNCTION (this);
LrWpanPhyEnumeration sensedChannelState;
LrWpanPhyEnumeration sensedChannelState = IEEE_802_15_4_PHY_UNSPECIFIED;
if ((PhyIsBusy ()) || (m_rxTotalNum > 0))
{
@@ -842,7 +997,7 @@ LrWpanPhy::EndSetTRXState ()
NS_LOG_FUNCTION (this);
NS_ABORT_IF ( (m_trxStatePending != IEEE_802_15_4_PHY_RX_ON) && (m_trxStatePending != IEEE_802_15_4_PHY_TX_ON) );
m_trxState = m_trxStatePending;
ChangeTrxState (m_trxStatePending);
m_trxStatePending = IEEE_802_15_4_PHY_IDLE;
if (!m_plmeSetTRXStateConfirmCallback.IsNull ())
@@ -880,25 +1035,38 @@ LrWpanPhy::EndTx ()
}
m_currentTxPacket.first = 0;
m_currentTxPacket.second = false;
// We may be waiting to apply a pending state change.
if (m_trxStatePending != IEEE_802_15_4_PHY_IDLE)
{
NS_LOG_LOGIC ("Apply pending state change to " << m_trxStatePending);
ChangeTrxState (m_trxStatePending);
m_trxStatePending = IEEE_802_15_4_PHY_IDLE;
if (!m_plmeSetTRXStateConfirmCallback.IsNull ())
// Only change the state immediately, if the transceiver is not already
// switching the state.
if (!m_setTRXState.IsRunning ())
{
m_plmeSetTRXStateConfirmCallback (IEEE_802_15_4_PHY_SUCCESS);
NS_LOG_LOGIC ("Apply pending state change to " << m_trxStatePending);
ChangeTrxState (m_trxStatePending);
m_trxStatePending = IEEE_802_15_4_PHY_IDLE;
if (!m_plmeSetTRXStateConfirmCallback.IsNull ())
{
m_plmeSetTRXStateConfirmCallback (IEEE_802_15_4_PHY_SUCCESS);
}
}
}
else
{
ChangeTrxState (IEEE_802_15_4_PHY_RX_ON);
if (m_trxState != IEEE_802_15_4_PHY_TRX_OFF)
{
ChangeTrxState (IEEE_802_15_4_PHY_TX_ON);
}
}
}
Time
LrWpanPhy::CalculateTxTime (Ptr<const Packet> packet)
{
NS_LOG_FUNCTION (this << packet);
Time txTime = Seconds (0);
bool isData = true;
@@ -911,6 +1079,8 @@ LrWpanPhy::CalculateTxTime (Ptr<const Packet> packet)
double
LrWpanPhy::GetDataOrSymbolRate (bool isData)
{
NS_LOG_FUNCTION (this << isData);
double rate = 0.0;
NS_ASSERT (m_phyOption < IEEE_802_15_4_INVALID_PHY_OPTION);
@@ -930,6 +1100,8 @@ LrWpanPhy::GetDataOrSymbolRate (bool isData)
double
LrWpanPhy::GetPpduHeaderTxTime (void)
{
NS_LOG_FUNCTION (this);
bool isData = false;
double totalPpduHdrSymbols;
@@ -946,6 +1118,8 @@ LrWpanPhy::GetPpduHeaderTxTime (void)
void
LrWpanPhy::SetMyPhyOption (void)
{
NS_LOG_FUNCTION (this);
m_phyOption = IEEE_802_15_4_INVALID_PHY_OPTION;
if (m_phyPIBAttributes.phyCurrentPage == 0)
@@ -990,6 +1164,7 @@ LrWpanPhy::SetMyPhyOption (void)
LrWpanPhyOption
LrWpanPhy::GetMyPhyOption (void)
{
NS_LOG_FUNCTION (this);
return m_phyOption;
}
@@ -1033,4 +1208,23 @@ LrWpanPhy::GetErrorModel (void) const
return m_errorModel;
}
uint64_t
LrWpanPhy::GetPhySHRDuration (void) const
{
NS_LOG_FUNCTION (this);
NS_ASSERT (m_phyOption < IEEE_802_15_4_INVALID_PHY_OPTION);
return ppduHeaderSymbolNumbers[m_phyOption].shrPreamble
+ ppduHeaderSymbolNumbers[m_phyOption].shrSfd;
}
double
LrWpanPhy::GetPhySymbolsPerOctet (void) const
{
NS_LOG_FUNCTION (this);
NS_ASSERT (m_phyOption < IEEE_802_15_4_INVALID_PHY_OPTION);
return dataSymbolRates [m_phyOption].symbolRate / (dataSymbolRates [m_phyOption].bitRate / 8);
}
} // namespace ns3

View File

@@ -15,34 +15,30 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Gary Pei <guangyu.pei@boeing.com>
* Author:
* Gary Pei <guangyu.pei@boeing.com>
* Sascha Alexander Jopen <jopen@cs.uni-bonn.de>
*/
#ifndef LR_WPAN_PHY_H
#define LR_WPAN_PHY_H
#include <stdint.h>
#include <math.h>
#include <ns3/callback.h>
#include <ns3/traced-callback.h>
#include "ns3/object.h"
#include <ns3/packet-burst.h>
#include <ns3/spectrum-phy.h>
#include <ns3/spectrum-channel.h>
#include <ns3/spectrum-interference.h>
#include <ns3/spectrum-value.h>
#include <ns3/antenna-model.h>
#include <ns3/mobility-model.h>
#include <ns3/packet.h>
#include <ns3/nstime.h>
#include <ns3/net-device.h>
#include <ns3/traced-callback.h>
#include <ns3/event-id.h>
#include <ns3/random-variable.h>
#include "lr-wpan-spectrum-value-helper.h"
#include "lr-wpan-error-model.h"
#include "lr-wpan-spectrum-signal-parameters.h"
namespace ns3 {
class Packet;
class SpectrumValue;
class LrWpanErrorModel;
struct LrWpanSpectrumSignalParameters;
class MobilityModel;
class SpectrumChannel;
class SpectrumModel;
class AntennaModel;
class NetDevice;
/**
* IEEE802.15.4-2006 Table 1 and 2 in section 6.1.1 and 6.1.2
*/
@@ -124,7 +120,7 @@ typedef struct
uint32_t phyMaxFrameDuration;
uint32_t phySHRDuration;
double phySymbolsPerOctet;
} LrWpanPhyPIBAttributes;
} LrWpanPhyPibAttributes;
/**
* This method implements the PD SAP: PdDataIndication
@@ -133,7 +129,7 @@ typedef struct
* @param p the packet to be transmitted
* @param lqi Link quality (LQI) value measured during reception of the PPDU
*/
typedef Callback< void, uint32_t, Ptr<Packet>, uint32_t > PdDataIndicationCallback;
typedef Callback< void, uint32_t, Ptr<Packet>, uint8_t > PdDataIndicationCallback;
/**
* This method implements the PD SAP: PdDataConfirm
@@ -166,7 +162,7 @@ typedef Callback< void, LrWpanPhyEnumeration,uint8_t > PlmeEdConfirmCallback;
*/
typedef Callback< void, LrWpanPhyEnumeration,
LrWpanPibAttributeIdentifier,
LrWpanPhyPIBAttributes* > PlmeGetAttributeConfirmCallback;
LrWpanPhyPibAttributes* > PlmeGetAttributeConfirmCallback;
/**
* This method implements the PD SAP: PlmeSetTRXStateConfirm
@@ -289,7 +285,7 @@ public:
* @param id the attributed identifier
* @param * attribute the attribute value
*/
void PlmeSetAttributeRequest (LrWpanPibAttributeIdentifier id, LrWpanPhyPIBAttributes* attribute);
void PlmeSetAttributeRequest (LrWpanPibAttributeIdentifier id, LrWpanPhyPibAttributes* attribute);
/**
* set the callback for the end of a RX, as part of the
@@ -367,7 +363,10 @@ public:
* @return pointer to LrWpanErrorModel in use
*/
Ptr<LrWpanErrorModel> GetErrorModel (void) const;
uint64_t GetPhySHRDuration (void) const;
double GetPhySymbolsPerOctet (void) const;
protected:
static const LrWpanPhyDataAndSymbolRates dataSymbolRates[7];
static const LrWpanPhyPpduHeaderSymbolNumber ppduHeaderSymbolNumbers[7];
@@ -394,7 +393,7 @@ private:
Ptr<const SpectrumValue> m_rxPsd;
Ptr<const SpectrumValue> m_noise;
Ptr<LrWpanErrorModel> m_errorModel;
LrWpanPhyPIBAttributes m_phyPIBAttributes;
LrWpanPhyPibAttributes m_phyPIBAttributes;
// State variables
LrWpanPhyEnumeration m_trxState; /// transceiver state
@@ -465,6 +464,7 @@ private:
PacketAndStatus m_currentRxPacket;
PacketAndStatus m_currentTxPacket;
EventId m_ccaRequest;
EventId m_edRequest;
EventId m_setTRXState;
EventId m_pdDataRequest;

View File

@@ -17,17 +17,16 @@
*
* Author: Gary Pei <guangyu.pei@boeing.com>
*/
#include "lr-wpan-spectrum-signal-parameters.h"
#include <ns3/log.h>
#include <ns3/packet-burst.h>
#include "lr-wpan-spectrum-signal-parameters.h"
NS_LOG_COMPONENT_DEFINE ("LrWpanSpectrumSignalParameters");
namespace ns3 {
LrWpanSpectrumSignalParameters::LrWpanSpectrumSignalParameters ()
LrWpanSpectrumSignalParameters::LrWpanSpectrumSignalParameters (void)
{
NS_LOG_FUNCTION (this);
}
@@ -40,7 +39,7 @@ LrWpanSpectrumSignalParameters::LrWpanSpectrumSignalParameters (const LrWpanSpec
}
Ptr<SpectrumSignalParameters>
LrWpanSpectrumSignalParameters::Copy ()
LrWpanSpectrumSignalParameters::Copy (void)
{
NS_LOG_FUNCTION (this);
return Create<LrWpanSpectrumSignalParameters> (*this);

View File

@@ -37,12 +37,12 @@ struct LrWpanSpectrumSignalParameters : public SpectrumSignalParameters
{
// inherited from SpectrumSignalParameters
virtual Ptr<SpectrumSignalParameters> Copy ();
virtual Ptr<SpectrumSignalParameters> Copy (void);
/**
* default constructor
*/
LrWpanSpectrumSignalParameters ();
LrWpanSpectrumSignalParameters (void);
/**
* copy constructor

View File

@@ -17,9 +17,12 @@
*
* Author: Gary Pei <guangyu.pei@boeing.com>
*/
#include "ns3/log.h"
#include "lr-wpan-spectrum-value-helper.h"
#include <ns3/log.h>
#include <ns3/spectrum-value.h>
#include <cmath>
NS_LOG_COMPONENT_DEFINE ("LrWpanSpectrumValueHelper");
namespace ns3 {
@@ -29,13 +32,14 @@ Ptr<SpectrumModel> g_LrWpanSpectrumModel;
class LrWpanSpectrumModelInitializer
{
public:
LrWpanSpectrumModelInitializer ()
LrWpanSpectrumModelInitializer (void)
{
NS_LOG_FUNCTION (this);
Bands bands;
// 1 MHz resolution from 2400 to 2483 MHz (center freq)
for (int i = -1; i < 85; i++)
// 1 MHz resolution, with center frequency of 2400, 2401, ... 2483
// overall frequency span of 2399.5 MHz through 2483.5 MHz (83 bands)
for (int i = -1; i < 83; i++)
{
BandInfo bi;
bi.fl = 2400.5e6 + i * 1.0e6;
@@ -48,13 +52,13 @@ public:
} g_LrWpanSpectrumModelInitializerInstance;
LrWpanSpectrumValueHelper::LrWpanSpectrumValueHelper ()
LrWpanSpectrumValueHelper::LrWpanSpectrumValueHelper (void)
{
NS_LOG_FUNCTION (this);
m_noiseFactor = 1.0;
}
LrWpanSpectrumValueHelper::~LrWpanSpectrumValueHelper ()
LrWpanSpectrumValueHelper::~LrWpanSpectrumValueHelper (void)
{
}
@@ -67,23 +71,26 @@ LrWpanSpectrumValueHelper::CreateTxPowerSpectralDensity (double txPower, uint32_
// txPower is expressed in dBm. We must convert it into natural unit.
txPower = pow (10., (txPower - 30) / 10);
// The effective occupied bandwidth of the signal is modelled to be 2 MHz.
// 99.5% of power is within +/- 1MHz of center frequency, and 0.5% is outside.
// There are 5 bands containing signal power. The middle (center) band
// contains half of the power. The two inner side bands contain 49.5%.
// The two outer side bands contain roughly 0.5%.
double txPowerDensity = txPower / 2.0e6;
NS_ASSERT_MSG ((channel >= 11 && channel <= 26), "Invalid channel numbers");
// The channel assignment is in section 6.1.2.1
// Table 25 specify the Tx PSD
(*txPsd)[2405 + 5 * (channel - 11) - 2400 - 5] = txPowerDensity * 0.01; // -20 dB
(*txPsd)[2405 + 5 * (channel - 11) - 2400 - 4] = txPowerDensity * 0.01; // -20 dB
(*txPsd)[2405 + 5 * (channel - 11) - 2400 - 3] = txPowerDensity * 0.1; // -10 dB
(*txPsd)[2405 + 5 * (channel - 11) - 2400 - 2] = txPowerDensity * 0.1; // -10 dB
(*txPsd)[2405 + 5 * (channel - 11) - 2400 - 1] = txPowerDensity * 0.5; // -3 dB
// Channel 11 centered at 2.405 GHz, 12 at 2.410 GHz, ... 26 at 2.480 GHz
(*txPsd)[2405 + 5 * (channel - 11) - 2400 - 2] = txPowerDensity * 0.005;
(*txPsd)[2405 + 5 * (channel - 11) - 2400 - 1] = txPowerDensity * 0.495;
(*txPsd)[2405 + 5 * (channel - 11) - 2400] = txPowerDensity; // center
(*txPsd)[2405 + 5 * (channel - 11) - 2400 + 1 ] = txPowerDensity * 0.5; // -3 dB
(*txPsd)[2405 + 5 * (channel - 11) - 2400 + 2 ] = txPowerDensity * 0.1; // -10 dB
(*txPsd)[2405 + 5 * (channel - 11) - 2400 + 3 ] = txPowerDensity * 0.1; // -10 dB
(*txPsd)[2405 + 5 * (channel - 11) - 2400 + 4 ] = txPowerDensity * 0.01; // -20 dB
(*txPsd)[2405 + 5 * (channel - 11) - 2400 + 5 ] = txPowerDensity * 0.01; // -20 dB
(*txPsd)[2405 + 5 * (channel - 11) - 2400 + 1 ] = txPowerDensity * 0.495;
(*txPsd)[2405 + 5 * (channel - 11) - 2400 + 2 ] = txPowerDensity * 0.005;
// If more power is allocated to more subbands in future revisions of
// this model, make sure to renormalize so that the integral of the
// txPsd still equals txPower
return txPsd;
}
@@ -102,31 +109,25 @@ LrWpanSpectrumValueHelper::CreateNoisePowerSpectralDensity (uint32_t channel)
NS_ASSERT_MSG ((channel >= 11 && channel <= 26), "Invalid channel numbers");
(*noisePsd)[2405 + 5 * (channel - 11) - 2400 - 1] = noisePowerDensity;
(*noisePsd)[2405 + 5 * (channel - 11) - 2400 - 2] = noisePowerDensity;
(*noisePsd)[2405 + 5 * (channel - 11) - 2400 - 3] = noisePowerDensity;
(*noisePsd)[2405 + 5 * (channel - 11) - 2400 - 4] = noisePowerDensity;
(*noisePsd)[2405 + 5 * (channel - 11) - 2400 - 5] = noisePowerDensity;
(*noisePsd)[2405 + 5 * (channel - 11) - 2400 - 1] = noisePowerDensity;
(*noisePsd)[2405 + 5 * (channel - 11) - 2400] = noisePowerDensity;
(*noisePsd)[2405 + 5 * (channel - 11) - 2400 + 1] = noisePowerDensity;
(*noisePsd)[2405 + 5 * (channel - 11) - 2400 + 2] = noisePowerDensity;
(*noisePsd)[2405 + 5 * (channel - 11) - 2400 + 3] = noisePowerDensity;
(*noisePsd)[2405 + 5 * (channel - 11) - 2400 + 4] = noisePowerDensity;
(*noisePsd)[2405 + 5 * (channel - 11) - 2400 + 5] = noisePowerDensity;
return noisePsd;
}
double
LrWpanSpectrumValueHelper::TotalAvgPower (const SpectrumValue &psd)
LrWpanSpectrumValueHelper::TotalAvgPower (Ptr<const SpectrumValue> psd)
{
NS_LOG_FUNCTION (this);
NS_LOG_FUNCTION (this << psd);
double totalAvgPower = 0.0;
// numerically integrate to get area under psd using
// 1 MHz resolution from 2400 to 2483 MHz (center freq)
totalAvgPower = Sum (psd * 1.0e6);
totalAvgPower = Sum (*psd * 1.0e6);
return totalAvgPower;
}

View File

@@ -20,11 +20,12 @@
#ifndef LR_WPAN_SPECTRUM_VALUE_HELPER_H
#define LR_WPAN_SPECTRUM_VALUE_HELPER_H
#include <ns3/spectrum-value.h>
#include <cmath>
#include <ns3/ptr.h>
namespace ns3 {
class SpectrumValue;
/**
* \ingroup lr-wpan
*
@@ -33,8 +34,8 @@ namespace ns3 {
class LrWpanSpectrumValueHelper
{
public:
LrWpanSpectrumValueHelper ();
virtual ~LrWpanSpectrumValueHelper ();
LrWpanSpectrumValueHelper (void);
virtual ~LrWpanSpectrumValueHelper (void);
/**
* \brief create spectrum value
@@ -56,7 +57,7 @@ public:
* \param power spectral density
* \return total power (using composite trap. rule to numerally integrate
*/
double TotalAvgPower (const SpectrumValue &psd);
double TotalAvgPower (Ptr<const SpectrumValue> psd);
private:
double m_noiseFactor;

View File

@@ -1,68 +0,0 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2011 The Boeing Company
*
* 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: kwong yin <kwong-sang.yin@boeing.com>
*/
#include "ns3/wpan-address.h"
namespace ns3 {
WpanAddress::WpanAddress ()
{
}
WpanAddress::WpanAddress (uint16_t addr)
{
SetAddress (addr);
}
WpanAddress::WpanAddress (uint64_t addr)
{
SetAddress (addr);
}
WpanAddress::~WpanAddress ()
{
}
void WpanAddress::SetAddress (uint64_t addr)
{
m_addr64 = addr;
}
void WpanAddress::SetAddress (uint16_t addr)
{
m_addr16 = addr;
}
uint16_t WpanAddress::GetShortAddress (void) const
{
return(m_addr16);
}
uint64_t WpanAddress::GetExtAddress (void) const
{
return(m_addr64);
}
} // namespace ns3

View File

@@ -1,53 +0,0 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2011 The Boeing Company
*
* 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: kwong yin <kwong-sang.yin@boeing.com>
*/
#ifndef WPANADDRESS_H_
#define WPANADDRESS_H_
#include <stdint.h>
namespace ns3 {
class WpanAddress
{
public:
WpanAddress ();
WpanAddress (uint16_t addr);
WpanAddress (uint64_t addr);
~WpanAddress ();
void SetAddress (uint64_t addr);
void SetAddress (uint16_t addr);
uint16_t GetShortAddress (void) const;
uint64_t GetExtAddress (void) const;
private:
union
{
uint64_t m_addr64; //8 octet for ext addr
uint16_t m_addr16; //2 octet for short addr
};
};
} //namespace ns3
#endif /* WPANADDRESS_H_ */

View File

@@ -1,91 +0,0 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2011 The Boeing Company
*
* 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
*
* Authors:
* Gary Pei <guangyu.pei@boeing.com>
*/
#include <ns3/mobility-model.h>
#include <ns3/wpan-spectrum-propagation-loss-model.h>
#include <math.h>
namespace ns3 {
NS_OBJECT_ENSURE_REGISTERED (WpanSpectrumPropagationLossModel);
WpanSpectrumPropagationLossModel::WpanSpectrumPropagationLossModel ()
{
m_simpleLossModel = 0;
}
WpanSpectrumPropagationLossModel::~WpanSpectrumPropagationLossModel ()
{
m_simpleLossModel = 0;
}
TypeId
WpanSpectrumPropagationLossModel::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::WpanSpectrumPropagationLossModel")
.SetParent<SpectrumPropagationLossModel> ()
.AddConstructor<WpanSpectrumPropagationLossModel> ()
;
return tid;
}
Ptr<SpectrumValue>
WpanSpectrumPropagationLossModel::DoCalcRxPowerSpectralDensity (Ptr<const SpectrumValue> txPsd,
Ptr<const MobilityModel> a,
Ptr<const MobilityModel> b) const
{
Ptr<SpectrumValue> rxPsd = Copy<SpectrumValue> (txPsd);
Values::iterator vit = rxPsd->ValuesBegin ();
Bands::const_iterator fit = rxPsd->ConstBandsBegin ();
NS_ASSERT (a);
NS_ASSERT (b);
//double d = a->GetDistanceFrom (b);
while (vit != rxPsd->ValuesEnd ())
{
NS_ASSERT (fit != rxPsd->ConstBandsEnd ());
*vit /= CalculateLossFromSimpleLossModel (a, b); // Prx = Ptx / loss
++vit;
++fit;
}
return rxPsd;
}
double
WpanSpectrumPropagationLossModel::CalculateLossFromSimpleLossModel (Ptr<const MobilityModel> a,
Ptr<const MobilityModel> b) const
{
double loss = 1.0;
if (m_simpleLossModel)
{
loss = m_simpleLossModel->CalcRxPower (0.0, ConstCast<MobilityModel> (a), ConstCast<MobilityModel> (b));
loss = pow (10.0, loss / 10.0);
loss = 1.0 / loss;
}
return loss;
}
}

View File

@@ -1,58 +0,0 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2011 The Boeing Company
*
* 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
*
* Authors:
* Gary Pei <guangyu.pei@boeing.com>
*/
#ifndef WPAN_SPECTRUM_PROPAGATION_LOSS_MODEL_H
#define WPAN_SPECTRUM_PROPAGATION_LOSS_MODEL_H
#include <ns3/spectrum-propagation-loss-model.h>
#include <ns3/propagation-loss-model.h>
namespace ns3 {
class MobilityModel;
/**
* \brief propagation loss model for WPAN that uses simple PropagationLossModel
*/
class WpanSpectrumPropagationLossModel : public SpectrumPropagationLossModel
{
public:
WpanSpectrumPropagationLossModel ();
~WpanSpectrumPropagationLossModel ();
static TypeId GetTypeId ();
virtual Ptr<SpectrumValue> DoCalcRxPowerSpectralDensity (Ptr<const SpectrumValue> txPsd,
Ptr<const MobilityModel> a,
Ptr<const MobilityModel> b) const;
private:
double CalculateLossFromSimpleLossModel (Ptr<const MobilityModel> a,
Ptr<const MobilityModel> b) const;
Ptr<PropagationLossModel> m_simpleLossModel;
};
}
#endif /* WPAN_SPECTRUM_PROPAGATION_LOSS_MODEL_H */

View File

@@ -17,21 +17,20 @@
*
* Author: Tom Henderson <thomas.r.henderson@boeing.com>
*/
#include <ns3/test.h>
#include "ns3/log.h"
#include "ns3/callback.h"
#include "ns3/packet.h"
#include "ns3/simulator.h"
#include "ns3/lr-wpan-error-model.h"
#include "ns3/propagation-loss-model.h"
#include "ns3/lr-wpan-net-device.h"
#include "ns3/lr-wpan-mac.h"
#include "ns3/node.h"
#include "ns3/net-device.h"
#include "ns3/single-model-spectrum-channel.h"
#include "ns3/mac16-address.h"
#include "ns3/constant-position-mobility-model.h"
#include <ns3/log.h>
#include <ns3/callback.h>
#include <ns3/packet.h>
#include <ns3/simulator.h>
#include <ns3/lr-wpan-error-model.h>
#include <ns3/propagation-loss-model.h>
#include <ns3/lr-wpan-net-device.h>
#include <ns3/lr-wpan-mac.h>
#include <ns3/node.h>
#include <ns3/net-device.h>
#include <ns3/single-model-spectrum-channel.h>
#include <ns3/mac16-address.h>
#include <ns3/constant-position-mobility-model.h>
NS_LOG_COMPONENT_DEFINE ("lr-wpan-error-model-test");
@@ -106,8 +105,8 @@ LrWpanErrorDistanceTestCase::DoRun (void)
dev1->GetMac ()->SetMcpsDataIndicationCallback (cb0);
McpsDataRequestParams params;
params.m_srcAddrMode = 2;
params.m_dstAddrMode = 2;
params.m_srcAddrMode = SHORT_ADDR;
params.m_dstAddrMode = SHORT_ADDR;
params.m_dstPanId = 0;
params.m_dstAddr = Mac16Address ("00:02");
params.m_msduHandle = 0;

View File

@@ -17,14 +17,13 @@
*
* Author: Tom Henderson <thomas.r.henderson@boeing.com>
*/
#include <ns3/test.h>
#include <ns3/packet.h>
#include <ns3/lr-wpan-mac-header.h>
#include <ns3/lr-wpan-mac-trailer.h>
#include <ns3/mac16-address.h>
#include <ns3/mac64-address.h>
#include "ns3/log.h"
#include <ns3/log.h>
NS_LOG_COMPONENT_DEFINE ("lr-wpan-packet-test");

View File

@@ -17,9 +17,9 @@
*
* Author: Gary Pei <guangyu.pei@boeing.com>
*/
#include <ns3/log.h>
#include <ns3/test.h>
#include <ns3/packet.h>
#include <ns3/lr-wpan-phy.h>
#include <ns3/lr-wpan-mac.h>
#include <ns3/simulator.h>
@@ -36,7 +36,7 @@ public:
private:
virtual void DoRun (void);
void ReceivePdDataInndication (uint32_t psduLength, Ptr<Packet> p, uint32_t lqi);
void ReceivePdDataInndication (uint32_t psduLength, Ptr<Packet> p, uint8_t lqi);
};
LrWpanPlmeAndPdInterfaceTestCase::LrWpanPlmeAndPdInterfaceTestCase ()
@@ -51,7 +51,7 @@ LrWpanPlmeAndPdInterfaceTestCase::~LrWpanPlmeAndPdInterfaceTestCase ()
void
LrWpanPlmeAndPdInterfaceTestCase::ReceivePdDataInndication (uint32_t psduLength,
Ptr<Packet> p,
uint32_t lqi)
uint8_t lqi)
{
NS_LOG_UNCOND ("At: " << Simulator::Now ()
<< " Received frame size: " << psduLength << " LQI: " <<

View File

@@ -17,10 +17,12 @@
*
* Author: Tom Henderson <thomas.r.henderson@boeing.com>
*/
#include <ns3/log.h>
#include <ns3/test.h>
#include <ns3/lr-wpan-spectrum-value-helper.h>
#include <ns3/spectrum-value.h>
#include <cmath>
using namespace ns3;
@@ -57,7 +59,7 @@ LrWpanSpectrumValueHelperTestCase::DoRun (void)
value = helper.CreateTxPowerSpectralDensity (pwrdBm, chan);
pwrWatts = pow (10.0, pwrdBm / 10.0) / 1000;
// Test that average power calculation is within +/- 25% of expected
NS_TEST_ASSERT_MSG_EQ_TOL (helper.TotalAvgPower (*value), pwrWatts, pwrWatts / 4.0, "Not equal for channel " << chan << " pwrdBm " << pwrdBm);
NS_TEST_ASSERT_MSG_EQ_TOL (helper.TotalAvgPower (value), pwrWatts, pwrWatts / 4.0, "Not equal for channel " << chan << " pwrdBm " << pwrdBm);
}
}
}

View File

@@ -12,6 +12,7 @@ def build(bld):
'model/lr-wpan-net-device.cc',
'model/lr-wpan-spectrum-value-helper.cc',
'model/lr-wpan-spectrum-signal-parameters.cc',
'model/lr-wpan-lqi-tag.cc',
'helper/lr-wpan-helper.cc',
]
@@ -35,6 +36,7 @@ def build(bld):
'model/lr-wpan-net-device.h',
'model/lr-wpan-spectrum-value-helper.h',
'model/lr-wpan-spectrum-signal-parameters.h',
'model/lr-wpan-lqi-tag.h',
'helper/lr-wpan-helper.h',
]