6LoWPAN module
authorTommaso Pecorella <tommaso.pecorella@unifi.it>
Sat, 07 Dec 2013 08:08:53 +0100
changeset 10479 fc4ee8106e4a
parent 10478 dc507f7d14a4
child 10480 223927c63666
6LoWPAN module
AUTHORS
CHANGES.html
RELEASE_NOTES
doc/models/Makefile
src/internet/model/udp-header.cc
src/internet/model/udp-header.h
src/sixlowpan/doc/sixlowpan.rst
src/sixlowpan/examples/example-sixlowpan.cc
src/sixlowpan/examples/wscript
src/sixlowpan/helper/sixlowpan-helper.cc
src/sixlowpan/helper/sixlowpan-helper.h
src/sixlowpan/model/sixlowpan-header.cc
src/sixlowpan/model/sixlowpan-header.h
src/sixlowpan/model/sixlowpan-net-device.cc
src/sixlowpan/model/sixlowpan-net-device.h
src/sixlowpan/test/error-channel-sixlow.cc
src/sixlowpan/test/error-channel-sixlow.h
src/sixlowpan/test/sixlowpan-fragmentation-test.cc
src/sixlowpan/test/sixlowpan-hc1-test.cc
src/sixlowpan/test/sixlowpan-iphc-test.cc
src/sixlowpan/wscript
--- a/AUTHORS	Fri Dec 06 13:37:03 2013 -0800
+++ b/AUTHORS	Sat Dec 07 08:08:53 2013 +0100
@@ -81,6 +81,7 @@
 Faker Moatamri (faker.moatamri@inria.fr)
 Edvin Močibob <edvin.mocibob@gmail.com>
 Mike Moreton (mjvm_ns@hotmail.com)
+Michele Muccio <michelemuccio@virgilio.it>
 Sidharth Nabar (snabar@uw.edu)
 Hemanth Narra (hemanth@ittc.ku.edu)
 Andreas Nilsson <andrnils@gmail.com>
--- a/CHANGES.html	Fri Dec 06 13:37:03 2013 -0800
+++ b/CHANGES.html	Sat Dec 07 08:08:53 2013 +0100
@@ -80,6 +80,15 @@
       their simulation program. The imlpementation previously
       provided by the EpcHelper class has been moved to the new
       derived class PointToPointEpcHelper.</li>
+    <li>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
+      <a href="http://www.ietf.org/rfc/rfc4944.txt">RFC 4944</a> and
+      <a href="http://www.ietf.org/rfc/rfc6262.txt">RFC 6262</a>), 
+      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.</li>
 </ul>
 <h2>Changes to build system:</h2>
 
--- a/RELEASE_NOTES	Fri Dec 06 13:37:03 2013 -0800
+++ b/RELEASE_NOTES	Sat Dec 07 08:08:53 2013 +0100
@@ -21,6 +21,12 @@
 
 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
--- a/doc/models/Makefile	Fri Dec 06 13:37:03 2013 -0800
+++ b/doc/models/Makefile	Sat Dec 07 08:08:53 2013 +0100
@@ -79,6 +79,7 @@
 	$(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
--- a/src/internet/model/udp-header.cc	Fri Dec 06 13:37:03 2013 -0800
+++ b/src/internet/model/udp-header.cc	Sat Dec 07 08:08:53 2013 +0100
@@ -33,7 +33,8 @@
 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 @@
 
   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 @@
       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 @@
   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 @@
 
   i.WriteHtonU16 (m_sourcePort);
   i.WriteHtonU16 (m_destinationPort);
-  i.WriteHtonU16 (start.GetSize ());
-  i.WriteU16 (0);
+  if (m_payloadSize == 0)
+    {
+      i.WriteHtonU16 (start.GetSize ());
+    }
+  else
+    {
+      i.WriteHtonU16 (m_payloadSize);
+    }
 
-  if (m_calcChecksum)
+  if ( m_checksum == 0)
     {
-      uint16_t headerChecksum = CalculateHeaderChecksum (start.GetSize ());
-      i = start;
-      uint16_t checksum = i.CalculateIpChecksum (start.GetSize (), headerChecksum);
+      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);
+          i = start;
+          i.Next (6);
+          i.WriteU16 (checksum);
+        }
+    }
+  else
+    {
+      i.WriteU16 (m_checksum);
     }
 }
 uint32_t
@@ -196,9 +223,9 @@
   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 @@
   return GetSerializedSize ();
 }
 
+uint16_t
+UdpHeader::GetChecksum ()
+{
+  return m_checksum;
+}
 
 } // namespace ns3
--- a/src/internet/model/udp-header.h	Fri Dec 06 13:37:03 2013 -0800
+++ b/src/internet/model/udp-header.h	Sat Dec 07 08:08:53 2013 +0100
@@ -131,6 +131,41 @@
    */
   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 @@
   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
 };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sixlowpan/doc/sixlowpan.rst	Sat Dec 07 08:08:53 2013 +0100
@@ -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.
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sixlowpan/examples/example-sixlowpan.cc	Sat Dec 07 08:08:53 2013 +0100
@@ -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 <tommaso.pecorella@unifi.it>
+ */
+
+
+// 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 <fstream>
+#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<Node> n0 = CreateObject<Node> ();
+  Ptr<Node> r = CreateObject<Node> ();
+  Ptr<Node> n1 = CreateObject<Node> ();
+
+
+  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.");
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sixlowpan/examples/wscript	Sat Dec 07 08:08:53 2013 +0100
@@ -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'
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sixlowpan/helper/sixlowpan-helper.cc	Sat Dec 07 08:08:53 2013 +0100
@@ -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 <tommaso.pecorella@unifi.it>
+ */
+
+#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<NetDevice> device = c.Get (i);
+      NS_ASSERT_MSG (device != 0, "No NetDevice found in the node " << int(i) );
+
+      Ptr<Node> node = device->GetNode ();
+      NS_LOG_LOGIC ("**** Install 6LoWPAN on node " << node->GetId ());
+
+      Ptr<SixLowPanNetDevice> dev = m_deviceFactory.Create<SixLowPanNetDevice> ();
+      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> netDevice;
+  for (NetDeviceContainer::Iterator i = c.Begin (); i != c.End (); ++i)
+    {
+      netDevice = (*i);
+      Ptr<SixLowPanNetDevice> dev = DynamicCast<SixLowPanNetDevice> (netDevice);
+      if (dev)
+        {
+          currentStream += dev->AssignStreams (currentStream);
+        }
+    }
+  return (currentStream - stream);
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sixlowpan/helper/sixlowpan-helper.h	Sat Dec 07 08:08:53 2013 +0100
@@ -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 <tommaso.pecorella@unifi.it>
+ */
+
+#ifndef SIXLOWPAN_HELPER_H
+#define SIXLOWPAN_HELPER_H
+
+#include "ns3/net-device-container.h"
+#include "ns3/object-factory.h"
+#include <string>
+
+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 */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sixlowpan/model/sixlowpan-header.cc	Sat Dec 07 08:08:53 2013 +0100
@@ -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 <tommaso.pecorella@unifi.it>
+ *         Michele Muccio <michelemuccio@virgilio.it>
+ */
+
+#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<Header> ().AddConstructor<SixLowPanHc1> ();
+  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<Header> ().AddConstructor<SixLowPanFrag1> ();
+  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<Header> ().AddConstructor<SixLowPanFragN> ();
+  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<Header> ().AddConstructor<SixLowPanIphc> ();
+  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<Header> ()
+    .AddConstructor<SixLowPanNhcExtension> ();
+  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<Header> ()
+    .AddConstructor<SixLowPanUdpNhcExtension> ();
+  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;
+}
+
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sixlowpan/model/sixlowpan-header.h	Sat Dec 07 08:08:53 2013 +0100
@@ -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 <tommaso.pecorella@unifi.it>
+ *         Michele Muccio <michelemuccio@virgilio.it>
+ */
+
+#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_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sixlowpan/model/sixlowpan-net-device.cc	Sat Dec 07 08:08:53 2013 +0100
@@ -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 <tommaso.pecorella@unifi.it>
+ *         Michele Muccio <michelemuccio@virgilio.it>
+ */
+
+#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<NetDevice> ()
+    .AddConstructor<SixLowPanNetDevice> ()
+    .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<uint16_t> ())
+    .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<uint16_t> ())
+    .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<UniformRandomVariable> ();
+}
+
+Ptr<NetDevice> SixLowPanNetDevice::GetNetDevice () const
+{
+  NS_LOG_FUNCTION (this);
+  return m_netDevice;
+}
+
+void SixLowPanNetDevice::SetNetDevice (Ptr<NetDevice> 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<NetDevice> incomingPort,
+                                            Ptr<const Packet> 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<Packet> copyPkt = packet->Copy ();
+
+  m_rxTrace (copyPkt, m_node->GetObject<SixLowPanNetDevice> (), 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<SixLowPanNetDevice> (), GetIfIndex ());
+      break;
+    case SixLowPanDispatch::LOWPAN_BC0:
+      NS_LOG_DEBUG ("Unsupported 6LoWPAN encoding: BC0, dropping.");
+      m_dropTrace (DROP_UNKNOWN_EXTENSION, copyPkt, m_node->GetObject<SixLowPanNetDevice> (), GetIfIndex ());
+      break;
+    case SixLowPanDispatch::LOWPAN_NOTCOMPRESSED:
+      NS_LOG_DEBUG ( "Packet without compression:" << *copyPkt );
+      NS_LOG_DEBUG ( "Packet length:" << copyPkt->GetSize () );
+      m_dropTrace (DROP_UNKNOWN_EXTENSION, copyPkt, m_node->GetObject<SixLowPanNetDevice> (), 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<SixLowPanNetDevice> (), 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<Channel> 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<void> 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> 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<Ptr<Packet> > fragmentList;
+      DoFragmentation (packet, origPacketSize, origHdrSize, fragmentList);
+      std::list<Ptr<Packet> >::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<SixLowPanNetDevice> (), 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<SixLowPanNetDevice> (), GetIfIndex ());
+      ret = m_netDevice->Send (packet, dest, protocolNumber);
+    }
+
+  return ret;
+}
+
+bool SixLowPanNetDevice::SendFrom (Ptr<Packet> 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<Ptr<Packet> > fragmentList;
+      DoFragmentation (packet, origPacketSize, origHdrSize, fragmentList);
+      std::list<Ptr<Packet> >::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<SixLowPanNetDevice> (), GetIfIndex ());
+          err |= !(m_netDevice->SendFrom (*it, src, dest, protocolNumber));
+        }
+      ret = !err;
+    }
+  else
+    {
+      NS_LOG_DEBUG ( "SixLowPanNetDevice::SendFrom " << *packet );
+      m_txTrace (packet, m_node->GetObject<SixLowPanNetDevice> (), GetIfIndex ());
+      ret = m_netDevice->SendFrom (packet, src, dest, protocolNumber);
+    }
+
+  return ret;
+}
+
+Ptr<Node> SixLowPanNetDevice::GetNode (void) const
+{
+  NS_LOG_FUNCTION (this);
+  return m_node;
+}
+
+void SixLowPanNetDevice::SetNode (Ptr<Node> 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> 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> 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> 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> 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> 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> 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> 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> 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> packet,
+                                          uint32_t origPacketSize,
+                                          uint32_t origHdrSize,
+                                          std::list<Ptr<Packet> >& listFragments)
+{
+  NS_LOG_FUNCTION (this << *packet);
+
+  Ptr<Packet> 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<Packet> 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<Packet> 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>& 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<Address, Address> (src, dst);
+
+  Ptr<Packet> 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<uint16_t, uint16_t> (frag1Header.GetDatagramSize (), frag1Header.GetDatagramTag ());
+    }
+  else
+    {
+      p->RemoveHeader (fragNHeader);
+      packetSize = fragNHeader.GetDatagramSize ();
+      offset = fragNHeader.GetDatagramOffset () << 3;
+      key.second = std::pair<uint16_t, uint16_t> (fragNHeader.GetDatagramSize (), fragNHeader.GetDatagramTag ());
+    }
+
+  Ptr<Fragments> 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<Packet> > storedFragments = m_fragments[oldestKey]->GetFraments ();
+          for (std::list< Ptr<Packet> >::iterator fragIter = storedFragments.begin ();
+               fragIter != storedFragments.end (); fragIter++)
+            {
+              m_dropTrace (DROP_FRAGMENT_BUFFER_FULL, *fragIter, m_node->GetObject<SixLowPanNetDevice> (), GetIfIndex ());
+            }
+
+          m_fragmentsTimers[oldestKey].Cancel ();
+          m_fragmentsTimers.erase (oldestKey);
+          m_fragments[oldestKey] = 0;
+          m_fragments.erase (oldestKey);
+
+        }
+      fragments = Create<Fragments> ();
+      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<Packet> fragment, uint16_t fragmentOffset)
+{
+  NS_LOG_FUNCTION (this << fragmentOffset << *fragment);
+
+  std::list<std::pair<Ptr<Packet>, 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<Ptr<Packet>, uint16_t> (fragment, fragmentOffset));
+    }
+}
+
+void SixLowPanNetDevice::Fragments::AddFirstFragment (Ptr<Packet> 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<std::pair<Ptr<Packet>, 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<Packet> SixLowPanNetDevice::Fragments::GetPacket () const
+{
+  NS_LOG_FUNCTION (this);
+
+  std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.begin ();
+
+  Ptr<Packet> p = Create<Packet> ();
+  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<Packet> > SixLowPanNetDevice::Fragments::GetFraments () const
+{
+  std::list< Ptr<Packet> > fragments;
+  std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator iter;
+  for ( iter = m_fragments.begin (); iter != m_fragments.end (); iter ++)
+    {
+      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<Packet> > storedFragments = it->second->GetFraments ();
+  for (std::list< Ptr<Packet> >::iterator fragIter = storedFragments.begin ();
+       fragIter != storedFragments.end (); fragIter++)
+    {
+      m_dropTrace (DROP_FRAGMENT_TIMEOUT, *fragIter, m_node->GetObject<SixLowPanNetDevice> (), 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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sixlowpan/model/sixlowpan-net-device.h	Sat Dec 07 08:08:53 2013 +0100
@@ -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 <tommaso.pecorella@unifi.it>
+ *         Michele Muccio <michelemuccio@virgilio.it>
+ */
+
+#ifndef SIXLOWPAN_NET_DEVICE_H
+#define SIXLOWPAN_NET_DEVICE_H
+
+#include <stdint.h>
+#include <string>
+#include <map>
+#include "ns3/traced-callback.h"
+#include "ns3/event-id.h"
+#include "ns3/nstime.h"
+#include "ns3/net-device.h"
+#include "ns3/packet.h"
+#include "sixlowpan-header.h"
+#include "ns3/random-variable-stream.h"
+
+namespace ns3 {
+
+class Node;
+
+/**
+ * \defgroup sixlowpan 6LoWPAN
+ * \brief Performs 6LoWPAN compression of IPv6 packets as specified by RFC 4944 and RFC 6262
+ *
+ * This module acts as a shim between IPv6 and a generic NetDevice.
+ *
+ * The module implements RFCs 4944 and 6262, with the following exceptions:
+ * <ul>
+ * <li> MESH and LOWPAN_BC0 dispatch types are not supported </li>
+ * <li> HC2 encoding is not supported </li>
+ * <li> IPHC's SAC and DAC are not supported </li>
+ *</ul>
+ */
+
+/**
+ * \ingroup sixlowpan
+ *
+ * \brief Shim performing 6LoWPAN compression, decompression and fragmentation.
+ *
+ * This class implements the shim between IPv6 and a generic NetDevice,
+ * performing packet compression, decompression and fragmentation in a transparent way.
+ * To this end, the class pretend to be a normal NetDevice, masquerading some functions
+ * of the underlying NetDevice.
+ */
+class SixLowPanNetDevice : public NetDevice
+{
+public:
+  /**
+   * Enumeration of the dropping reasons in SixLoWPAN.
+   */
+  enum DropReason
+  {
+    DROP_FRAGMENT_TIMEOUT = 1, /**< Fragment timeout exceeded */
+    DROP_FRAGMENT_BUFFER_FULL, /**< Fragment buffer size exceeded */
+    DROP_UNKNOWN_EXTENSION /**< Unsupported compression kind */
+  };
+
+  /**
+   * \brief Get the type ID.
+   * \return the object TypeId
+   */
+  static TypeId GetTypeId (void);
+
+  /**
+   * Constructor for the SixLowPanNetDevice.
+   */
+  SixLowPanNetDevice ();
+
+  // inherited from NetDevice base class
+  virtual void SetIfIndex (const uint32_t index);
+  virtual uint32_t GetIfIndex (void) const;
+  virtual Ptr<Channel> GetChannel (void) const;
+  virtual void SetAddress (Address address);
+  virtual Address GetAddress (void) const;
+  virtual bool SetMtu (const uint16_t mtu);
+
+  /**
+   * \brief Returns the link-layer MTU for this interface.
+   * If the link-layer MTU is smaller than IPv6's minimum MTU (RFC 4944),
+   * 1280 will be returned.
+   *
+   * \return the link-level MTU in bytes for this interface.
+   */
+  virtual uint16_t GetMtu (void) const;
+  virtual bool IsLinkUp (void) const;
+  virtual void AddLinkChangeCallback (Callback<void> callback);
+  virtual bool IsBroadcast (void) const;
+  virtual Address GetBroadcast (void) const;
+  virtual bool IsMulticast (void) const;
+  virtual Address GetMulticast (Ipv4Address multicastGroup) const;
+  virtual bool IsPointToPoint (void) const;
+  virtual bool IsBridge (void) const;
+  virtual bool Send (Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber);
+  virtual bool SendFrom (Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber);
+  virtual Ptr<Node> GetNode (void) const;
+  virtual void SetNode (Ptr<Node> node);
+  virtual bool NeedsArp (void) const;
+  virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb);
+  virtual void SetPromiscReceiveCallback (NetDevice::PromiscReceiveCallback cb);
+  virtual bool SupportsSendFrom () const;
+  virtual Address GetMulticast (Ipv6Address addr) const;
+
+  /**
+   * \brief Returns a smart pointer to the underlying NetDevice.
+   *
+   * \return a smart pointer to the underlying NetDevice.
+   */
+  Ptr<NetDevice> GetNetDevice () const;
+
+  /**
+   * \brief Setup SixLowPan to be a proxy for the specified NetDevice.
+   * All the packets incoming and outgoing from the NetDevice will be
+   * processed by SixLowPanNetDevice.
+   *
+   * \param device a smart pointer to the NetDevice to be proxied.
+   */
+  void SetNetDevice (Ptr<NetDevice> device);
+
+  /**
+   * 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.
+   *
+   * \param stream first stream index to use
+   * \return the number of stream indices assigned by this model
+   */
+  int64_t AssignStreams (int64_t stream);
+
+protected:
+  virtual void DoDispose (void);
+
+private:
+  /**
+   * \brief receives all the packets from a NetDevice for further processing.
+   * \param device the NetDevice the packet ws received from
+   * \param packet the received packet
+   * \param protocol the protocol (if known)
+   * \param source the source address
+   * \param destination the destination address
+   * \param packetType the packet kind (e.g., HOST, BROADCAST, etc.)
+   * \return the IPv6 link-local address
+   */
+  void ReceiveFromDevice (Ptr<NetDevice> device, Ptr<const Packet> packet, uint16_t protocol,
+                          Address const &source, Address const &destination, PacketType packetType);
+
+  /**
+   * The callback used to notify higher layers that a packet has been received.
+   */
+  NetDevice::ReceiveCallback m_rxCallback;
+
+  /**
+   * The callback used to notify higher layers that a packet has been received in promiscuous mode.
+   */
+  NetDevice::PromiscReceiveCallback m_promiscRxCallback;
+
+  /**
+   * \brief Callback to trace TX (transmission) packets.
+   *
+   * Data passed:
+   * \li Packet received (including 6LoWPAN header)
+   * \li Ptr to SixLowPanNetDevice
+   * \li interface index
+   */
+  TracedCallback<Ptr<const Packet>, Ptr<SixLowPanNetDevice>, uint32_t> m_txTrace;
+
+  /**
+   * \brief Callback to trace RX (reception) packets.
+   *
+   * Data passed:
+   * \li Packet received (including 6LoWPAN header)
+   * \li Ptr to SixLowPanNetDevice
+   * \li interface index
+   */
+  TracedCallback<Ptr<const Packet>, Ptr<SixLowPanNetDevice>, uint32_t> m_rxTrace;
+
+  /**
+   * \brief Callback to trace drop packets.
+   *
+   * Data passed:
+   * \li DropReason
+   * \li Packet dropped (including 6LoWPAN header)
+   * \li Ptr to SixLowPanNetDevice
+   * \li interface index
+   */
+  TracedCallback<DropReason, Ptr<const Packet>, Ptr<SixLowPanNetDevice>, uint32_t> m_dropTrace;
+
+  /**
+   * \brief make a link-local address from a MAC address.
+   * \param addr the MAC address
+   * \return the IPv6 link-local address
+   */
+  Ipv6Address MakeLinkLocalAddressFromMac (Address const &addr);
+
+  /**
+   * \brief make a global address from a MAC address.
+   * \param addr the MAC address
+   * \param prefix the address prefix
+   * \return the IPv6 address
+   */
+  Ipv6Address MakeGlobalAddressFromMac (Address const &addr, Ipv6Address prefix);
+
+  /**
+   * \brief Compress the headers according to HC1 compression.
+   * \param packet the packet to be compressed
+   * \param src the MAC source address
+   * \param dst the MAC destination address
+   * \return the size of the removed headers
+   */
+  uint32_t CompressLowPanHc1 (Ptr<Packet> packet, Address const &src, Address const &dst);
+
+  /**
+   * \brief Decompress the headers according to HC1 compression.
+   * \param packet the packet to be compressed
+   * \param src the MAC source address
+   * \param dst the MAC destination address
+   */
+  void DecompressLowPanHc1 (Ptr<Packet> packet, Address const &src, Address const &dst);
+
+  /**
+   * \brief Compress the headers according to IPHC compression.
+   * \param packet the packet to be compressed
+   * \param src the MAC source address
+   * \param dst the MAC destination address
+   * \return the size of the removed headers
+   */
+  uint32_t CompressLowPanIphc (Ptr<Packet> packet, Address const &src, Address const &dst);
+
+  /**
+   * \brief Checks if the next header can be compressed using NHC.
+   * \param headerType the header kind to be compressed
+   * \return true if the header can be compressed
+   */
+  bool CanCompressLowPanNhc (uint8_t headerType);
+
+  /**
+   * \brief Decompress the headers according to IPHC compression.
+   * \param packet the packet to be compressed
+   * \param src the MAC source address
+   * \param dst the MAC destination address
+   */
+  void DecompressLowPanIphc (Ptr<Packet> packet, Address const &src, Address const &dst);
+
+  /**
+   * \brief Compress the headers according to NHC compression.
+   * \param packet the packet to be compressed
+   * \param headerType the header type
+   * \param src the MAC source address
+   * \param dst the MAC destination address
+   * \return the size of the removed headers
+   */
+  uint32_t CompressLowPanNhc (Ptr<Packet> packet, uint8_t headerType, Address const &src, Address const &dst);
+
+  /**
+   * \brief Decompress the headers according to NHC compression.
+   * \param packet the packet to be compressed
+   * \param src the MAC source address
+   * \param dst the MAC destination address
+   * \param srcAddress the IPv6 source address
+   * \param dstAddress the IPv6 destination address
+   * \return the decompressed header type
+   */
+  uint8_t DecompressLowPanNhc (Ptr<Packet> packet, Address const &src, Address const &dst, Ipv6Address srcAddress, Ipv6Address dstAddress);
+
+  /**
+   * \brief Compress the headers according to NHC compression.
+   * \param packet the packet to be compressed
+   * \param omitChecksum omit UDP checksum (if true)
+   * \return the size of the removed headers
+   */
+  uint32_t CompressLowPanUdpNhc (Ptr<Packet> packet, bool omitChecksum);
+
+  /**
+   * \brief Decompress the headers according to NHC compression.
+   * \param packet the packet to be compressed
+   * \param saddr the IPv6 source address
+   * \param daddr the IPv6 destination address
+   */
+  void DecompressLowPanUdpNhc (Ptr<Packet> packet, Ipv6Address saddr, Ipv6Address daddr);
+
+  /**
+   * Fragment identifier type: src/dst address src/dst port
+   */
+  typedef std::pair< std::pair<Address, Address>, std::pair<uint16_t, uint16_t> > FragmentKey;
+
+  /**
+   * \class Fragments
+   * \brief A Set of Fragment
+   */
+  class Fragments : public SimpleRefCount<Fragments>
+  {
+public:
+    /**
+     * \brief Constructor.
+     */
+    Fragments ();
+
+    /**
+     * \brief Destructor.
+     */
+    ~Fragments ();
+
+    /**
+     * \brief Add a fragment to the pool.
+     * \param fragment the fragment
+     * \param fragmentOffset the offset of the fragment
+     */
+    void AddFragment (Ptr<Packet> fragment, uint16_t fragmentOffset);
+
+    /**
+     * \brief Add the first packet fragment. The first fragment is needed to
+     * allow the post-defragmentation decompression.
+     * \param fragment the fragment
+     */
+    void AddFirstFragment (Ptr<Packet> fragment);
+
+    /**
+     * \brief If all fragments have been added.
+     * \returns true if the packet is entire
+     */
+    bool IsEntire () const;
+
+    /**
+     * \brief Get the entire packet.
+     * \return the entire packet
+     */
+    Ptr<Packet> GetPacket () const;
+
+    /**
+     * \brief Set the packet-to-be-defragmented size.
+     * \param packetSize the packet size (bytes)
+     */
+    void SetPacketSize (uint32_t packetSize);
+
+    /**
+     * \brief Get a list of the current stored fragments.
+     */
+    std::list< Ptr<Packet> > GetFraments () const;
+
+private:
+    /**
+     * \brief The size of the reconstructed packet (bytes).
+     */
+    uint32_t m_packetSize;
+
+    /**
+     * \brief The current fragments.
+     */
+    std::list<std::pair<Ptr<Packet>, uint16_t> > m_fragments;
+
+    /**
+     * \brief The very first fragment
+     */
+    Ptr<Packet> m_firstFragment;
+
+  };
+
+  /**
+   * \brief Return the instance type identifier.
+   * \param packet the packet to be fragmented (with headers already compressed with 6LoWPAN)
+   * \param origPacketSize the size of the IP packet before the 6LoWPAN header compression, including the IP/L4 headers
+   * \param origHdrSize the size of the IP header before the 6LoWPAN header compression
+   * \param listFragments a reference to the list of the resulting packets, all with the proper headers in place
+   */
+  void DoFragmentation (Ptr<Packet> packet, uint32_t origPacketSize, uint32_t origHdrSize,
+                        std::list<Ptr<Packet> >& listFragments);
+
+  /**
+   * \brief Process a packet fragment
+   * \param packet the packet
+   * \param src the source MAC address
+   * \param dst the destination MAC address
+   * \param isFirst true if it is the first fragment, false otherwise
+   * \return true is the fragment completed the packet
+   */
+  bool ProcessFragment (Ptr<Packet>& packet, Address const &src, Address const &dst, bool isFirst);
+
+  /**
+   * \brief Process the timeout for packet fragments
+   * \param key representing the packet fragments
+   * \param iif Input Interface
+   */
+  void HandleFragmentsTimeout ( FragmentKey key, uint32_t iif);
+
+  /**
+   * \brief Drops the oldest fragment set
+   */
+  void DropOldestFragmentSet ();
+
+  /**
+   * Container for fragment key -> fragments
+   */
+  typedef std::map< FragmentKey, Ptr<Fragments> > MapFragments_t;
+  /**
+   * Container Iterator for fragment key -> fragments
+   */
+  typedef std::map< FragmentKey, Ptr<Fragments> >::iterator MapFragmentsI_t;
+  /**
+   * Container for fragment key -> exiration event
+   */
+  typedef std::map< FragmentKey, EventId > MapFragmentsTimers_t;
+  /**
+   * Container Iterator for fragment key -> exiration event
+   */
+  typedef std::map< FragmentKey, EventId >::iterator MapFragmentsTimersI_t;
+
+  MapFragments_t       m_fragments; /**< Fragments hold to be rebuilt */
+  MapFragmentsTimers_t m_fragmentsTimers; /**< Timers related to fragment rebuilding */
+  Time                 m_fragmentExpirationTimeout; /**< Time limit for fragment rebuilding */
+
+  /**
+   * \brief How many packets can be rebuilt at the same time.
+   * Some real implementation do limit this. Zero means no limit.
+   */
+  uint16_t             m_fragmentReassemblyListSize;
+
+  bool m_useIphc; /**< Use IPHC or HC1 */
+
+  Ptr<Node> m_node; /**< Smart pointer to the Node */
+  Ptr<NetDevice> m_netDevice; /**< Smart pointer to the underlying NetDevice */
+  uint32_t m_ifIndex; /**< Interface index */
+
+  /**
+   * \brief Force the EtherType number.
+   * Also implying that the underlying NetDevice is using 48-bit Addresses, e.g., Ethernet, WiFi, etc.
+   */
+  bool m_forceEtherType;
+
+  uint16_t m_etherType; /**< EtherType number (used only if m_forceEtherType is true) */
+  bool m_omitUdpChecksum; /**< Omit UDP checksum in NC1 encoding */
+
+  Ptr<UniformRandomVariable> m_rng; //!< Rng for the fragments tag.
+};
+
+} // namespace ns3
+
+#endif /* SIXLOWPAN_NET_DEVICE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sixlowpan/test/error-channel-sixlow.cc	Sat Dec 07 08:08:53 2013 +0100
@@ -0,0 +1,196 @@
+/* -*- 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 <tommaso.pecorella@unifi.it>
+ */
+#include "error-channel-sixlow.h"
+#include "ns3/simple-net-device.h"
+#include "ns3/simulator.h"
+#include "ns3/packet.h"
+#include "ns3/node.h"
+#include "ns3/log.h"
+
+NS_LOG_COMPONENT_DEFINE ("ErrorChannelSixlow")
+  ;
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (ErrorChannelSixlow)
+  ;
+
+TypeId
+ErrorChannelSixlow::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::ErrorChannelSixlow")
+    .SetParent<Channel> ()
+    .AddConstructor<ErrorChannelSixlow> ()
+  ;
+  return tid;
+}
+
+ErrorChannelSixlow::ErrorChannelSixlow ()
+{
+  m_jumpingTime = Seconds (0.5);
+  m_jumping = false;
+  m_jumpingState = 0;
+  m_duplicateTime = Seconds (0.1);
+  m_duplicate = false;
+}
+
+void
+ErrorChannelSixlow::SetJumpingTime (Time delay)
+{
+  m_jumpingTime = delay;
+}
+
+void
+ErrorChannelSixlow::SetJumpingMode (bool mode)
+{
+  m_jumping = mode;
+  m_jumpingState = 0;
+}
+
+void
+ErrorChannelSixlow::SetDuplicateTime (Time delay)
+{
+  m_duplicateTime = delay;
+}
+
+void
+ErrorChannelSixlow::SetDuplicateMode (bool mode)
+{
+  m_duplicate = mode;
+  m_duplicateState = 0;
+}
+
+
+void
+ErrorChannelSixlow::Send (Ptr<Packet> p, uint16_t protocol,
+                          Mac48Address to, Mac48Address from,
+                          Ptr<SimpleNetDevice> sender)
+{
+  NS_LOG_FUNCTION (p << protocol << to << from << sender);
+  for (std::vector<Ptr<SimpleNetDevice> >::const_iterator i = m_devices.begin (); i != m_devices.end (); ++i)
+    {
+      Ptr<SimpleNetDevice> tmp = *i;
+      if (tmp == sender)
+        {
+          continue;
+        }
+      if (m_jumping)
+        {
+          if (m_jumpingState % 2)
+            {
+              Simulator::ScheduleWithContext (tmp->GetNode ()->GetId (), Seconds (0),
+                                              &SimpleNetDevice::Receive, tmp, p->Copy (), protocol, to, from);
+            }
+          else
+            {
+              Simulator::ScheduleWithContext (tmp->GetNode ()->GetId (), m_jumpingTime,
+                                              &SimpleNetDevice::Receive, tmp, p->Copy (), protocol, to, from);
+            }
+          m_jumpingState++;
+        }
+      else if (m_duplicate)
+        {
+          if (m_duplicateState % 2)
+            {
+              Simulator::ScheduleWithContext (tmp->GetNode ()->GetId (), Seconds (0),
+                                              &SimpleNetDevice::Receive, tmp, p->Copy (), protocol, to, from);
+            }
+          else
+            {
+              Simulator::ScheduleWithContext (tmp->GetNode ()->GetId (), Seconds (0),
+                                              &SimpleNetDevice::Receive, tmp, p->Copy (), protocol, to, from);
+              Simulator::ScheduleWithContext (tmp->GetNode ()->GetId (), m_duplicateTime,
+                                              &SimpleNetDevice::Receive, tmp, p->Copy (), protocol, to, from);
+            }
+          m_duplicateState++;
+        }
+      else
+        {
+          Simulator::ScheduleWithContext (tmp->GetNode ()->GetId (), Seconds (0),
+                                          &SimpleNetDevice::Receive, tmp, p->Copy (), protocol, to, from);
+        }
+    }
+}
+
+void
+ErrorChannelSixlow::Add (Ptr<SimpleNetDevice> device)
+{
+  m_devices.push_back (device);
+}
+
+uint32_t
+ErrorChannelSixlow::GetNDevices (void) const
+{
+  return m_devices.size ();
+}
+Ptr<NetDevice>
+ErrorChannelSixlow::GetDevice (uint32_t i) const
+{
+  return m_devices[i];
+}
+
+NS_OBJECT_ENSURE_REGISTERED (BinaryErrorSixlowModel)
+  ;
+
+TypeId BinaryErrorSixlowModel::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::BinaryErrorSixlowModel")
+    .SetParent<ErrorModel> ()
+    .AddConstructor<BinaryErrorSixlowModel> ()
+  ;
+  return tid;
+}
+
+BinaryErrorSixlowModel::BinaryErrorSixlowModel ()
+{
+  m_counter = 0;
+}
+
+BinaryErrorSixlowModel::~BinaryErrorSixlowModel ()
+{
+}
+
+
+bool
+BinaryErrorSixlowModel::DoCorrupt (Ptr<Packet> p)
+{
+  if (!IsEnabled ())
+    {
+      return false;
+    }
+  bool ret = m_counter % 2;
+  m_counter++;
+  return ret;
+}
+
+void
+BinaryErrorSixlowModel::Reset (void)
+{
+  DoReset ();
+}
+
+void
+BinaryErrorSixlowModel::DoReset (void)
+{
+  m_counter = 0;
+}
+
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sixlowpan/test/error-channel-sixlow.h	Sat Dec 07 08:08:53 2013 +0100
@@ -0,0 +1,107 @@
+/* -*- 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 <tommaso.pecorella@unifi.it>
+ */
+#ifndef ERROR_CHANNEL_SIXLOW_H
+#define ERROR_CHANNEL_SIXLOW_H
+
+#include "ns3/channel.h"
+#include "ns3/simple-channel.h"
+#include "ns3/error-model.h"
+#include "ns3/mac48-address.h"
+#include "ns3/nstime.h"
+#include <vector>
+
+namespace ns3 {
+
+class SimpleNetDevice;
+class Packet;
+
+/**
+ * \ingroup channel
+ * \brief A Error channel, introducing deterministic delays on even/odd packets. Used for testing
+ */
+class ErrorChannelSixlow : public SimpleChannel
+{
+public:
+  static TypeId GetTypeId (void);
+  ErrorChannelSixlow ();
+
+  virtual void Send (Ptr<Packet> p, uint16_t protocol, Mac48Address to, Mac48Address from,
+                     Ptr<SimpleNetDevice> sender);
+
+  virtual void Add (Ptr<SimpleNetDevice> device);
+
+  // inherited from ns3::Channel
+  virtual uint32_t GetNDevices (void) const;
+  virtual Ptr<NetDevice> GetDevice (uint32_t i) const;
+
+  /**
+   * \brief Set the delay for the odd packets (even ones are not delayed)
+   * \param delay Delay for the odd packets.
+   */
+  void SetJumpingTime (Time delay);
+
+  /**
+   * \brief Set if the odd packets are delayed (even ones are not delayed ever)
+   * \param mode true if the odd packets should be delayed.
+   */
+  void SetJumpingMode (bool mode);
+
+  /**
+   * \brief Set the delay for the odd duplicate packets (even ones are not duplicated)
+   * \param delay Delay for the odd packets.
+   */
+  void SetDuplicateTime (Time delay);
+
+  /**
+   * \brief Set if the odd packets are duplicated (even ones are not duplicated ever)
+   * \param mode true if the odd packets should be duplicated.
+   */
+  void SetDuplicateMode (bool mode);
+
+private:
+  std::vector<Ptr<SimpleNetDevice> > m_devices;
+  Time m_jumpingTime;
+  uint8_t m_jumpingState;
+  bool m_jumping;
+  Time m_duplicateTime;
+  bool m_duplicate;
+  uint8_t m_duplicateState;
+};
+
+class BinaryErrorSixlowModel : public ErrorModel
+{
+public:
+  static TypeId GetTypeId (void);
+
+  BinaryErrorSixlowModel ();
+  virtual ~BinaryErrorSixlowModel ();
+  void Reset (void);
+
+private:
+  virtual bool DoCorrupt (Ptr<Packet> p);
+  virtual void DoReset (void);
+
+  uint8_t m_counter;
+
+};
+
+} // namespace ns3
+
+#endif /* ERROR_CHANNEL_SIXLOW_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sixlowpan/test/sixlowpan-fragmentation-test.cc	Sat Dec 07 08:08:53 2013 +0100
@@ -0,0 +1,463 @@
+/* -*-  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 <tommaso.pecorella@unifi.it>
+ */
+#define NS3_LOG_ENABLE 1
+
+#include "ns3/test.h"
+#include "ns3/config.h"
+#include "ns3/uinteger.h"
+#include "ns3/socket-factory.h"
+#include "ns3/ipv6-raw-socket-factory.h"
+#include "ns3/udp-socket-factory.h"
+#include "ns3/simulator.h"
+#include "error-channel-sixlow.h"
+#include "ns3/simple-net-device.h"
+#include "ns3/drop-tail-queue.h"
+#include "ns3/socket.h"
+#include "ns3/udp-socket.h"
+
+#include "ns3/log.h"
+#include "ns3/node.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/boolean.h"
+
+#include "ns3/ipv6-static-routing.h"
+#include "ns3/ipv6-list-routing.h"
+#include "ns3/inet6-socket-address.h"
+#include "ns3/sixlowpan-net-device.h"
+
+#include "ns3/udp-l4-protocol.h"
+
+#include "ns3/ipv6-l3-protocol.h"
+#include "ns3/icmpv6-l4-protocol.h"
+
+#include <string>
+#include <limits>
+#include <netinet/in.h>
+
+using namespace ns3;
+
+class UdpSocketImpl;
+
+static void
+AddInternetStack (Ptr<Node> node)
+{
+  //IPV6
+  Ptr<Ipv6L3Protocol> ipv6 = CreateObject<Ipv6L3Protocol> ();
+
+  //Routing for Ipv6
+  Ptr<Ipv6ListRouting> ipv6Routing = CreateObject<Ipv6ListRouting> ();
+  ipv6->SetRoutingProtocol (ipv6Routing);
+  Ptr<Ipv6StaticRouting> ipv6staticRouting = CreateObject<Ipv6StaticRouting> ();
+  ipv6Routing->AddRoutingProtocol (ipv6staticRouting, 0);
+  node->AggregateObject (ipv6);
+
+  //ICMPv6
+  Ptr<Icmpv6L4Protocol> icmp6 = CreateObject<Icmpv6L4Protocol> ();
+  node->AggregateObject (icmp6);
+
+  //Ipv6 Extensions
+  ipv6->RegisterExtensions ();
+  ipv6->RegisterOptions ();
+
+  //UDP
+  Ptr<UdpL4Protocol> udp = CreateObject<UdpL4Protocol> ();
+  node->AggregateObject (udp);
+}
+
+
+class SixlowpanFragmentationTest : public TestCase
+{
+  Ptr<Packet> m_sentPacketClient;
+  Ptr<Packet> m_receivedPacketClient;
+  Ptr<Packet> m_receivedPacketServer;
+
+
+  Ptr<Socket> m_socketServer;
+  Ptr<Socket> m_socketClient;
+  uint32_t m_dataSize;
+  uint8_t *m_data;
+  uint32_t m_size;
+  uint8_t m_icmpType;
+  uint8_t m_icmpCode;
+
+public:
+  virtual void DoRun (void);
+  SixlowpanFragmentationTest ();
+  ~SixlowpanFragmentationTest ();
+
+  // server part
+  void StartServer (Ptr<Node> ServerNode);
+  void HandleReadServer (Ptr<Socket> socket);
+
+  // client part
+  void StartClient (Ptr<Node> ClientNode);
+  void HandleReadClient (Ptr<Socket> socket);
+  void HandleReadIcmpClient (Ipv6Address icmpSource, uint8_t icmpTtl, uint8_t icmpType,
+                             uint8_t icmpCode,uint32_t icmpInfo);
+
+  void SetFill (uint8_t *fill, uint32_t fillSize, uint32_t dataSize);
+  Ptr<Packet> SendClient (void);
+
+};
+
+
+SixlowpanFragmentationTest::SixlowpanFragmentationTest ()
+  : TestCase ("Verify the 6LoWPAN protocol fragmentation and reassembly")
+{
+  m_socketServer = 0;
+  m_data = 0;
+  m_dataSize = 0;
+}
+
+SixlowpanFragmentationTest::~SixlowpanFragmentationTest ()
+{
+  if ( m_data )
+    {
+      delete[] m_data;
+    }
+  m_data = 0;
+  m_dataSize = 0;
+}
+
+
+void
+SixlowpanFragmentationTest::StartServer (Ptr<Node> ServerNode)
+{
+
+  if (m_socketServer == 0)
+    {
+      TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
+      m_socketServer = Socket::CreateSocket (ServerNode, tid);
+      Inet6SocketAddress local = Inet6SocketAddress (Ipv6Address ("2001:0100::1"), 9);
+      m_socketServer->Bind (local);
+      Ptr<UdpSocket> udpSocket = DynamicCast<UdpSocket> (m_socketServer);
+    }
+
+  m_socketServer->SetRecvCallback (MakeCallback (&SixlowpanFragmentationTest::HandleReadServer, this));
+}
+
+void
+SixlowpanFragmentationTest::HandleReadServer (Ptr<Socket> socket)
+{
+  Ptr<Packet> packet;
+  Address from;
+  while ((packet = socket->RecvFrom (from)))
+    {
+      if (Inet6SocketAddress::IsMatchingType (from))
+        {
+          packet->RemoveAllPacketTags ();
+          packet->RemoveAllByteTags ();
+
+          m_receivedPacketServer = packet->Copy ();
+        }
+    }
+}
+
+void
+SixlowpanFragmentationTest::StartClient (Ptr<Node> ClientNode)
+{
+
+  if (m_socketClient == 0)
+    {
+      TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
+      m_socketClient = Socket::CreateSocket (ClientNode, tid);
+      m_socketClient->Bind (Inet6SocketAddress (Ipv6Address::GetAny (), 9));
+      m_socketClient->Connect (Inet6SocketAddress (Ipv6Address ("2001:0100::1"), 9));
+      CallbackValue cbValue = MakeCallback (&SixlowpanFragmentationTest::HandleReadIcmpClient, this);
+      m_socketClient->SetAttribute ("IcmpCallback6", cbValue);
+    }
+
+  m_socketClient->SetRecvCallback (MakeCallback (&SixlowpanFragmentationTest::HandleReadClient, this));
+}
+
+void
+SixlowpanFragmentationTest::HandleReadClient (Ptr<Socket> socket)
+{
+  Ptr<Packet> packet;
+  Address from;
+  while ((packet = socket->RecvFrom (from)))
+    {
+      if (Inet6SocketAddress::IsMatchingType (from))
+        {
+          m_receivedPacketClient = packet->Copy ();
+        }
+    }
+}
+
+void
+SixlowpanFragmentationTest::HandleReadIcmpClient (Ipv6Address icmpSource,
+                                                  uint8_t icmpTtl, uint8_t icmpType,
+                                                  uint8_t icmpCode, uint32_t icmpInfo)
+{
+  m_icmpType = icmpType;
+  m_icmpCode = icmpCode;
+}
+
+void
+SixlowpanFragmentationTest::SetFill (uint8_t *fill, uint32_t fillSize, uint32_t dataSize)
+{
+  if (dataSize != m_dataSize)
+    {
+      delete [] m_data;
+      m_data = new uint8_t [dataSize];
+      m_dataSize = dataSize;
+    }
+
+  if (fillSize >= dataSize)
+    {
+      memcpy (m_data, fill, dataSize);
+      return;
+    }
+
+  uint32_t filled = 0;
+  while (filled + fillSize < dataSize)
+    {
+      memcpy (&m_data[filled], fill, fillSize);
+      filled += fillSize;
+    }
+
+  memcpy (&m_data[filled], fill, dataSize - filled);
+
+  m_size = dataSize;
+}
+
+Ptr<Packet> SixlowpanFragmentationTest::SendClient (void)
+{
+  Ptr<Packet> p;
+  if (m_dataSize)
+    {
+      p = Create<Packet> (m_data, m_dataSize);
+    }
+  else
+    {
+      p = Create<Packet> (m_size);
+    }
+  m_socketClient->Send (p);
+
+  return p;
+}
+
+void
+SixlowpanFragmentationTest::DoRun (void)
+{
+  // Create topology
+
+  // Receiver Node
+  Ptr<Node> serverNode = CreateObject<Node> ();
+  AddInternetStack (serverNode);
+  Ptr<SimpleNetDevice> serverDev;
+  Ptr<BinaryErrorSixlowModel> serverDevErrorModel = CreateObject<BinaryErrorSixlowModel> ();
+  {
+    serverDev = CreateObject<SimpleNetDevice> ();
+    serverDev->SetAddress (Mac48Address::ConvertFrom (Mac48Address::Allocate ()));
+    serverDev->SetMtu (1500);
+    serverDev->SetReceiveErrorModel (serverDevErrorModel);
+    serverDevErrorModel->Disable ();
+    serverNode->AddDevice (serverDev);
+
+    Ptr<SixLowPanNetDevice> serverSix = CreateObject<SixLowPanNetDevice> ();
+    serverSix->SetAttribute ("ForceEtherType", BooleanValue (true) );
+    serverNode->AddDevice (serverSix);
+    serverSix->SetNetDevice (serverDev);
+
+    Ptr<Ipv6> ipv6 = serverNode->GetObject<Ipv6> ();
+    ipv6->AddInterface (serverDev);
+    uint32_t netdev_idx = ipv6->AddInterface (serverSix);
+    Ipv6InterfaceAddress ipv6Addr = Ipv6InterfaceAddress (Ipv6Address ("2001:0100::1"), Ipv6Prefix (64));
+    ipv6->AddAddress (netdev_idx, ipv6Addr);
+    ipv6->SetUp (netdev_idx);
+
+    Ptr<Icmpv6L4Protocol> icmpv6l4 = serverNode->GetObject<Icmpv6L4Protocol> ();
+    icmpv6l4->SetAttribute ("DAD", BooleanValue (false));
+  }
+  StartServer (serverNode);
+
+  // Sender Node
+  Ptr<Node> clientNode = CreateObject<Node> ();
+  AddInternetStack (clientNode);
+  Ptr<SimpleNetDevice> clientDev;
+  Ptr<BinaryErrorSixlowModel> clientDevErrorModel = CreateObject<BinaryErrorSixlowModel> ();
+  {
+    clientDev = CreateObject<SimpleNetDevice> ();
+    clientDev->SetAddress (Mac48Address::ConvertFrom (Mac48Address::Allocate ()));
+    clientDev->SetMtu (150);
+    clientDev->SetReceiveErrorModel (clientDevErrorModel);
+    clientDevErrorModel->Disable ();
+    clientNode->AddDevice (clientDev);
+
+    Ptr<SixLowPanNetDevice> clientSix = CreateObject<SixLowPanNetDevice> ();
+    clientSix->SetAttribute ("ForceEtherType", BooleanValue (true) );
+    serverNode->AddDevice (clientSix);
+    clientSix->SetNetDevice (clientDev);
+
+    Ptr<Ipv6> ipv6 = clientNode->GetObject<Ipv6> ();
+    ipv6->AddInterface (clientDev);
+    uint32_t netdev_idx = ipv6->AddInterface (clientSix);
+    Ipv6InterfaceAddress ipv6Addr = Ipv6InterfaceAddress (Ipv6Address ("2001:0100::2"), Ipv6Prefix (64));
+    ipv6->AddAddress (netdev_idx, ipv6Addr);
+    ipv6->SetUp (netdev_idx);
+
+    Ptr<Icmpv6L4Protocol> icmpv6l4 = clientNode->GetObject<Icmpv6L4Protocol> ();
+    icmpv6l4->SetAttribute ("DAD", BooleanValue (false));
+  }
+  StartClient (clientNode);
+
+  // link the two nodes
+  Ptr<ErrorChannelSixlow> channel = CreateObject<ErrorChannelSixlow> ();
+  serverDev->SetChannel (channel);
+  clientDev->SetChannel (channel);
+
+
+  // some small packets, some rather big ones
+  uint32_t packetSizes[5] = {200, 300, 400, 500, 600};
+
+  // using the alphabet
+  uint8_t fillData[78];
+  for ( uint32_t k = 48; k <= 125; k++ )
+    {
+      fillData[k - 48] = k;
+    }
+
+  // First test: normal channel, no errors, no delays
+  for ( int i = 0; i < 5; i++)
+    {
+      uint32_t packetSize = packetSizes[i];
+
+      SetFill (fillData, 78, packetSize);
+
+      m_receivedPacketServer = Create<Packet> ();
+      Simulator::ScheduleWithContext (m_socketClient->GetNode ()->GetId (), Seconds (0),
+                                      &SixlowpanFragmentationTest::SendClient, this);
+      Simulator::Run ();
+
+      uint8_t recvBuffer[65000];
+
+      uint16_t recvSize = m_receivedPacketServer->GetSize ();
+
+      NS_TEST_EXPECT_MSG_EQ (recvSize, packetSizes[i],
+                             "Packet size not correct: recvSize: " << recvSize << " packetSizes[" << i << "]: " << packetSizes[i] );
+
+      m_receivedPacketServer->CopyData (recvBuffer, 65000);
+      NS_TEST_EXPECT_MSG_EQ (memcmp (m_data, recvBuffer, m_receivedPacketServer->GetSize ()),
+                             0, "Packet content differs");
+    }
+
+  // Second test: normal channel, no errors, delays each 2 packets.
+  // Each other fragment will arrive out-of-order.
+  // The packets should be received correctly since reassembly will reorder the fragments.
+  channel->SetJumpingMode (true);
+  for ( int i = 0; i < 5; i++)
+    {
+      uint32_t packetSize = packetSizes[i];
+
+      SetFill (fillData, 78, packetSize);
+
+      m_receivedPacketServer = Create<Packet> ();
+      Simulator::ScheduleWithContext (m_socketClient->GetNode ()->GetId (), Seconds (0),
+                                      &SixlowpanFragmentationTest::SendClient, this);
+      Simulator::Run ();
+
+      uint8_t recvBuffer[65000];
+
+      uint16_t recvSize = m_receivedPacketServer->GetSize ();
+
+      NS_TEST_EXPECT_MSG_EQ (recvSize, packetSizes[i],
+                             "Packet size not correct: recvSize: " << recvSize << " packetSizes[" << i << "]: " << packetSizes[i] );
+
+      m_receivedPacketServer->CopyData (recvBuffer, 65000);
+      NS_TEST_EXPECT_MSG_EQ (memcmp (m_data, recvBuffer, m_receivedPacketServer->GetSize ()),
+                             0, "Packet content differs");
+    }
+  channel->SetJumpingMode (false);
+
+
+  // Third test: normal channel, some packets are duplicate.
+  // The duplicate fragments should be discarded, so no error should be fired.
+  channel->SetDuplicateMode (true);
+  for ( int i = 1; i < 5; i++)
+    {
+      uint32_t packetSize = packetSizes[i];
+
+      SetFill (fillData, 78, packetSize);
+
+      // reset the model, we want to receive the very first fragment.
+      serverDevErrorModel->Reset ();
+
+      m_receivedPacketServer = Create<Packet> ();
+      m_icmpType = 0;
+      m_icmpCode = 0;
+      Simulator::ScheduleWithContext (m_socketClient->GetNode ()->GetId (), Seconds (0),
+                                      &SixlowpanFragmentationTest::SendClient, this);
+      Simulator::Run ();
+
+      uint8_t recvBuffer[65000];
+
+      uint16_t recvSize = m_receivedPacketServer->GetSize ();
+
+      NS_TEST_EXPECT_MSG_EQ (recvSize, packetSizes[i],
+                             "Packet size not correct: recvSize: " << recvSize << " packetSizes[" << i << "]: " << packetSizes[i] );
+
+      m_receivedPacketServer->CopyData (recvBuffer, 65000);
+      NS_TEST_EXPECT_MSG_EQ (memcmp (m_data, recvBuffer, m_receivedPacketServer->GetSize ()),
+                             0, "Packet content differs");
+    }
+  channel->SetDuplicateMode (false);
+
+  // Fourth test: normal channel, some errors, no delays.
+  // The reassembly procedure does NOT fire any ICMP, so we do not expect any reply from the server.
+  // Client -> Server : errors enabled
+  // Server -> Client : errors disabled
+  clientDevErrorModel->Disable ();
+  serverDevErrorModel->Enable ();
+  for ( int i = 1; i < 5; i++)
+    {
+      uint32_t packetSize = packetSizes[i];
+
+      SetFill (fillData, 78, packetSize);
+
+      // reset the model, we want to receive the very first fragment.
+      serverDevErrorModel->Reset ();
+
+      m_receivedPacketServer = Create<Packet> ();
+      m_icmpType = 0;
+      m_icmpCode = 0;
+      Simulator::ScheduleWithContext (m_socketClient->GetNode ()->GetId (), Seconds (0),
+                                      &SixlowpanFragmentationTest::SendClient, this);
+      Simulator::Run ();
+
+      uint16_t recvSize = m_receivedPacketServer->GetSize ();
+
+      NS_TEST_EXPECT_MSG_EQ ((recvSize == 0), true, "Server got a packet, something wrong");
+      // Note that a 6LoWPAN fragment timeout does NOT send any ICMPv6.
+    }
+
+
+
+  Simulator::Destroy ();
+}
+//-----------------------------------------------------------------------------
+class SixlowpanFragmentationTestSuite : public TestSuite
+{
+public:
+  SixlowpanFragmentationTestSuite () : TestSuite ("sixlowpan-fragmentation", UNIT)
+  {
+    AddTestCase (new SixlowpanFragmentationTest, TestCase::QUICK);
+  }
+} g_sixlowpanFragmentationTestSuite;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sixlowpan/test/sixlowpan-hc1-test.cc	Sat Dec 07 08:08:53 2013 +0100
@@ -0,0 +1,216 @@
+/* -*- 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 <tommaso.pecorella@unifi.it>
+ */
+
+#include "ns3/test.h"
+#include "ns3/socket-factory.h"
+#include "ns3/udp-socket-factory.h"
+#include "ns3/simulator.h"
+#include "ns3/simple-channel.h"
+#include "ns3/simple-net-device.h"
+#include "ns3/drop-tail-queue.h"
+#include "ns3/socket.h"
+#include "ns3/boolean.h"
+
+#include "ns3/log.h"
+#include "ns3/node.h"
+#include "ns3/inet6-socket-address.h"
+
+#include "ns3/ipv6-l3-protocol.h"
+#include "ns3/icmpv6-l4-protocol.h"
+#include "ns3/udp-l4-protocol.h"
+#include "ns3/ipv6-list-routing.h"
+#include "ns3/ipv6-static-routing.h"
+
+#include "ns3/sixlowpan-net-device.h"
+
+#include <string>
+#include <limits>
+
+using namespace ns3;
+
+static void
+AddInternetStack6 (Ptr<Node> node)
+{
+  //IPV6
+  Ptr<Ipv6L3Protocol> ipv6 = CreateObject<Ipv6L3Protocol> ();
+  //Routing for Ipv6
+  Ptr<Ipv6ListRouting> ipv6Routing = CreateObject<Ipv6ListRouting> ();
+  ipv6->SetRoutingProtocol (ipv6Routing);
+  Ptr<Ipv6StaticRouting> ipv6staticRouting = CreateObject<Ipv6StaticRouting> ();
+  ipv6Routing->AddRoutingProtocol (ipv6staticRouting, 0);
+  node->AggregateObject (ipv6);
+  //ICMP
+  Ptr<Icmpv6L4Protocol> icmp = CreateObject<Icmpv6L4Protocol> ();
+  node->AggregateObject (icmp);
+  //Ipv6 Extensions
+  ipv6->RegisterExtensions ();
+  ipv6->RegisterOptions ();
+  //UDP
+  Ptr<UdpL4Protocol> udp = CreateObject<UdpL4Protocol> ();
+  node->AggregateObject (udp);
+}
+
+
+class SixlowpanHc1ImplTest : public TestCase
+{
+  Ptr<Packet> m_receivedPacket;
+  void DoSendData (Ptr<Socket> socket, std::string to);
+  void SendData (Ptr<Socket> socket, std::string to);
+
+public:
+  virtual void DoRun (void);
+  SixlowpanHc1ImplTest ();
+
+  void ReceivePacket (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from);
+  void ReceivePkt (Ptr<Socket> socket);
+};
+
+SixlowpanHc1ImplTest::SixlowpanHc1ImplTest ()
+  : TestCase ("Sixlowpan implementation")
+{
+}
+
+void SixlowpanHc1ImplTest::ReceivePacket (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from)
+{
+  m_receivedPacket = packet;
+}
+
+void SixlowpanHc1ImplTest::ReceivePkt (Ptr<Socket> socket)
+{
+  uint32_t availableData;
+  availableData = socket->GetRxAvailable ();
+  m_receivedPacket = socket->Recv (std::numeric_limits<uint32_t>::max (), 0);
+  NS_ASSERT (availableData == m_receivedPacket->GetSize ());
+  //cast availableData to void, to suppress 'availableData' set but not used
+  //compiler warning
+  (void) availableData;
+}
+
+void
+SixlowpanHc1ImplTest::DoSendData (Ptr<Socket> socket, std::string to)
+{
+  Address realTo = Inet6SocketAddress (Ipv6Address (to.c_str ()), 1234);
+  uint8_t buffer [] = "\"Can you tell me where my country lies?\" \\ said the unifaun to his true love's eyes. \\ \"It lies with me!\" cried the Queen of Maybe \\ - for her merchandise, he traded in his prize.";
+
+  Ptr<Packet> packet = Create<Packet> (buffer, 180);
+  NS_TEST_EXPECT_MSG_EQ (socket->SendTo (packet, 0, realTo),
+                         180, "200");
+}
+
+void
+SixlowpanHc1ImplTest::SendData (Ptr<Socket> socket, std::string to)
+{
+  m_receivedPacket = Create<Packet> ();
+  Simulator::ScheduleWithContext (socket->GetNode ()->GetId (), Seconds (0),
+                                  &SixlowpanHc1ImplTest::DoSendData, this, socket, to);
+  Simulator::Run ();
+}
+
+void
+SixlowpanHc1ImplTest::DoRun (void)
+{
+  // Create topology
+
+  // Receiver Node
+  Ptr<Node> rxNode = CreateObject<Node> ();
+  AddInternetStack6 (rxNode);
+  Ptr<SimpleNetDevice> rxDev;
+  { // first interface
+    rxDev = CreateObject<SimpleNetDevice> ();
+    rxDev->SetAddress (Mac48Address::ConvertFrom (Mac48Address::Allocate ()));
+    rxNode->AddDevice (rxDev);
+
+    Ptr<SixLowPanNetDevice> rxSix = CreateObject<SixLowPanNetDevice> ();
+    rxSix->SetAttribute ("ForceEtherType", BooleanValue (true) );
+    rxSix->SetAttribute ("Rfc6282", BooleanValue (false) );
+    rxNode->AddDevice (rxSix);
+    rxSix->SetNetDevice (rxDev);
+
+    Ptr<Ipv6> ipv6 = rxNode->GetObject<Ipv6> ();
+    ipv6->AddInterface (rxDev);
+    uint32_t netdev_idx = ipv6->AddInterface (rxSix);
+    Ipv6InterfaceAddress ipv6Addr = Ipv6InterfaceAddress (Ipv6Address ("2001:0100::1"), Ipv6Prefix (64));
+    ipv6->AddAddress (netdev_idx, ipv6Addr);
+    ipv6->SetUp (netdev_idx);
+  }
+
+  // Sender Node
+  Ptr<Node> txNode = CreateObject<Node> ();
+  AddInternetStack6 (txNode);
+  Ptr<SimpleNetDevice> txDev;
+  {
+    txDev = CreateObject<SimpleNetDevice> ();
+    txDev->SetAddress (Mac48Address::ConvertFrom (Mac48Address::Allocate ()));
+    txNode->AddDevice (txDev);
+
+    Ptr<SixLowPanNetDevice> txSix = CreateObject<SixLowPanNetDevice> ();
+    txSix->SetAttribute ("ForceEtherType", BooleanValue (true) );
+    txSix->SetAttribute ("Rfc6282", BooleanValue (false) );
+    txNode->AddDevice (txSix);
+    txSix->SetNetDevice (txDev);
+
+    Ptr<Ipv6> ipv6 = txNode->GetObject<Ipv6> ();
+    ipv6->AddInterface (txDev);
+    uint32_t netdev_idx = ipv6->AddInterface (txSix);
+    Ipv6InterfaceAddress ipv6Addr = Ipv6InterfaceAddress (Ipv6Address ("2001:0100::2"), Ipv6Prefix (64));
+    ipv6->AddAddress (netdev_idx, ipv6Addr);
+    ipv6->SetUp (netdev_idx);
+  }
+
+  // link the two nodes
+  Ptr<SimpleChannel> channel1 = CreateObject<SimpleChannel> ();
+  rxDev->SetChannel (channel1);
+  txDev->SetChannel (channel1);
+
+  // Create the UDP sockets
+  Ptr<SocketFactory> rxSocketFactory = rxNode->GetObject<UdpSocketFactory> ();
+  Ptr<Socket> rxSocket = rxSocketFactory->CreateSocket ();
+  NS_TEST_EXPECT_MSG_EQ (rxSocket->Bind (Inet6SocketAddress (Ipv6Address ("2001:0100::1"), 1234)), 0, "trivial");
+  rxSocket->SetRecvCallback (MakeCallback (&SixlowpanHc1ImplTest::ReceivePkt, this));
+
+  Ptr<SocketFactory> txSocketFactory = txNode->GetObject<UdpSocketFactory> ();
+  Ptr<Socket> txSocket = txSocketFactory->CreateSocket ();
+  txSocket->SetAllowBroadcast (true);
+  // ------ Now the tests ------------
+
+  // Unicast test
+  SendData (txSocket, "2001:0100::1");
+  NS_TEST_EXPECT_MSG_EQ (m_receivedPacket->GetSize (), 180, "trivial");
+  uint8_t rxBuffer [180];
+  uint8_t txBuffer [180] = "\"Can you tell me where my country lies?\" \\ said the unifaun to his true love's eyes. \\ \"It lies with me!\" cried the Queen of Maybe \\ - for her merchandise, he traded in his prize.";
+  m_receivedPacket->CopyData (rxBuffer, 180);
+  NS_TEST_EXPECT_MSG_EQ (memcmp (rxBuffer, txBuffer, 180), 0, "trivial");
+
+  m_receivedPacket->RemoveAllByteTags ();
+
+  Simulator::Destroy ();
+
+}
+
+
+//-----------------------------------------------------------------------------
+class SixlowpanHc1TestSuite : public TestSuite
+{
+public:
+  SixlowpanHc1TestSuite () : TestSuite ("sixlowpan-hc1", UNIT)
+  {
+    AddTestCase (new SixlowpanHc1ImplTest, TestCase::QUICK);
+  }
+} g_sixlowpanHc1TestSuite;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sixlowpan/test/sixlowpan-iphc-test.cc	Sat Dec 07 08:08:53 2013 +0100
@@ -0,0 +1,214 @@
+/* -*- 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 <tommaso.pecorella@unifi.it>
+ */
+
+#include "ns3/test.h"
+#include "ns3/socket-factory.h"
+#include "ns3/udp-socket-factory.h"
+#include "ns3/simulator.h"
+#include "ns3/simple-channel.h"
+#include "ns3/simple-net-device.h"
+#include "ns3/drop-tail-queue.h"
+#include "ns3/socket.h"
+#include "ns3/boolean.h"
+
+#include "ns3/log.h"
+#include "ns3/node.h"
+#include "ns3/inet6-socket-address.h"
+
+#include "ns3/ipv6-l3-protocol.h"
+#include "ns3/icmpv6-l4-protocol.h"
+#include "ns3/udp-l4-protocol.h"
+#include "ns3/ipv6-list-routing.h"
+#include "ns3/ipv6-static-routing.h"
+
+#include "ns3/sixlowpan-net-device.h"
+
+#include <string>
+#include <limits>
+
+using namespace ns3;
+
+static void
+AddInternetStack6 (Ptr<Node> node)
+{
+  //IPV6
+  Ptr<Ipv6L3Protocol> ipv6 = CreateObject<Ipv6L3Protocol> ();
+  //Routing for Ipv6
+  Ptr<Ipv6ListRouting> ipv6Routing = CreateObject<Ipv6ListRouting> ();
+  ipv6->SetRoutingProtocol (ipv6Routing);
+  Ptr<Ipv6StaticRouting> ipv6staticRouting = CreateObject<Ipv6StaticRouting> ();
+  ipv6Routing->AddRoutingProtocol (ipv6staticRouting, 0);
+  node->AggregateObject (ipv6);
+  //ICMP
+  Ptr<Icmpv6L4Protocol> icmp = CreateObject<Icmpv6L4Protocol> ();
+  node->AggregateObject (icmp);
+  //Ipv6 Extensions
+  ipv6->RegisterExtensions ();
+  ipv6->RegisterOptions ();
+  //UDP
+  Ptr<UdpL4Protocol> udp = CreateObject<UdpL4Protocol> ();
+  node->AggregateObject (udp);
+}
+
+
+class SixlowpanIphcImplTest : public TestCase
+{
+  Ptr<Packet> m_receivedPacket;
+  void DoSendData (Ptr<Socket> socket, std::string to);
+  void SendData (Ptr<Socket> socket, std::string to);
+
+public:
+  virtual void DoRun (void);
+  SixlowpanIphcImplTest ();
+
+  void ReceivePacket (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from);
+  void ReceivePkt (Ptr<Socket> socket);
+};
+
+SixlowpanIphcImplTest::SixlowpanIphcImplTest ()
+  : TestCase ("Sixlowpan implementation")
+{
+}
+
+void SixlowpanIphcImplTest::ReceivePacket (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from)
+{
+  m_receivedPacket = packet;
+}
+
+void SixlowpanIphcImplTest::ReceivePkt (Ptr<Socket> socket)
+{
+  uint32_t availableData;
+  availableData = socket->GetRxAvailable ();
+  m_receivedPacket = socket->Recv (std::numeric_limits<uint32_t>::max (), 0);
+  NS_ASSERT (availableData == m_receivedPacket->GetSize ());
+  //cast availableData to void, to suppress 'availableData' set but not used
+  //compiler warning
+  (void) availableData;
+}
+
+void
+SixlowpanIphcImplTest::DoSendData (Ptr<Socket> socket, std::string to)
+{
+  Address realTo = Inet6SocketAddress (Ipv6Address (to.c_str ()), 1234);
+  uint8_t buffer [] = "\"Can you tell me where my country lies?\" \\ said the unifaun to his true love's eyes. \\ \"It lies with me!\" cried the Queen of Maybe \\ - for her merchandise, he traded in his prize.";
+
+  Ptr<Packet> packet = Create<Packet> (buffer, 180);
+  NS_TEST_EXPECT_MSG_EQ (socket->SendTo (packet, 0, realTo),
+                         180, "200");
+}
+
+void
+SixlowpanIphcImplTest::SendData (Ptr<Socket> socket, std::string to)
+{
+  m_receivedPacket = Create<Packet> ();
+  Simulator::ScheduleWithContext (socket->GetNode ()->GetId (), Seconds (0),
+                                  &SixlowpanIphcImplTest::DoSendData, this, socket, to);
+  Simulator::Run ();
+}
+
+void
+SixlowpanIphcImplTest::DoRun (void)
+{
+  // Create topology
+
+  // Receiver Node
+  Ptr<Node> rxNode = CreateObject<Node> ();
+  AddInternetStack6 (rxNode);
+  Ptr<SimpleNetDevice> rxDev;
+  { // first interface
+    rxDev = CreateObject<SimpleNetDevice> ();
+    rxDev->SetAddress (Mac48Address::ConvertFrom (Mac48Address::Allocate ()));
+    rxNode->AddDevice (rxDev);
+
+    Ptr<SixLowPanNetDevice> rxSix = CreateObject<SixLowPanNetDevice> ();
+    rxSix->SetAttribute ("ForceEtherType", BooleanValue (true) );
+    rxNode->AddDevice (rxSix);
+    rxSix->SetNetDevice (rxDev);
+
+    Ptr<Ipv6> ipv6 = rxNode->GetObject<Ipv6> ();
+    ipv6->AddInterface (rxDev);
+    uint32_t netdev_idx = ipv6->AddInterface (rxSix);
+    Ipv6InterfaceAddress ipv6Addr = Ipv6InterfaceAddress (Ipv6Address ("2001:0100::1"), Ipv6Prefix (64));
+    ipv6->AddAddress (netdev_idx, ipv6Addr);
+    ipv6->SetUp (netdev_idx);
+  }
+
+  // Sender Node
+  Ptr<Node> txNode = CreateObject<Node> ();
+  AddInternetStack6 (txNode);
+  Ptr<SimpleNetDevice> txDev;
+  {
+    txDev = CreateObject<SimpleNetDevice> ();
+    txDev->SetAddress (Mac48Address::ConvertFrom (Mac48Address::Allocate ()));
+    txNode->AddDevice (txDev);
+
+    Ptr<SixLowPanNetDevice> txSix = CreateObject<SixLowPanNetDevice> ();
+    txSix->SetAttribute ("ForceEtherType", BooleanValue (true) );
+    txNode->AddDevice (txSix);
+    txSix->SetNetDevice (txDev);
+
+    Ptr<Ipv6> ipv6 = txNode->GetObject<Ipv6> ();
+    ipv6->AddInterface (txDev);
+    uint32_t netdev_idx = ipv6->AddInterface (txSix);
+    Ipv6InterfaceAddress ipv6Addr = Ipv6InterfaceAddress (Ipv6Address ("2001:0100::2"), Ipv6Prefix (64));
+    ipv6->AddAddress (netdev_idx, ipv6Addr);
+    ipv6->SetUp (netdev_idx);
+  }
+
+  // link the two nodes
+  Ptr<SimpleChannel> channel1 = CreateObject<SimpleChannel> ();
+  rxDev->SetChannel (channel1);
+  txDev->SetChannel (channel1);
+
+  // Create the UDP sockets
+  Ptr<SocketFactory> rxSocketFactory = rxNode->GetObject<UdpSocketFactory> ();
+  Ptr<Socket> rxSocket = rxSocketFactory->CreateSocket ();
+  NS_TEST_EXPECT_MSG_EQ (rxSocket->Bind (Inet6SocketAddress (Ipv6Address ("2001:0100::1"), 1234)), 0, "trivial");
+  rxSocket->SetRecvCallback (MakeCallback (&SixlowpanIphcImplTest::ReceivePkt, this));
+
+  Ptr<SocketFactory> txSocketFactory = txNode->GetObject<UdpSocketFactory> ();
+  Ptr<Socket> txSocket = txSocketFactory->CreateSocket ();
+  txSocket->SetAllowBroadcast (true);
+  // ------ Now the tests ------------
+
+  // Unicast test
+  SendData (txSocket, "2001:0100::1");
+  NS_TEST_EXPECT_MSG_EQ (m_receivedPacket->GetSize (), 180, "trivial");
+  uint8_t rxBuffer [180];
+  uint8_t txBuffer [180] = "\"Can you tell me where my country lies?\" \\ said the unifaun to his true love's eyes. \\ \"It lies with me!\" cried the Queen of Maybe \\ - for her merchandise, he traded in his prize.";
+  m_receivedPacket->CopyData (rxBuffer, 180);
+  NS_TEST_EXPECT_MSG_EQ (memcmp (rxBuffer, txBuffer, 180), 0, "trivial");
+
+  m_receivedPacket->RemoveAllByteTags ();
+
+  Simulator::Destroy ();
+
+}
+
+
+//-----------------------------------------------------------------------------
+class SixlowpanIphcTestSuite : public TestSuite
+{
+public:
+  SixlowpanIphcTestSuite () : TestSuite ("sixlowpan-iphc", UNIT)
+  {
+    AddTestCase (new SixlowpanIphcImplTest, TestCase::QUICK);
+  }
+} g_sixlowpanIphcTestSuite;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sixlowpan/wscript	Sat Dec 07 08:08:53 2013 +0100
@@ -0,0 +1,33 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+
+def build(bld):
+    module = bld.create_ns3_module('sixlowpan', ['internet', 'network', 'core'])
+    module.includes = '.'
+    module.source = [
+        'model/sixlowpan-net-device.cc',
+        'model/sixlowpan-header.cc',
+        'helper/sixlowpan-helper.cc',
+        ]
+
+    module_test = bld.create_ns3_module_test_library('sixlowpan')
+    module_test.source = [
+        'test/sixlowpan-hc1-test.cc',
+        'test/sixlowpan-iphc-test.cc',
+        'test/error-channel-sixlow.cc',
+        'test/sixlowpan-fragmentation-test.cc',
+        
+        ]
+
+    headers = bld(features=['ns3header'])
+    headers.module = 'sixlowpan'
+    headers.source = [
+        'model/sixlowpan-net-device.h',
+        'model/sixlowpan-header.h',
+        'helper/sixlowpan-helper.h',
+        ]
+
+
+    if (bld.env['ENABLE_EXAMPLES']):
+        bld.recurse('examples')
+   
+    bld.ns3_python_bindings()
\ No newline at end of file