sixlowpan: 6LoWPAN mesh-under flood routing

This commit is contained in:
Tommaso Pecorella
2020-01-29 23:33:02 +00:00
parent fdacda9721
commit 6f42c72d77
9 changed files with 909 additions and 79 deletions

View File

@@ -6,7 +6,7 @@
-----------------------------------------------------------------
This chapter describes the implementation of |ns3| model for the
compression of IPv6 packets over IEEE 802.15.4-Based Networks
compression of IPv6 packets over IEEE 802.15.4-Based Networks
as specified by :rfc:`4944` and :rfc:`6282`.
Model Description
@@ -17,31 +17,27 @@ The source code for the sixlowpan module lives in the directory ``src/sixlowpan`
Design
======
The model design does not follow strictly the standard from an architectural
The model design does not follow strictly the standard from an architectural
standpoint, as it does extend it beyond the original scope by supporting also
other kinds of networks.
Other than that, the module strictly follows :rfc:`4944` and :rfc:`6282`, with the
Other than that, the module strictly follows :rfc:`4944` and :rfc:`6282`, with the
following exceptions:
* MESH and LOWPAN_BC0 dispatch types are not supported
* HC2 encoding is not supported
* IPHC's SAC and DAC are not supported
The MESH and LOWPAN_BC0 are not supported as they do apply only to mesh-under
architecture, which is not one of the goals of the module development.
The HC2 encoding is not supported, as it has been superseded by IPHC and NHC
compression type (\ :rfc:`6282`).
IPHC SAC and DAC are not yet supported, as they do require :rfc:`6775` for full
compliance. It is planned to support them in the future.
IPHC SAC and DAC are not yet supported, as they do require :rfc:`6775` for full
compliance. It is planned to support them in the future.
NetDevice
#########
The whole module is developed as a transparent NetDevice, which can act as a
proxy between IPv6 and any NetDevice (the module has been successfully tested
proxy between IPv6 and any NetDevice (the module has been successfully tested
with PointToPointNedevice, CsmaNetDevice and LrWpanNetDevice).
For this reason, the module implements a virtual NetDevice, and all the calls are passed
@@ -55,19 +51,23 @@ The attributes are:
* OmitUdpChecksum (boolean, default true), used to activate UDP checksum compression in IPHC.
* FragmentReassemblyListSize (integer, default 0), indicating the number of packets that can be reassembled at the same time. If the limit is reached, the oldest packet is discarded. Zero means infinite.
* FragmentExpirationTimeout (Time, default 60 seconds), being the timeout to wait for further fragments before discarding a partial packet.
* CompressionThreshold (unsigned 32 bits integer, default 0), minimum compressed payload size.
* ForceEtherType (boolean, default false), and
* CompressionThreshold (unsigned 32 bits integer, default 0), minimum compressed payload size.
* ForceEtherType (boolean, default false).
* EtherType (unsigned 16 bits integer, default 0xFFFF), to force a particular L2 EtherType.
* UseMeshUnder (boolean, default false), it enables mesh-under flood routing.
* MeshUnderRadius (unsigned 8 bits integer, default 10), the maximum number of hops that a packet will be forwarded.
* MeshCacheLength (unsigned 16 bits integer, default 10), the length of the cache for each source.
* MeshUnderJitter (ns3::UniformRandomVariable[Min=0.0|Max=10.0]), the jitter in ms a node uses to forward mesh-under packets - used to prevent collisions.
The CompressionThreshold attribute is similar to Contiki's SICSLOWPAN_CONF_MIN_MAC_PAYLOAD
option. If a compressed packet size is less than the threshold, the uncompressed version is
used (plus one byte for the correct dispatch header).
This option is useful when a MAC requires a minimum frame size (e.g., ContikiMAC) and the
This option is useful when a MAC requires a minimum frame size (e.g., ContikiMAC) and the
compression would violate the requirement.
The last two attributes are needed to use the module with a NetDevice other than 802.15.4, as
neither IANA or IEEE did reserve an EtherType for 6LoWPAN. As a consequence there might be a
conflict with the L2 multiplexer/demultiplexer which is based on EtherType. The default
conflict with the L2 multiplexer/demultiplexer which is based on EtherType. The default
value is 0xFFFF, which is reserved by IEEE (see [IANA802]_ and [Ethertype]_).
The default module behaviour is to not change the EtherType, however this would not work with
any NetDevice actually understanding and using the EtherType.
@@ -92,12 +92,34 @@ The Trace sources are:
The Tx and Rx traces are called as soon as a packet is received or sent. The Drop trace is
invoked when a packet (or a fragment) is discarded.
Mesh-Under routing
##################
The module provides a very simple mesh-under routing [Shelby]_, implemented as a flooding
(a mesh-under routing protocol is a routing system implemented below IP).
This functionality can be activated through the UseMeshUnder attribute and fine-tuned using
the MeshUnderRadius and MeshUnderJitter attributes.
Note that flooding in a PAN generates a lot of overhead, which is often not wanted.
Moreover, when using the mesh-under facility, ALL the packets are sent without acknowledgment
because, at lower level, they are sent to a broadcast address.
At node level, each packet is re-broadcasted if its BC0 Sequence Number is not in the cache of the
recently seen packets. The cache length (by default 10) can be changed through the MeshCacheLength
attribute.
Scope and Limitations
=====================
Future versions of this module will support :rfc:`6775`, however no timeframe is guaranteed.
It would be a good idea to improve the mesh-under flooding by providing the following:
* Adaptive hop-limit calculation,
* Adaptive forwarding jitter,
* Use of direct (non mesh) transmission for packets directed to 1-hop neighbors.
Using 6LoWPAN with IPv4 (or other L3 protocols)
###############################################
@@ -110,7 +132,7 @@ in advance.
In the |ns3| implementation it is possible, but not advisable, to violate this requirement
if the underlying NetDevice is capable of discriminating different protocols. As an example,
CsmaNetDevice can carry IPv4 and 6LoWPAN at the same time. However, this configuration has
CsmaNetDevice can carry IPv4 and 6LoWPAN at the same time. However, this configuration has
not been tested.
References
@@ -121,6 +143,7 @@ References
.. [RFC6775] :rfc:`6775`, "Neighbor Discovery Optimization for IPv6 over Low-Power Wireless Personal Area Networks (6LoWPANs)"
.. [IANA802] IANA, assigned IEEE 802 numbers: http://www.iana.org/assignments/ieee-802-numbers/ieee-802-numbers.xml
.. [Ethertype] IEEE Ethertype numbers: http://standards.ieee.org/develop/regauth/ethertype/eth.txt
.. [Shelby] Z. Shelby and C. Bormann, 6LoWPAN: The Wireless Embedded Internet. Wiley, 2011. [Online]. Available: https://books.google.it/books?id=3Nm7ZCxscMQC
Usage
*****
@@ -133,7 +156,7 @@ Add ``sixlowpan`` to the list of modules built with |ns3|.
Helper
======
The helper is patterned after other device helpers.
The helper is patterned after other device helpers.
Examples
========
@@ -156,5 +179,3 @@ Validation
The model has been validated against WireShark, checking whatever the packets are correctly
interpreted and validated.

View File

@@ -0,0 +1,141 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2019 Universita' di Firenze, Italy
*
* 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: Tommaso Pecorella <tommaso.pecorella@unifi.it>
*/
#include <fstream>
#include "ns3/core-module.h"
#include "ns3/internet-module.h"
#include "ns3/internet-apps-module.h"
#include "ns3/mobility-module.h"
#include "ns3/spectrum-module.h"
#include "ns3/propagation-module.h"
#include "ns3/sixlowpan-module.h"
#include "ns3/lr-wpan-module.h"
#include "ns3/csma-module.h"
using namespace ns3;
int main (int argc, char** argv)
{
bool verbose = false;
Packet::EnablePrinting ();
CommandLine cmd;
cmd.AddValue ("verbose", "turn on log components", verbose);
cmd.Parse (argc, argv);
if (verbose)
{
LogComponentEnable ("Ping6Application", LOG_LEVEL_ALL);
LogComponentEnable ("LrWpanMac", LOG_LEVEL_ALL);
LogComponentEnable ("LrWpanPhy", LOG_LEVEL_ALL);
LogComponentEnable ("LrWpanNetDevice", LOG_LEVEL_ALL);
LogComponentEnable ("SixLowPanNetDevice", LOG_LEVEL_ALL);
}
uint32_t nWsnNodes = 4;
NodeContainer wsnNodes;
wsnNodes.Create (nWsnNodes);
NodeContainer wiredNodes;
wiredNodes.Create (1);
wiredNodes.Add (wsnNodes.Get (0));
MobilityHelper mobility;
mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
mobility.SetPositionAllocator ("ns3::GridPositionAllocator",
"MinX", DoubleValue (0.0),
"MinY", DoubleValue (0.0),
"DeltaX", DoubleValue (80),
"DeltaY", DoubleValue (80),
"GridWidth", UintegerValue (10),
"LayoutType", StringValue ("RowFirst"));
mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
mobility.Install (wsnNodes);
LrWpanHelper lrWpanHelper;
// Add and install the LrWpanNetDevice for each node
NetDeviceContainer lrwpanDevices = lrWpanHelper.Install (wsnNodes);
// Fake PAN association and short address assignment.
// This is needed because the lr-wpan module does not provide (yet)
// a full PAN association procedure.
lrWpanHelper.AssociateToPan (lrwpanDevices, 0);
InternetStackHelper internetv6;
internetv6.Install (wsnNodes);
internetv6.Install (wiredNodes.Get (0));
SixLowPanHelper sixLowPanHelper;
NetDeviceContainer sixLowPanDevices = sixLowPanHelper.Install (lrwpanDevices);
CsmaHelper csmaHelper;
NetDeviceContainer csmaDevices = csmaHelper.Install (wiredNodes);
Ipv6AddressHelper ipv6;
ipv6.SetBase (Ipv6Address ("2001:cafe::"), Ipv6Prefix (64));
Ipv6InterfaceContainer wiredDeviceInterfaces;
wiredDeviceInterfaces = ipv6.Assign (csmaDevices);
wiredDeviceInterfaces.SetForwarding (1, true);
wiredDeviceInterfaces.SetDefaultRouteInAllNodes (1);
ipv6.SetBase (Ipv6Address ("2001:f00d::"), Ipv6Prefix (64));
Ipv6InterfaceContainer wsnDeviceInterfaces;
wsnDeviceInterfaces = ipv6.Assign (sixLowPanDevices);
wsnDeviceInterfaces.SetForwarding (0, true);
wsnDeviceInterfaces.SetDefaultRouteInAllNodes (0);
for (uint32_t i = 0; i < sixLowPanDevices.GetN (); i++)
{
Ptr<NetDevice> dev = sixLowPanDevices.Get (i);
dev->SetAttribute ("UseMeshUnder", BooleanValue (true));
dev->SetAttribute ("MeshUnderRadius", UintegerValue (10));
}
uint32_t packetSize = 10;
uint32_t maxPacketCount = 5;
Time interPacketInterval = Seconds (1.);
Ping6Helper ping6;
ping6.SetLocal (wsnDeviceInterfaces.GetAddress (nWsnNodes - 1, 1));
ping6.SetRemote (wiredDeviceInterfaces.GetAddress (0, 1));
ping6.SetAttribute ("MaxPackets", UintegerValue (maxPacketCount));
ping6.SetAttribute ("Interval", TimeValue (interPacketInterval));
ping6.SetAttribute ("PacketSize", UintegerValue (packetSize));
ApplicationContainer apps = ping6.Install (wsnNodes.Get (nWsnNodes - 1));
apps.Start (Seconds (1.0));
apps.Stop (Seconds (10.0));
AsciiTraceHelper ascii;
lrWpanHelper.EnableAsciiAll (ascii.CreateFileStream ("Ping-6LoW-lr-wpan-meshunder-lr-wpan.tr"));
lrWpanHelper.EnablePcapAll (std::string ("Ping-6LoW-lr-wpan-meshunder-lr-wpan"), true);
csmaHelper.EnableAsciiAll (ascii.CreateFileStream ("Ping-6LoW-lr-wpan-meshunder-csma.tr"));
csmaHelper.EnablePcapAll (std::string ("Ping-6LoW-lr-wpan-meshunder-csma"), true);
Simulator::Stop (Seconds (10));
Simulator::Run ();
Simulator::Destroy ();
}

View File

@@ -23,12 +23,9 @@
#include "ns3/core-module.h"
#include "ns3/internet-module.h"
#include "ns3/internet-apps-module.h"
#include "ns3/ipv6-static-routing-helper.h"
#include "ns3/mobility-module.h"
#include "ns3/spectrum-module.h"
#include "ns3/propagation-loss-model.h"
#include "ns3/log.h"
#include "ns3/ipv6-routing-table-entry.h"
#include "ns3/propagation-module.h"
#include "ns3/sixlowpan-module.h"
#include "ns3/lr-wpan-module.h"
@@ -38,16 +35,20 @@ using namespace ns3;
int main (int argc, char** argv)
{
bool verbose = false;
CommandLine cmd;
cmd.AddValue ("verbose", "turn on log components", verbose);
cmd.Parse (argc, argv);
#if 0
LogComponentEnable ("Ping6Application", LOG_LEVEL_ALL);
LogComponentEnable ("LrWpanMac",LOG_LEVEL_ALL);
LogComponentEnable ("LrWpanPhy",LOG_LEVEL_ALL);
LogComponentEnable ("LrWpanNetDevice", LOG_LEVEL_ALL);
LogComponentEnable ("SixLowPanNetDevice", LOG_LEVEL_ALL);
#endif
if (verbose)
{
LogComponentEnable ("Ping6Application", LOG_LEVEL_ALL);
LogComponentEnable ("LrWpanMac", LOG_LEVEL_ALL);
LogComponentEnable ("LrWpanPhy", LOG_LEVEL_ALL);
LogComponentEnable ("LrWpanNetDevice", LOG_LEVEL_ALL);
LogComponentEnable ("SixLowPanNetDevice", LOG_LEVEL_ALL);
}
NodeContainer nodes;
nodes.Create(2);
@@ -69,6 +70,8 @@ int main (int argc, char** argv)
NetDeviceContainer lrwpanDevices = lrWpanHelper.Install(nodes);
// Fake PAN association and short address assignment.
// This is needed because the lr-wpan module does not provide (yet)
// a full PAN association procedure.
lrWpanHelper.AssociateToPan (lrwpanDevices, 0);
InternetStackHelper internetv6;

View File

@@ -43,9 +43,6 @@
#include "ns3/internet-module.h"
#include "ns3/csma-module.h"
#include "ns3/internet-apps-module.h"
#include "ns3/ipv6-static-routing-helper.h"
#include "ns3/ipv6-routing-table-entry.h"
#include "ns3/sixlowpan-module.h"
using namespace ns3;

View File

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

View File

@@ -23,6 +23,9 @@
#include "ns3/log.h"
#include "ns3/abort.h"
#include "ns3/ipv6-header.h"
#include "ns3/mac64-address.h"
#include "ns3/mac16-address.h"
#include "ns3/ipv6-header.h"
#include "sixlowpan-header.h"
@@ -128,7 +131,7 @@ void SixLowPanHc1::Print (std::ostream & os) const
encoding <<= 1;
encoding |= m_hc2HeaderPresent;
os << "encoding " << static_cast<int> (encoding) << ", hopLimit " << static_cast<int> (m_hopLimit);
os << "encoding " << +encoding << ", hopLimit " << +m_hopLimit;
}
uint32_t SixLowPanHc1::GetSerializedSize () const
@@ -545,7 +548,7 @@ NS_OBJECT_ENSURE_REGISTERED (SixLowPanFrag1);
SixLowPanFrag1::SixLowPanFrag1 ()
: m_datagramSize (0),
m_datagramTag (0)
m_datagramTag (0)
{
}
@@ -632,8 +635,8 @@ NS_OBJECT_ENSURE_REGISTERED (SixLowPanFragN);
SixLowPanFragN::SixLowPanFragN ()
: m_datagramSize (0),
m_datagramTag (0),
m_datagramOffset (0)
m_datagramTag (0),
m_datagramOffset (0)
{
}
/*
@@ -655,7 +658,7 @@ TypeId SixLowPanFragN::GetInstanceTypeId (void) const
void SixLowPanFragN::Print (std::ostream & os) const
{
os << "datagram size " << m_datagramSize << " tag " << m_datagramTag << " offset " << static_cast<int> (m_datagramOffset);
os << "datagram size " << m_datagramSize << " tag " << m_datagramTag << " offset " << +m_datagramOffset;
}
uint32_t SixLowPanFragN::GetSerializedSize () const
@@ -815,7 +818,7 @@ TypeId SixLowPanIphc::GetInstanceTypeId (void) const
void SixLowPanIphc::Print (std::ostream & os) const
{
os << "Compression kind: " << static_cast<int> (m_baseFormat);
os << "Compression kind: " << +m_baseFormat;
}
uint32_t SixLowPanIphc::GetSerializedSize () const
@@ -1508,7 +1511,7 @@ TypeId SixLowPanNhcExtension::GetInstanceTypeId (void) const
void SixLowPanNhcExtension::Print (std::ostream & os) const
{
os << "Compression kind: " << static_cast<int> (m_nhcExtensionHeader) << " Size: " << GetSerializedSize ();
os << "Compression kind: " << +m_nhcExtensionHeader << " Size: " << GetSerializedSize ();
}
uint32_t SixLowPanNhcExtension::GetSerializedSize () const
@@ -1637,7 +1640,7 @@ TypeId SixLowPanUdpNhcExtension::GetInstanceTypeId (void) const
void SixLowPanUdpNhcExtension::Print (std::ostream & os) const
{
os << "Compression kind: " << static_cast<int> (m_baseFormat);
os << "Compression kind: " << +m_baseFormat;
}
uint32_t SixLowPanUdpNhcExtension::GetSerializedSize () const
@@ -1805,6 +1808,317 @@ std::ostream & operator << (std::ostream & os, const SixLowPanUdpNhcExtension &
return os;
}
/*
* SixLowPanBc0
*/
NS_OBJECT_ENSURE_REGISTERED (SixLowPanBc0);
SixLowPanBc0::SixLowPanBc0 ()
{
m_seqNumber = 66;
}
TypeId SixLowPanBc0::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::SixLowPanBc0")
.SetParent<Header> ()
.SetGroupName ("SixLowPan")
.AddConstructor<SixLowPanBc0> ();
return tid;
}
TypeId SixLowPanBc0::GetInstanceTypeId (void) const
{
return GetTypeId ();
}
void SixLowPanBc0::Print (std::ostream & os) const
{
os << "Sequence number: " << +m_seqNumber;
}
uint32_t SixLowPanBc0::GetSerializedSize () const
{
return 2;
}
void SixLowPanBc0::Serialize (Buffer::Iterator start) const
{
Buffer::Iterator i = start;
i.WriteU8 (0x50);
i.WriteU8 (m_seqNumber);
}
uint32_t SixLowPanBc0::Deserialize (Buffer::Iterator start)
{
Buffer::Iterator i = start;
uint8_t dispatch = i.ReadU8 ();
if (dispatch != 0x50)
{
return 0;
}
m_seqNumber = i.ReadU8 ();
return GetSerializedSize ();
}
void SixLowPanBc0::SetSequenceNumber (uint8_t seqNumber)
{
m_seqNumber = seqNumber;
}
uint8_t SixLowPanBc0::GetSequenceNumber (void) const
{
return m_seqNumber;
}
std::ostream & operator << (std::ostream & os, const SixLowPanBc0 & h)
{
h.Print (os);
return os;
}
/*
* SixLowPanMesh
*/
NS_OBJECT_ENSURE_REGISTERED (SixLowPanMesh);
SixLowPanMesh::SixLowPanMesh ()
{
m_hopsLeft = 0;
m_src = Address ();
m_dst = Address ();
m_v = false;
m_f = false;
}
TypeId SixLowPanMesh::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::SixLowPanMesh")
.SetParent<Header> ()
.SetGroupName ("SixLowPan")
.AddConstructor<SixLowPanMesh> ();
return tid;
}
TypeId SixLowPanMesh::GetInstanceTypeId (void) const
{
return GetTypeId ();
}
void SixLowPanMesh::Print (std::ostream & os) const
{
os << "Hops left: " << +m_hopsLeft << ", src: ";
if (Mac64Address::IsMatchingType (m_src))
{
os << Mac64Address::ConvertFrom (m_src);
}
else
{
os << Mac16Address::ConvertFrom (m_src);
}
os << ", dst: ";
if (Mac64Address::IsMatchingType (m_dst))
{
os << Mac64Address::ConvertFrom (m_dst);
}
else
{
os << Mac16Address::ConvertFrom (m_dst);
}
}
uint32_t SixLowPanMesh::GetSerializedSize () const
{
uint32_t serializedSize = 1;
if (m_hopsLeft >= 0xF)
{
serializedSize++;
}
if (m_v)
{
serializedSize += 2;
}
else
{
serializedSize += 8;
}
if (m_f)
{
serializedSize += 2;
}
else
{
serializedSize += 8;
}
return serializedSize;
}
void SixLowPanMesh::Serialize (Buffer::Iterator start) const
{
Buffer::Iterator i = start;
uint8_t dispatch = 0x80;
if (m_v)
{
dispatch |= 0x20;
}
if (m_f)
{
dispatch |= 0x10;
}
if (m_hopsLeft < 0xF)
{
dispatch |= m_hopsLeft;
i.WriteU8 (dispatch);
}
else
{
dispatch |= 0xF;
i.WriteU8 (dispatch);
i.WriteU8 (m_hopsLeft);
}
uint8_t buffer[8];
m_src.CopyTo (buffer);
if (m_v)
{
i.Write (buffer, 2);
}
else
{
i.Write (buffer, 8);
}
m_dst.CopyTo (buffer);
if (m_f)
{
i.Write (buffer, 2);
}
else
{
i.Write (buffer, 8);
}
}
uint32_t SixLowPanMesh::Deserialize (Buffer::Iterator start)
{
Buffer::Iterator i = start;
uint8_t temp = i.ReadU8 ();
if ((temp & 0xC0) != 0x80)
{
return 0;
}
m_v = temp & 0x20;
m_f = temp & 0x10;
m_hopsLeft = temp & 0xF;
if (m_hopsLeft == 0xF)
{
m_hopsLeft = i.ReadU8 ();
}
uint8_t buffer[8];
uint8_t addrSize;
if (m_v)
{
addrSize = 2;
}
else
{
addrSize = 8;
}
i.Read (buffer, addrSize);
m_src.CopyFrom (buffer, addrSize);
if (m_f)
{
addrSize = 2;
}
else
{
addrSize = 8;
}
i.Read (buffer, addrSize);
m_dst.CopyFrom (buffer, addrSize);
return GetSerializedSize ();
}
void SixLowPanMesh::SetOriginator (Address originator)
{
if (Mac64Address::IsMatchingType (originator))
{
m_v = false;
}
else if (Mac16Address::IsMatchingType (originator))
{
m_v = true;
}
else
{
NS_ABORT_MSG ("SixLowPanMesh::SetOriginator - incompatible address");
}
m_src = originator;
}
Address SixLowPanMesh::GetOriginator (void) const
{
return m_src;
}
void SixLowPanMesh::SetFinalDst (Address finalDst)
{
if (Mac64Address::IsMatchingType (finalDst))
{
m_f = false;
}
else if (Mac16Address::IsMatchingType (finalDst))
{
m_f = true;
}
else
{
NS_ABORT_MSG ("SixLowPanMesh::SetFinalDst - incompatible address");
}
m_dst = finalDst;
}
Address SixLowPanMesh::GetFinalDst (void) const
{
return m_dst;
}
void SixLowPanMesh::SetHopsLeft (uint8_t hopsLeft)
{
m_hopsLeft = hopsLeft;
}
uint8_t SixLowPanMesh::GetHopsLeft (void) const
{
return m_hopsLeft;
}
std::ostream & operator << (std::ostream & os, const SixLowPanMesh & h)
{
h.Print (os);
return os;
}
}

View File

@@ -1236,6 +1236,168 @@ private:
*/
std::ostream & operator<< (std::ostream & os, SixLowPanUdpNhcExtension const &header);
/**
* \ingroup sixlowpan
* \brief 6LoWPAN BC0 header - see \RFC{4944}.
*/
class SixLowPanBc0 : public Header
{
public:
SixLowPanBc0 (void);
/**
* \brief Get the type ID.
* \return The object TypeId.
*/
static TypeId GetTypeId (void);
/**
* \brief Return the instance type identifier.
* \return Instance type ID.
*/
virtual TypeId GetInstanceTypeId (void) const;
virtual void Print (std::ostream& os) const;
/**
* \brief Get the serialized size of the packet.
* \return Size.
*/
virtual uint32_t GetSerializedSize (void) const;
/**
* \brief Serialize the packet.
* \param [in] start Buffer iterator.
*/
virtual void Serialize (Buffer::Iterator start) const;
/**
* \brief Deserialize the packet.
* \param [in] start Buffer iterator.
* \return Size of the packet.
*/
virtual uint32_t Deserialize (Buffer::Iterator start);
/**
* \brief Set the "Sequence Number" field.
* \param [in] seqNumber The sequence number value.
*/
void SetSequenceNumber (uint8_t seqNumber);
/**
* \brief Get the "Sequence Number" field.
* \return The sequence number value.
*/
uint8_t GetSequenceNumber (void) const;
private:
uint8_t m_seqNumber; //!< Sequence number.
};
/**
* \brief Stream insertion operator.
*
* \param [in] os The reference to the output stream.
* \param [in] header The BC0 Extension Header.
* \returns The reference to the output stream.
*/
std::ostream & operator<< (std::ostream & os, SixLowPanBc0 const &header);
/**
* \ingroup sixlowpan
* \brief 6LoWPAN Mesh header - see \RFC{4944}.
*/
class SixLowPanMesh : public Header
{
public:
SixLowPanMesh (void);
/**
* \brief Get the type ID.
* \return The object TypeId.
*/
static TypeId GetTypeId (void);
/**
* \brief Return the instance type identifier.
* \return Instance type ID.
*/
virtual TypeId GetInstanceTypeId (void) const;
virtual void Print (std::ostream& os) const;
/**
* \brief Get the serialized size of the packet.
* \return Size.
*/
virtual uint32_t GetSerializedSize (void) const;
/**
* \brief Serialize the packet.
* \param [in] start Buffer iterator.
*/
virtual void Serialize (Buffer::Iterator start) const;
/**
* \brief Deserialize the packet.
* \param [in] start Buffer iterator.
* \return Size of the packet.
*/
virtual uint32_t Deserialize (Buffer::Iterator start);
/**
* \brief Set the "Hops Left" field.
* \param [in] hopsLeft The number of hops left.
*/
void SetHopsLeft (uint8_t hopsLeft);
/**
* \brief Get the "Hops Left" field.
* \return The number of hops left.
*/
uint8_t GetHopsLeft (void) const;
/**
* \brief Set the "Originator" address.
* \param [in] originator The Originator address (Mac64Address or Mac16Address).
*/
void SetOriginator (Address originator);
/**
* \brief Get the "Originator" address.
* \return The Originator address (Mac64Address or Mac16Address).
*/
Address GetOriginator (void) const;
/**
* \brief Set the "Final Destination" address.
* \param [in] finalDst The Final Destination address (Mac64Address or Mac16Address).
*/
void SetFinalDst (Address finalDst);
/**
* \brief Get the "Final Destination" address.
* \return The Final Destination address (Mac64Address or Mac16Address).
*/
Address GetFinalDst (void) const;
private:
uint8_t m_hopsLeft; //!< Hops left.
bool m_v; //!< True if Originator address is 16 bit
bool m_f; //!< True if Destination address is 16 bit
Address m_src; //!< Originator (source) address.
Address m_dst; //!< Destination (final) address.
};
/**
* \brief Stream insertion operator.
*
* \param [in] os The reference to the output stream.
* \param [in] header The Mesh Extension Header.
* \returns The reference to the output stream.
*/
std::ostream & operator<< (std::ostream & os, SixLowPanMesh const &header);
}
#endif /* SIXLOWPANHEADER_H_ */

View File

@@ -19,6 +19,8 @@
* Michele Muccio <michelemuccio@virgilio.it>
*/
#include <algorithm>
#include "ns3/node.h"
#include "ns3/channel.h"
#include "ns3/packet.h"
@@ -33,7 +35,8 @@
#include "ns3/ipv6-extension-header.h"
#include "ns3/udp-header.h"
#include "ns3/udp-l4-protocol.h"
#include "ns3/random-variable-stream.h"
#include "ns3/string.h"
#include "ns3/pointer.h"
#include "sixlowpan-net-device.h"
#include "sixlowpan-header.h"
@@ -82,6 +85,26 @@ TypeId SixLowPanNetDevice::GetTypeId (void)
UintegerValue (0xFFFF),
MakeUintegerAccessor (&SixLowPanNetDevice::m_etherType),
MakeUintegerChecker<uint16_t> ())
.AddAttribute ("UseMeshUnder",
"Use a mesh-under routing protocol.",
BooleanValue (false),
MakeBooleanAccessor (&SixLowPanNetDevice::m_meshUnder),
MakeBooleanChecker ())
.AddAttribute ("MeshUnderRadius",
"Hops Left to use in mesh-under.",
UintegerValue (10),
MakeUintegerAccessor (&SixLowPanNetDevice::m_meshUnderHopsLeft),
MakeUintegerChecker<uint8_t> ())
.AddAttribute ("MeshCacheLength",
"Length of the cache for each source.",
UintegerValue (10),
MakeUintegerAccessor (&SixLowPanNetDevice::m_meshCacheLength),
MakeUintegerChecker<uint16_t> ())
.AddAttribute ("MeshUnderJitter",
"The jitter in ms a node uses to forward mesh-under packets - used to prevent collisions",
StringValue ("ns3::UniformRandomVariable[Min=0.0|Max=10.0]"),
MakePointerAccessor (&SixLowPanNetDevice::m_meshUnderJitter),
MakePointerChecker<RandomVariableStream> ())
.AddTraceSource ("Tx",
"Send - packet (including 6LoWPAN header), "
"SixLoWPanNetDevice Ptr, interface index.",
@@ -103,12 +126,13 @@ TypeId SixLowPanNetDevice::GetTypeId (void)
SixLowPanNetDevice::SixLowPanNetDevice ()
: m_node (0),
m_netDevice (0),
m_ifIndex (0)
m_netDevice (0),
m_ifIndex (0)
{
NS_LOG_FUNCTION (this);
m_netDevice = 0;
m_rng = CreateObject<UniformRandomVariable> ();
m_bc0Serial = 0;
}
Ptr<NetDevice> SixLowPanNetDevice::GetNetDevice () const
@@ -138,7 +162,8 @@ int64_t SixLowPanNetDevice::AssignStreams (int64_t stream)
{
NS_LOG_FUNCTION (this << stream);
m_rng->SetStream (stream);
return 1;
m_meshUnderJitter->SetStream (stream + 1);
return 2;
}
void SixLowPanNetDevice::DoDispose ()
@@ -188,14 +213,102 @@ void SixLowPanNetDevice::ReceiveFromDevice (Ptr<NetDevice> incomingPort,
NS_LOG_DEBUG ( "Packet length: " << copyPkt->GetSize () );
NS_LOG_DEBUG ( "Dispatches: " << int(dispatchRawVal) << " - " << int(dispatchVal) );
SixLowPanMesh meshHdr;
SixLowPanBc0 bc0Hdr;
bool hasMesh = false;
bool hasBc0 = false;
if ( dispatchVal == SixLowPanDispatch::LOWPAN_MESH )
{
hasMesh = true;
copyPkt->RemoveHeader (meshHdr);
copyPkt->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
dispatchVal = SixLowPanDispatch::GetDispatchType (dispatchRawVal);
}
if ( dispatchVal == SixLowPanDispatch::LOWPAN_BC0 )
{
hasBc0 = true;
copyPkt->RemoveHeader (bc0Hdr);
copyPkt->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
dispatchVal = SixLowPanDispatch::GetDispatchType (dispatchRawVal);
}
if (hasMesh)
{
if (!hasBc0)
{
NS_LOG_LOGIC ("Dropped packet - we only support mesh if it is paired with a BC0");
m_dropTrace (DROP_UNKNOWN_EXTENSION, copyPkt, m_node->GetObject<SixLowPanNetDevice> (), GetIfIndex ());
return;
}
if (find (m_seenPkts[meshHdr.GetOriginator ()].begin (),
m_seenPkts[meshHdr.GetOriginator ()].end (),
bc0Hdr.GetSequenceNumber ()) != m_seenPkts[meshHdr.GetOriginator ()].end ())
{
NS_LOG_LOGIC ("We have already seen this, no further processing.");
return;
}
m_seenPkts[meshHdr.GetOriginator ()].push_back (bc0Hdr.GetSequenceNumber ());
if (m_seenPkts[meshHdr.GetOriginator ()].size () > m_meshCacheLength)
{
m_seenPkts[meshHdr.GetOriginator ()].pop_front ();
}
NS_ABORT_MSG_IF (!Mac16Address::IsMatchingType (meshHdr.GetFinalDst ()), "SixLowPan mesh-under flooding can not currently handle extended address final destinations: " << meshHdr.GetFinalDst ());
NS_ABORT_MSG_IF (!Mac48Address::IsMatchingType (m_netDevice->GetAddress ()), "SixLowPan mesh-under flooding can not currently handle devices using extended addresses: " << m_netDevice->GetAddress ());
Mac16Address finalDst = Mac16Address::ConvertFrom (meshHdr.GetFinalDst ());
// See if the packet is for others than me. In case forward it.
if (meshHdr.GetFinalDst () != Get16MacFrom48Mac (m_netDevice->GetAddress ())
|| finalDst.IsBroadcast ()
|| finalDst.IsMulticast ()
)
{
uint8_t hopsLeft = meshHdr.GetHopsLeft ();
if (hopsLeft == 0)
{
NS_LOG_LOGIC ("Not forwarding packet -- hop limit reached");
}
else if (meshHdr.GetOriginator () == Get16MacFrom48Mac (m_netDevice->GetAddress ()))
{
NS_LOG_LOGIC ("Not forwarding packet -- I am the originator");
}
else
{
meshHdr.SetHopsLeft (hopsLeft - 1);
Ptr<Packet> sendPkt = copyPkt->Copy ();
sendPkt->AddHeader (bc0Hdr);
sendPkt->AddHeader (meshHdr);
Simulator::Schedule (Time (MilliSeconds (m_meshUnderJitter->GetValue ())), &NetDevice::Send, m_netDevice, sendPkt, m_netDevice->GetBroadcast (), protocol);
}
if (!finalDst.IsBroadcast () && !finalDst.IsMulticast ())
{
return;
}
}
}
Address realDst = dst;
Address realSrc = src;
if (hasMesh)
{
realSrc = meshHdr.GetOriginator ();
realDst = meshHdr.GetFinalDst ();
}
if ( dispatchVal == SixLowPanDispatch::LOWPAN_FRAG1 )
{
isPktDecompressed = ProcessFragment (copyPkt, src, dst, true);
isPktDecompressed = ProcessFragment (copyPkt, realSrc, realDst, true);
fragmented = true;
}
else if ( dispatchVal == SixLowPanDispatch::LOWPAN_FRAGN )
{
isPktDecompressed = ProcessFragment (copyPkt, src, dst, false);
isPktDecompressed = ProcessFragment (copyPkt, realSrc, realDst, false);
fragmented = true;
}
if ( fragmented )
@@ -213,28 +326,20 @@ void SixLowPanNetDevice::ReceiveFromDevice (Ptr<NetDevice> incomingPort,
switch ( dispatchVal )
{
case SixLowPanDispatch::LOWPAN_MESH:
NS_LOG_DEBUG ("Unsupported 6LoWPAN encoding: MESH, dropping.");
m_dropTrace (DROP_UNKNOWN_EXTENSION, copyPkt, m_node->GetObject<SixLowPanNetDevice> (), GetIfIndex ());
break;
case SixLowPanDispatch::LOWPAN_BC0:
NS_LOG_DEBUG ("Unsupported 6LoWPAN encoding: BC0, dropping.");
m_dropTrace (DROP_UNKNOWN_EXTENSION, copyPkt, m_node->GetObject<SixLowPanNetDevice> (), GetIfIndex ());
break;
case SixLowPanDispatch::LOWPAN_IPv6:
NS_LOG_DEBUG ( "Packet without compression. Length: " << copyPkt->GetSize () );
{
SixLowPanIpv6 uncompressedHdr;
copyPkt->RemoveHeader(uncompressedHdr);
copyPkt->RemoveHeader (uncompressedHdr);
isPktDecompressed = true;
}
break;
case SixLowPanDispatch::LOWPAN_HC1:
DecompressLowPanHc1 (copyPkt, src, dst);
DecompressLowPanHc1 (copyPkt, realSrc, realDst);
isPktDecompressed = true;
break;
case SixLowPanDispatch::LOWPAN_IPHC:
DecompressLowPanIphc (copyPkt, src, dst);
DecompressLowPanIphc (copyPkt, realSrc, realDst);
isPktDecompressed = true;
break;
default:
@@ -253,10 +358,10 @@ void SixLowPanNetDevice::ReceiveFromDevice (Ptr<NetDevice> incomingPort,
if (!m_promiscRxCallback.IsNull ())
{
m_promiscRxCallback (this, copyPkt, Ipv6L3Protocol::PROT_NUMBER, src, dst, packetType);
m_promiscRxCallback (this, copyPkt, Ipv6L3Protocol::PROT_NUMBER, realSrc, realDst, packetType);
}
m_rxCallback (this, copyPkt, Ipv6L3Protocol::PROT_NUMBER, src);
m_rxCallback (this, copyPkt, Ipv6L3Protocol::PROT_NUMBER, realSrc);
return;
}
@@ -429,6 +534,10 @@ bool SixLowPanNetDevice::DoSend (Ptr<Packet> packet,
uint32_t origPacketSize = packet->GetSize ();
bool ret = false;
Address destination = dest;
bool useMesh = m_meshUnder;
if (m_forceEtherType)
{
protocolNumber = m_etherType;
@@ -437,23 +546,59 @@ bool SixLowPanNetDevice::DoSend (Ptr<Packet> packet,
if (m_useIphc)
{
NS_LOG_LOGIC ("Compressing packet using IPHC");
origHdrSize += CompressLowPanIphc (packet, m_netDevice->GetAddress (), dest);
origHdrSize += CompressLowPanIphc (packet, m_netDevice->GetAddress (), destination);
}
else
{
NS_LOG_LOGIC ("Compressing packet using HC1");
origHdrSize += CompressLowPanHc1 (packet, m_netDevice->GetAddress (), dest);
origHdrSize += CompressLowPanHc1 (packet, m_netDevice->GetAddress (), destination);
}
if (packet->GetSize () < m_compressionThreshold)
uint16_t pktSize = packet->GetSize ();
SixLowPanMesh meshHdr;
SixLowPanBc0 bc0Hdr;
if (useMesh)
{
Address source = src;
if (!doSendFrom)
{
source = m_netDevice->GetAddress ();
}
if (Mac48Address::IsMatchingType (source))
{
// We got a Mac48 pseudo-MAC. We need its original Mac16 here.
source = Get16MacFrom48Mac (source);
}
if (Mac48Address::IsMatchingType (destination))
{
// We got a Mac48 pseudo-MAC. We need its original Mac16 here.
destination = Get16MacFrom48Mac (destination);
}
meshHdr.SetOriginator (source);
meshHdr.SetFinalDst (destination);
meshHdr.SetHopsLeft (m_meshUnderHopsLeft);
destination = m_netDevice->GetBroadcast ();
pktSize += meshHdr.GetSerializedSize () + bc0Hdr.GetSerializedSize ();
}
if (pktSize < m_compressionThreshold)
{
NS_LOG_LOGIC ("Compressed packet too short, using uncompressed one");
packet = origPacket;
SixLowPanIpv6 ipv6UncompressedHdr;
packet->AddHeader (ipv6UncompressedHdr);
pktSize = packet->GetSize ();
if (useMesh)
{
pktSize += meshHdr.GetSerializedSize () + bc0Hdr.GetSerializedSize ();
}
}
if ( packet->GetSize () > m_netDevice->GetMtu () )
if (pktSize > m_netDevice->GetMtu ())
{
NS_LOG_LOGIC ("Fragmentation: Packet size " << packet->GetSize () << " - Mtu " << m_netDevice->GetMtu () );
// fragment
@@ -465,13 +610,20 @@ bool SixLowPanNetDevice::DoSend (Ptr<Packet> packet,
{
NS_LOG_DEBUG ( "SixLowPanNetDevice::Send (Fragment) " << **it );
m_txTrace (*it, m_node->GetObject<SixLowPanNetDevice> (), GetIfIndex ());
if (useMesh)
{
bc0Hdr.SetSequenceNumber (m_bc0Serial++);
(*it)->AddHeader (bc0Hdr);
(*it)->AddHeader (meshHdr);
}
if (doSendFrom)
{
success &= m_netDevice->SendFrom (*it, src, dest, protocolNumber);
success &= m_netDevice->SendFrom (*it, src, destination, protocolNumber);
}
else
{
success &= m_netDevice->Send (*it, dest, protocolNumber);
success &= m_netDevice->Send (*it, destination, protocolNumber);
}
}
ret = success;
@@ -479,15 +631,23 @@ bool SixLowPanNetDevice::DoSend (Ptr<Packet> packet,
else
{
m_txTrace (packet, m_node->GetObject<SixLowPanNetDevice> (), GetIfIndex ());
if (useMesh)
{
bc0Hdr.SetSequenceNumber (m_bc0Serial++);
packet->AddHeader (bc0Hdr);
packet->AddHeader (meshHdr);
}
if (doSendFrom)
{
NS_LOG_DEBUG ( "SixLowPanNetDevice::SendFrom " << m_node->GetId () << " " << *packet );
ret = m_netDevice->SendFrom (packet, src, dest, protocolNumber);
ret = m_netDevice->SendFrom (packet, src, destination, protocolNumber);
}
else
{
NS_LOG_DEBUG ( "SixLowPanNetDevice::Send " << m_node->GetId () << " " << *packet );
ret = m_netDevice->Send (packet, dest, protocolNumber);
ret = m_netDevice->Send (packet, destination, protocolNumber);
}
}
@@ -1405,7 +1565,7 @@ SixLowPanNetDevice::DecompressLowPanNhc (Ptr<Packet> packet, Address const &src,
uint32_t blobSize;
uint8_t blobData[260];
blobSize = encoding.CopyBlob (blobData + 2, 260-2);
blobSize = encoding.CopyBlob (blobData + 2, 260 - 2);
uint8_t paddingSize = 0;
uint8_t actualEncodedHeaderType = encoding.GetEid ();
@@ -1836,9 +1996,9 @@ bool SixLowPanNetDevice::ProcessFragment (Ptr<Packet>& packet, Address const &sr
case SixLowPanDispatch::LOWPAN_IPv6:
{
SixLowPanIpv6 uncompressedHdr;
p->RemoveHeader(uncompressedHdr);
p->RemoveHeader (uncompressedHdr);
}
break;
break;
case SixLowPanDispatch::LOWPAN_HC1:
DecompressLowPanHc1 (p, src, dst);
break;
@@ -2053,7 +2213,7 @@ std::list< Ptr<Packet> > SixLowPanNetDevice::Fragments::GetFraments () const
{
std::list< Ptr<Packet> > fragments;
std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator iter;
for ( iter = m_fragments.begin (); iter != m_fragments.end (); iter ++)
for ( iter = m_fragments.begin (); iter != m_fragments.end (); iter++)
{
fragments.push_back (iter->first);
}
@@ -2078,6 +2238,19 @@ void SixLowPanNetDevice::HandleFragmentsTimeout (FragmentKey key, uint32_t iif)
m_fragmentsTimers.erase (key);
}
Address SixLowPanNetDevice::Get16MacFrom48Mac (Address addr)
{
NS_ASSERT_MSG (Mac48Address::IsMatchingType (addr), "Need a Mac48Address" << addr);
uint8_t buf[6];
addr.CopyTo (buf);
Mac16Address shortAddr;
shortAddr.CopyFrom (buf + 4);
return shortAddr;
}
}
// namespace ns3

View File

@@ -28,6 +28,7 @@
#include "ns3/traced-callback.h"
#include "ns3/nstime.h"
#include "ns3/net-device.h"
#include "ns3/random-variable-stream.h"
namespace ns3 {
@@ -153,9 +154,9 @@ public:
* is deprecated and will be changed to \c Ptr<const SixLowPanNetDevice>
* in a future release.
*/
typedef void (* RxTxTracedCallback)
(Ptr<const Packet> packet, Ptr<SixLowPanNetDevice> sixNetDevice,
uint32_t ifindex);
typedef void (* RxTxTracedCallback)(Ptr<const Packet> packet,
Ptr<SixLowPanNetDevice> sixNetDevice,
uint32_t ifindex);
/**
* TracedCallback signature for
@@ -168,11 +169,11 @@ public:
* is deprecated and will be changed to \c Ptr<const SixLowPanNetDevice>
* in a future release.
*/
typedef void (* DropTracedCallback)
(DropReason reason, Ptr<const Packet> packet,
Ptr<SixLowPanNetDevice> sixNetDevice,
uint32_t ifindex);
typedef void (* DropTracedCallback)(DropReason reason,
Ptr<const Packet> packet,
Ptr<SixLowPanNetDevice> sixNetDevice,
uint32_t ifindex);
protected:
virtual void DoDispose (void);
@@ -457,6 +458,13 @@ private:
*/
void DropOldestFragmentSet ();
/**
* Get a Mac16 from its Mac48 pseudo-MAC
* \param addr the PseudoMac adddress
* \return the Mac16Address
*/
Address Get16MacFrom48Mac (Address addr);
/**
* Container for fragment key -> fragments.
*/
@@ -486,6 +494,13 @@ private:
bool m_useIphc; //!< Use IPHC or HC1.
bool m_meshUnder; //!< Use a mesh-under routing.
uint8_t m_bc0Serial; //!< Serial number used in BC0 header.
uint8_t m_meshUnderHopsLeft; //!< Start value for mesh-under hops left.
uint16_t m_meshCacheLength; //!< length of the cache for each source.
Ptr<RandomVariableStream> m_meshUnderJitter; //!< Random variable for the mesh-under packet retransmission.
std::map <Address /* OriginatorAdddress */, std::list <uint8_t /* SequenceNumber */> > m_seenPkts; //!< Seen packets, memorized by OriginatorAdddress, SequenceNumber.
Ptr<Node> m_node; //!< Smart pointer to the Node.
Ptr<NetDevice> m_netDevice; //!< Smart pointer to the underlying NetDevice.
uint32_t m_ifIndex; //!< Interface index.