diff --git a/AUTHORS b/AUTHORS
index bce5553bf..5e7291b4e 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -81,6 +81,7 @@ Marco Miozzo (mmiozzo@cttc.es)
Faker Moatamri (faker.moatamri@inria.fr)
Edvin Močibob
Mike Moreton (mjvm_ns@hotmail.com)
+Michele Muccio
Sidharth Nabar (snabar@uw.edu)
Hemanth Narra (hemanth@ittc.ku.edu)
Andreas Nilsson
diff --git a/CHANGES.html b/CHANGES.html
index 73fc05c40..2f7a97430 100644
--- a/CHANGES.html
+++ b/CHANGES.html
@@ -80,6 +80,15 @@ us a note on ns-developers mailing list.
their simulation program. The imlpementation previously
provided by the EpcHelper class has been moved to the new
derived class PointToPointEpcHelper.
+ New SixLowPanNetDevice class providing a shim between
+ IPv6 and real NetDevices. The new module implements 6LoWPAN:
+ "Transmission of IPv6 Packets over IEEE 802.15.4 Networks" (see
+ RFC 4944 and
+ RFC 6262),
+ resulting in a heavy header compression for IPv6 packets.
+ The module is intended to be used on 802.15.4 NetDevices, but
+ it can be used over other NetDevices. See the manual for
+ further discussion.
Changes to build system:
diff --git a/RELEASE_NOTES b/RELEASE_NOTES
index 30c8b8f06..e19a42eea 100644
--- a/RELEASE_NOTES
+++ b/RELEASE_NOTES
@@ -21,6 +21,12 @@ Supported platforms
New user-visible features
-------------------------
+- new SixLowPanNetDevice model, headers and associated helpers. The
+ SixLowPanNetDevice is able to act as a shim between IPv6 and a NetDevice,
+ compressing IPv6 headers according to RFCs 4944 and 6262.
+ The SixLowPanNetDevice is meant to be used over 802.15.4 NetDevices,
+ but it can be used on other NetDevices as well (see the manual for full
+ details).
- A new wifi extension for vehicular simulation support is available in src/wave
directory. The current code represents an interim capability to realize an
diff --git a/doc/models/Makefile b/doc/models/Makefile
index 4b043b850..0e6423ef5 100644
--- a/doc/models/Makefile
+++ b/doc/models/Makefile
@@ -79,6 +79,7 @@ SOURCES = \
$(SRC)/netanim/doc/animation.rst \
$(SRC)/flow-monitor/doc/flow-monitor.rst \
$(SRC)/wave/doc/wave.rst \
+ $(SRC)/sixlowpan/doc/sixlowpan.rst \
# list all model library figure files that need to be copied to
# $SOURCETEMP/figures. For each figure to be included in all
diff --git a/src/internet/model/udp-header.cc b/src/internet/model/udp-header.cc
index 01eacc7ca..17b6b6486 100644
--- a/src/internet/model/udp-header.cc
+++ b/src/internet/model/udp-header.cc
@@ -33,7 +33,8 @@ NS_OBJECT_ENSURE_REGISTERED (UdpHeader)
UdpHeader::UdpHeader ()
: m_sourcePort (0xfffd),
m_destinationPort (0xfffd),
- m_payloadSize (0xfffd),
+ m_payloadSize (0),
+ m_checksum (0),
m_calcChecksum (false),
m_goodChecksum (true)
{
@@ -108,7 +109,7 @@ UdpHeader::CalculateHeaderChecksum (uint16_t size) const
WriteTo (it, m_source);
WriteTo (it, m_destination);
- if (Ipv4Address::IsMatchingType(m_source))
+ if (Ipv4Address::IsMatchingType (m_source))
{
it.WriteU8 (0); /* protocol */
it.WriteU8 (m_protocol); /* protocol */
@@ -116,7 +117,7 @@ UdpHeader::CalculateHeaderChecksum (uint16_t size) const
it.WriteU8 (size & 0xff); /* length */
hdrSize = 12;
}
- else if (Ipv6Address::IsMatchingType(m_source))
+ else if (Ipv6Address::IsMatchingType (m_source))
{
it.WriteU16 (0);
it.WriteU8 (size >> 8); /* length */
@@ -138,6 +139,17 @@ UdpHeader::IsChecksumOk (void) const
return m_goodChecksum;
}
+void
+UdpHeader::ForceChecksum (uint16_t checksum)
+{
+ m_checksum = checksum;
+}
+
+void
+UdpHeader::ForcePayloadSize (uint16_t payloadSize)
+{
+ m_payloadSize = payloadSize;
+}
TypeId
UdpHeader::GetTypeId (void)
@@ -175,18 +187,33 @@ UdpHeader::Serialize (Buffer::Iterator start) const
i.WriteHtonU16 (m_sourcePort);
i.WriteHtonU16 (m_destinationPort);
- i.WriteHtonU16 (start.GetSize ());
- i.WriteU16 (0);
-
- if (m_calcChecksum)
+ if (m_payloadSize == 0)
{
- uint16_t headerChecksum = CalculateHeaderChecksum (start.GetSize ());
- i = start;
- uint16_t checksum = i.CalculateIpChecksum (start.GetSize (), headerChecksum);
+ i.WriteHtonU16 (start.GetSize ());
+ }
+ else
+ {
+ i.WriteHtonU16 (m_payloadSize);
+ }
- i = start;
- i.Next (6);
- i.WriteU16 (checksum);
+ if ( m_checksum == 0)
+ {
+ i.WriteU16 (0);
+
+ if (m_calcChecksum)
+ {
+ uint16_t headerChecksum = CalculateHeaderChecksum (start.GetSize ());
+ i = start;
+ uint16_t checksum = i.CalculateIpChecksum (start.GetSize (), headerChecksum);
+
+ i = start;
+ i.Next (6);
+ i.WriteU16 (checksum);
+ }
+ }
+ else
+ {
+ i.WriteU16 (m_checksum);
}
}
uint32_t
@@ -196,9 +223,9 @@ UdpHeader::Deserialize (Buffer::Iterator start)
m_sourcePort = i.ReadNtohU16 ();
m_destinationPort = i.ReadNtohU16 ();
m_payloadSize = i.ReadNtohU16 () - GetSerializedSize ();
- i.Next (2);
+ m_checksum = i.ReadU16 ();
- if(m_calcChecksum)
+ if (m_calcChecksum)
{
uint16_t headerChecksum = CalculateHeaderChecksum (start.GetSize ());
i = start;
@@ -210,5 +237,10 @@ UdpHeader::Deserialize (Buffer::Iterator start)
return GetSerializedSize ();
}
+uint16_t
+UdpHeader::GetChecksum ()
+{
+ return m_checksum;
+}
} // namespace ns3
diff --git a/src/internet/model/udp-header.h b/src/internet/model/udp-header.h
index a5854b136..3e131dc40 100644
--- a/src/internet/model/udp-header.h
+++ b/src/internet/model/udp-header.h
@@ -131,6 +131,41 @@ public:
*/
bool IsChecksumOk (void) const;
+ /**
+ * \brief Force the UDP checksum to a given value.
+ *
+ * This might be useful for test purposes or to
+ * restore the UDP checksum when the UDP header
+ * has been compressed (e.g., in 6LoWPAN).
+ * Note that, normally, the header checksum is
+ * calculated on the fly when the packet is
+ * serialized.
+ *
+ * When this option is used, the UDP checksum is written in
+ * the header, regardless of the global ChecksumEnabled option.
+ *
+ * \note The checksum value must be a big endian number.
+ *
+ * \param checksum the checksum to use (big endian).
+ */
+ void ForceChecksum (uint16_t checksum);
+
+ /**
+ * \brief Force the UDP payload length to a given value.
+ *
+ * This might be useful when forging a packet for test
+ * purposes.
+ *
+ * \param payloadSize the payload length to use.
+ */
+ void ForcePayloadSize (uint16_t payloadSize);
+
+ /**
+ * \brief Return the checksum (only known after a Deserialize)
+ * \return The checksum for this UdpHeader
+ */
+ uint16_t GetChecksum ();
+
private:
/**
* \brief Calculate the header checksum
@@ -145,6 +180,7 @@ private:
Address m_source; //!< Source IP address
Address m_destination; //!< Destination IP address
uint8_t m_protocol; //!< Protocol number
+ uint16_t m_checksum; //!< Forced Checksum value
bool m_calcChecksum; //!< Flag to calculate checksum
bool m_goodChecksum; //!< Flag to indicate that checksum is correct
};
diff --git a/src/sixlowpan/doc/sixlowpan.rst b/src/sixlowpan/doc/sixlowpan.rst
new file mode 100644
index 000000000..033cb0a66
--- /dev/null
+++ b/src/sixlowpan/doc/sixlowpan.rst
@@ -0,0 +1,147 @@
+PageBreak
+
+Transmission of IPv6 Packets over IEEE 802.15.4 Networks (6LoWPAN)
+------------------------------------------------------------------
+
+This chapter describes the implementation of |ns3| model for the
+compression of IPv6 packets over IEEE 802.15.4-Based Networks
+as specified by RFC 4944 and RFC 6262.
+
+Model Description
+*****************
+
+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
+standpoint, as it does extend it beyond the original scope by supporting also
+other kinds of networks.
+
+Other than that, the module strictly follows RFCs 4944 and 6262, 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 6262).
+
+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
+with PointToPointNedevice, CsmaNetDevice and LrWpanNetDevice).
+
+For this reason, the module implements a virtual NetDevice, and all the calls are passed
+without modifications to the underlying NetDevice. The only important difference is in
+GetMtu behaviour. It will always return *at least* 1280 bytes, as is the minumum IPv6 MTU.
+
+The module does provide some attributes and some tracesources.
+The attributes are:
+* Rfc6282 (boolean, default true), used to activate HC1 (RFC 4944) or IPHC (RFC 6282) compression.
+* 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.
+* ForceEtherType (boolean, default false), and
+* EtherType (unsigned 16 bits integer, default 0xFFFF), to force a particular L2 EtherType.
+
+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
+value is 0xFFFF, which is reserved by IEEE.
+The default module behaviour is to not change the EtherType, however this would not work with
+any NetDevice actually understanding and using the EtherType.
+
+Note that the `ForceEtherType` parameter have also a direct effect on the MAC address kind the
+module is expecting to handle:
+* ForceEtherType true: Mac48Address (Ethernet, WiFi, etc.).
+* ForceEtherType false: Mac16Address or Mac64Address (IEEE 802.15.4).
+
+Note that using 6LoWPAN over any NetDevice other than 802.15.4 will produce valid .pcap files,
+but they will not be correctly dissected by Wireshark.
+The reason lies on the fact that 6LoWPAN was really meant to be used only over 802.15.4, so
+Wireshark dissectors will not even try to decode 6LoWPAN headers on top of protocols other than
+802.15.4.
+
+The Trace sources are:
+* Tx - exposing packet (including 6LoWPAN header), SixLoWPanNetDevice Ptr, interface index.
+* Rx - exposing packet (including 6LoWPAN header), SixLoWPanNetDevice Ptr, interface index.
+* Drop - exposing DropReason, packet (including 6LoWPAN header), SixLoWPanNetDevice Ptr, interface index.
+
+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.
+
+
+Scope and Limitations
+=====================
+
+Future versions of this module will support RFC 6775, however no timeframe is guaranteed.
+
+Using 6LoWPAN with IPv4 (or other L3 protocols)
+###############################################
+
+As the name implies, 6LoWPAN can handle only IPv6 packets. Any other protocol will be discarded.
+Moreover, 6LoWPAN assumes that the network is uniform, as is all the devices connected by the
+same same channel are using 6LoWPAN. Mixed environments are not supported by the standard.
+The reason is simple: 802.15.4 frame doesn't have a "protocol" field. As a consequence,
+there is no demultiplexing at MAC layer and the protocol carried by L2 frames must be known
+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
+not been tested.
+
+References
+==========
+
+* RFC 4944, "Transmission of IPv6 Packets over IEEE 802.15.4 Networks".
+* RFC 6282, "Compression Format for IPv6 Datagrams over IEEE 802.15.4-Based Networks".
+* http://www.iana.org/assignments/ieee-802-numbers/ieee-802-numbers.xml
+* http://standards.ieee.org/develop/regauth/ethertype/eth.txt
+
+Usage
+*****
+
+Enabling sixlowpan
+==================
+
+Add ``sixlowpan`` to the list of modules built with |ns3|.
+
+Helper
+======
+
+The helper is patterned after other device helpers.
+
+Examples
+========
+
+The following example can be found in ``src/sixlowpan/examples/``:
+
+* ``example-sixlowpan.cc``: A simple example showing end-to-end data transfer.
+
+In particular, the example enables a very simplified end-to-end data
+transfer scenario, with a CSMA network forced to carry 6LoWPAN compressed packets.
+
+
+Tests
+=====
+
+The test provided checks the connection between two UDP clients and the correctness of the received packets.
+
+Validation
+**********
+
+The model has been validated against WireShark, checking whatever the packets are correctly
+interpreted and validated.
+
+
diff --git a/src/sixlowpan/examples/example-sixlowpan.cc b/src/sixlowpan/examples/example-sixlowpan.cc
new file mode 100644
index 000000000..fd2935502
--- /dev/null
+++ b/src/sixlowpan/examples/example-sixlowpan.cc
@@ -0,0 +1,139 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013 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
+ */
+
+
+// Network topology
+//
+// n0 n1
+// +---------+ +--------+
+// | UDP | r | UDP |
+// +---------+ +---------+--------+ +--------+
+// | IPv6 | | IPv6 | IPv6 | | IPv6 |
+// +---------+ +---------+ | | |
+// | 6LoWPAN | | 6LoWPAN | | | |
+// +---------+ +---------+--------+ +--------+
+// | CSMA | | CSMA | CSMA | | CSMA |
+// +---------+ +---------+--------+ +--------+
+// | | | |
+// ================ =================
+//
+// - Tracing of queues and packet receptions to file "example-sixlowpan.tr"
+// Note that the Pcap packet dissection will not be very meaningful.
+// See the module's documentation for a discussion about this.
+
+#include
+#include "ns3/core-module.h"
+#include "ns3/internet-module.h"
+#include "ns3/csma-module.h"
+#include "ns3/applications-module.h"
+#include "ns3/ipv6-static-routing-helper.h"
+
+#include "ns3/ipv6-routing-table-entry.h"
+#include "ns3/sixlowpan-module.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE ("ExampleSixlowpan")
+ ;
+
+int main (int argc, char** argv)
+{
+ bool verbose = false;
+
+ CommandLine cmd;
+ cmd.AddValue ("verbose", "turn on some relevant log components", verbose);
+ cmd.Parse (argc, argv);
+
+ if (verbose)
+ {
+ LogComponentEnable ("SixLowPanNetDevice", LOG_LEVEL_ALL);
+ LogComponentEnable ("Ping6Application", LOG_LEVEL_ALL);
+ }
+
+ Packet::EnablePrinting ();
+ Packet::EnableChecking ();
+
+ NS_LOG_INFO ("Create nodes.");
+ Ptr n0 = CreateObject ();
+ Ptr r = CreateObject ();
+ Ptr n1 = CreateObject ();
+
+
+ NodeContainer net1 (n0, r);
+ NodeContainer net2 (r, n1);
+ NodeContainer all (n0, r, n1);
+
+ NS_LOG_INFO ("Create IPv6 Internet Stack");
+ InternetStackHelper internetv6;
+ internetv6.Install (all);
+
+ NS_LOG_INFO ("Create channels.");
+ CsmaHelper csma;
+ csma.SetChannelAttribute ("DataRate", DataRateValue (5000000));
+ csma.SetChannelAttribute ("Delay", TimeValue (MilliSeconds (2)));
+ NetDeviceContainer d2 = csma.Install (net2);
+ csma.SetDeviceAttribute ("Mtu", UintegerValue (150));
+ NetDeviceContainer d1 = csma.Install (net1);
+
+ SixLowPanHelper sixlowpan;
+ sixlowpan.SetDeviceAttribute ("ForceEtherType", BooleanValue (true) );
+ NetDeviceContainer six1 = sixlowpan.Install (d1);
+
+ NS_LOG_INFO ("Create networks and assign IPv6 Addresses.");
+ Ipv6AddressHelper ipv6;
+ ipv6.SetBase (Ipv6Address ("2001:1::"), Ipv6Prefix (64));
+ Ipv6InterfaceContainer i1 = ipv6.Assign (six1);
+ i1.SetForwarding (1, true);
+ i1.SetDefaultRouteInAllNodes (1);
+
+ ipv6.SetBase (Ipv6Address ("2001:2::"), Ipv6Prefix (64));
+ Ipv6InterfaceContainer i2 = ipv6.Assign (d2);
+ i2.SetForwarding (0, true);
+ i2.SetDefaultRouteInAllNodes (0);
+
+ /* Create a Ping6 application to send ICMPv6 echo request from n0 to n1 via r */
+ uint32_t packetSize = 200;
+ uint32_t maxPacketCount = 50;
+ Time interPacketInterval = Seconds (1.);
+ Ping6Helper ping6;
+
+ ping6.SetLocal (i1.GetAddress (0, 1));
+ ping6.SetRemote (i2.GetAddress (1, 1));
+
+ ping6.SetAttribute ("MaxPackets", UintegerValue (maxPacketCount));
+ ping6.SetAttribute ("Interval", TimeValue (interPacketInterval));
+ ping6.SetAttribute ("PacketSize", UintegerValue (packetSize));
+ ApplicationContainer apps = ping6.Install (net1.Get (0));
+
+ apps.Start (Seconds (5.0));
+ apps.Stop (Seconds (15.0));
+
+
+ AsciiTraceHelper ascii;
+ csma.EnableAsciiAll (ascii.CreateFileStream ("example-sixlowpan.tr"));
+ csma.EnablePcapAll (std::string ("example-sixlowpan"), true);
+
+ Simulator::Stop (Seconds (100));
+ NS_LOG_INFO ("Run Simulation.");
+ Simulator::Run ();
+ Simulator::Destroy ();
+ NS_LOG_INFO ("Done.");
+}
+
diff --git a/src/sixlowpan/examples/wscript b/src/sixlowpan/examples/wscript
new file mode 100644
index 000000000..d7951f94e
--- /dev/null
+++ b/src/sixlowpan/examples/wscript
@@ -0,0 +1,9 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+
+def build(bld):
+ if not bld.env['ENABLE_EXAMPLES']:
+ return;
+
+ obj = bld.create_ns3_program('example-sixlowpan',
+ ['network', 'sixlowpan', 'internet', 'csma'])
+ obj.source = 'example-sixlowpan.cc'
diff --git a/src/sixlowpan/helper/sixlowpan-helper.cc b/src/sixlowpan/helper/sixlowpan-helper.cc
new file mode 100644
index 000000000..27fb2c95a
--- /dev/null
+++ b/src/sixlowpan/helper/sixlowpan-helper.cc
@@ -0,0 +1,83 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 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
+ */
+
+#include "sixlowpan-helper.h"
+#include "ns3/log.h"
+#include "ns3/sixlowpan-net-device.h"
+#include "ns3/node.h"
+#include "ns3/names.h"
+
+NS_LOG_COMPONENT_DEFINE ("SixLowPanHelper")
+ ;
+
+namespace ns3 {
+
+SixLowPanHelper::SixLowPanHelper ()
+{
+ NS_LOG_FUNCTION (this);
+ m_deviceFactory.SetTypeId ("ns3::SixLowPanNetDevice");
+}
+
+void SixLowPanHelper::SetDeviceAttribute (std::string n1,
+ const AttributeValue &v1)
+{
+ NS_LOG_FUNCTION (this);
+ m_deviceFactory.Set (n1, v1);
+}
+
+NetDeviceContainer SixLowPanHelper::Install (const NetDeviceContainer c)
+{
+ NS_LOG_FUNCTION (this);
+
+ NetDeviceContainer devs;
+
+ for (uint32_t i = 0; i < c.GetN (); ++i)
+ {
+ Ptr device = c.Get (i);
+ NS_ASSERT_MSG (device != 0, "No NetDevice found in the node " << int(i) );
+
+ Ptr node = device->GetNode ();
+ NS_LOG_LOGIC ("**** Install 6LoWPAN on node " << node->GetId ());
+
+ Ptr dev = m_deviceFactory.Create ();
+ devs.Add (dev);
+ node->AddDevice (dev);
+ dev->SetNetDevice (device);
+ }
+ return devs;
+}
+
+int64_t SixLowPanHelper::AssignStreams (NetDeviceContainer c, int64_t stream)
+{
+ int64_t currentStream = stream;
+ Ptr netDevice;
+ for (NetDeviceContainer::Iterator i = c.Begin (); i != c.End (); ++i)
+ {
+ netDevice = (*i);
+ Ptr dev = DynamicCast (netDevice);
+ if (dev)
+ {
+ currentStream += dev->AssignStreams (currentStream);
+ }
+ }
+ return (currentStream - stream);
+}
+
+} // namespace ns3
diff --git a/src/sixlowpan/helper/sixlowpan-helper.h b/src/sixlowpan/helper/sixlowpan-helper.h
new file mode 100644
index 000000000..c38b26c7b
--- /dev/null
+++ b/src/sixlowpan/helper/sixlowpan-helper.h
@@ -0,0 +1,102 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 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
+ */
+
+#ifndef SIXLOWPAN_HELPER_H
+#define SIXLOWPAN_HELPER_H
+
+#include "ns3/net-device-container.h"
+#include "ns3/object-factory.h"
+#include
+
+namespace ns3 {
+
+class Node;
+class AttributeValue;
+
+/**
+ * \ingroup sixlowpan
+ *
+ * \brief Setup a sixlowpan stack to be used as a shim between IPv6 and a generic NetDevice.
+ */
+class SixLowPanHelper
+{
+public:
+ /*
+ * Construct a SixlowpanHelper
+ */
+ SixLowPanHelper ();
+ /**
+ * Set an attribute on each ns3::SixlowpanNetDevice created by
+ * SixlowpanHelper::Install.
+ *
+ * \param n1 the name of the attribute to set
+ * \param v1 the value of the attribute to set
+ */
+ void SetDeviceAttribute (std::string n1,
+ const AttributeValue &v1);
+
+ /**
+ * \brief Install the SixLoWPAN stack on top of an existing NetDevice.
+ *
+ * This function requires a set of properly configured NetDevices
+ * passed in as the parameter "c". The new NetDevices will have to
+ * be used instead of the original ones. In this way these
+ * SixLoWPAN devices will behave as shims between the NetDevices
+ * passed in and IPv6.
+ *
+ * Note that only IPv6 (and related protocols, such as ICMPv6) can
+ * be transmitted over a 6LoWPAN interface.
+ * Any other protocol (e.g., IPv4) will be discarded by 6LoWPAN.
+ *
+ * Other protocols (e.g., IPv4) could be used on the original NetDevices
+ * with some limitations.
+ * See the manual for a complete discussion.
+ *
+ * \note IPv6 stack must be installed \a after SixLoWPAN,
+ * using the SixLoWPAN NetDevices. See the example in the
+ * examples directory.
+ *
+ *
+ * \param c the NetDevice container
+ * \return a container with the newly created SixLowPanNetDevices
+ */
+ NetDeviceContainer Install (NetDeviceContainer c);
+
+ /**
+ * Assign a fixed random variable stream number to the random variables
+ * used by this model. Return the number of streams (possibly zero) that
+ * have been assigned. The Install() method should have previously been
+ * called by the user.
+ *
+ * \param c NetDeviceContainer of the set of net devices for which the
+ * SixLowPanNetDevice should be modified to use a fixed stream
+ * \param stream first stream index to use
+ * \return the number of stream indices assigned by this helper
+ */
+ int64_t AssignStreams (NetDeviceContainer c, int64_t stream);
+
+private:
+ ObjectFactory m_deviceFactory; //!< Object factory
+};
+
+} // namespace ns3
+
+
+#endif /* SIXLOWPAN_HELPER_H */
diff --git a/src/sixlowpan/model/sixlowpan-header.cc b/src/sixlowpan/model/sixlowpan-header.cc
new file mode 100644
index 000000000..222c8ff45
--- /dev/null
+++ b/src/sixlowpan/model/sixlowpan-header.cc
@@ -0,0 +1,1747 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013 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
+ * Michele Muccio
+ */
+
+#include "ns3/assert.h"
+#include "ns3/log.h"
+#include "ns3/abort.h"
+#include "ns3/address-utils.h"
+#include "sixlowpan-header.h"
+
+
+namespace ns3 {
+
+/*
+ * SixLowPanDispatch
+ */
+
+
+SixLowPanDispatch::SixLowPanDispatch ()
+{
+}
+
+
+SixLowPanDispatch::Dispatch_e
+SixLowPanDispatch::GetDispatchType (uint8_t dispatch)
+{
+ if (dispatch <= LOWPAN_NALP_N)
+ {
+ return LOWPAN_NALP;
+ }
+ else if (dispatch == LOWPAN_NOTCOMPRESSED)
+ {
+ return LOWPAN_NOTCOMPRESSED;
+ }
+ else if (dispatch == LOWPAN_HC1)
+ {
+ return LOWPAN_HC1;
+ }
+ else if (dispatch == LOWPAN_BC0)
+ {
+ return LOWPAN_BC0;
+ }
+ else if ((dispatch >= LOWPAN_IPHC) && (dispatch <= LOWPAN_IPHC_N))
+ {
+ return LOWPAN_IPHC;
+ }
+ else if ((dispatch >= LOWPAN_MESH) && (dispatch <= LOWPAN_MESH_N))
+ {
+ return LOWPAN_MESH;
+ }
+ else if ((dispatch >= LOWPAN_FRAG1) && (dispatch <= LOWPAN_FRAG1_N))
+ {
+ return LOWPAN_FRAG1;
+ }
+ else if ((dispatch >= LOWPAN_FRAGN) && (dispatch <= LOWPAN_FRAGN_N))
+ {
+ return LOWPAN_FRAGN;
+ }
+ return LOWPAN_UNSUPPORTED;
+}
+
+SixLowPanDispatch::NhcDispatch_e
+SixLowPanDispatch::GetNhcDispatchType (uint8_t dispatch)
+{
+ if ((dispatch >= LOWPAN_NHC) && (dispatch <= LOWPAN_NHC_N))
+ {
+ return LOWPAN_NHC;
+ }
+ else if ((dispatch >= LOWPAN_UDPNHC) && (dispatch <= LOWPAN_UDPNHC_N))
+ {
+ return LOWPAN_UDPNHC;
+ }
+ return LOWPAN_NHCUNSUPPORTED;
+}
+
+
+/*
+ * SixLowPanHc1
+ */
+NS_OBJECT_ENSURE_REGISTERED (SixLowPanHc1)
+ ;
+
+SixLowPanHc1::SixLowPanHc1 ()
+ : m_hopLimit (0)
+{
+}
+
+TypeId SixLowPanHc1::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::SixLowPanHc1").SetParent ().AddConstructor ();
+ return tid;
+}
+
+TypeId SixLowPanHc1::GetInstanceTypeId (void) const
+{
+ return GetTypeId ();
+}
+
+void SixLowPanHc1::Print (std::ostream & os) const
+{
+ uint8_t encoding;
+ encoding = m_srcCompression;
+ encoding <<= 2;
+ encoding |= m_dstCompression;
+ encoding <<= 1;
+ encoding |= m_tcflCompression;
+ encoding <<= 2;
+ encoding |= m_nextHeaderCompression;
+ encoding <<= 1;
+ encoding |= m_hc2HeaderPresent;
+
+ os << "encoding " << int(encoding) << ", hopLimit " << int(m_hopLimit);
+}
+
+uint32_t SixLowPanHc1::GetSerializedSize () const
+{
+ uint32_t serializedSize = 3;
+
+ switch (m_srcCompression)
+ {
+ case HC1_PIII:
+ serializedSize += 16;
+ break;
+ case HC1_PIIC:
+ serializedSize += 8;
+ break;
+ case HC1_PCII:
+ serializedSize += 8;
+ break;
+ case HC1_PCIC:
+ break;
+ }
+ switch (m_dstCompression)
+ {
+ case HC1_PIII:
+ serializedSize += 16;
+ break;
+ case HC1_PIIC:
+ serializedSize += 8;
+ break;
+ case HC1_PCII:
+ serializedSize += 8;
+ break;
+ case HC1_PCIC:
+ break;
+ }
+
+ if (m_tcflCompression == false )
+ {
+ serializedSize += 4;
+ }
+
+ if (m_nextHeaderCompression == HC1_NC )
+ {
+ serializedSize++;
+ }
+
+ return serializedSize;
+}
+
+void SixLowPanHc1::Serialize (Buffer::Iterator start) const
+{
+ Buffer::Iterator i = start;
+ uint8_t encoding;
+ encoding = m_srcCompression;
+ encoding <<= 2;
+ encoding |= m_dstCompression;
+ encoding <<= 1;
+ encoding |= m_tcflCompression;
+ encoding <<= 2;
+ encoding |= m_nextHeaderCompression;
+ encoding <<= 1;
+ encoding |= m_hc2HeaderPresent;
+
+ i.WriteU8 (SixLowPanDispatch::LOWPAN_HC1);
+ i.WriteU8 (encoding);
+ i.WriteU8 (m_hopLimit);
+ switch (m_srcCompression)
+ {
+ case HC1_PIII:
+ for ( int j = 0; j < 8; j++ )
+ {
+ i.WriteU8 (m_srcPrefix[j]);
+ }
+ for ( int j = 0; j < 8; j++ )
+ {
+ i.WriteU8 (m_srcInterface[j]);
+ }
+ break;
+ case HC1_PIIC:
+ for ( int j = 0; j < 8; j++ )
+ {
+ i.WriteU8 (m_srcPrefix[j]);
+ }
+ break;
+ case HC1_PCII:
+ for ( int j = 0; j < 8; j++ )
+ {
+ i.WriteU8 (m_srcInterface[j]);
+ }
+ break;
+ case HC1_PCIC:
+ break;
+ }
+ switch (m_dstCompression)
+ {
+ case HC1_PIII:
+ for ( int j = 0; j < 8; j++ )
+ {
+ i.WriteU8 (m_dstPrefix[j]);
+ }
+ for ( int j = 0; j < 8; j++ )
+ {
+ i.WriteU8 (m_dstInterface[j]);
+ }
+ break;
+ case HC1_PIIC:
+ for ( int j = 0; j < 8; j++ )
+ {
+ i.WriteU8 (m_dstPrefix[j]);
+ }
+ break;
+ case HC1_PCII:
+ for ( int j = 0; j < 8; j++ )
+ {
+ i.WriteU8 (m_dstInterface[j]);
+ }
+ break;
+ case HC1_PCIC:
+ break;
+ }
+
+ if ( m_tcflCompression == false )
+ {
+ i.WriteU8 (m_trafficClass);
+ uint8_t temp[3];
+ temp[0] = uint8_t (m_flowLabel & 0xff);
+ temp[1] = uint8_t ((m_flowLabel >> 8) & 0xff);
+ temp[2] = uint8_t ((m_flowLabel >> 16) & 0xff);
+ i.Write (temp, 3);
+ }
+
+ if (m_nextHeaderCompression == HC1_NC )
+ {
+ i.WriteU8 (m_nextHeader);
+ }
+
+ // TODO: HC2 is not yet supported. Should be.
+ NS_ASSERT_MSG ( m_hc2HeaderPresent != true, "Can not compress HC2, exiting. Very sorry." );
+}
+
+uint32_t SixLowPanHc1::Deserialize (Buffer::Iterator start)
+{
+ Buffer::Iterator i = start;
+ uint32_t serializedSize = 3;
+
+ uint8_t dispatch = i.ReadU8 ();
+ if (dispatch != SixLowPanDispatch::LOWPAN_HC1)
+ {
+ return 0;
+ }
+
+ uint8_t encoding = i.ReadU8 ();
+ m_hopLimit = i.ReadU8 ();
+
+ m_srcCompression = LowPanHc1Addr_e (encoding >> 6);
+ m_dstCompression = LowPanHc1Addr_e ( (encoding >> 4) & 0x3);
+ m_tcflCompression = (encoding >> 3) & 0x1;
+ m_nextHeaderCompression = LowPanHc1NextHeader_e ( (encoding >> 1) & 0x3);
+ m_hc2HeaderPresent = encoding & 0x1;
+
+ switch (m_srcCompression)
+ {
+ case HC1_PIII:
+ for ( int j = 0; j < 8; j++)
+ {
+ m_srcPrefix[j] = i.ReadU8 ();
+ }
+ for ( int j = 0; j < 8; j++)
+ {
+ m_srcInterface[j] = i.ReadU8 ();
+ }
+ serializedSize += 16;
+ break;
+ case HC1_PIIC:
+ for ( int j = 0; j < 8; j++)
+ {
+ m_srcPrefix[j] = i.ReadU8 ();
+ }
+ serializedSize += 8;
+ break;
+ case HC1_PCII:
+ for ( int j = 0; j < 8; j++)
+ {
+ m_srcInterface[j] = i.ReadU8 ();
+ }
+ serializedSize += 8;
+ break;
+ case HC1_PCIC:
+ break;
+ }
+ switch (m_dstCompression)
+ {
+ case HC1_PIII:
+ for ( int j = 0; j < 8; j++)
+ {
+ m_dstPrefix[j] = i.ReadU8 ();
+ }
+ for ( int j = 0; j < 8; j++)
+ {
+ m_dstInterface[j] = i.ReadU8 ();
+ }
+ serializedSize += 16;
+ break;
+ case HC1_PIIC:
+ for ( int j = 0; j < 8; j++)
+ {
+ m_dstPrefix[j] = i.ReadU8 ();
+ }
+ serializedSize += 8;
+ break;
+ case HC1_PCII:
+ for ( int j = 0; j < 8; j++)
+ {
+ m_dstInterface[j] = i.ReadU8 ();
+ }
+ serializedSize += 8;
+ break;
+ case HC1_PCIC:
+ break;
+ }
+
+ if ( m_tcflCompression == false )
+ {
+ m_trafficClass = i.ReadU8 ();
+ uint8_t temp[3];
+ i.Read (temp, 3);
+ m_flowLabel = temp[2];
+ m_flowLabel = (m_flowLabel << 8) | temp[1];
+ m_flowLabel = (m_flowLabel << 8) | temp[0];
+ serializedSize += 4;
+ }
+
+ switch ( m_nextHeaderCompression )
+ {
+ case HC1_NC:
+ m_nextHeader = i.ReadU8 ();
+ serializedSize++;
+ break;
+ case HC1_TCP:
+ m_nextHeader = Ipv6Header::IPV6_TCP;
+ break;
+ case HC1_UDP:
+ m_nextHeader = Ipv6Header::IPV6_UDP;
+ break;
+ case HC1_ICMP:
+ m_nextHeader = Ipv6Header::IPV6_ICMPV6;
+ break;
+ }
+
+ NS_ASSERT_MSG ( m_hc2HeaderPresent != true, "Can not compress HC2, exiting. Very sorry." );
+
+ return GetSerializedSize ();
+}
+
+void SixLowPanHc1::SetHopLimit (uint8_t limit)
+{
+ m_hopLimit = limit;
+}
+
+uint8_t SixLowPanHc1::GetHopLimit () const
+{
+ return m_hopLimit;
+}
+
+SixLowPanHc1::LowPanHc1Addr_e SixLowPanHc1::GetDstCompression () const
+{
+ return m_dstCompression;
+}
+
+const uint8_t* SixLowPanHc1::GetDstInterface () const
+{
+ return m_dstInterface;
+}
+
+const uint8_t* SixLowPanHc1::GetDstPrefix () const
+{
+ return m_dstPrefix;
+}
+
+uint32_t SixLowPanHc1::GetFlowLabel () const
+{
+ return m_flowLabel;
+}
+
+uint8_t SixLowPanHc1::GetNextHeader () const
+{
+ return m_nextHeader;
+}
+
+SixLowPanHc1::LowPanHc1Addr_e SixLowPanHc1::GetSrcCompression () const
+{
+ return m_srcCompression;
+}
+
+const uint8_t* SixLowPanHc1::GetSrcInterface () const
+{
+ return m_srcInterface;
+}
+
+const uint8_t* SixLowPanHc1::GetSrcPrefix () const
+{
+ return m_srcPrefix;
+}
+
+uint8_t SixLowPanHc1::GetTrafficClass () const
+{
+ return m_trafficClass;
+}
+
+bool SixLowPanHc1::IsTcflCompression () const
+{
+ return m_tcflCompression;
+}
+
+bool SixLowPanHc1::IsHc2HeaderPresent () const
+{
+ return m_hc2HeaderPresent;
+}
+
+void SixLowPanHc1::SetDstCompression (LowPanHc1Addr_e dstCompression)
+{
+ m_dstCompression = dstCompression;
+}
+
+void SixLowPanHc1::SetDstInterface (const uint8_t* dstInterface)
+{
+ for ( int i = 0; i < 8; i++)
+ {
+ m_dstInterface[i] = dstInterface[i];
+ }
+}
+
+void SixLowPanHc1::SetDstPrefix (const uint8_t* dstPrefix)
+{
+ for ( int i = 0; i < 8; i++)
+ {
+ m_dstPrefix[i] = dstPrefix[i];
+ }
+}
+
+void SixLowPanHc1::SetFlowLabel (uint32_t flowLabel)
+{
+ m_flowLabel = flowLabel;
+}
+
+void SixLowPanHc1::SetNextHeader (uint8_t nextHeader)
+{
+ m_nextHeader = nextHeader;
+
+ switch (m_nextHeader)
+ {
+ case Ipv6Header::IPV6_UDP:
+ m_nextHeaderCompression = HC1_UDP;
+ break;
+ case Ipv6Header::IPV6_TCP:
+ m_nextHeaderCompression = HC1_TCP;
+ break;
+ case Ipv6Header::IPV6_ICMPV6:
+ m_nextHeaderCompression = HC1_ICMP;
+ break;
+ default:
+ m_nextHeaderCompression = HC1_NC;
+ break;
+ }
+}
+
+void SixLowPanHc1::SetSrcCompression (LowPanHc1Addr_e srcCompression)
+{
+ m_srcCompression = srcCompression;
+}
+
+void SixLowPanHc1::SetSrcInterface (const uint8_t* srcInterface)
+{
+ for ( int i = 0; i < 8; i++)
+ {
+ m_srcInterface[i] = srcInterface[i];
+ }
+}
+
+void SixLowPanHc1::SetSrcPrefix (const uint8_t* srcPrefix)
+{
+ for ( int i = 0; i < 8; i++)
+ {
+ m_srcPrefix[i] = srcPrefix[i];
+ }
+}
+
+void SixLowPanHc1::SetTcflCompression (bool tcflCompression)
+{
+ m_tcflCompression = tcflCompression;
+}
+
+void SixLowPanHc1::SetTrafficClass (uint8_t trafficClass)
+{
+ m_trafficClass = trafficClass;
+}
+
+
+void SixLowPanHc1::SetHc2HeaderPresent (bool hc2HeaderPresent)
+{
+ m_hc2HeaderPresent = hc2HeaderPresent;
+}
+
+
+std::ostream & operator << (std::ostream & os, const SixLowPanHc1 & h)
+{
+ h.Print (os);
+ return os;
+}
+
+/*
+ * SixLowPanFrag1
+ */
+NS_OBJECT_ENSURE_REGISTERED (SixLowPanFrag1)
+ ;
+
+SixLowPanFrag1::SixLowPanFrag1 ()
+ : m_datagramSize (0),
+ m_datagramTag (0)
+{
+}
+
+TypeId SixLowPanFrag1::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::SixLowPanFrag1").SetParent ().AddConstructor ();
+ return tid;
+}
+
+TypeId SixLowPanFrag1::GetInstanceTypeId (void) const
+{
+ return GetTypeId ();
+}
+
+void SixLowPanFrag1::Print (std::ostream & os) const
+{
+ os << "datagram size " << m_datagramSize << " tag " << m_datagramTag;
+}
+
+uint32_t SixLowPanFrag1::GetSerializedSize () const
+{
+ return 4;
+}
+
+void SixLowPanFrag1::Serialize (Buffer::Iterator start) const
+{
+ Buffer::Iterator i = start;
+
+ uint16_t temp = m_datagramSize | ( uint16_t (SixLowPanDispatch::LOWPAN_FRAG1) << 8 );
+
+ i.WriteU8 (uint8_t (temp >> 8));
+ i.WriteU8 (uint8_t (temp & 0xff));
+
+ i.WriteU16 (m_datagramTag);
+}
+
+uint32_t SixLowPanFrag1::Deserialize (Buffer::Iterator start)
+{
+ Buffer::Iterator i = start;
+
+ uint8_t temp = i.ReadU8 ();
+ m_datagramSize = (uint16_t (temp) << 8) | i.ReadU8 ();
+ m_datagramSize &= 0x7FF;
+
+ m_datagramTag = i.ReadU16 ();
+ return GetSerializedSize ();
+}
+
+void SixLowPanFrag1::SetDatagramSize (uint16_t datagramSize)
+{
+ m_datagramSize = datagramSize & 0x7FF;
+}
+
+uint16_t SixLowPanFrag1::GetDatagramSize () const
+{
+ return m_datagramSize & 0x7FF;
+}
+
+void SixLowPanFrag1::SetDatagramTag (uint16_t datagramTag)
+{
+ m_datagramTag = datagramTag;
+}
+
+uint16_t SixLowPanFrag1::GetDatagramTag () const
+{
+ return m_datagramTag;
+}
+
+std::ostream & operator << (std::ostream & os, const SixLowPanFrag1 & h)
+{
+ h.Print (os);
+ return os;
+}
+
+
+/*
+ * SixLowPanFragN
+ */
+
+NS_OBJECT_ENSURE_REGISTERED (SixLowPanFragN)
+ ;
+
+SixLowPanFragN::SixLowPanFragN ()
+ : m_datagramSize (0),
+ m_datagramTag (0),
+ m_datagramOffset (0)
+{
+}
+/*
+ * SixLowPanFragmentOffset
+ */
+TypeId SixLowPanFragN::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::SixLowPanFragN").SetParent ().AddConstructor ();
+ return tid;
+}
+
+TypeId SixLowPanFragN::GetInstanceTypeId (void) const
+{
+ return GetTypeId ();
+}
+
+void SixLowPanFragN::Print (std::ostream & os) const
+{
+ os << "datagram size " << m_datagramSize << " tag " << m_datagramTag << " offset " << int(m_datagramOffset);
+}
+
+uint32_t SixLowPanFragN::GetSerializedSize () const
+{
+ return 5;
+}
+
+void SixLowPanFragN::Serialize (Buffer::Iterator start) const
+{
+ Buffer::Iterator i = start;
+
+ uint16_t temp = m_datagramSize | ( uint16_t (SixLowPanDispatch::LOWPAN_FRAGN) << 8 );
+
+ i.WriteU8 (uint8_t (temp >> 8));
+ i.WriteU8 (uint8_t (temp & 0xff));
+
+ i.WriteU16 (m_datagramTag);
+ i.WriteU8 (m_datagramOffset);
+}
+
+uint32_t SixLowPanFragN::Deserialize (Buffer::Iterator start)
+{
+ Buffer::Iterator i = start;
+
+ uint8_t temp = i.ReadU8 ();
+ m_datagramSize = (uint16_t (temp) << 8) | i.ReadU8 ();
+ m_datagramSize &= 0x7FF;
+
+ m_datagramTag = i.ReadU16 ();
+ m_datagramOffset = i.ReadU8 ();
+
+ return GetSerializedSize ();
+}
+
+void SixLowPanFragN::SetDatagramSize (uint16_t datagramSize)
+{
+ m_datagramSize = datagramSize & 0x7FF;
+}
+
+uint16_t SixLowPanFragN::GetDatagramSize () const
+{
+ return m_datagramSize & 0x7FF;
+}
+
+void SixLowPanFragN::SetDatagramTag (uint16_t datagramTag)
+{
+ m_datagramTag = datagramTag;
+}
+
+uint16_t SixLowPanFragN::GetDatagramTag () const
+{
+ return m_datagramTag;
+}
+
+void SixLowPanFragN::SetDatagramOffset (uint8_t datagramOffset)
+{
+ m_datagramOffset = datagramOffset;
+}
+
+uint8_t SixLowPanFragN::GetDatagramOffset () const
+{
+ return m_datagramOffset;
+}
+
+std::ostream & operator << (std::ostream & os, const SixLowPanFragN & h)
+{
+ h.Print (os);
+ return os;
+}
+
+/*
+ * SixLowPanIphcHeader
+ */
+NS_OBJECT_ENSURE_REGISTERED (SixLowPanIphc)
+ ;
+
+SixLowPanIphc::SixLowPanIphc ()
+{
+ // 011x xxxx xxxx xxxx
+ m_baseFormat = 0x6000;
+}
+
+SixLowPanIphc::SixLowPanIphc (uint8_t dispatch)
+{
+ // 011x xxxx xxxx xxxx
+ m_baseFormat = dispatch;
+ m_baseFormat <<= 8;
+}
+
+TypeId SixLowPanIphc::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::SixLowPanIphc").SetParent ().AddConstructor ();
+ return tid;
+}
+
+TypeId SixLowPanIphc::GetInstanceTypeId (void) const
+{
+ return GetTypeId ();
+}
+
+void SixLowPanIphc::Print (std::ostream & os) const
+{
+ os << "Compression kind: " << m_baseFormat;
+}
+
+uint32_t SixLowPanIphc::GetSerializedSize () const
+{
+ uint32_t serializedSize = 2;
+
+ if ( GetCid () )
+ {
+ serializedSize++;
+ }
+ switch ( GetTf () )
+ {
+ case TF_FULL:
+ serializedSize += 4;
+ break;
+ case TF_DSCP_ELIDED:
+ serializedSize += 3;
+ break;
+ case TF_FL_ELIDED:
+ serializedSize++;
+ break;
+ default:
+ break;
+ }
+ if ( GetNh () == false )
+ {
+ serializedSize++;
+ }
+ if ( GetHlim () == HLIM_INLINE)
+ {
+ serializedSize++;
+ }
+ switch (GetSam () )
+ {
+ case HC_INLINE:
+ if ( GetSac () == false )
+ {
+ serializedSize += 16;
+ }
+ break;
+ case HC_COMPR_64:
+ serializedSize += 8;
+ break;
+ case HC_COMPR_16:
+ serializedSize += 2;
+ break;
+ case HC_COMPR_0:
+ default:
+ break;
+ }
+ if ( GetM () == false)
+ {
+ switch (GetDam () )
+ {
+ case HC_INLINE:
+ if ( GetDac () == false )
+ {
+ serializedSize += 16;
+ }
+ break;
+ case HC_COMPR_64:
+ serializedSize += 8;
+ break;
+ case HC_COMPR_16:
+ serializedSize += 2;
+ break;
+ case HC_COMPR_0:
+ default:
+ break;
+ }
+ }
+ else
+ {
+ switch (GetDam () )
+ {
+ case HC_INLINE:
+ if ( GetDac () == false )
+ {
+ serializedSize += 16;
+ }
+ else
+ {
+ serializedSize += 6;
+ }
+ break;
+ case HC_COMPR_64:
+ if ( GetDac () == false )
+ {
+ serializedSize += 6;
+ }
+ break;
+ case HC_COMPR_16:
+ if ( GetDac () == false )
+ {
+ serializedSize += 4;
+ }
+ break;
+ case HC_COMPR_0:
+ default:
+ if ( GetDac () == false )
+ {
+ serializedSize++;
+ }
+ break;
+ }
+ }
+
+
+
+ return serializedSize;
+}
+
+void SixLowPanIphc::Serialize (Buffer::Iterator start) const
+{
+ Buffer::Iterator i = start;
+
+ i.WriteHtonU16 (m_baseFormat);
+
+ if ( GetCid () )
+ {
+ i.WriteU8 (m_srcdstContextId);
+ }
+ // Traffic Class and Flow Label
+ switch ( GetTf () )
+ {
+ uint8_t temp;
+ case TF_FULL:
+ temp = (m_ecn << 6) | m_dscp;
+ i.WriteU8 (temp);
+ temp = m_flowLabel >> 16;
+ i.WriteU8 (temp);
+ temp = (m_flowLabel >> 8) & 0xff;
+ i.WriteU8 (temp);
+ temp = m_flowLabel & 0xff;
+ i.WriteU8 (temp);
+ break;
+ case TF_DSCP_ELIDED:
+ temp = (m_ecn << 6) | (m_flowLabel >> 16 );
+ i.WriteU8 (temp);
+ temp = (m_flowLabel >> 8) & 0xff;
+ i.WriteU8 (temp);
+ temp = m_flowLabel & 0xff;
+ i.WriteU8 (temp);
+ break;
+ case TF_FL_ELIDED:
+ temp = (m_ecn << 6) | m_dscp;
+ i.WriteU8 (temp);
+ break;
+ default:
+ break;
+ }
+ // Next Header
+ if ( GetNh () == false )
+ {
+ i.WriteU8 (m_nextHeader);
+ }
+ // Hop Limit
+ if ( GetHlim () == HLIM_INLINE )
+ {
+ i.WriteU8 (m_hopLimit);
+ }
+ // Source Address
+ switch (GetSam () )
+ {
+ uint8_t temp[16];
+ case HC_INLINE:
+ if ( GetSac () == false )
+ {
+ uint8_t temp[16];
+ m_srcAddress.Serialize (temp);
+ i.Write (temp, 16);
+ }
+ break;
+ case HC_COMPR_64:
+ m_srcAddress.Serialize (temp);
+ i.Write (temp + 8, 8);
+ break;
+ case HC_COMPR_16:
+ m_srcAddress.Serialize (temp);
+ i.Write (temp + 14, 2);
+ break;
+ case HC_COMPR_0:
+ default:
+ break;
+ }
+ // Destination Address
+ if ( GetM () == false)
+ {
+ uint8_t temp[16];
+ switch (GetDam () )
+ {
+ case HC_INLINE:
+ if ( GetDac () == false )
+ {
+ m_dstAddress.Serialize (temp);
+ i.Write (temp, 16);
+ }
+ break;
+ case HC_COMPR_64:
+ m_dstAddress.Serialize (temp);
+ i.Write (temp + 8, 8);
+ break;
+ case HC_COMPR_16:
+ m_dstAddress.Serialize (temp);
+ i.Write (temp + 14, 2);
+ break;
+ case HC_COMPR_0:
+ default:
+ break;
+ }
+ }
+ else
+ {
+ switch (GetDam () )
+ {
+ uint8_t temp[16];
+ case HC_INLINE:
+ if ( GetDac () == false )
+ {
+ m_dstAddress.Serialize (temp);
+ i.Write (temp, 16);
+ }
+ else
+ {
+ m_dstAddress.Serialize (temp);
+ i.Write (temp + 1, 2);
+ i.Write (temp + 12, 4);
+ }
+ break;
+ case HC_COMPR_64:
+ if ( GetDac () == false )
+ {
+ m_dstAddress.Serialize (temp);
+ i.Write (temp + 1, 1);
+ i.Write (temp + 11, 5);
+ }
+ break;
+ case HC_COMPR_16:
+ if ( GetDac () == false )
+ {
+ m_dstAddress.Serialize (temp);
+ i.Write (temp + 1, 1);
+ i.Write (temp + 13, 3);
+ }
+ break;
+ case HC_COMPR_0:
+ default:
+ if ( GetDac () == false )
+ {
+ m_dstAddress.Serialize (temp);
+ i.WriteU8 (temp[15]);
+ }
+ break;
+ }
+ }
+}
+
+uint32_t SixLowPanIphc::Deserialize (Buffer::Iterator start)
+{
+ Buffer::Iterator i = start;
+
+ m_baseFormat = i.ReadNtohU16 ();
+
+ if ( GetCid () )
+ {
+ m_srcdstContextId = i.ReadU8 ();
+ }
+ // Traffic Class and Flow Label
+ switch ( GetTf () )
+ {
+ uint8_t temp;
+ case TF_FULL:
+ temp = i.ReadU8 ();
+ m_ecn = temp >> 6;
+ m_dscp = temp & 0x3F;
+ temp = i.ReadU8 ();
+ m_flowLabel = temp;
+ temp = i.ReadU8 ();
+ m_flowLabel = (m_flowLabel << 8) | temp;
+ temp = i.ReadU8 ();
+ m_flowLabel = (m_flowLabel << 8) | temp;
+ break;
+ case TF_DSCP_ELIDED:
+ temp = i.ReadU8 ();
+ m_ecn = temp >> 6;
+ m_flowLabel = temp & 0x3F;
+ temp = i.ReadU8 ();
+ m_flowLabel = (m_flowLabel << 8) | temp;
+ temp = i.ReadU8 ();
+ m_flowLabel = (m_flowLabel << 8) | temp;
+ break;
+ case TF_FL_ELIDED:
+ temp = i.ReadU8 ();
+ m_ecn = temp >> 6;
+ m_dscp = temp & 0x3F;
+ break;
+ default:
+ break;
+ }
+ // Next Header
+ if ( GetNh () == false )
+ {
+ m_nextHeader = i.ReadU8 ();
+ }
+ // Hop Limit
+ switch ( GetHlim () )
+ {
+ case HLIM_INLINE:
+ m_hopLimit = i.ReadU8 ();
+ break;
+ case HLIM_COMPR_1:
+ m_hopLimit = 1;
+ break;
+ case HLIM_COMPR_64:
+ m_hopLimit = 64;
+ break;
+ case HLIM_COMPR_255:
+ default:
+ m_hopLimit = 255;
+ break;
+
+ }
+ // Source Address
+ switch (GetSam () )
+ {
+ uint8_t temp[16];
+ case HC_INLINE:
+ if ( GetSac () == false )
+ {
+ i.Read (temp, 16);
+ m_srcAddress = Ipv6Address::Deserialize (temp);
+ }
+ break;
+ case HC_COMPR_64:
+ memset (temp, 0x00, sizeof (temp));
+ i.Read (temp + 8, 8);
+ temp[0] = 0xfe;
+ temp[1] = 0x80;
+ m_srcAddress = Ipv6Address::Deserialize (temp);
+ break;
+ case HC_COMPR_16:
+ memset (temp, 0x00, sizeof (temp));
+ i.Read (temp + 14, 2);
+ temp[0] = 0xfe;
+ temp[1] = 0x80;
+ temp[11] = 0xff;
+ temp[12] = 0xfe;
+ m_srcAddress = Ipv6Address::Deserialize (temp);
+ break;
+ case HC_COMPR_0:
+ default:
+ break;
+ }
+ if ( GetSac () == true )
+ {
+ PostProcessSac ();
+ }
+ // Destination Address
+ if ( GetM () == false)
+ {
+ uint8_t temp[16];
+ switch (GetDam () )
+ {
+ case HC_INLINE:
+ if ( GetDac () == false )
+ {
+ i.Read (temp, 16);
+ m_dstAddress = Ipv6Address::Deserialize (temp);
+ }
+ break;
+ case HC_COMPR_64:
+ memset (temp, 0x00, sizeof (temp));
+ i.Read (temp + 8, 8);
+ temp[0] = 0xfe;
+ temp[1] = 0x80;
+ m_dstAddress = Ipv6Address::Deserialize (temp);
+ break;
+ case HC_COMPR_16:
+ memset (temp, 0x00, sizeof (temp));
+ i.Read (temp + 14, 2);
+ temp[0] = 0xfe;
+ temp[1] = 0x80;
+ temp[11] = 0xff;
+ temp[12] = 0xfe;
+ m_dstAddress = Ipv6Address::Deserialize (temp);
+ break;
+ case HC_COMPR_0:
+ default:
+ break;
+ }
+ }
+ else
+ {
+ switch (GetDam () )
+ {
+ uint8_t temp[16];
+ case HC_INLINE:
+ if ( GetDac () == false )
+ {
+ i.Read (temp, 16);
+ m_dstAddress = Ipv6Address::Deserialize (temp);
+ }
+ else
+ {
+ memset (temp, 0x00, sizeof (temp));
+ i.Read (temp + 1, 2);
+ i.Read (temp + 12, 4);
+ temp[0] = 0xff;
+ m_dstAddress = Ipv6Address::Deserialize (temp);
+ }
+ break;
+ case HC_COMPR_64:
+ if ( GetDac () == false )
+ {
+ memset (temp, 0x00, sizeof (temp));
+ i.Read (temp + 1, 1);
+ i.Read (temp + 11, 5);
+ temp[0] = 0xff;
+ m_dstAddress = Ipv6Address::Deserialize (temp);
+ }
+ break;
+ case HC_COMPR_16:
+ if ( GetDac () == false )
+ {
+ memset (temp, 0x00, sizeof (temp));
+ i.Read (temp + 1, 1);
+ i.Read (temp + 13, 3);
+ temp[0] = 0xff;
+ m_dstAddress = Ipv6Address::Deserialize (temp);
+ }
+ break;
+ case HC_COMPR_0:
+ default:
+ if ( GetDac () == false )
+ {
+ memset (temp, 0x00, sizeof (temp));
+ temp[15] = i.ReadU8 ();
+ temp[0] = 0xff;
+ temp[1] = 0x02;
+ m_dstAddress = Ipv6Address::Deserialize (temp);
+ }
+ break;
+ }
+ }
+ if ( GetDac () == true )
+ {
+ PostProcessDac ();
+ }
+ return GetSerializedSize ();
+}
+
+void SixLowPanIphc::SetTf (TrafficClassFlowLabel_e tfField)
+{
+ uint16_t field = tfField;
+ m_baseFormat |= (field << 11);
+}
+
+SixLowPanIphc::TrafficClassFlowLabel_e SixLowPanIphc::GetTf (void) const
+{
+ return TrafficClassFlowLabel_e ((m_baseFormat >> 11) & 0x3);
+}
+
+void SixLowPanIphc::SetNh (bool nhField)
+{
+ uint16_t field = nhField;
+ m_baseFormat |= (field << 10);
+}
+
+bool SixLowPanIphc::GetNh (void) const
+{
+ return ((m_baseFormat >> 10) & 0x1);
+}
+
+void SixLowPanIphc::SetHlim (Hlim_e hlimField)
+{
+ uint16_t field = hlimField;
+ m_baseFormat |= (field << 8);
+}
+
+SixLowPanIphc::Hlim_e SixLowPanIphc::GetHlim (void) const
+{
+ return Hlim_e ((m_baseFormat >> 8) & 0x3);
+}
+
+void SixLowPanIphc::SetCid (bool cidField)
+{
+ uint16_t field = cidField;
+ m_baseFormat |= (field << 7);
+}
+
+bool SixLowPanIphc::GetCid (void) const
+{
+ return ((m_baseFormat >> 7) & 0x1);
+}
+
+void SixLowPanIphc::SetSac (bool sacField)
+{
+ uint16_t field = sacField;
+ m_baseFormat |= (field << 6);
+}
+
+bool SixLowPanIphc::GetSac (void) const
+{
+ return ((m_baseFormat >> 6) & 0x1);
+}
+
+void SixLowPanIphc::SetSam (HeaderCompression_e samField)
+{
+ uint16_t field = samField;
+ m_baseFormat |= (field << 4);
+}
+
+SixLowPanIphc::HeaderCompression_e SixLowPanIphc::GetSam (void) const
+{
+ return HeaderCompression_e ((m_baseFormat >> 4) & 0x3);
+}
+
+void SixLowPanIphc::SetM (bool mField)
+{
+ uint16_t field = mField;
+ m_baseFormat |= (field << 3);
+}
+
+bool SixLowPanIphc::GetM (void) const
+{
+ return ((m_baseFormat >> 3) & 0x1);
+}
+
+void SixLowPanIphc::SetDac (bool dacField)
+{
+ uint16_t field = dacField;
+ m_baseFormat |= (field << 2);
+}
+
+bool SixLowPanIphc::GetDac (void) const
+{
+ return ((m_baseFormat >> 2) & 0x1);
+}
+
+void SixLowPanIphc::SetDam (HeaderCompression_e damField)
+{
+ uint16_t field = damField;
+ m_baseFormat |= field;
+}
+
+SixLowPanIphc::HeaderCompression_e SixLowPanIphc::GetDam (void) const
+{
+ return HeaderCompression_e (m_baseFormat & 0x3);
+}
+
+void SixLowPanIphc::SetSrcContextId (uint8_t srcContextId)
+{
+ NS_ASSERT_MSG (srcContextId < 16, "Src Context ID too large");
+ m_srcdstContextId |= srcContextId << 4;
+}
+
+uint8_t SixLowPanIphc::GetSrcContextId (void) const
+{
+ return ( m_srcdstContextId >> 4);
+}
+
+void SixLowPanIphc::SetDstContextId (uint8_t dstContextId)
+{
+ NS_ASSERT_MSG (dstContextId < 16, "Dst Context ID too large");
+ m_srcdstContextId |= (dstContextId & 0xF);
+}
+
+uint8_t SixLowPanIphc::GetDstContextId (void) const
+{
+ return (m_srcdstContextId & 0xF);
+}
+
+void SixLowPanIphc::SetEcn (uint8_t ecn)
+{
+ NS_ASSERT_MSG (ecn < 4, "ECN too large");
+ m_ecn = ecn;
+}
+
+uint8_t SixLowPanIphc::GetEcn (void) const
+{
+ return m_ecn;
+}
+
+void SixLowPanIphc::SetDscp (uint8_t dscp)
+{
+ NS_ASSERT_MSG (dscp < 64, "DSCP too large");
+ m_dscp = dscp;
+}
+
+uint8_t SixLowPanIphc::GetDscp (void) const
+{
+ return m_dscp;
+}
+
+void SixLowPanIphc::SetFlowLabel (uint32_t flowLabel)
+{
+ NS_ASSERT_MSG (flowLabel < 0x100000, "Flow Label too large");
+ m_flowLabel = flowLabel;
+}
+
+uint32_t SixLowPanIphc::GetFlowLabel (void) const
+{
+ return m_flowLabel;
+}
+
+void SixLowPanIphc::SetNextHeader (uint8_t nextHeader)
+{
+ m_nextHeader = nextHeader;
+}
+
+uint8_t SixLowPanIphc::GetNextHeader (void) const
+{
+ return m_nextHeader;
+}
+
+void SixLowPanIphc::SetHopLimit (uint8_t hopLimit)
+{
+ m_hopLimit = hopLimit;
+}
+
+uint8_t SixLowPanIphc::GetHopLimit (void) const
+{
+ return m_hopLimit;
+}
+
+void SixLowPanIphc::SetSrcAddress (Ipv6Address srcAddress)
+{
+ m_srcAddress = srcAddress;
+}
+
+Ipv6Address SixLowPanIphc::GetSrcAddress () const
+{
+ return m_srcAddress;
+}
+
+void SixLowPanIphc::SetDstAddress (Ipv6Address dstAddress)
+{
+ m_dstAddress = dstAddress;
+}
+
+Ipv6Address SixLowPanIphc::GetDstAddress () const
+{
+ return m_dstAddress;
+}
+
+void SixLowPanIphc::PostProcessSac ()
+{
+ NS_ABORT_MSG ("Unsupported; Context destination is not implemented");
+ return;
+}
+
+void SixLowPanIphc::PostProcessDac ()
+{
+ NS_ABORT_MSG ("Unsupported; Context destination is not implemented");
+ return;
+}
+
+std::ostream & operator << (std::ostream & os, const SixLowPanIphc & h)
+{
+ h.Print (os);
+ return os;
+}
+
+/*
+ * SixLowPanNhcExtensionHeader
+ */
+NS_OBJECT_ENSURE_REGISTERED (SixLowPanNhcExtension)
+ ;
+
+SixLowPanNhcExtension::SixLowPanNhcExtension ()
+{
+ // 1110 xxxx
+ m_nhcExtensionHeader = 0xE0;
+ m_nhcNextHeader = 0;
+ m_nhcBlobLength = 0;
+}
+
+TypeId SixLowPanNhcExtension::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::SixLowPanNhcExtension")
+ .SetParent ()
+ .AddConstructor ();
+ return tid;
+}
+
+TypeId SixLowPanNhcExtension::GetInstanceTypeId (void) const
+{
+ return GetTypeId ();
+}
+
+void SixLowPanNhcExtension::Print (std::ostream & os) const
+{
+ os << "Compression kind: " << int (m_nhcExtensionHeader) << " Size: " << int(GetSerializedSize ());
+}
+
+uint32_t SixLowPanNhcExtension::GetSerializedSize () const
+{
+ uint32_t serializedSize = 2;
+ if ( GetNh () == false )
+ {
+ serializedSize++;
+ }
+ return serializedSize + m_nhcBlobLength;
+}
+
+void SixLowPanNhcExtension::Serialize (Buffer::Iterator start) const
+{
+ Buffer::Iterator i = start;
+ i.WriteU8 (m_nhcExtensionHeader);
+ if ( GetNh () == false )
+ {
+ i.WriteU8 (m_nhcNextHeader);
+ }
+ i.WriteU8 (m_nhcBlobLength);
+ i.Write (m_nhcBlob, m_nhcBlobLength);
+}
+
+uint32_t SixLowPanNhcExtension::Deserialize (Buffer::Iterator start)
+{
+ Buffer::Iterator i = start;
+ m_nhcExtensionHeader = i.ReadU8 ();
+ if ( GetNh () == false )
+ {
+ m_nhcNextHeader = i.ReadU8 ();
+ }
+ m_nhcBlobLength = i.ReadU8 ();
+ i.Read (m_nhcBlob, m_nhcBlobLength);
+
+ return GetSerializedSize ();
+}
+
+SixLowPanDispatch::NhcDispatch_e
+SixLowPanNhcExtension::GetNhcDispatchType (void) const
+{
+ return SixLowPanDispatch::LOWPAN_NHC;
+}
+
+void SixLowPanNhcExtension::SetEid (Eid_e extensionHeaderType)
+{
+ uint8_t field = extensionHeaderType;
+ m_nhcExtensionHeader |= (field << 1);
+}
+
+SixLowPanNhcExtension::Eid_e SixLowPanNhcExtension::GetEid (void) const
+{
+ return Eid_e ((m_nhcExtensionHeader >> 1) & 0x7);
+}
+
+void SixLowPanNhcExtension::SetNextHeader (uint8_t nextHeader)
+{
+ m_nhcNextHeader = nextHeader;
+}
+
+uint8_t SixLowPanNhcExtension::GetNextHeader (void) const
+{
+ return m_nhcNextHeader;
+}
+
+void SixLowPanNhcExtension::SetNh (bool nhField)
+{
+ uint8_t field = nhField;
+ m_nhcExtensionHeader |= field;
+}
+
+bool SixLowPanNhcExtension::GetNh (void) const
+{
+ return m_nhcExtensionHeader & 0x01;
+}
+
+void SixLowPanNhcExtension::SetBlob (const uint8_t* blob, uint32_t size)
+{
+ NS_ASSERT_MSG ( size < 255, "Buffer too long" );
+
+ m_nhcBlobLength = size;
+ std::memcpy (m_nhcBlob, blob, size);
+}
+
+uint32_t SixLowPanNhcExtension::CopyBlob (uint8_t* blob, uint32_t size) const
+{
+ NS_ASSERT_MSG ( size > m_nhcBlobLength, "Buffer too short" );
+
+ std::memcpy (blob, m_nhcBlob, m_nhcBlobLength);
+ return m_nhcBlobLength;
+}
+
+std::ostream & operator << (std::ostream & os, const SixLowPanNhcExtension & h)
+{
+ h.Print (os);
+ return os;
+}
+
+/*
+ * SixLowPanUdpNhcExtension
+ */
+NS_OBJECT_ENSURE_REGISTERED (SixLowPanUdpNhcExtension)
+ ;
+
+SixLowPanUdpNhcExtension::SixLowPanUdpNhcExtension ()
+{
+ // 1111 0xxx
+ m_baseFormat = 0xF0;
+ m_checksum = 0;
+ m_srcPort = 0;
+ m_dstPort = 0;
+}
+
+TypeId SixLowPanUdpNhcExtension::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::SixLowPanUdpNhcExtension")
+ .SetParent ()
+ .AddConstructor ();
+ return tid;
+}
+
+TypeId SixLowPanUdpNhcExtension::GetInstanceTypeId (void) const
+{
+ return GetTypeId ();
+}
+
+void SixLowPanUdpNhcExtension::Print (std::ostream & os) const
+{
+ os << "Compression kind: " << uint8_t (m_baseFormat);
+}
+
+uint32_t SixLowPanUdpNhcExtension::GetSerializedSize () const
+{
+ uint32_t serializedSize = 1;
+ if ( !GetC () )
+ {
+ serializedSize += 2;
+ }
+ switch (GetPorts ())
+ {
+ case PORTS_INLINE:
+ serializedSize += 4;
+ break;
+ case PORTS_ALL_SRC_LAST_DST:
+ case PORTS_LAST_SRC_ALL_DST:
+ serializedSize += 3;
+ break;
+ case PORTS_LAST_SRC_LAST_DST:
+ serializedSize += 1;
+ break;
+ default:
+ break;
+ }
+ return serializedSize;
+}
+
+void SixLowPanUdpNhcExtension::Serialize (Buffer::Iterator start) const
+{
+ Buffer::Iterator i = start;
+ i.WriteU8 (m_baseFormat);
+ uint8_t temp;
+
+ // Ports
+ switch ( GetPorts () )
+ {
+ case PORTS_INLINE:
+ i.WriteHtonU16 (m_srcPort);
+ i.WriteHtonU16 (m_dstPort);
+ break;
+ case PORTS_ALL_SRC_LAST_DST:
+ i.WriteHtonU16 (m_srcPort);
+ i.WriteU8 (m_dstPort & 0xff);
+ break;
+ case PORTS_LAST_SRC_ALL_DST:
+ i.WriteU8 (m_srcPort & 0xff);
+ i.WriteHtonU16 (m_dstPort);
+ break;
+ case PORTS_LAST_SRC_LAST_DST:
+ temp = ((m_srcPort & 0xf) << 4) | (m_dstPort & 0xf);
+ i.WriteU8 (temp);
+ break;
+ default:
+ break;
+ }
+
+ // Checksum
+ if ( !GetC () )
+ {
+ i.WriteU16 (m_checksum);
+ }
+
+}
+
+uint32_t SixLowPanUdpNhcExtension::Deserialize (Buffer::Iterator start)
+{
+ Buffer::Iterator i = start;
+ m_baseFormat = i.ReadU8 ();
+ uint8_t temp;
+
+ // Ports
+ switch ( GetPorts () )
+ {
+ case PORTS_INLINE:
+ m_srcPort = i.ReadNtohU16 ();
+ m_dstPort = i.ReadNtohU16 ();
+ break;
+ case PORTS_ALL_SRC_LAST_DST:
+ m_srcPort = i.ReadNtohU16 ();
+ m_dstPort = i.ReadU8 ();
+ break;
+ case PORTS_LAST_SRC_ALL_DST:
+ m_srcPort = i.ReadU8 ();
+ m_dstPort = i.ReadNtohU16 ();
+ break;
+ case PORTS_LAST_SRC_LAST_DST:
+ temp = i.ReadU8 ();
+ m_srcPort = temp >> 4;
+ m_dstPort = temp & 0xf;
+ break;
+ default:
+ break;
+ }
+
+ // Checksum
+ if ( !GetC () )
+ {
+ m_checksum = i.ReadU16 ();
+ }
+
+ return GetSerializedSize ();
+}
+
+SixLowPanDispatch::NhcDispatch_e
+SixLowPanUdpNhcExtension::GetNhcDispatchType (void) const
+{
+ return SixLowPanDispatch::LOWPAN_UDPNHC;
+}
+
+void SixLowPanUdpNhcExtension::SetPorts (Ports_e ports)
+{
+ uint16_t field = ports;
+ m_baseFormat |= field;
+}
+
+SixLowPanUdpNhcExtension::Ports_e SixLowPanUdpNhcExtension::GetPorts (void) const
+{
+ return Ports_e (m_baseFormat & 0x3);
+}
+
+void SixLowPanUdpNhcExtension::SetSrcPort (uint16_t srcport)
+{
+ m_srcPort = srcport;
+}
+
+uint16_t SixLowPanUdpNhcExtension::GetSrcPort (void) const
+{
+ return m_srcPort;
+}
+
+void SixLowPanUdpNhcExtension::SetDstPort (uint16_t dstport)
+{
+ m_dstPort = dstport;
+}
+
+uint16_t SixLowPanUdpNhcExtension::GetDstPort (void) const
+{
+ return m_dstPort;
+}
+
+void SixLowPanUdpNhcExtension::SetC (bool cField)
+{
+ uint16_t field = cField;
+ m_baseFormat |= (field << 2);
+}
+
+bool SixLowPanUdpNhcExtension::GetC (void) const
+{
+ return ((m_baseFormat >> 2) & 0x1);
+}
+
+void SixLowPanUdpNhcExtension::SetChecksum (uint16_t checksum)
+{
+ m_checksum = checksum;
+}
+
+uint16_t SixLowPanUdpNhcExtension::GetChecksum (void) const
+{
+ return m_checksum;
+}
+
+std::ostream & operator << (std::ostream & os, const SixLowPanUdpNhcExtension & h)
+{
+ h.Print (os);
+ return os;
+}
+
+
+}
+
diff --git a/src/sixlowpan/model/sixlowpan-header.h b/src/sixlowpan/model/sixlowpan-header.h
new file mode 100644
index 000000000..5c954adaa
--- /dev/null
+++ b/src/sixlowpan/model/sixlowpan-header.h
@@ -0,0 +1,1214 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013 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
+ * Michele Muccio
+ */
+
+#ifndef SIXLOWPANHEADER_H_
+#define SIXLOWPANHEADER_H_
+
+#include "ns3/header.h"
+#include "ns3/ipv6-address.h"
+#include "ns3/packet.h"
+#include "ns3/ipv6-header.h"
+
+namespace ns3 {
+
+/**
+* \ingroup sixlowpan
+* \brief Dispatch header helper. This class only purpose is to interpret
+* the Dispatch header into its correct type.
+*
+* The dispatch type is defined by a zero bit as the first bit and a one
+* bit as the second bit.
+ \verbatim
+ 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ |0 1| Dispatch | type-specific header
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ \endverbatim
+*/
+class SixLowPanDispatch
+{
+public:
+ /**
+ * \brief Dispatch values, as defined in RFC4944 and RFC6282
+ \verbatim
+ Pattern Header Type
+ +------------+------------------------------------------------+
+ | 00 xxxxxx | NALP - Not a LoWPAN frame |
+ | 01 000000 | ESC - Additional Dispatch byte follows |
+ | 01 000001 | IPv6 - Uncompressed IPv6 Addresses |
+ | 01 000010 | LOWPAN_HC1 - LOWPAN_HC1 compressed IPv6 |
+ | 01 000011 | reserved - Reserved for future use |
+ | ... | reserved - Reserved for future use |
+ | 01 001111 | reserved - Reserved for future use |
+ | 01 010000 | LOWPAN_BC0 - LOWPAN_BC0 broadcast |
+ | 01 010001 | reserved - Reserved for future use |
+ | ... | reserved - Reserved for future use |
+ | 01 1xxxxx | LOWPAN_IPHC - LOWPAN_IPHC compressed IPv6 |
+ | 10 xxxxxx | MESH - Mesh Header |
+ | 11 000xxx | FRAG1 - Fragmentation Header (first) |
+ | 11 001000 | reserved - Reserved for future use |
+ | ... | reserved - Reserved for future use |
+ | 11 011111 | reserved - Reserved for future use |
+ | 11 100xxx | FRAGN - Fragmentation Header (subsequent)|
+ | 11 101000 | reserved - Reserved for future use |
+ | ... | reserved - Reserved for future use |
+ | 11 111111 | reserved - Reserved for future use |
+ +------------+------------------------------------------------+
+ \endverbatim
+ */
+ enum Dispatch_e
+ {
+ LOWPAN_NALP = 0x0,
+ LOWPAN_NALP_N = 0x3F,
+ LOWPAN_NOTCOMPRESSED = 0x41,
+ LOWPAN_HC1 = 0x42,
+ LOWPAN_BC0 = 0x50,
+ LOWPAN_IPHC = 0x60,
+ LOWPAN_IPHC_N = 0x7F,
+ LOWPAN_MESH = 0x80,
+ LOWPAN_MESH_N = 0xBF,
+ LOWPAN_FRAG1 = 0xC0,
+ LOWPAN_FRAG1_N = 0xC7,
+ LOWPAN_FRAGN = 0xE0,
+ LOWPAN_FRAGN_N = 0xE7,
+ LOWPAN_UNSUPPORTED = 0xFF
+ };
+
+ /**
+ * \brief Dispatch values for Next Header compression.
+ *
+ * The dispatch values reflect the dispatch use, since
+ * some dispatch bits carry actual header compression bits.
+ */
+ enum NhcDispatch_e
+ {
+ LOWPAN_NHC = 0xE0,
+ LOWPAN_NHC_N = 0xEF,
+ LOWPAN_UDPNHC = 0xF0,
+ LOWPAN_UDPNHC_N = 0xF7,
+ LOWPAN_NHCUNSUPPORTED = 0xFF
+ };
+
+ SixLowPanDispatch (void);
+
+ /**
+ * \brief Get the Dispatch type.
+ * \param dispatch the dispatch value
+ * \return the Dispatch type
+ */
+ static Dispatch_e GetDispatchType (uint8_t dispatch);
+
+ /**
+ * \brief Get the NhcDispatch type.
+ * \param dispatch the dispatch value
+ * \return the NhcDispatch type
+ */
+ static NhcDispatch_e GetNhcDispatchType (uint8_t dispatch);
+
+};
+
+/**
+ * \ingroup sixlowpan
+ * \brief 6LoWPAN HC1 header - see RFC 4944
+ */
+class SixLowPanHc1 : public Header
+{
+public:
+ /**
+ * \brief Kind of address compression.
+ *
+ * The address compression is handled in 4 bits and might mean:
+ * PI: Prefix inline, PC: Prefix Compressed,
+ * II: Interface Identifier, Inline, IC: Interface Identifier Compressed
+ */
+ enum LowPanHc1Addr_e
+ {
+ HC1_PIII = 0x00,
+ HC1_PIIC = 0x01,
+ HC1_PCII = 0x02,
+ HC1_PCIC = 0x03
+ };
+
+ /**
+ * \brief Next header information.
+ *
+ * The Next header compression is handled in 4 bits and might mean:
+ * NC: Not Compressed, UDP, ICMP or TCP.
+ */
+ enum LowPanHc1NextHeader_e
+ {
+ HC1_NC = 0x00,
+ HC1_UDP = 0x01,
+ HC1_ICMP = 0x02,
+ HC1_TCP = 0x03
+ };
+
+ SixLowPanHc1 (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 start Buffer iterator
+ */
+ virtual void Serialize (Buffer::Iterator start) const;
+
+ /**
+ * \brief Deserialize the packet.
+ * \param start Buffer iterator
+ * \return size of the packet
+ */
+ virtual uint32_t Deserialize (Buffer::Iterator start);
+
+ /**
+ * \brief Get the Dispatch type.
+ * \return the Dispatch type
+ */
+ // virtual Dispatch_e GetDispatchType (void) const;
+
+ /**
+ * \brief Set the "Hop limit" field (TTL).
+ * \param limit the hop limit value
+ */
+ void SetHopLimit (uint8_t limit);
+
+ /**
+ * \brief Get the "Hop limit" field (TTL).
+ * \return the hop limit value
+ */
+ uint8_t GetHopLimit (void) const;
+
+ /**
+ * \brief Get Destination Compression type
+ * \returns the kind of address compression
+ */
+ LowPanHc1Addr_e GetDstCompression () const;
+
+ /**
+ * \brief Get the destination interface
+ * \returns the destination interface
+ */
+ const uint8_t* GetDstInterface () const;
+
+ /**
+ * \brief Get the destination prefix
+ * \returns the destination prefix
+ */
+ const uint8_t* GetDstPrefix () const;
+
+ /**
+ * \brief Get the Flow Label value
+ * \returns the Flow Label
+ */
+ uint32_t GetFlowLabel () const;
+
+ /**
+ * \brief Get the Next Header value
+ * \returns the Next Header value
+ */
+ uint8_t GetNextHeader () const;
+
+ /**
+ * \brief Get Source Compression type
+ * \returns the kind of address compression
+ */
+ LowPanHc1Addr_e GetSrcCompression () const;
+
+ /**
+ * \brief Get the source interface
+ * \returns the source interface
+ */
+ const uint8_t* GetSrcInterface () const;
+
+ /**
+ * \brief Get the source prefix
+ * \returns the source prefix
+ */
+ const uint8_t* GetSrcPrefix () const;
+
+ /**
+ * \brief Get the Traffic Class value
+ * \returns the Traffic Class value
+ */
+ uint8_t GetTrafficClass () const;
+
+ /**
+ * \brief Check if the Traffic Class and Flow Labels are compressed
+ * \returns true if TC and FL are compressed
+ */
+ bool IsTcflCompression () const;
+
+ /**
+ * \brief Check if there is a HC2 compressed header
+ * \returns true if next header is HC2 copressed
+ */
+ bool IsHc2HeaderPresent () const;
+
+ /**
+ * \brief Set Destination Compression type
+ * \param dstCompression the kind of address compression
+ */
+ void SetDstCompression (LowPanHc1Addr_e dstCompression);
+
+ /**
+ * \brief Set the destination interface
+ * \param dstInterface the destination interface
+ */
+ void SetDstInterface (const uint8_t* dstInterface);
+
+ /**
+ * \brief Set the destination prefix
+ * \param dstPrefix the destination prefix
+ */
+ void SetDstPrefix (const uint8_t* dstPrefix);
+
+ /**
+ * \brief Set the Flow Label value
+ * \param flowLabel the Flow Label
+ */
+ void SetFlowLabel (uint32_t flowLabel);
+
+ /**
+ * \brief Set the Next Header value
+ * \param nextHeader the Next Header value
+ */
+ void SetNextHeader (uint8_t nextHeader);
+
+ /**
+ * \brief Set Source Compression type
+ * \param srcCompression the kind of address compression
+ */
+ void SetSrcCompression (LowPanHc1Addr_e srcCompression);
+
+ /**
+ * \brief Set the source interface
+ * \param srcInterface the source interface
+ */
+ void SetSrcInterface (const uint8_t* srcInterface);
+
+ /**
+ * \brief Set the source prefix
+ * \param srcPrefix the source prefix
+ */
+ void SetSrcPrefix (const uint8_t* srcPrefix);
+
+ /**
+ * \brief Set the Traffic Class and Flow Labels as compressed
+ * \param tcflCompression true if TC and FL are compressed
+ */
+ void SetTcflCompression (bool tcflCompression);
+
+ /**
+ * \brief Set the next header a HC2 compressed header
+ * \param hc2HeaderPresent true if next header is HC2 compressed
+ */
+ void SetHc2HeaderPresent (bool hc2HeaderPresent);
+
+ /**
+ * \brief Set the Traffic Class value
+ * \param trafficClass the Traffic Class value
+ */
+ void SetTrafficClass (uint8_t trafficClass);
+
+private:
+ uint8_t m_hopLimit; //!< Hop Limit
+ uint8_t m_srcPrefix[8]; //!< Source prefix
+ uint8_t m_srcInterface[8]; //!< Source interface
+ uint8_t m_dstPrefix[8]; //!< Destinaiton prefix
+ uint8_t m_dstInterface[8]; //!< Destination interface
+ uint8_t m_trafficClass; //!< Traffic Class
+ uint32_t m_flowLabel; //!< Flow Label
+ uint8_t m_nextHeader; //!< Next header
+ LowPanHc1Addr_e m_srcCompression; //!< Source compresison type
+ LowPanHc1Addr_e m_dstCompression; //!< Destination compresison type
+ bool m_tcflCompression; //!< is TC and FL compressed
+ LowPanHc1NextHeader_e m_nextHeaderCompression; //!< next header compression
+ bool m_hc2HeaderPresent; //!< is next header HC2 compressed
+};
+
+/**
+ * \brief Stream insertion operator.
+ *
+ * \param os the reference to the output stream
+ * \param header the HC1 Header
+ * \returns the reference to the output stream
+ */
+std::ostream & operator<< (std::ostream & os, SixLowPanHc1 const &header);
+
+/**
+ * \ingroup sixlowpan
+ * \brief 6LoWPAN FRAG1 header - see RFC 4944
+ */
+class SixLowPanFrag1 : public Header
+{
+public:
+ SixLowPanFrag1 (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 start Buffer iterator
+ */
+ virtual void Serialize (Buffer::Iterator start) const;
+
+ /**
+ * \brief Deserialize the packet.
+ * \param start Buffer iterator
+ * \return size of the packet
+ */
+ virtual uint32_t Deserialize (Buffer::Iterator start);
+
+ /**
+ * \brief Get the Dispatch type.
+ * \return the Dispatch type
+ */
+ // virtual Dispatch_e GetDispatchType (void) const;
+
+ /**
+ * \brief Set the datagram size
+ * \param datagramSize the datagram size
+ */
+ void SetDatagramSize (uint16_t datagramSize);
+
+ /**
+ * \brief Get the datagram size
+ * \returns the datagram size
+ */
+ uint16_t GetDatagramSize (void) const;
+
+ /**
+ * \brief Set the datagram tag
+ * \param datagramTag the datagram tag
+ */
+ void SetDatagramTag (uint16_t datagramTag);
+
+ /**
+ * \brief Get the datagram tag
+ * \returns the datagram tag
+ */
+ uint16_t GetDatagramTag (void) const;
+
+private:
+ uint16_t m_datagramSize; //!< datagram size
+ uint16_t m_datagramTag; //!< datagram tag
+
+};
+
+/**
+ * \brief Stream insertion operator.
+ *
+ * \param os the reference to the output stream
+ * \param header the Frag1 Header
+ * \returns the reference to the output stream
+ */
+std::ostream & operator<< (std::ostream & os, SixLowPanFrag1 const & header);
+
+/**
+ * \ingroup sixlowpan
+ * \brief 6LoWPAN FRAGN header - see RFC 4944
+ */
+class SixLowPanFragN : public Header
+{
+public:
+ SixLowPanFragN (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 start Buffer iterator
+ */
+ virtual void Serialize (Buffer::Iterator start) const;
+
+ /**
+ * \brief Deserialize the packet.
+ * \param start Buffer iterator
+ * \return size of the packet
+ */
+ virtual uint32_t Deserialize (Buffer::Iterator start);
+
+ /**
+ * \brief Get the Dispatch type.
+ * \return the Dispatch type
+ */
+ // virtual Dispatch_e GetDispatchType (void) const;
+
+ /**
+ * \brief Set the datagram size
+ * \param datagramSize the datagram size
+ */
+ void SetDatagramSize (uint16_t datagramSize);
+
+ /**
+ * \brief Get the datagram size
+ * \returns the datagram size
+ */
+ uint16_t GetDatagramSize (void) const;
+
+ /**
+ * \brief Set the datagram tag
+ * \param datagramTag the datagram tag
+ */
+ void SetDatagramTag (uint16_t datagramTag);
+
+ /**
+ * \brief Get the datagram tag
+ * \returns the datagram tag
+ */
+ uint16_t GetDatagramTag (void) const;
+
+ /**
+ * \brief Set the datagram offset
+ * \param datagramOffset the datagram offset
+ */
+ void SetDatagramOffset (uint8_t datagramOffset);
+
+ /**
+ * \brief Get the datagram offset
+ * \returns the datagram offset
+ */
+ uint8_t GetDatagramOffset (void) const;
+
+private:
+ uint16_t m_datagramSize; //!< datagram size
+ uint16_t m_datagramTag; //!< datagram tag
+ uint8_t m_datagramOffset; //!< datagram offset
+
+};
+
+/**
+ * \brief Stream insertion operator.
+ *
+ * \param os the reference to the output stream
+ * \param header the FragN Header
+ * \returns the reference to the output stream
+ */
+std::ostream & operator<< (std::ostream & os, SixLowPanFragN const &header);
+
+/**
+* \ingroup sixlowpan
+* \brief LOWPAN_IPHC base Encoding - see RFC 6262
+ \verbatim
+ 0 1
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+ | 0 | 1 | 1 | TF |NH | HLIM |CID|SAC| SAM | M |DAC| DAM |
+ +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+ \endverbatim
+*/
+class SixLowPanIphc : public Header
+{
+public:
+ /**
+ * \brief TF: Traffic Class, Flow Label
+ *
+ * 00: ECN + DSCP + 4-bit Pad + Flow Label (4 bytes)
+ * 01: ECN + 2-bit Pad + Flow Label (3 bytes), DSCP is elided.
+ * 10: ECN + DSCP (1 byte), Flow Label is elided.
+ * 11: Traffic Class and Flow Label are elided.
+ *
+ */
+ enum TrafficClassFlowLabel_e
+ {
+ TF_FULL = 0,
+ TF_DSCP_ELIDED,
+ TF_FL_ELIDED,
+ TF_ELIDED
+ };
+
+ /**
+ * \brief HLIM: Hop Limit
+ *
+ * 00: The Hop Limit field is carried in-line.
+ * 01: The Hop Limit field is compressed and the hop limit is 1.
+ * 10: The Hop Limit field is compressed and the hop limit is 64.
+ * 11: The Hop Limit field is compressed and the hop limit is 255.
+ */
+ enum Hlim_e
+ {
+ HLIM_INLINE = 0,
+ HLIM_COMPR_1,
+ HLIM_COMPR_64,
+ HLIM_COMPR_255
+ };
+
+ /**
+ * \brief Source or Destination Address Mode
+ *
+ * 00: 128 bits.
+ * 01: 64 bits (or 48 bits if multicast).
+ * 10: 16 bits (or 32 bits if multicast).
+ * 11: Fully elided (or 8 bits if multicast).
+ */
+ enum HeaderCompression_e
+ {
+ HC_INLINE = 0,
+ HC_COMPR_64,
+ HC_COMPR_16,
+ HC_COMPR_0
+ };
+
+ SixLowPanIphc (void);
+ /**
+ * \brief Constructor
+ * \param dispatch dispatch value
+ */
+ SixLowPanIphc (uint8_t dispatch);
+
+ /**
+ * \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 start Buffer iterator
+ */
+ virtual void Serialize (Buffer::Iterator start) const;
+
+ /**
+ * \brief Deserialize the packet.
+ * \param start Buffer iterator
+ * \return size of the packet
+ */
+ virtual uint32_t Deserialize (Buffer::Iterator start);
+
+ /**
+ * \brief Get the Dispatch type.
+ * \return the Dispatch type
+ */
+ // virtual Dispatch_e GetDispatchType (void) const;
+
+ /**
+ * \brief Set the TF (Traffic Class, Flow Label) compression.
+ * \param tfField ECN, DSCP, Flow Label compression type
+ */
+ void SetTf (TrafficClassFlowLabel_e tfField);
+
+ /**
+ * \brief Get the TF (Traffic Class, Flow Label) compression.
+ * \return the ECN, DSCP, Flow Label compression type
+ */
+ TrafficClassFlowLabel_e GetTf (void) const;
+
+ /**
+ * \brief Set the NH (Next Header) compression.
+ * \param nhField false (Next Header carried in-line), true (compressed NH)
+ */
+ void SetNh (bool nhField);
+
+ /**
+ * \brief Get the NH (Next Header) compression.
+ * \return false (Next Header carried in-line), true (compressed NH)
+ */
+ bool GetNh (void) const;
+
+ /**
+ * \brief Set the HLIM (Hop Limit) compression.
+ * \param hlimField Hop Limit compression type
+ */
+ void SetHlim (Hlim_e hlimField);
+
+ /**
+ * \brief Get the HLIM (Hop Limit) compression.
+ * \return Hop Limit compression type
+ */
+ Hlim_e GetHlim (void) const;
+
+ /**
+ * \brief Set the CID (Context Identifier Extension) compression.
+ * \param cidField false (no CID present), true (CID follows)
+ */
+ void SetCid (bool cidField);
+
+ /**
+ * \brief Get the CID (Context Identifier Extension) compression.
+ * \return false (no CID present), true (CID follows)
+ */
+ bool GetCid (void) const;
+
+ /**
+ * \brief Set the SAC (Source Address Compression) compression.
+ * \param sacField false (stateless), true (stateful)
+ */
+ void SetSac (bool sacField);
+
+ /**
+ * \brief Get the SAC (Source Address Compression) compression.
+ * \return false (stateless), true (stateful)
+ */
+ bool GetSac (void) const;
+
+ /**
+ * \brief Set the SAM (Source Address Mode) compression.
+ * \param samField - depends on the SAC
+ */
+ void SetSam (HeaderCompression_e samField);
+
+ /**
+ * \brief Get the SAM (Source Address Mode) compression.
+ * \return depends on the SAC field
+ */
+ HeaderCompression_e GetSam (void) const;
+
+ /**
+ * \brief Set the M (Multicast) compression.
+ * \param mField true if destination is multicast
+ */
+ void SetM (bool mField);
+
+ /**
+ * \brief Get the M (Multicast) compression.
+ * \return true if destination is multicast
+ */
+ bool GetM (void) const;
+
+ /**
+ * \brief Set the DAC (Destination Address Compression) compression.
+ * \param dacField false (stateless), true (stateful)
+ */
+ void SetDac (bool dacField);
+
+ /**
+ * \brief Get the DAC (Destination Address Compression) compression.
+ * \return false (stateless), true (stateful)
+ */
+ bool GetDac (void) const;
+
+ /**
+ * \brief Set the DAM (Destination Address Mode) compression.
+ * \param damField - depends on the DAC and M fields
+ */
+ void SetDam (HeaderCompression_e damField);
+
+ /**
+ * \brief Get the DAM (Destination Address Mode) compression.
+ * \return depends on the DAC and M fields
+ */
+ HeaderCompression_e GetDam (void) const;
+
+ /**
+ * \brief Set the SrcContextId.
+ * \param srcContextId - valid values are [0:15]
+ */
+ void SetSrcContextId (uint8_t srcContextId);
+
+ /**
+ * \brief Get the SrcContextId.
+ * \return the SrcContextId
+ */
+ uint8_t GetSrcContextId (void) const;
+
+ /**
+ * \brief Set the DstContextId.
+ * \param dstContextId - valid values are [0:15]
+ */
+ void SetDstContextId (uint8_t dstContextId);
+
+ /**
+ * \brief Get the DstContextId.
+ * \return the DstContextId
+ */
+ uint8_t GetDstContextId (void) const;
+
+ /**
+ * \brief Set the ECN (2bits).
+ * \param ecn - valid values are [0:3]
+ */
+ void SetEcn (uint8_t ecn);
+
+ /**
+ * \brief Get the ECN.
+ * \return the ECN
+ */
+ uint8_t GetEcn (void) const;
+
+ /**
+ * \brief Set the DSCP (6bits).
+ * \param dscp - valid values are [0:63]
+ */
+ void SetDscp (uint8_t dscp);
+
+ /**
+ * \brief Get the DSCP.
+ * \return the DSCP
+ */
+ uint8_t GetDscp (void) const;
+
+ /**
+ * \brief Set the Flow Label (20bits).
+ * \param flowLabel - valid values are 20 bits long.
+ */
+ void SetFlowLabel (uint32_t flowLabel);
+
+ /**
+ * \brief Get the Flow Label.
+ * \return the Flow Label
+ */
+ uint32_t GetFlowLabel (void) const;
+
+ /**
+ * \brief Set the Next Header field.
+ * \param nextHeader Next Header field.
+ */
+ void SetNextHeader (uint8_t nextHeader);
+
+ /**
+ * \brief Get the Next Header field.
+ * \return the Next Header field.
+ */
+ uint8_t GetNextHeader (void) const;
+
+ /**
+ * \brief Set the Hop Limit field.
+ * \param hopLimit Hop Limit field.
+ */
+ void SetHopLimit (uint8_t hopLimit);
+
+ /**
+ * \brief Get the Hop Limit field.
+ * \return the Hop Limit field.
+ */
+ uint8_t GetHopLimit (void) const;
+
+ /**
+ * \brief Set the Source Address.
+ * \param srcAddress the Source Address.
+ */
+ void SetSrcAddress (Ipv6Address srcAddress);
+
+ /**
+ * \brief Get the Source Address.
+ * \return the Source Address.
+ */
+ Ipv6Address GetSrcAddress () const;
+
+ /**
+ * \brief Set the Destination Address.
+ * \param dstAddress the Destination Address.
+ */
+ void SetDstAddress (Ipv6Address dstAddress);
+
+ /**
+ * \brief Get the Destination Address.
+ * \return the Destination Address.
+ */
+ Ipv6Address GetDstAddress () const;
+
+private:
+ uint16_t m_baseFormat; //!< Dispatch + encoding fields
+ uint8_t m_srcdstContextId; //!< Src and Dst Context ID
+ uint8_t m_ecn : 2; //!< ECN bits
+ uint8_t m_dscp : 6; //!< DSCP bits
+ uint32_t m_flowLabel : 20; //!< Flow Label bits
+ uint8_t m_nextHeader; //!< Next header
+ uint8_t m_hopLimit; //!< Hop Limit
+ Ipv6Address m_srcAddress; //!< Src address
+ Ipv6Address m_dstAddress; //!< Dst address
+
+ /**
+ * \brief Post-process the Source address stateful compression
+ * \note currently unsupported
+ */
+ void PostProcessSac ();
+ /**
+ * \brief Post-process the Destination address stateful compression
+ * \note currently unsupported
+ */
+ void PostProcessDac ();
+
+};
+
+/**
+ * \brief Stream insertion operator.
+ *
+ * \param os the reference to the output stream
+ * \param header the IPHC Header
+ * \returns the reference to the output stream
+ */
+std::ostream & operator<< (std::ostream & os, SixLowPanIphc const &header);
+
+/**
+* \ingroup sixlowpan
+* \brief LOWPAN_NHC Extension Header Encoding - see RFC 6262
+ \verbatim
+ 0 1 2 3 4 5 6 7
+ +---+---+---+---+---+---+---+---+
+ | 1 | 1 | 1 | 0 | EID |NH |
+ +---+---+---+---+---+---+---+---+
+ \endverbatim
+*/
+class SixLowPanNhcExtension : public Header
+{
+public:
+ /**
+ * \brief EID: IPv6 Extension Header ID
+ *
+ * EID: IPv6 Extension Header ID:
+ * 0: IPv6 Hop-by-Hop Options Header [RFC2460]
+ * 1: IPv6 Routing Header [RFC2460]
+ * 2: IPv6 Fragment Header [RFC2460]
+ * 3: IPv6 Destination Options Header [RFC2460]
+ * 4: IPv6 Mobility Header [RFC6275]
+ * 5: Reserved
+ * 6: Reserved
+ * 7: IPv6 Header
+ */
+ enum Eid_e
+ {
+ EID_HOPBYHOP_OPTIONS_H = 0,
+ EID_ROUTING_H,
+ EID_FRAGMENTATION_H,
+ EID_DESTINATION_OPTIONS_H,
+ EID_MOBILITY_H,
+ EID_IPv6_H = 7
+ };
+
+ SixLowPanNhcExtension (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 start Buffer iterator
+ */
+ virtual void Serialize (Buffer::Iterator start) const;
+
+ /**
+ * \brief Deserialize the packet.
+ * \param start Buffer iterator
+ * \return size of the packet
+ */
+ virtual uint32_t Deserialize (Buffer::Iterator start);
+
+ /**
+ * \brief Get the NhcDispatch type.
+ * \return the NhcDispatch type
+ */
+ virtual SixLowPanDispatch::NhcDispatch_e GetNhcDispatchType (void) const;
+
+ /**
+ * \brief Set the Extension Header Type.
+ * \param extensionHeaderType the Extension Header Type
+ */
+ void SetEid (Eid_e extensionHeaderType);
+
+ /**
+ * \brief Get the Extension Header Type.
+ * \return the Extension Header Type
+ */
+ Eid_e GetEid (void) const;
+
+ /**
+ * \brief Set the Next Header field values.
+ * \param nextHeader the Next Header field value
+ */
+ void SetNextHeader (uint8_t nextHeader);
+
+ /**
+ * \brief Get the Next Header field value.
+ * \return the Next Header field value
+ */
+ uint8_t GetNextHeader (void) const;
+
+ /**
+ * \brief Set the NH field values.
+ * \param nhField the NH field value
+ */
+ void SetNh (bool nhField);
+
+ /**
+ * \brief Get the Next Header field value.
+ * \return the NH field value
+ */
+ bool GetNh (void) const;
+
+ /**
+ * \brief Set the option header data blob.
+ * \param blob a buffer holding the blob data
+ * \param size the data blob size
+ */
+ void SetBlob (const uint8_t* blob, uint32_t size);
+
+ /**
+ * \brief Get the option header data blob.
+ * \param blob a buffer to copy the blob data into
+ * \param size the size of the buffer
+ * \return the length of the copied data
+ */
+ uint32_t CopyBlob (uint8_t* blob, uint32_t size) const;
+
+private:
+ uint8_t m_nhcExtensionHeader; //!< NHC extension header type
+ uint8_t m_nhcNextHeader; //!< Next header
+ uint8_t m_nhcBlobLength; //!< Length of the NHC compressed header
+ uint8_t m_nhcBlob[256]; //!< NHC compressed header
+};
+
+/**
+ * \brief Stream insertion operator.
+ *
+ * \param os the reference to the output stream
+ * \param header the NHC Extension Header
+ * \returns the reference to the output stream
+ */
+std::ostream & operator<< (std::ostream & os, SixLowPanNhcExtension const &header);
+
+
+/**
+* \ingroup sixlowpan
+* \brief UDP LOWPAN_NHC Extension Header Encoding - see RFC 6262
+ \verbatim
+ 0 1 2 3 4 5 6 7
+ +---+---+---+---+---+---+---+---+
+ | 1 | 1 | 1 | 1 | 0 | C | P |
+ +---+---+---+---+---+---+---+---+
+ \endverbatim
+*/
+class SixLowPanUdpNhcExtension : public Header
+{
+public:
+ /**
+ * \brief Ports:
+ *
+ * 00: 16 bits for both Source Port and Destination Port
+ * 01: 16 bits for Source Port. Last 8 bits for Destination Port
+ * 10: Last 8 bits for Source Port. All 16 bits for Destination Port
+ * 11: Last 4 bits of both Source Port and Destination Port
+ */
+ enum Ports_e
+ {
+ PORTS_INLINE = 0,
+ PORTS_ALL_SRC_LAST_DST,
+ PORTS_LAST_SRC_ALL_DST,
+ PORTS_LAST_SRC_LAST_DST
+ };
+
+ SixLowPanUdpNhcExtension (void);
+
+ /**
+ * \brief Return the instance type identifier.
+ * \return instance type ID
+ */
+ 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 start Buffer iterator
+ */
+ virtual void Serialize (Buffer::Iterator start) const;
+
+ /**
+ * \brief Deserialize the packet.
+ * \param start Buffer iterator
+ * \return size of the packet
+ */
+ virtual uint32_t Deserialize (Buffer::Iterator start);
+
+ /**
+ * \brief Get the NhcDispatch type.
+ * \return the NhcDispatch type
+ */
+ virtual SixLowPanDispatch::NhcDispatch_e GetNhcDispatchType (void) const;
+
+ /**
+ * \brief Set the compressed Src and Dst Ports.
+ * \param port Src and Dst the Ports
+ */
+ void SetPorts (Ports_e port);
+
+ /**
+ * \brief Get the compressed Src and Dst Ports.
+ * \return the Src and Dst Ports
+ */
+ Ports_e GetPorts (void) const;
+
+ /**
+ * \brief Set the Destination Port.
+ * \param port the Destination Port.
+ */
+ void SetSrcPort (uint16_t port);
+
+ /**
+ * \brief Get the Destination Port.
+ * \return the Destination Port.
+ */
+ uint16_t GetSrcPort () const;
+
+ /**
+ * \brief Set the Destination Port.
+ * \param port the Destination Port.
+ */
+ void SetDstPort (uint16_t port);
+
+ /**
+ * \brief Get the Destination Port.
+ * \return the Destination Port.
+ */
+ uint16_t GetDstPort () const;
+
+ /**
+ * \brief Set the C (Checksum).
+ * \param cField false (All checksum carried in-line), true (Checksum elided)
+ */
+ void SetC (bool cField);
+
+ /**
+ * \brief Get the C (Checksum).
+ * \return false (All checksum carried in-line), true (Checksum elided)
+ */
+ bool GetC (void) const;
+
+ /**
+ * \brief Set the Checksum field values.
+ * \param checksum the Checksum field value
+ */
+ void SetChecksum (uint16_t checksum);
+
+ /**
+ * \brief Get the Checksum field value.
+ * \return the Checksum field value
+ */
+ uint16_t GetChecksum (void) const;
+
+private:
+ uint8_t m_baseFormat; //!< Dispatch + encoding fields
+ uint16_t m_checksum; //!< Checksum
+ uint16_t m_srcPort; //!< Source port
+ uint16_t m_dstPort; //!< Destination port
+};
+
+/**
+ * \brief Stream insertion operator.
+ *
+ * \param os the reference to the output stream
+ * \param header the UDP NHC Extension Header
+ * \returns the reference to the output stream
+ */
+std::ostream & operator<< (std::ostream & os, SixLowPanUdpNhcExtension const &header);
+
+}
+
+#endif /* SIXLOWPANHEADER_H_ */
diff --git a/src/sixlowpan/model/sixlowpan-net-device.cc b/src/sixlowpan/model/sixlowpan-net-device.cc
new file mode 100644
index 000000000..8b945956a
--- /dev/null
+++ b/src/sixlowpan/model/sixlowpan-net-device.cc
@@ -0,0 +1,2118 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013 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
+ * Michele Muccio
+ */
+
+#include "ns3/node.h"
+#include "ns3/channel.h"
+#include "ns3/packet.h"
+#include "ns3/log.h"
+#include "ns3/boolean.h"
+#include "ns3/abort.h"
+#include "ns3/simulator.h"
+#include "ns3/uinteger.h"
+#include "ns3/icmpv6-header.h"
+#include "ns3/ipv6-header.h"
+#include "ns3/random-variable.h"
+#include "ns3/mac16-address.h"
+#include "ns3/mac48-address.h"
+#include "ns3/mac64-address.h"
+#include "ns3/unused.h"
+#include "ns3/ipv6-l3-protocol.h"
+#include "ns3/ipv6-extension-header.h"
+#include "ns3/udp-header.h"
+#include "ns3/udp-l4-protocol.h"
+#include "sixlowpan-net-device.h"
+#include "sixlowpan-header.h"
+
+NS_LOG_COMPONENT_DEFINE ("SixLowPanNetDevice")
+ ;
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (SixLowPanNetDevice)
+ ;
+
+TypeId SixLowPanNetDevice::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::SixLowPanNetDevice")
+ .SetParent ()
+ .AddConstructor ()
+ .AddAttribute ("Rfc6282", "Use RFC6282 (IPHC) if true, RFC4944 (HC1) otherwise.",
+ BooleanValue (true),
+ MakeBooleanAccessor (&SixLowPanNetDevice::m_useIphc),
+ MakeBooleanChecker ())
+ .AddAttribute ("OmitUdpChecksum",
+ "Omit the UDP checksum in IPHC compression.",
+ BooleanValue (true),
+ MakeBooleanAccessor (&SixLowPanNetDevice::m_omitUdpChecksum),
+ MakeBooleanChecker ())
+ .AddAttribute ("FragmentReassemblyListSize", "The maximum size of the reassembly buffer (in packets). Zero meaning infinite.",
+ UintegerValue (0),
+ MakeUintegerAccessor (&SixLowPanNetDevice::m_fragmentReassemblyListSize),
+ MakeUintegerChecker ())
+ .AddAttribute ("FragmentExpirationTimeout",
+ "When this timeout expires, the fragments will be cleared from the buffer.",
+ TimeValue (Seconds (60)),
+ MakeTimeAccessor (&SixLowPanNetDevice::m_fragmentExpirationTimeout),
+ MakeTimeChecker ())
+ .AddAttribute ("ForceEtherType",
+ "Force a specific EtherType in L2 frames.",
+ BooleanValue (false),
+ MakeBooleanAccessor (&SixLowPanNetDevice::m_forceEtherType),
+ MakeBooleanChecker ())
+ .AddAttribute ("EtherType",
+ "The specific EtherType to be used in L2 frames.",
+ UintegerValue (0xFFFF),
+ MakeUintegerAccessor (&SixLowPanNetDevice::m_etherType),
+ MakeUintegerChecker ())
+ .AddTraceSource ("Tx", "Send - packet (including 6LoWPAN header), SixLoWPanNetDevice Ptr, interface index.",
+ MakeTraceSourceAccessor (&SixLowPanNetDevice::m_txTrace))
+ .AddTraceSource ("Rx", "Receive - packet (including 6LoWPAN header), SixLoWPanNetDevice Ptr, interface index.",
+ MakeTraceSourceAccessor (&SixLowPanNetDevice::m_rxTrace))
+ .AddTraceSource ("Drop", "Drop - DropReason, packet (including 6LoWPAN header), SixLoWPanNetDevice Ptr, interface index.",
+ MakeTraceSourceAccessor (&SixLowPanNetDevice::m_dropTrace))
+ ;
+ return tid;
+}
+
+SixLowPanNetDevice::SixLowPanNetDevice ()
+ : m_node (0),
+ m_netDevice (0),
+ m_ifIndex (0)
+{
+ NS_LOG_FUNCTION (this);
+ m_netDevice = 0;
+ m_rng = CreateObject ();
+}
+
+Ptr SixLowPanNetDevice::GetNetDevice () const
+{
+ NS_LOG_FUNCTION (this);
+ return m_netDevice;
+}
+
+void SixLowPanNetDevice::SetNetDevice (Ptr device)
+{
+ NS_LOG_FUNCTION (this << device);
+ m_netDevice = device;
+
+ NS_LOG_DEBUG ("RegisterProtocolHandler for " << device->GetInstanceTypeId ().GetName ());
+
+ uint16_t protocolType = 0;
+ if ( m_forceEtherType )
+ {
+ protocolType = m_etherType;
+ }
+ m_node->RegisterProtocolHandler (MakeCallback (&SixLowPanNetDevice::ReceiveFromDevice,
+ this),
+ protocolType, device, false);
+}
+
+int64_t SixLowPanNetDevice::AssignStreams (int64_t stream)
+{
+ NS_LOG_FUNCTION (this << stream);
+ m_rng->SetStream (stream);
+ return 1;
+}
+
+void SixLowPanNetDevice::DoDispose ()
+{
+ NS_LOG_FUNCTION (this);
+
+ m_netDevice = 0;
+ m_node = 0;
+
+ for (MapFragmentsTimersI_t iter = m_fragmentsTimers.begin (); iter != m_fragmentsTimers.end (); iter++)
+ {
+ iter->second.Cancel ();
+ }
+ m_fragmentsTimers.clear ();
+
+ for (MapFragmentsI_t iter = m_fragments.begin (); iter != m_fragments.end (); iter++)
+ {
+ iter->second = 0;
+ }
+ m_fragments.clear ();
+
+ NetDevice::DoDispose ();
+}
+
+void SixLowPanNetDevice::ReceiveFromDevice (Ptr incomingPort,
+ Ptr packet,
+ uint16_t protocol,
+ Address const &src,
+ Address const &dst,
+ PacketType packetType)
+{
+ NS_LOG_FUNCTION (this << incomingPort << packet << protocol << src << dst);
+ NS_LOG_DEBUG ("UID is " << packet->GetUid ());
+
+ uint8_t dispatchRawVal = 0;
+ SixLowPanDispatch::Dispatch_e dispatchVal;
+ Ptr copyPkt = packet->Copy ();
+
+ m_rxTrace (copyPkt, m_node->GetObject (), GetIfIndex ());
+
+ copyPkt->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
+ dispatchVal = SixLowPanDispatch::GetDispatchType (dispatchRawVal);
+ bool isPktDecompressed = false;
+ bool fragmented = false;
+
+ NS_LOG_DEBUG ( "Packet received: " << *copyPkt );
+ NS_LOG_DEBUG ( "Packet length: " << copyPkt->GetSize () );
+ NS_LOG_DEBUG ( "Dispatches: " << int(dispatchRawVal) << " - " << int(dispatchVal) );
+
+ if ( dispatchVal == SixLowPanDispatch::LOWPAN_FRAG1 )
+ {
+ isPktDecompressed = ProcessFragment (copyPkt, src, dst, true);
+ fragmented = true;
+ }
+ else if ( dispatchVal == SixLowPanDispatch::LOWPAN_FRAGN )
+ {
+ isPktDecompressed = ProcessFragment (copyPkt, src, dst, false);
+ fragmented = true;
+ }
+ if ( fragmented )
+ {
+ if ( !isPktDecompressed )
+ {
+ return;
+ }
+ else
+ {
+ copyPkt->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
+ dispatchVal = SixLowPanDispatch::GetDispatchType (dispatchRawVal);
+ }
+ }
+
+ switch ( dispatchVal )
+ {
+ case SixLowPanDispatch::LOWPAN_MESH:
+ NS_LOG_DEBUG ("Unsupported 6LoWPAN encoding: MESH, dropping.");
+ m_dropTrace (DROP_UNKNOWN_EXTENSION, copyPkt, m_node->GetObject (), GetIfIndex ());
+ break;
+ case SixLowPanDispatch::LOWPAN_BC0:
+ NS_LOG_DEBUG ("Unsupported 6LoWPAN encoding: BC0, dropping.");
+ m_dropTrace (DROP_UNKNOWN_EXTENSION, copyPkt, m_node->GetObject (), GetIfIndex ());
+ break;
+ case SixLowPanDispatch::LOWPAN_NOTCOMPRESSED:
+ NS_LOG_DEBUG ( "Packet without compression:" << *copyPkt );
+ NS_LOG_DEBUG ( "Packet length:" << copyPkt->GetSize () );
+ m_dropTrace (DROP_UNKNOWN_EXTENSION, copyPkt, m_node->GetObject (), GetIfIndex ());
+ break;
+ case SixLowPanDispatch::LOWPAN_HC1:
+ DecompressLowPanHc1 (copyPkt, src, dst);
+ isPktDecompressed = true;
+ break;
+ case SixLowPanDispatch::LOWPAN_IPHC:
+ DecompressLowPanIphc (copyPkt, src, dst);
+ isPktDecompressed = true;
+ break;
+ default:
+ NS_LOG_DEBUG ("Unsupported 6LoWPAN encoding: dropping.");
+ m_dropTrace (DROP_UNKNOWN_EXTENSION, copyPkt, m_node->GetObject (), GetIfIndex ());
+ break;
+ }
+
+ if ( !isPktDecompressed )
+ {
+ return;
+ }
+
+ NS_LOG_DEBUG ( "Packet decompressed length: " << copyPkt->GetSize () );
+ NS_LOG_DEBUG ( "Packet decompressed received: " << *copyPkt );
+
+ if (!m_promiscRxCallback.IsNull ())
+ {
+ m_promiscRxCallback (this, copyPkt, Ipv6L3Protocol::PROT_NUMBER, src, dst, packetType);
+ }
+
+ m_rxCallback (this, copyPkt, Ipv6L3Protocol::PROT_NUMBER, src);
+
+ return;
+}
+
+void SixLowPanNetDevice::SetIfIndex (const uint32_t index)
+{
+ NS_LOG_FUNCTION (this << index);
+ // NS_ASSERT_MSG ( m_port != 0, "Sixlowpan: can't find any lower-layer protocol " << m_port );
+ m_ifIndex = index;
+}
+
+uint32_t SixLowPanNetDevice::GetIfIndex (void) const
+{
+ NS_LOG_FUNCTION (this);
+ // NS_ASSERT_MSG ( m_port != 0, "Sixlowpan: can't find any lower-layer protocol " << m_port );
+ return m_netDevice->GetIfIndex ();
+}
+
+Ptr SixLowPanNetDevice::GetChannel (void) const
+{
+ NS_LOG_FUNCTION (this);
+ NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
+
+ return m_netDevice->GetChannel ();
+}
+
+void SixLowPanNetDevice::SetAddress (Address address)
+{
+ NS_LOG_FUNCTION (this << address);
+ NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
+
+ m_netDevice->SetAddress (address);
+}
+
+Address SixLowPanNetDevice::GetAddress (void) const
+{
+ NS_LOG_FUNCTION (this);
+ NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
+
+ return m_netDevice->GetAddress ();
+}
+
+bool SixLowPanNetDevice::SetMtu (const uint16_t mtu)
+{
+ NS_LOG_FUNCTION (this << mtu);
+ NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
+
+ return m_netDevice->SetMtu (mtu);
+}
+
+uint16_t SixLowPanNetDevice::GetMtu (void) const
+{
+ NS_LOG_FUNCTION (this);
+
+ uint16_t mtu = m_netDevice->GetMtu ();
+
+ // RFC 4944, section 4.
+ if (mtu < 1280)
+ {
+ mtu = 1280;
+ }
+ return mtu;
+}
+
+bool SixLowPanNetDevice::IsLinkUp (void) const
+{
+ NS_LOG_FUNCTION (this);
+ NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
+
+ return m_netDevice->IsLinkUp ();
+}
+
+void SixLowPanNetDevice::AddLinkChangeCallback (Callback callback)
+{
+ NS_LOG_FUNCTION (this);
+ NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
+
+ return m_netDevice->AddLinkChangeCallback (callback);
+}
+
+bool SixLowPanNetDevice::IsBroadcast (void) const
+{
+ NS_LOG_FUNCTION (this);
+ NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
+
+ return m_netDevice->IsBroadcast ();
+}
+
+Address SixLowPanNetDevice::GetBroadcast (void) const
+{
+ NS_LOG_FUNCTION (this);
+ NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
+
+ return m_netDevice->GetBroadcast ();
+}
+
+bool SixLowPanNetDevice::IsMulticast (void) const
+{
+ NS_LOG_FUNCTION (this);
+ NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
+
+ return m_netDevice->IsMulticast ();
+}
+
+Address SixLowPanNetDevice::GetMulticast (Ipv4Address multicastGroup) const
+{
+ NS_LOG_FUNCTION (this << multicastGroup);
+ NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
+
+ return m_netDevice->GetMulticast (multicastGroup);
+}
+
+Address SixLowPanNetDevice::GetMulticast (Ipv6Address addr) const
+{
+ NS_LOG_FUNCTION (this << addr);
+ NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
+
+ return m_netDevice->GetMulticast (addr);
+}
+
+bool SixLowPanNetDevice::IsPointToPoint (void) const
+{
+ NS_LOG_FUNCTION (this);
+ NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
+
+ return m_netDevice->IsPointToPoint ();
+}
+
+bool SixLowPanNetDevice::IsBridge (void) const
+{
+ NS_LOG_FUNCTION (this);
+ NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
+
+ return m_netDevice->IsBridge ();
+}
+
+bool SixLowPanNetDevice::Send (Ptr packet,
+ const Address& dest,
+ uint16_t protocolNumber)
+{
+ NS_LOG_FUNCTION (this << *packet << dest << protocolNumber);
+ NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
+
+ uint32_t origHdrSize = 0;
+ uint32_t origPacketSize = packet->GetSize ();
+ bool ret = false;
+
+ if (m_forceEtherType)
+ {
+ protocolNumber = m_etherType;
+ }
+
+ if (m_useIphc)
+ {
+ origHdrSize += CompressLowPanIphc (packet, m_netDevice->GetAddress (), dest);
+ }
+ else
+ {
+ origHdrSize += CompressLowPanHc1 (packet, m_netDevice->GetAddress (), dest);
+ }
+
+ if ( packet->GetSize () > m_netDevice->GetMtu () )
+ {
+ NS_LOG_LOGIC ("Fragmentation: Packet size " << packet->GetSize () << " - Mtu " << m_netDevice->GetMtu () );
+ // fragment
+ std::list > fragmentList;
+ DoFragmentation (packet, origPacketSize, origHdrSize, fragmentList);
+ std::list >::iterator it;
+ bool success = true;
+ for ( it = fragmentList.begin (); it != fragmentList.end (); it++ )
+ {
+ NS_LOG_DEBUG ( "SixLowPanNetDevice::Send (Fragment) " << **it );
+ m_txTrace (*it, m_node->GetObject (), GetIfIndex ());
+ success &= m_netDevice->Send (*it, dest, protocolNumber);
+ }
+ ret = success;
+ }
+ else
+ {
+ NS_LOG_DEBUG ( "SixLowPanNetDevice::Send " << m_node->GetId () << " " << *packet );
+ m_txTrace (packet, m_node->GetObject (), GetIfIndex ());
+ ret = m_netDevice->Send (packet, dest, protocolNumber);
+ }
+
+ return ret;
+}
+
+bool SixLowPanNetDevice::SendFrom (Ptr packet,
+ const Address& src,
+ const Address& dest,
+ uint16_t protocolNumber)
+{
+ NS_LOG_FUNCTION (this << packet << src << dest << protocolNumber);
+ NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
+
+ uint32_t origHdrSize = 0;
+ uint32_t origPacketSize = packet->GetSize ();
+ bool ret = false;
+
+ if (m_forceEtherType)
+ {
+ protocolNumber = m_etherType;
+ }
+
+ if (m_useIphc)
+ {
+ origHdrSize += CompressLowPanIphc (packet, m_netDevice->GetAddress (), dest);
+ }
+ else
+ {
+ origHdrSize += CompressLowPanHc1 (packet, m_netDevice->GetAddress (), dest);
+ }
+
+ if ( packet->GetSize () > m_netDevice->GetMtu () )
+ {
+ // fragment
+ std::list > fragmentList;
+ DoFragmentation (packet, origPacketSize, origHdrSize, fragmentList);
+ std::list >::iterator it;
+ bool err = false;
+ for ( it = fragmentList.begin (); it != fragmentList.end (); it++ )
+ {
+ NS_LOG_DEBUG ( "SixLowPanNetDevice::SendFrom (Fragment) " << **it );
+ m_txTrace (*it, m_node->GetObject (), GetIfIndex ());
+ err |= !(m_netDevice->SendFrom (*it, src, dest, protocolNumber));
+ }
+ ret = !err;
+ }
+ else
+ {
+ NS_LOG_DEBUG ( "SixLowPanNetDevice::SendFrom " << *packet );
+ m_txTrace (packet, m_node->GetObject (), GetIfIndex ());
+ ret = m_netDevice->SendFrom (packet, src, dest, protocolNumber);
+ }
+
+ return ret;
+}
+
+Ptr SixLowPanNetDevice::GetNode (void) const
+{
+ NS_LOG_FUNCTION (this);
+ return m_node;
+}
+
+void SixLowPanNetDevice::SetNode (Ptr node)
+{
+ NS_LOG_FUNCTION (this << node);
+ m_node = node;
+}
+
+bool SixLowPanNetDevice::NeedsArp (void) const
+{
+ NS_LOG_FUNCTION (this);
+ NS_ASSERT_MSG ( m_netDevice != 0, "Sixlowpan: can't find any lower-layer protocol " << m_netDevice );
+
+ return m_netDevice->NeedsArp ();
+}
+
+void SixLowPanNetDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb)
+{
+ NS_LOG_FUNCTION (this << &cb);
+ m_rxCallback = cb;
+}
+
+void SixLowPanNetDevice::SetPromiscReceiveCallback (NetDevice::PromiscReceiveCallback cb)
+{
+ NS_LOG_FUNCTION (this << &cb);
+ m_promiscRxCallback = cb;
+}
+
+bool SixLowPanNetDevice::SupportsSendFrom () const
+{
+ NS_LOG_FUNCTION (this);
+ return true;
+}
+
+uint32_t
+SixLowPanNetDevice::CompressLowPanHc1 (Ptr packet, Address const &src, Address const &dst)
+{
+ NS_LOG_FUNCTION (this << *packet << src << dst);
+
+ Ipv6Header ipHeader;
+ SixLowPanHc1 hc1Header;
+ uint32_t size = 0;
+
+ if ( packet->PeekHeader (ipHeader) != 0 )
+ {
+ packet->RemoveHeader (ipHeader);
+ size += ipHeader.GetSerializedSize ();
+
+ hc1Header.SetHopLimit (ipHeader.GetHopLimit ());
+
+ uint8_t bufOne[16];
+ uint8_t bufTwo[16];
+ Ipv6Address srcAddr = ipHeader.GetSourceAddress ();
+ srcAddr.GetBytes (bufOne);
+ Ipv6Address mySrcAddr = MakeLinkLocalAddressFromMac (src);
+
+ NS_LOG_LOGIC ("Checking source compression: " << mySrcAddr << " - " << srcAddr );
+
+ mySrcAddr.GetBytes (bufTwo);
+ bool isSrcSrc = (memcmp (bufOne + 8, bufTwo + 8, 8) == 0);
+
+ if (srcAddr.IsLinkLocal () && isSrcSrc )
+ {
+ hc1Header.SetSrcCompression (SixLowPanHc1::HC1_PCIC);
+ }
+ else if (srcAddr.IsLinkLocal () )
+ {
+ hc1Header.SetSrcCompression (SixLowPanHc1::HC1_PCII);
+ hc1Header.SetSrcInterface (bufOne + 8);
+ }
+ else if ( isSrcSrc )
+ {
+ hc1Header.SetSrcCompression (SixLowPanHc1::HC1_PIIC);
+ hc1Header.SetSrcPrefix (bufOne);
+ }
+ else
+ {
+ hc1Header.SetSrcCompression (SixLowPanHc1::HC1_PIII);
+ hc1Header.SetSrcInterface (bufOne + 8);
+ hc1Header.SetSrcPrefix (bufOne);
+ }
+
+ Ipv6Address dstAddr = ipHeader.GetDestinationAddress ();
+ dstAddr.GetBytes (bufOne);
+ Ipv6Address myDstAddr = MakeLinkLocalAddressFromMac (dst);
+
+ NS_LOG_LOGIC ("Checking destination compression: " << myDstAddr << " - " << dstAddr );
+
+ myDstAddr.GetBytes (bufTwo);
+ bool isDstDst = (memcmp (bufOne + 8, bufTwo + 8, 8) == 0);
+
+ if (dstAddr.IsLinkLocal () && isDstDst )
+ {
+ hc1Header.SetDstCompression (SixLowPanHc1::HC1_PCIC);
+ }
+ else if (dstAddr.IsLinkLocal () )
+ {
+ hc1Header.SetDstCompression (SixLowPanHc1::HC1_PCII);
+ hc1Header.SetDstInterface (bufOne + 8);
+ }
+ else if ( isDstDst )
+ {
+ hc1Header.SetDstCompression (SixLowPanHc1::HC1_PIIC);
+ hc1Header.SetDstPrefix (bufOne);
+ }
+ else
+ {
+ hc1Header.SetDstCompression (SixLowPanHc1::HC1_PIII);
+ hc1Header.SetDstInterface (bufOne + 8);
+ hc1Header.SetDstPrefix (bufOne);
+ }
+
+ if ( (ipHeader.GetFlowLabel () == 0) && (ipHeader.GetTrafficClass () == 0) )
+ {
+ hc1Header.SetTcflCompression (true);
+ }
+ else
+ {
+ hc1Header.SetTcflCompression (false);
+ hc1Header.SetTrafficClass (ipHeader.GetTrafficClass ());
+ hc1Header.SetFlowLabel (ipHeader.GetFlowLabel ());
+ }
+
+ uint8_t nextHeader = ipHeader.GetNextHeader ();
+ hc1Header.SetNextHeader (nextHeader);
+
+ // \todo implement HC2 compression
+ hc1Header.SetHc2HeaderPresent (false);
+
+ NS_LOG_DEBUG ("HC1 Compression - HC1 header size = " << hc1Header.GetSerializedSize () );
+ NS_LOG_DEBUG ("HC1 Compression - packet size = " << packet->GetSize () );
+
+ packet->AddHeader (hc1Header);
+
+ return size;
+ }
+
+ return 0;
+}
+
+void
+SixLowPanNetDevice::DecompressLowPanHc1 (Ptr packet, Address const &src, Address const &dst)
+{
+ NS_LOG_FUNCTION (this << *packet << src << dst);
+
+ Ipv6Header ipHeader;
+ SixLowPanHc1 encoding;
+
+ uint32_t ret = packet->RemoveHeader (encoding);
+ NS_LOG_DEBUG ("removed " << ret << " bytes - pkt is " << *packet);
+ NS_UNUSED (ret);
+
+ ipHeader.SetHopLimit (encoding.GetHopLimit ());
+
+ switch (encoding.GetSrcCompression ())
+ {
+ const uint8_t* interface;
+ const uint8_t* prefix;
+ uint8_t address[16];
+
+ case SixLowPanHc1::HC1_PIII:
+ prefix = encoding.GetSrcPrefix ();
+ interface = encoding.GetSrcInterface ();
+ for (int j = 0; j < 8; j++)
+ {
+ address[j + 8] = interface[j];
+ address[j] = prefix[j];
+ }
+ ipHeader.SetSourceAddress ( Ipv6Address (address) );
+ break;
+ case SixLowPanHc1::HC1_PIIC:
+ prefix = encoding.GetSrcPrefix ();
+ for (int j = 0; j < 8; j++)
+ {
+ address[j + 8] = 0;
+ address[j] = prefix[j];
+ }
+ ipHeader.SetSourceAddress ( MakeGlobalAddressFromMac (src, Ipv6Address (address)));
+ break;
+ case SixLowPanHc1::HC1_PCII:
+ interface = encoding.GetSrcInterface ();
+ address[0] = 0xfe;
+ address[1] = 0x80;
+ for (int j = 0; j < 8; j++)
+ {
+ address[j + 8] = interface[j];
+ }
+ ipHeader.SetSourceAddress ( Ipv6Address (address) );
+ break;
+ case SixLowPanHc1::HC1_PCIC:
+ ipHeader.SetSourceAddress (MakeLinkLocalAddressFromMac (src));
+ break;
+ }
+
+ switch (encoding.GetDstCompression ())
+ {
+ const uint8_t* interface;
+ const uint8_t* prefix;
+ uint8_t address[16];
+
+ case SixLowPanHc1::HC1_PIII:
+ prefix = encoding.GetDstPrefix ();
+ interface = encoding.GetDstInterface ();
+ for (int j = 0; j < 8; j++)
+ {
+ address[j + 8] = interface[j];
+ address[j] = prefix[j];
+ }
+ ipHeader.SetDestinationAddress ( Ipv6Address (address) );
+ break;
+ case SixLowPanHc1::HC1_PIIC:
+ prefix = encoding.GetDstPrefix ();
+ for (int j = 0; j < 8; j++)
+ {
+ address[j + 8] = 0;
+ address[j] = prefix[j];
+ }
+ ipHeader.SetDestinationAddress ( MakeGlobalAddressFromMac (dst, Ipv6Address (address)));
+ break;
+ case SixLowPanHc1::HC1_PCII:
+ interface = encoding.GetDstInterface ();
+ address[0] = 0xfe;
+ address[1] = 0x80;
+ for (int j = 0; j < 8; j++)
+ {
+ address[j + 8] = interface[j];
+ }
+ ipHeader.SetDestinationAddress ( Ipv6Address (address) );
+ break;
+ case SixLowPanHc1::HC1_PCIC:
+ ipHeader.SetDestinationAddress (MakeLinkLocalAddressFromMac (dst));
+ break;
+ }
+
+ if ( !encoding.IsTcflCompression () )
+ {
+ ipHeader.SetFlowLabel (encoding.GetFlowLabel ());
+ ipHeader.SetTrafficClass (encoding.GetTrafficClass ());
+ }
+ else
+ {
+ ipHeader.SetFlowLabel (0);
+ ipHeader.SetTrafficClass (0);
+ }
+
+ ipHeader.SetNextHeader (encoding.GetNextHeader ());
+
+ ipHeader.SetPayloadLength (packet->GetSize ());
+
+ NS_ASSERT_MSG (encoding.IsHc2HeaderPresent () == false,
+ "6LoWPAN: error in decompressing HC1 encoding, unsupported L4 compressed header present.");
+
+ packet->AddHeader (ipHeader);
+
+ NS_LOG_DEBUG ( "Rebuilt packet: " << *packet << " Size " << packet->GetSize () );
+}
+
+uint32_t
+SixLowPanNetDevice::CompressLowPanIphc (Ptr packet, Address const &src, Address const &dst)
+{
+ NS_LOG_FUNCTION (this << *packet << src << dst);
+
+ Ipv6Header ipHeader;
+ SixLowPanIphc iphcHeader;
+ uint32_t size = 0;
+
+
+ if ( packet->PeekHeader (ipHeader) != 0 )
+ {
+ packet->RemoveHeader (ipHeader);
+ size += ipHeader.GetSerializedSize ();
+
+ // Set the TF field
+ if ( (ipHeader.GetFlowLabel () == 0) && (ipHeader.GetTrafficClass () == 0) )
+ {
+ iphcHeader.SetTf (SixLowPanIphc::TF_ELIDED);
+ }
+ else if ( (ipHeader.GetFlowLabel () != 0) && (ipHeader.GetTrafficClass () != 0) )
+ {
+ iphcHeader.SetTf (SixLowPanIphc::TF_FULL);
+ iphcHeader.SetEcn ( (ipHeader.GetTrafficClass () & 0xC0) >> 6);
+ iphcHeader.SetDscp ( ipHeader.GetTrafficClass () & 0x3F );
+ iphcHeader.SetFlowLabel (ipHeader.GetFlowLabel ());
+ }
+ else if ( (ipHeader.GetFlowLabel () == 0) && (ipHeader.GetTrafficClass () != 0) )
+ {
+ iphcHeader.SetTf (SixLowPanIphc::TF_FL_ELIDED);
+ iphcHeader.SetEcn ( (ipHeader.GetTrafficClass () & 0xC0) >> 6);
+ iphcHeader.SetDscp ( ipHeader.GetTrafficClass () & 0x3F );
+ }
+ else
+ {
+ iphcHeader.SetTf (SixLowPanIphc::TF_DSCP_ELIDED);
+ iphcHeader.SetEcn ( (ipHeader.GetTrafficClass () & 0xC0) >> 6);
+ iphcHeader.SetFlowLabel (ipHeader.GetFlowLabel ());
+ }
+
+ // Set the NH field and NextHeader
+
+ uint8_t nextHeader = ipHeader.GetNextHeader ();
+ if (CanCompressLowPanNhc (nextHeader))
+ {
+ if (nextHeader == Ipv6Header::IPV6_UDP)
+ {
+ iphcHeader.SetNh (true);
+ size += CompressLowPanUdpNhc (packet, m_omitUdpChecksum);
+ }
+ else if (nextHeader == Ipv6Header::IPV6_IPV6)
+ {
+ iphcHeader.SetNh (true);
+ size += CompressLowPanIphc (packet, src, dst);
+ }
+ else
+ {
+ uint32_t sizeNhc = CompressLowPanNhc (packet, nextHeader, src, dst);
+ // the compression might fail due to Extension header size.
+ if (sizeNhc)
+ {
+ iphcHeader.SetNh (true);
+ size += sizeNhc;
+ }
+ else
+ {
+ iphcHeader.SetNh (false);
+ iphcHeader.SetNextHeader (nextHeader);
+ }
+ }
+ }
+ else
+ {
+ iphcHeader.SetNh (false);
+ iphcHeader.SetNextHeader (nextHeader);
+ }
+
+
+ // Set the HLIM field
+ if (ipHeader.GetHopLimit () == 1)
+ {
+ iphcHeader.SetHlim (SixLowPanIphc::HLIM_COMPR_1);
+ }
+ else if (ipHeader.GetHopLimit () == 0x40)
+ {
+ iphcHeader.SetHlim (SixLowPanIphc::HLIM_COMPR_64);
+ }
+ else if (ipHeader.GetHopLimit () == 0xFF)
+ {
+ iphcHeader.SetHlim (SixLowPanIphc::HLIM_COMPR_255);
+ }
+ else
+ {
+ iphcHeader.SetHlim (SixLowPanIphc::HLIM_INLINE);
+ // Set the HopLimit
+ iphcHeader.SetHopLimit (ipHeader.GetHopLimit ());
+ }
+
+ // \todo Add the check of CID if there is context-based compression
+ // Set the CID field
+ iphcHeader.SetCid (false);
+
+ // \todo Add the check of SAC if there is context-based compression
+ // Set the SAC field
+ iphcHeader.SetSac (false);
+
+ uint8_t addressBuf[16];
+ uint8_t unicastAddrCheckerBuf[16];
+ Ipv6Address srcAddr = ipHeader.GetSourceAddress ();
+ srcAddr.GetBytes (addressBuf);
+
+ Ipv6Address checker = Ipv6Address ("fe80:0000:0000:0000:0000:00ff:fe00:1");
+ checker.GetBytes (unicastAddrCheckerBuf);
+
+ // \todo Add the check of SAC if there is context-based compression
+ // Set the Source Address
+ iphcHeader.SetSrcAddress (srcAddr);
+
+ Ipv6Address mySrcAddr = MakeLinkLocalAddressFromMac (src);
+ NS_LOG_LOGIC ("Checking source compression: " << mySrcAddr << " - " << srcAddr );
+
+ if ( mySrcAddr == srcAddr )
+ {
+ iphcHeader.SetSam (SixLowPanIphc::HC_COMPR_0);
+ }
+ else if (memcmp (addressBuf, unicastAddrCheckerBuf, 14) == 0)
+ {
+ iphcHeader.SetSam (SixLowPanIphc::HC_COMPR_16);
+ }
+ else if ( srcAddr.IsLinkLocal () )
+ {
+ iphcHeader.SetSam (SixLowPanIphc::HC_COMPR_64);
+ }
+ else
+ {
+ iphcHeader.SetSam (SixLowPanIphc::HC_INLINE);
+ }
+
+ // Set the M field
+ if (ipHeader.GetDestinationAddress ().IsMulticast ())
+ {
+ iphcHeader.SetM (true);
+ }
+ else
+ {
+ iphcHeader.SetM (false);
+ }
+
+ // \todo Add the check of DAC if there is context-based compression
+ // Set the DAC field
+ iphcHeader.SetDac (false);
+
+ Ipv6Address dstAddr = ipHeader.GetDestinationAddress ();
+ dstAddr.GetBytes (addressBuf);
+
+ // \todo Add the check of DAC if there is context-based compression
+ // Set the Destination Address
+ iphcHeader.SetDstAddress (dstAddr);
+
+ Ipv6Address myDstAddr = MakeLinkLocalAddressFromMac (dst);
+ NS_LOG_LOGIC ("Checking destination compression: " << myDstAddr << " - " << dstAddr );
+
+ if ( !iphcHeader.GetM () )
+ // Unicast address
+ {
+ if ( myDstAddr == dstAddr )
+ {
+ iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_0);
+ }
+ else if (memcmp (addressBuf, unicastAddrCheckerBuf, 14) == 0)
+ {
+ iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_16);
+ }
+ else if ( dstAddr.IsLinkLocal () )
+ {
+ iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_64);
+ }
+ else
+ {
+ iphcHeader.SetDam (SixLowPanIphc::HC_INLINE);
+ }
+ }
+ else
+ {
+ // Multicast address
+ uint8_t multicastAddrCheckerBuf[16];
+ Ipv6Address multicastCheckAddress = Ipv6Address ("ff02::1");
+ multicastCheckAddress.GetBytes (multicastAddrCheckerBuf);
+
+ // The address takes the form ff02::00XX.
+ if ( memcmp (addressBuf, multicastAddrCheckerBuf, 15) == 0 )
+ {
+ iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_0);
+ }
+ // The address takes the form ffXX::00XX:XXXX.
+ // ffXX:0000:0000:0000:0000:0000:00XX:XXXX.
+ else if ( (addressBuf[0] == multicastAddrCheckerBuf[0])
+ && (memcmp (addressBuf + 2, multicastAddrCheckerBuf + 2, 11) ) )
+ {
+ iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_16);
+ }
+ // The address takes the form ffXX::00XX:XXXX:XXXX.
+ // ffXX:0000:0000:0000:0000:00XX:XXXX:XXXX.
+ else if ( (addressBuf[0] == multicastAddrCheckerBuf[0])
+ && (memcmp (addressBuf + 2, multicastAddrCheckerBuf + 2, 9) ) )
+ {
+ iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_64);
+ }
+ else
+ {
+ iphcHeader.SetDam (SixLowPanIphc::HC_INLINE);
+ }
+ }
+
+ NS_LOG_DEBUG ("IPHC Compression - IPHC header size = " << iphcHeader.GetSerializedSize () );
+ NS_LOG_DEBUG ("IPHC Compression - packet size = " << packet->GetSize () );
+
+ packet->AddHeader (iphcHeader);
+
+ NS_LOG_DEBUG ("Packet after IPHC compression: " << *packet);
+
+ return size;
+ }
+
+ return 0;
+}
+
+bool
+SixLowPanNetDevice::CanCompressLowPanNhc (uint8_t nextHeader)
+{
+ bool ret = false;
+
+ switch (nextHeader)
+ {
+ case Ipv6Header::IPV6_UDP:
+ case Ipv6Header::IPV6_EXT_HOP_BY_HOP:
+ case Ipv6Header::IPV6_EXT_ROUTING:
+ case Ipv6Header::IPV6_EXT_FRAGMENTATION:
+ case Ipv6Header::IPV6_IPV6:
+ ret = true;
+ break;
+ case Ipv6Header::IPV6_EXT_MOBILITY:
+ default:
+ ret = false;
+ }
+ return ret;
+}
+
+void
+SixLowPanNetDevice::DecompressLowPanIphc (Ptr packet, Address const &src, Address const &dst)
+{
+ NS_LOG_FUNCTION (this << *packet << src << dst);
+
+ Ipv6Header ipHeader;
+ SixLowPanIphc encoding;
+
+ uint32_t ret = packet->RemoveHeader (encoding);
+ NS_LOG_DEBUG ("removed " << ret << " bytes - pkt is " << *packet);
+ NS_UNUSED (ret);
+
+ // Hop Limit
+ ipHeader.SetHopLimit (encoding.GetHopLimit ());
+
+ // Source address
+ if ( encoding.GetSac () )
+ {
+ if ( encoding.GetSam () == SixLowPanIphc::HC_INLINE )
+ {
+ ipHeader.SetSourceAddress ( Ipv6Address::GetAny () );
+ }
+ else
+ {
+ NS_ABORT_MSG ("SAC option not yet implemented");
+ }
+ }
+ else
+ {
+ if ( encoding.GetSam () == SixLowPanIphc::HC_COMPR_0 )
+ {
+ ipHeader.SetSourceAddress (MakeLinkLocalAddressFromMac (src));
+ }
+ else
+ {
+ ipHeader.SetSourceAddress ( encoding.GetSrcAddress () );
+ }
+ }
+ // Destination address
+ if ( encoding.GetDac () )
+ {
+ if ((encoding.GetDam () == SixLowPanIphc::HC_INLINE && !encoding.GetM ())
+ || (encoding.GetDam () == SixLowPanIphc::HC_COMPR_64 && encoding.GetM ())
+ || (encoding.GetDam () == SixLowPanIphc::HC_COMPR_16 && encoding.GetM ())
+ || (encoding.GetDam () == SixLowPanIphc::HC_COMPR_0 && encoding.GetM ()) )
+ {
+ NS_ABORT_MSG ("Reserved code found");
+ }
+ else
+ {
+ NS_ABORT_MSG ("DAC option not yet implemented");
+ }
+ }
+ else
+ {
+ if ( !encoding.GetM () && encoding.GetDam () == SixLowPanIphc::HC_COMPR_0 )
+ {
+ ipHeader.SetDestinationAddress (MakeLinkLocalAddressFromMac (dst));
+ }
+ else
+ {
+ ipHeader.SetDestinationAddress ( encoding.GetDstAddress () );
+ }
+ }
+
+ // Traffic class and Flow Label
+ uint8_t traf = 0x00;
+ switch (encoding.GetTf ())
+ {
+ case SixLowPanIphc::TF_FULL:
+ traf |= encoding.GetEcn ();
+ traf = ( traf << 6 ) | encoding.GetDscp ();
+ ipHeader.SetTrafficClass (traf);
+ ipHeader.SetFlowLabel ( encoding.GetFlowLabel () & 0xfff ); //Add 4-bit pad
+ break;
+ case SixLowPanIphc::TF_DSCP_ELIDED:
+ traf |= encoding.GetEcn ();
+ traf <<= 2; // Add 2-bit pad
+ ipHeader.SetTrafficClass (traf);
+ ipHeader.SetFlowLabel (encoding.GetFlowLabel ());
+ break;
+ case SixLowPanIphc::TF_FL_ELIDED:
+ traf |= encoding.GetEcn ();
+ traf = ( traf << 6 ) | encoding.GetDscp ();
+ ipHeader.SetTrafficClass (traf);
+ ipHeader.SetFlowLabel (0);
+ break;
+ case SixLowPanIphc::TF_ELIDED:
+ ipHeader.SetFlowLabel (0);
+ ipHeader.SetTrafficClass (0);
+ break;
+ }
+
+ if ( encoding.GetNh () )
+ {
+ // Next Header
+ uint8_t dispatchRawVal = 0;
+ SixLowPanDispatch::NhcDispatch_e dispatchVal;
+
+ packet->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
+ dispatchVal = SixLowPanDispatch::GetNhcDispatchType (dispatchRawVal);
+
+ if (dispatchVal == SixLowPanDispatch::LOWPAN_UDPNHC)
+ {
+ ipHeader.SetNextHeader (Ipv6Header::IPV6_UDP);
+ DecompressLowPanUdpNhc (packet, ipHeader.GetSourceAddress (), ipHeader.GetDestinationAddress ());
+ }
+ else
+ {
+ ipHeader.SetNextHeader (DecompressLowPanNhc (packet, src, dst, ipHeader.GetSourceAddress (), ipHeader.GetDestinationAddress ()));
+ }
+ }
+ else
+ {
+ ipHeader.SetNextHeader (encoding.GetNextHeader ());
+ }
+
+ ipHeader.SetPayloadLength (packet->GetSize ());
+
+ packet->AddHeader (ipHeader);
+
+ NS_LOG_DEBUG ( "Rebuilt packet: " << *packet << " Size " << packet->GetSize () );
+
+}
+
+uint32_t
+SixLowPanNetDevice::CompressLowPanNhc (Ptr packet, uint8_t headerType, Address const &src, Address const &dst)
+{
+ NS_LOG_FUNCTION (this << *packet << int(headerType));
+
+ SixLowPanNhcExtension nhcHeader;
+ uint32_t size = 0;
+ Buffer blob;
+
+ if (headerType == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
+ {
+ Ipv6ExtensionHopByHopHeader hopHeader;
+ packet->PeekHeader (hopHeader);
+ if (hopHeader.GetLength () >= 0xff)
+ {
+ NS_LOG_DEBUG ("LOWPAN_NHC MUST NOT be used to encode IPv6 Extension Headers "
+ "that have more than 255 octets following the Length field after compression. "
+ "Packet uncompressed.");
+ return 0;
+ }
+
+ size += packet->RemoveHeader (hopHeader);
+ nhcHeader.SetEid (SixLowPanNhcExtension::EID_HOPBYHOP_OPTIONS_H);
+
+ // recursively compress other headers
+ uint8_t nextHeader = hopHeader.GetNextHeader ();
+ if (CanCompressLowPanNhc (nextHeader))
+ {
+ if (nextHeader == Ipv6Header::IPV6_UDP)
+ {
+ nhcHeader.SetNh (true);
+ size += CompressLowPanUdpNhc (packet, m_omitUdpChecksum);
+ }
+ else if (nextHeader == Ipv6Header::IPV6_IPV6)
+ {
+ nhcHeader.SetNh (true);
+ size += CompressLowPanIphc (packet, src, dst);
+ }
+ else
+ {
+ uint32_t sizeNhc = CompressLowPanNhc (packet, nextHeader, src, dst);
+ // the compression might fail due to Extension header size.
+ if (sizeNhc)
+ {
+ nhcHeader.SetNh (true);
+ size += sizeNhc;
+ }
+ else
+ {
+ nhcHeader.SetNh (false);
+ nhcHeader.SetNextHeader (nextHeader);
+ }
+ }
+ }
+ else
+ {
+ nhcHeader.SetNh (false);
+ nhcHeader.SetNextHeader (nextHeader);
+ }
+
+ uint32_t blobSize = hopHeader.GetSerializedSize ();
+ blob.AddAtStart (blobSize);
+ hopHeader.Serialize (blob.Begin ());
+ blob.RemoveAtStart (2);
+ blobSize = blob.GetSize ();
+ nhcHeader.SetBlob (blob.PeekData (), blobSize);
+ }
+ else if (headerType == Ipv6Header::IPV6_EXT_ROUTING)
+ {
+ Ipv6ExtensionRoutingHeader routingHeader;
+ packet->PeekHeader (routingHeader);
+ if (routingHeader.GetLength () >= 0xff)
+ {
+ NS_LOG_DEBUG ("LOWPAN_NHC MUST NOT be used to encode IPv6 Extension Headers "
+ "that have more than 255 octets following the Length field after compression. "
+ "Packet uncompressed.");
+ return 0;
+ }
+
+ size += packet->RemoveHeader (routingHeader);
+ nhcHeader.SetEid (SixLowPanNhcExtension::EID_ROUTING_H);
+
+ // recursively compress other headers
+ uint8_t nextHeader = routingHeader.GetNextHeader ();
+ if (CanCompressLowPanNhc (nextHeader))
+ {
+ if (nextHeader == Ipv6Header::IPV6_UDP)
+ {
+ nhcHeader.SetNh (true);
+ size += CompressLowPanUdpNhc (packet, m_omitUdpChecksum);
+ }
+ else if (nextHeader == Ipv6Header::IPV6_IPV6)
+ {
+ nhcHeader.SetNh (true);
+ size += CompressLowPanIphc (packet, src, dst);
+ }
+ else
+ {
+ uint32_t sizeNhc = CompressLowPanNhc (packet, nextHeader, src, dst);
+ // the compression might fail due to Extension header size.
+ if (sizeNhc)
+ {
+ nhcHeader.SetNh (true);
+ size += sizeNhc;
+ }
+ else
+ {
+ nhcHeader.SetNh (false);
+ nhcHeader.SetNextHeader (nextHeader);
+ }
+ }
+ }
+ else
+ {
+ nhcHeader.SetNh (false);
+ nhcHeader.SetNextHeader (nextHeader);
+ }
+
+ uint32_t blobSize = routingHeader.GetSerializedSize ();
+ blob.AddAtStart (blobSize);
+ routingHeader.Serialize (blob.Begin ());
+ blob.RemoveAtStart (2);
+ blobSize = blob.GetSize ();
+ nhcHeader.SetBlob (blob.PeekData (), blobSize);
+ }
+ else if (headerType == Ipv6Header::IPV6_EXT_FRAGMENTATION)
+ {
+ Ipv6ExtensionFragmentHeader fragHeader;
+ packet->PeekHeader (fragHeader);
+ if (fragHeader.GetLength () >= 0xff)
+ {
+ NS_LOG_DEBUG ("LOWPAN_NHC MUST NOT be used to encode IPv6 Extension Headers "
+ "that have more than 255 octets following the Length field after compression. "
+ "Packet uncompressed.");
+ return 0;
+ }
+ size += packet->RemoveHeader (fragHeader);
+ nhcHeader.SetEid (SixLowPanNhcExtension::EID_FRAGMENTATION_H);
+
+ // recursively compress other headers
+ uint8_t nextHeader = fragHeader.GetNextHeader ();
+ if (CanCompressLowPanNhc (nextHeader))
+ {
+ if (nextHeader == Ipv6Header::IPV6_UDP)
+ {
+ nhcHeader.SetNh (true);
+ size += CompressLowPanUdpNhc (packet, m_omitUdpChecksum);
+ }
+ else if (nextHeader == Ipv6Header::IPV6_IPV6)
+ {
+ nhcHeader.SetNh (true);
+ size += CompressLowPanIphc (packet, src, dst);
+ }
+ else
+ {
+ uint32_t sizeNhc = CompressLowPanNhc (packet, nextHeader, src, dst);
+ // the compression might fail due to Extension header size.
+ if (sizeNhc)
+ {
+ nhcHeader.SetNh (true);
+ size += sizeNhc;
+ }
+ else
+ {
+ nhcHeader.SetNh (false);
+ nhcHeader.SetNextHeader (nextHeader);
+ }
+ }
+ }
+ else
+ {
+ nhcHeader.SetNh (false);
+ nhcHeader.SetNextHeader (nextHeader);
+ }
+
+ uint32_t blobSize = fragHeader.GetSerializedSize ();
+ blob.AddAtStart (blobSize);
+ fragHeader.Serialize (blob.Begin ());
+ blob.RemoveAtStart (2);
+ blobSize = blob.GetSize ();
+ nhcHeader.SetBlob (blob.PeekData (), blobSize);
+ }
+ else if (headerType == Ipv6Header::IPV6_EXT_DESTINATION)
+ {
+ Ipv6ExtensionDestinationHeader destHeader;
+ packet->PeekHeader (destHeader);
+ if (destHeader.GetLength () >= 0xff)
+ {
+ NS_LOG_DEBUG ("LOWPAN_NHC MUST NOT be used to encode IPv6 Extension Headers "
+ "that have more than 255 octets following the Length field after compression. "
+ "Packet uncompressed.");
+ return 0;
+ }
+ size += packet->RemoveHeader (destHeader);
+ nhcHeader.SetEid (SixLowPanNhcExtension::EID_DESTINATION_OPTIONS_H);
+
+ // recursively compress other headers
+ uint8_t nextHeader = destHeader.GetNextHeader ();
+ if (CanCompressLowPanNhc (nextHeader))
+ {
+ if (nextHeader == Ipv6Header::IPV6_UDP)
+ {
+ nhcHeader.SetNh (true);
+ size += CompressLowPanUdpNhc (packet, m_omitUdpChecksum);
+ }
+ else if (nextHeader == Ipv6Header::IPV6_IPV6)
+ {
+ nhcHeader.SetNh (true);
+ size += CompressLowPanIphc (packet, src, dst);
+ }
+ else
+ {
+ uint32_t sizeNhc = CompressLowPanNhc (packet, nextHeader, src, dst);
+ // the compression might fail due to Extension header size.
+ if (sizeNhc)
+ {
+ nhcHeader.SetNh (true);
+ size += sizeNhc;
+ }
+ else
+ {
+ nhcHeader.SetNh (false);
+ nhcHeader.SetNextHeader (nextHeader);
+ }
+ }
+ }
+ else
+ {
+ nhcHeader.SetNh (false);
+ nhcHeader.SetNextHeader (nextHeader);
+ }
+
+ uint32_t blobSize = destHeader.GetSerializedSize ();
+ blob.AddAtStart (blobSize);
+ destHeader.Serialize (blob.Begin ());
+ blob.RemoveAtStart (2);
+ blobSize = blob.GetSize ();
+ nhcHeader.SetBlob (blob.PeekData (), blobSize);
+ }
+ else if (headerType == Ipv6Header::IPV6_EXT_MOBILITY)
+ {
+ // \todo: IPv6 Mobility Header is not supported in ns-3
+ NS_ABORT_MSG ("IPv6 Mobility Header is not supported in ns-3 yet");
+ return 0;
+ }
+ else
+ {
+ NS_ABORT_MSG ("Unexpected Extension Header");
+ }
+
+ NS_LOG_DEBUG ("NHC Compression - NHC header size = " << nhcHeader.GetSerializedSize () );
+ NS_LOG_DEBUG ("NHC Compression - packet size = " << packet->GetSize () );
+
+ packet->AddHeader (nhcHeader);
+
+ NS_LOG_DEBUG ("Packet after NHC compression: " << *packet);
+ return size;
+}
+
+uint8_t
+SixLowPanNetDevice::DecompressLowPanNhc (Ptr packet, Address const &src, Address const &dst, Ipv6Address srcAddress, Ipv6Address dstAddress)
+{
+ NS_LOG_FUNCTION (this << *packet);
+
+ SixLowPanNhcExtension encoding;
+
+ uint32_t ret = packet->RemoveHeader (encoding);
+ NS_LOG_DEBUG ("removed " << ret << " bytes - pkt is " << *packet);
+ NS_UNUSED (ret);
+
+ Ipv6ExtensionHopByHopHeader hopHeader;
+ Ipv6ExtensionRoutingHeader routingHeader;
+ Ipv6ExtensionFragmentHeader fragHeader;
+ Ipv6ExtensionDestinationHeader destHeader;
+
+ uint32_t blobSize;
+ uint8_t blobData[260];
+ blobSize = encoding.CopyBlob (blobData + 2, 260);
+ uint8_t paddingSize = 0;
+
+ uint8_t actualEncodedHeaderType = encoding.GetEid ();
+ uint8_t actualHeaderType;
+ Buffer blob;
+
+ switch (actualEncodedHeaderType)
+ {
+ case SixLowPanNhcExtension::EID_HOPBYHOP_OPTIONS_H:
+ actualHeaderType = Ipv6Header::IPV6_EXT_HOP_BY_HOP;
+ if ( encoding.GetNh () )
+ {
+ // Next Header
+ uint8_t dispatchRawVal = 0;
+ SixLowPanDispatch::NhcDispatch_e dispatchVal;
+
+ packet->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
+ dispatchVal = SixLowPanDispatch::GetNhcDispatchType (dispatchRawVal);
+
+ if (dispatchVal == SixLowPanDispatch::LOWPAN_UDPNHC)
+ {
+ blobData [0] = Ipv6Header::IPV6_UDP;
+ DecompressLowPanUdpNhc (packet, srcAddress, dstAddress);
+ }
+ else
+ {
+ blobData [0] = DecompressLowPanNhc (packet, src, dst, srcAddress, dstAddress);
+ }
+ }
+ else
+ {
+ blobData [0] = encoding.GetNextHeader ();
+ }
+
+ // manually add some padding if needed
+ if ((blobSize + 2) % 8 > 0)
+ {
+ paddingSize = 8 - (blobSize + 2) % 8;
+ }
+ if (paddingSize == 1)
+ {
+ blobData[blobSize + 2] = 0;
+ }
+ else if (paddingSize > 1)
+ {
+ blobData[blobSize + 2] = 1;
+ blobData[blobSize + 2 + 1] = paddingSize - 2;
+ for (uint8_t i = 0; i < paddingSize - 2; i++)
+ {
+ blobData[blobSize + 2 + 2 + i] = 0;
+ }
+ }
+ blobData [1] = ((blobSize + 2 + paddingSize) >> 3) - 1;
+ blob.AddAtStart (blobSize + 2 + paddingSize);
+ blob.Begin ().Write (blobData, blobSize + 2 + paddingSize);
+ hopHeader.Deserialize (blob.Begin ());
+
+ packet->AddHeader (hopHeader);
+ break;
+
+ case SixLowPanNhcExtension::EID_ROUTING_H:
+ actualHeaderType = Ipv6Header::IPV6_EXT_ROUTING;
+ if ( encoding.GetNh () )
+ {
+ // Next Header
+ uint8_t dispatchRawVal = 0;
+ SixLowPanDispatch::NhcDispatch_e dispatchVal;
+
+ packet->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
+ dispatchVal = SixLowPanDispatch::GetNhcDispatchType (dispatchRawVal);
+
+ if (dispatchVal == SixLowPanDispatch::LOWPAN_UDPNHC)
+ {
+ blobData [0] = Ipv6Header::IPV6_UDP;
+ DecompressLowPanUdpNhc (packet, srcAddress, dstAddress);
+ }
+ else
+ {
+ blobData [0] = DecompressLowPanNhc (packet, src, dst, srcAddress, dstAddress);
+ }
+ }
+ else
+ {
+ blobData [0] = encoding.GetNextHeader ();
+ }
+ blobData [1] = ((blobSize + 2) >> 3) - 1;
+ blob.AddAtStart (blobSize + 2);
+ blob.Begin ().Write (blobData, blobSize + 2);
+ routingHeader.Deserialize (blob.Begin ());
+ packet->AddHeader (routingHeader);
+ break;
+
+ case SixLowPanNhcExtension::EID_FRAGMENTATION_H:
+ actualHeaderType = Ipv6Header::IPV6_EXT_FRAGMENTATION;
+ if ( encoding.GetNh () )
+ {
+ // Next Header
+ uint8_t dispatchRawVal = 0;
+ SixLowPanDispatch::NhcDispatch_e dispatchVal;
+
+ packet->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
+ dispatchVal = SixLowPanDispatch::GetNhcDispatchType (dispatchRawVal);
+
+ if (dispatchVal == SixLowPanDispatch::LOWPAN_UDPNHC)
+ {
+ blobData [0] = Ipv6Header::IPV6_UDP;
+ DecompressLowPanUdpNhc (packet, srcAddress, dstAddress);
+ }
+ else
+ {
+ blobData [0] = DecompressLowPanNhc (packet, src, dst, srcAddress, dstAddress);
+ }
+ }
+ else
+ {
+ blobData [0] = encoding.GetNextHeader ();
+ }
+ blobData [1] = 0;
+ fragHeader.Deserialize (blob.Begin ());
+ packet->AddHeader (fragHeader);
+ break;
+
+ case SixLowPanNhcExtension::EID_DESTINATION_OPTIONS_H:
+ actualHeaderType = Ipv6Header::IPV6_EXT_DESTINATION;
+ if ( encoding.GetNh () )
+ {
+ // Next Header
+ uint8_t dispatchRawVal = 0;
+ SixLowPanDispatch::NhcDispatch_e dispatchVal;
+
+ packet->CopyData (&dispatchRawVal, sizeof(dispatchRawVal));
+ dispatchVal = SixLowPanDispatch::GetNhcDispatchType (dispatchRawVal);
+
+ if (dispatchVal == SixLowPanDispatch::LOWPAN_UDPNHC)
+ {
+ blobData [0] = Ipv6Header::IPV6_UDP;
+ DecompressLowPanUdpNhc (packet, srcAddress, dstAddress);
+ }
+ else
+ {
+ blobData [0] = DecompressLowPanNhc (packet, src, dst, srcAddress, dstAddress);
+ }
+ }
+ else
+ {
+ blobData [0] = encoding.GetNextHeader ();
+ }
+
+ // manually add some padding if needed
+ if ((blobSize + 2) % 8 > 0)
+ {
+ paddingSize = 8 - (blobSize + 2) % 8;
+ }
+ if (paddingSize == 1)
+ {
+ blobData[blobSize + 2] = 0;
+ }
+ else if (paddingSize > 1)
+ {
+ blobData[blobSize + 2] = 1;
+ blobData[blobSize + 2 + 1] = paddingSize - 2;
+ for (uint8_t i = 0; i < paddingSize - 2; i++)
+ {
+ blobData[blobSize + 2 + 2 + i] = 0;
+ }
+ }
+ blobData [1] = ((blobSize + 2 + paddingSize) >> 3) - 1;
+ blob.AddAtStart (blobSize + 2 + paddingSize);
+ blob.Begin ().Write (blobData, blobSize + 2 + paddingSize);
+ destHeader.Deserialize (blob.Begin ());
+
+ packet->AddHeader (destHeader);
+ break;
+ case SixLowPanNhcExtension::EID_MOBILITY_H:
+ // \todo: IPv6 Mobility Header is not supported in ns-3
+ NS_ABORT_MSG ("IPv6 Mobility Header is not supported in ns-3 yet");
+ break;
+ case SixLowPanNhcExtension::EID_IPv6_H:
+ actualHeaderType = Ipv6Header::IPV6_IPV6;
+ DecompressLowPanIphc (packet, src, dst);
+ break;
+ default:
+ NS_ABORT_MSG ("Trying to decode unknown Extension Header");
+ break;
+ }
+
+ NS_LOG_DEBUG ( "Rebuilt packet: " << *packet << " Size " << packet->GetSize () );
+ return actualHeaderType;
+}
+
+uint32_t
+SixLowPanNetDevice::CompressLowPanUdpNhc (Ptr packet, bool omitChecksum)
+{
+ NS_LOG_FUNCTION (this << *packet << int(omitChecksum));
+
+ UdpHeader udpHeader;
+ SixLowPanUdpNhcExtension udpNhcHeader;
+ uint32_t size = 0;
+
+ NS_ASSERT_MSG (packet->PeekHeader (udpHeader) != 0, "UDP header not found, abort");
+
+ size += packet->RemoveHeader (udpHeader);
+
+ // Set the C field and checksum
+ udpNhcHeader.SetC (false);
+ uint16_t checksum = udpHeader.GetChecksum ();
+ udpNhcHeader.SetChecksum (checksum);
+
+ if (omitChecksum && udpHeader.IsChecksumOk ())
+ {
+ udpNhcHeader.SetC (true);
+ }
+
+ // Set the value of the ports
+ udpNhcHeader.SetSrcPort (udpHeader.GetSourcePort ());
+ udpNhcHeader.SetDstPort (udpHeader.GetDestinationPort ());
+
+ //Set the P field
+ if ( (udpHeader.GetSourcePort () >> 4 ) == 0xf0b && (udpHeader.GetDestinationPort () >> 4 ) == 0xf0b )
+ {
+ udpNhcHeader.SetPorts (SixLowPanUdpNhcExtension::PORTS_LAST_SRC_LAST_DST);
+ }
+ else if ( (udpHeader.GetSourcePort () >> 8 ) == 0xf0 && (udpHeader.GetDestinationPort () >> 8 ) != 0xf0 )
+ {
+ udpNhcHeader.SetPorts (SixLowPanUdpNhcExtension::PORTS_LAST_SRC_ALL_DST);
+ }
+ else if ( (udpHeader.GetSourcePort () >> 8 ) != 0xf0 && (udpHeader.GetDestinationPort () >> 8 ) == 0xf0 )
+ {
+ udpNhcHeader.SetPorts (SixLowPanUdpNhcExtension::PORTS_ALL_SRC_LAST_DST);
+ }
+ else
+ {
+ udpNhcHeader.SetPorts (SixLowPanUdpNhcExtension::PORTS_INLINE);
+ }
+
+ NS_LOG_DEBUG ("UDP_NHC Compression - UDP_NHC header size = " << udpNhcHeader.GetSerializedSize () );
+ NS_LOG_DEBUG ("UDP_NHC Compression - packet size = " << packet->GetSize () );
+
+ packet->AddHeader (udpNhcHeader);
+
+ NS_LOG_DEBUG ("Packet after UDP_NHC compression: " << *packet);
+
+ return size;
+}
+
+void
+SixLowPanNetDevice::DecompressLowPanUdpNhc (Ptr packet, Ipv6Address saddr, Ipv6Address daddr)
+{
+ NS_LOG_FUNCTION (this << *packet);
+
+ UdpHeader udpHeader;
+ SixLowPanUdpNhcExtension encoding;
+
+ uint32_t ret = packet->RemoveHeader (encoding);
+ NS_LOG_DEBUG ("removed " << ret << " bytes - pkt is " << *packet);
+ NS_UNUSED (ret);
+
+ // Set the value of the ports
+ switch ( encoding.GetPorts () )
+ {
+ uint16_t temp;
+ case SixLowPanUdpNhcExtension::PORTS_INLINE:
+ udpHeader.SetSourcePort (encoding.GetSrcPort ());
+ udpHeader.SetDestinationPort (encoding.GetDstPort ());
+ break;
+ case SixLowPanUdpNhcExtension::PORTS_ALL_SRC_LAST_DST:
+ udpHeader.SetSourcePort (encoding.GetSrcPort ());
+ temp = 0xf0;
+ temp |= (temp << 8) | encoding.GetDstPort ();
+ udpHeader.SetDestinationPort (temp);
+ break;
+ case SixLowPanUdpNhcExtension::PORTS_LAST_SRC_ALL_DST:
+ temp = 0xf0;
+ temp |= (temp << 8) | encoding.GetSrcPort ();
+ udpHeader.SetSourcePort (temp);
+ udpHeader.SetDestinationPort (encoding.GetDstPort ());
+ break;
+ case SixLowPanUdpNhcExtension::PORTS_LAST_SRC_LAST_DST:
+ temp = 0xf0b;
+ temp |= (temp << 4) | encoding.GetSrcPort ();
+ udpHeader.SetSourcePort (temp);
+ temp = 0xf0b;
+ temp |= (temp << 4) | encoding.GetDstPort ();
+ udpHeader.SetDestinationPort (temp);
+ break;
+ }
+
+ // Get the C field and checksum
+ if (Node::ChecksumEnabled ())
+ {
+ if ( encoding.GetC () )
+ {
+ NS_LOG_LOGIC ("Recalculating UDP Checksum");
+ udpHeader.EnableChecksums ();
+ udpHeader.InitializeChecksum (saddr,
+ daddr,
+ UdpL4Protocol::PROT_NUMBER);
+ packet->AddHeader (udpHeader);
+ }
+ else
+ {
+ NS_LOG_LOGIC ("Forcing UDP Checksum to " << encoding.GetChecksum ());
+ udpHeader.ForceChecksum (encoding.GetChecksum ());
+ packet->AddHeader (udpHeader);
+ NS_LOG_LOGIC ("UDP checksum is ok ? " << udpHeader.IsChecksumOk ());
+ }
+ }
+ else
+ {
+ packet->AddHeader (udpHeader);
+ }
+
+ NS_LOG_DEBUG ( "Rebuilt packet: " << *packet << " Size " << packet->GetSize () );
+}
+
+void SixLowPanNetDevice::DoFragmentation (Ptr packet,
+ uint32_t origPacketSize,
+ uint32_t origHdrSize,
+ std::list >& listFragments)
+{
+ NS_LOG_FUNCTION (this << *packet);
+
+ Ptr p = packet->Copy ();
+
+ uint16_t offsetData = 0;
+ uint16_t offset = 0;
+ uint16_t l2Mtu = m_netDevice->GetMtu ();
+ uint32_t packetSize = packet->GetSize ();
+ uint32_t compressedHeaderSize = packetSize - (origPacketSize - origHdrSize);
+
+ uint16_t tag = uint16_t (m_rng->GetValue (0, 65535));
+ NS_LOG_LOGIC ("random tag " << tag << " - test " << packetSize );
+
+ // first fragment
+ SixLowPanFrag1 frag1Hdr;
+ frag1Hdr.SetDatagramTag (tag);
+
+ uint32_t size;
+ NS_ASSERT_MSG ( l2Mtu > frag1Hdr.GetSerializedSize (),
+ "6LoWPAN: can not fragment, 6LoWPAN headers are bigger than MTU");
+
+ size = l2Mtu - frag1Hdr.GetSerializedSize () - compressedHeaderSize;
+ size -= size % 8;
+ size += compressedHeaderSize;
+
+ frag1Hdr.SetDatagramSize (origPacketSize);
+
+ Ptr fragment1 = p->CreateFragment (offsetData, size);
+ offset += size + origHdrSize - compressedHeaderSize;
+ offsetData += size;
+
+ fragment1->AddHeader (frag1Hdr);
+ listFragments.push_back (fragment1);
+
+ bool moreFrag = true;
+ do
+ {
+ SixLowPanFragN fragNHdr;
+ fragNHdr.SetDatagramTag (tag);
+ fragNHdr.SetDatagramSize (origPacketSize);
+ fragNHdr.SetDatagramOffset ((offset) >> 3);
+
+ size = l2Mtu - fragNHdr.GetSerializedSize ();
+ size -= size % 8;
+
+ if ( (offsetData + size) > packetSize )
+ {
+ size = packetSize - offsetData;
+ moreFrag = false;
+ }
+
+ NS_LOG_LOGIC ("Fragment creation - " << offset << ", " << offset );
+ Ptr fragment = p->CreateFragment (offsetData, size);
+ NS_LOG_LOGIC ("Fragment created - " << offset << ", " << fragment->GetSize () );
+
+ offset += size;
+ offsetData += size;
+
+ fragment->AddHeader (fragNHdr);
+ listFragments.push_back (fragment);
+
+ }
+ while (moreFrag);
+
+ return;
+}
+
+bool SixLowPanNetDevice::ProcessFragment (Ptr& packet, Address const &src, Address const &dst, bool isFirst)
+{
+ NS_LOG_FUNCTION ( this << *packet );
+ SixLowPanFrag1 frag1Header;
+ SixLowPanFragN fragNHeader;
+ FragmentKey key;
+ uint16_t packetSize;
+ key.first = std::pair (src, dst);
+
+ Ptr p = packet->Copy ();
+ uint16_t offset = 0;
+
+ /* Implementation note:
+ *
+ * The fragment offset is relative to the *uncompressed* packet.
+ * On the other hand, the packet can not be uncompressed correctly without all
+ * its fragments, as the UDP checksum can not be computed otherwise.
+ *
+ * As a consequence we must uncompress the packet twice, and save its first
+ * fragment for the final one.
+ */
+
+ if ( isFirst )
+ {
+ uint8_t dispatchRawValFrag1 = 0;
+ SixLowPanDispatch::Dispatch_e dispatchValFrag1;
+
+ p->RemoveHeader (frag1Header);
+ packetSize = frag1Header.GetDatagramSize ();
+ p->CopyData (&dispatchRawValFrag1, sizeof(dispatchRawValFrag1));
+ dispatchValFrag1 = SixLowPanDispatch::GetDispatchType (dispatchRawValFrag1);
+ NS_LOG_DEBUG ( "Dispatches: " << int(dispatchRawValFrag1) << " - " << int(dispatchValFrag1) );
+ NS_LOG_DEBUG ( "Packet: " << *p );
+
+ switch ( dispatchValFrag1 )
+ {
+ case SixLowPanDispatch::LOWPAN_NOTCOMPRESSED:
+ NS_LOG_DEBUG ( "Packet without compression:" << *p );
+ NS_LOG_DEBUG ( "Packet length:" << p->GetSize () );
+ break;
+ case SixLowPanDispatch::LOWPAN_HC1:
+ DecompressLowPanHc1 (p, src, dst);
+ break;
+ case SixLowPanDispatch::LOWPAN_IPHC:
+ DecompressLowPanIphc (p, src, dst);
+ break;
+ default:
+ NS_FATAL_ERROR ("Unsupported 6LoWPAN encoding, exiting.");
+ break;
+ }
+
+ key.second = std::pair (frag1Header.GetDatagramSize (), frag1Header.GetDatagramTag ());
+ }
+ else
+ {
+ p->RemoveHeader (fragNHeader);
+ packetSize = fragNHeader.GetDatagramSize ();
+ offset = fragNHeader.GetDatagramOffset () << 3;
+ key.second = std::pair (fragNHeader.GetDatagramSize (), fragNHeader.GetDatagramTag ());
+ }
+
+ Ptr fragments;
+
+ MapFragments_t::iterator it = m_fragments.find (key);
+ if (it == m_fragments.end ())
+ {
+ // erase the oldest packet.
+ if ( m_fragmentReassemblyListSize && (m_fragments.size () >= m_fragmentReassemblyListSize) )
+ {
+ MapFragmentsTimers_t::iterator iter;
+ MapFragmentsTimers_t::iterator iterFound = m_fragmentsTimers.begin ();
+ for ( iter = m_fragmentsTimers.begin (); iter != m_fragmentsTimers.end (); iter++)
+ {
+ if ( iter->second.GetTs () < iterFound->second.GetTs () )
+ {
+ iterFound = iter;
+ }
+ }
+ FragmentKey oldestKey = iterFound->first;
+
+ std::list< Ptr > storedFragments = m_fragments[oldestKey]->GetFraments ();
+ for (std::list< Ptr >::iterator fragIter = storedFragments.begin ();
+ fragIter != storedFragments.end (); fragIter++)
+ {
+ m_dropTrace (DROP_FRAGMENT_BUFFER_FULL, *fragIter, m_node->GetObject (), GetIfIndex ());
+ }
+
+ m_fragmentsTimers[oldestKey].Cancel ();
+ m_fragmentsTimers.erase (oldestKey);
+ m_fragments[oldestKey] = 0;
+ m_fragments.erase (oldestKey);
+
+ }
+ fragments = Create ();
+ fragments->SetPacketSize (packetSize);
+ m_fragments.insert (std::make_pair (key, fragments));
+ uint32_t ifIndex = GetIfIndex ();
+ m_fragmentsTimers[key] = Simulator::Schedule (m_fragmentExpirationTimeout,
+ &SixLowPanNetDevice::HandleFragmentsTimeout, this,
+ key, ifIndex);
+ }
+ else
+ {
+ fragments = it->second;
+ }
+
+ fragments->AddFragment (p, offset);
+
+ // add the very first fragment so we can correctly decode the packet once is rebuilt.
+ // this is needed because otherwise the UDP header length and checksum can not be calculated.
+ if ( isFirst )
+ {
+ fragments->AddFirstFragment (packet);
+ }
+
+ if ( fragments->IsEntire () )
+ {
+ packet = fragments->GetPacket ();
+ NS_LOG_LOGIC ("Reconstructed packet: " << *packet);
+
+ SixLowPanFrag1 frag1Header;
+ packet->RemoveHeader (frag1Header);
+
+ NS_LOG_LOGIC ("Rebuilt packet. Size " << packet->GetSize () << " - " << *packet);
+ fragments = 0;
+ m_fragments.erase (key);
+ if (m_fragmentsTimers[key].IsRunning ())
+ {
+ NS_LOG_LOGIC ("Stopping 6LoWPAN WaitFragmentsTimer at " << Simulator::Now ().GetSeconds () << " due to complete packet");
+ m_fragmentsTimers[key].Cancel ();
+ }
+ m_fragmentsTimers.erase (key);
+ return true;
+ }
+
+ return false;
+}
+
+SixLowPanNetDevice::Fragments::Fragments ()
+{
+ NS_LOG_FUNCTION (this);
+ m_packetSize = 0;
+}
+
+SixLowPanNetDevice::Fragments::~Fragments ()
+{
+ NS_LOG_FUNCTION (this);
+}
+
+void SixLowPanNetDevice::Fragments::AddFragment (Ptr fragment, uint16_t fragmentOffset)
+{
+ NS_LOG_FUNCTION (this << fragmentOffset << *fragment);
+
+ std::list, uint16_t> >::iterator it;
+ bool duplicate = false;
+
+ for (it = m_fragments.begin (); it != m_fragments.end (); it++)
+ {
+ if (it->second > fragmentOffset)
+ {
+ break;
+ }
+ if (it->second == fragmentOffset)
+ {
+ duplicate = true;
+ NS_ASSERT_MSG (fragment->GetSize () == it->first->GetSize (), "Duplicate fragment size differs. Aborting.");
+ break;
+ }
+ }
+ if (!duplicate)
+ {
+ m_fragments.insert (it, std::make_pair, uint16_t> (fragment, fragmentOffset));
+ }
+}
+
+void SixLowPanNetDevice::Fragments::AddFirstFragment (Ptr fragment)
+{
+ NS_LOG_FUNCTION (this << *fragment);
+
+ m_firstFragment = fragment;
+}
+
+bool SixLowPanNetDevice::Fragments::IsEntire () const
+{
+ NS_LOG_FUNCTION (this);
+
+ bool ret = m_fragments.size () > 0;
+ uint16_t lastEndOffset = 0;
+
+ if (ret)
+ {
+ for (std::list, uint16_t> >::const_iterator it = m_fragments.begin (); it != m_fragments.end (); it++)
+ {
+ // overlapping fragments should not exist
+ NS_LOG_LOGIC ("Checking overlaps " << lastEndOffset << " - " << it->second );
+
+ if (lastEndOffset < it->second)
+ {
+ ret = false;
+ break;
+ }
+ // fragments might overlap in strange ways
+ uint16_t fragmentEnd = it->first->GetSize () + it->second;
+ lastEndOffset = std::max ( lastEndOffset, fragmentEnd );
+ }
+ }
+
+ if ( ret && (lastEndOffset == m_packetSize))
+ {
+ return true;
+ }
+ return false;
+}
+
+Ptr SixLowPanNetDevice::Fragments::GetPacket () const
+{
+ NS_LOG_FUNCTION (this);
+
+ std::list, uint16_t> >::const_iterator it = m_fragments.begin ();
+
+ Ptr p = Create ();
+ uint16_t lastEndOffset = 0;
+
+ p->AddAtEnd (m_firstFragment);
+ it = m_fragments.begin ();
+ lastEndOffset = it->first->GetSize ();
+
+ for ( it++; it != m_fragments.end (); it++)
+ {
+ if ( lastEndOffset > it->second )
+ {
+ NS_ABORT_MSG ("Overlapping fragments found, forbidden condition");
+ }
+ else
+ {
+ NS_LOG_LOGIC ("Adding: " << *(it->first) );
+ p->AddAtEnd (it->first);
+ }
+ lastEndOffset += it->first->GetSize ();
+ }
+
+ return p;
+}
+
+void SixLowPanNetDevice::Fragments::SetPacketSize (uint32_t packetSize)
+{
+ NS_LOG_FUNCTION (this << packetSize);
+ m_packetSize = packetSize;
+}
+
+std::list< Ptr > SixLowPanNetDevice::Fragments::GetFraments () const
+{
+ std::list< Ptr > fragments;
+ std::list, uint16_t> >::const_iterator iter;
+ for ( iter = m_fragments.begin (); iter != m_fragments.end (); iter ++)
+ {
+ fragments.push_back (iter->first);
+ }
+ return fragments;
+}
+
+void SixLowPanNetDevice::HandleFragmentsTimeout (FragmentKey key, uint32_t iif)
+{
+ NS_LOG_FUNCTION (this);
+
+ MapFragments_t::iterator it = m_fragments.find (key);
+ std::list< Ptr > storedFragments = it->second->GetFraments ();
+ for (std::list< Ptr >::iterator fragIter = storedFragments.begin ();
+ fragIter != storedFragments.end (); fragIter++)
+ {
+ m_dropTrace (DROP_FRAGMENT_TIMEOUT, *fragIter, m_node->GetObject (), iif);
+ }
+ // clear the buffers
+ it->second = 0;
+
+ m_fragments.erase (key);
+ m_fragmentsTimers.erase (key);
+}
+
+Ipv6Address SixLowPanNetDevice::MakeLinkLocalAddressFromMac (Address const &addr)
+{
+ Ipv6Address ipv6Addr = Ipv6Address::GetAny ();
+
+ if (m_forceEtherType && Mac48Address::IsMatchingType (addr))
+ {
+ ipv6Addr = Ipv6Address::MakeAutoconfiguredLinkLocalAddress (Mac48Address::ConvertFrom (addr));
+ }
+ else
+ {
+ if (Mac64Address::IsMatchingType (addr))
+ {
+ ipv6Addr = Ipv6Address::MakeAutoconfiguredLinkLocalAddress (Mac64Address::ConvertFrom (addr));
+ }
+ else if (Mac16Address::IsMatchingType (addr))
+ {
+ ipv6Addr = Ipv6Address::MakeAutoconfiguredLinkLocalAddress (Mac16Address::ConvertFrom (addr));
+ }
+ }
+ if (ipv6Addr.IsAny ())
+ {
+ NS_ABORT_MSG ("Unknown address type");
+ }
+ return ipv6Addr;
+}
+
+Ipv6Address SixLowPanNetDevice::MakeGlobalAddressFromMac (Address const &addr, Ipv6Address prefix)
+{
+ Ipv6Address ipv6Addr = Ipv6Address::GetAny ();
+
+ if (m_forceEtherType && Mac48Address::IsMatchingType (addr))
+ {
+ ipv6Addr = Ipv6Address::MakeAutoconfiguredAddress (Mac48Address::ConvertFrom (addr), Ipv6Address (prefix) );
+ }
+ else
+ {
+ if (Mac64Address::IsMatchingType (addr))
+ {
+ ipv6Addr = Ipv6Address::MakeAutoconfiguredAddress (Mac64Address::ConvertFrom (addr), Ipv6Address (prefix));
+ }
+ else if (Mac16Address::IsMatchingType (addr))
+ {
+ ipv6Addr = Ipv6Address::MakeAutoconfiguredAddress (Mac16Address::ConvertFrom (addr), Ipv6Address (prefix) );
+ }
+ }
+ if (ipv6Addr.IsAny ())
+ {
+ NS_ABORT_MSG ("Unknown address type");
+ }
+ return ipv6Addr;
+}
+
+}
+
+// namespace ns3
diff --git a/src/sixlowpan/model/sixlowpan-net-device.h b/src/sixlowpan/model/sixlowpan-net-device.h
new file mode 100644
index 000000000..4b5b069cc
--- /dev/null
+++ b/src/sixlowpan/model/sixlowpan-net-device.h
@@ -0,0 +1,455 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013 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
+ * Michele Muccio
+ */
+
+#ifndef SIXLOWPAN_NET_DEVICE_H
+#define SIXLOWPAN_NET_DEVICE_H
+
+#include
+#include
+#include