--- 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