sixlowpan: 6LoWPAN mesh-under flood routing
This commit is contained in:
@@ -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.
|
||||
|
||||
|
||||
|
||||
141
src/sixlowpan/examples/example-ping-lr-wpan-mesh-under.cc
Normal file
141
src/sixlowpan/examples/example-ping-lr-wpan-mesh-under.cc
Normal 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 ();
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user