Initial IPv6 capability
authorvincent@clarinet.u-strasbg.fr
Fri, 07 Nov 2008 11:36:15 -0800
changeset 3852 9cf7ad0cac85
parent 3851 cc6a7f93dc3f
child 3853 f04e7f61b1ed
Initial IPv6 capability
AUTHORS
examples/test-ipv6.cc
examples/wscript
src/devices/bridge/bridge-net-device.cc
src/devices/bridge/bridge-net-device.h
src/devices/csma/csma-net-device.cc
src/devices/csma/csma-net-device.h
src/devices/emu/emu-net-device.cc
src/devices/emu/emu-net-device.h
src/devices/point-to-point/point-to-point-net-device.cc
src/devices/point-to-point/point-to-point-net-device.h
src/devices/wifi/wifi-net-device.cc
src/devices/wifi/wifi-net-device.h
src/node/address-utils.cc
src/node/address-utils.h
src/node/icmp-socket.cc
src/node/icmp-socket.h
src/node/inet6-socket-address.cc
src/node/inet6-socket-address.h
src/node/ipv6-address.cc
src/node/ipv6-address.h
src/node/ipv6-header.cc
src/node/ipv6-header.h
src/node/mac48-address.cc
src/node/mac48-address.h
src/node/net-device.h
src/node/simple-net-device.cc
src/node/simple-net-device.h
src/node/wscript
--- a/AUTHORS	Thu Nov 06 15:04:25 2008 -0800
+++ b/AUTHORS	Fri Nov 07 11:36:15 2008 -0800
@@ -9,4 +9,8 @@
 George F. Riley (riley@ece.gatech.edu)
 Guillaume Vu-Brugier (gvubrugier@gmail.com)
 Florian Westphal (fw@strlen.de)
+Sebastien Vincent (vincent@lsiit.u-strasbg.fr)
+David Gross (gdavid.devel@gmail.com)
+Mehdi Benamor (mehdi.benamor@telecom-bretagne.eu)
+Angelos Chatzipapas (chatzipa@ceid.upatras.gr)
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/test-ipv6.cc	Fri Nov 07 11:36:15 2008 -0800
@@ -0,0 +1,70 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 Louis Pasteur University / Telecom Bretagne
+ *
+ * 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: Angelos Chatzipapas <Angelos.CHATZIPAPAS@enst-bretagne.fr> /
+ * <chatzipa@ceid.upatras.gr>
+ */
+
+#include "ns3/log.h"
+//#include "ns3/ipv6.h"
+#include "ns3/ipv6-address.h"
+#include "ns3/node.h"
+#include "ns3/mac48-address.h"
+
+NS_LOG_COMPONENT_DEFINE ("TestIpv6");
+
+using namespace ns3;
+
+int 
+main (int argc, char *argv[])
+{
+  LogComponentEnable ("TestIpv6", LOG_LEVEL_ALL);
+
+  NS_LOG_INFO ("Test Ipv6");
+
+  Mac48Address m_addresses[10];
+
+  m_addresses[0]=("00:00:00:00:00:01");
+  m_addresses[1]=("00:00:00:00:00:02");
+  m_addresses[2]=("00:00:00:00:00:03");
+  m_addresses[3]=("00:00:00:00:00:04");
+  m_addresses[4]=("00:00:00:00:00:05");
+  m_addresses[5]=("00:00:00:00:00:06");
+  m_addresses[6]=("00:00:00:00:00:07");
+  m_addresses[7]=("00:00:00:00:00:08");
+  m_addresses[8]=("00:00:00:00:00:09");
+  m_addresses[9]=("00:00:00:00:00:10");
+
+  Ipv6Address prefix1 ("2001:1::");
+  NS_LOG_INFO ("prefix = " << prefix1);
+  for (uint32_t i = 0; i < 10 ; ++i)
+    {
+      NS_LOG_INFO ("address = " <<m_addresses[i]);
+      Ipv6Address ipv6address=Ipv6Address::MakeAutoconfiguredAddress(m_addresses[i], prefix1);
+      NS_LOG_INFO ("address = " <<ipv6address);
+    }
+
+  Ipv6Address prefix2 ("2002:1:1::");
+
+  NS_LOG_INFO ("prefix = " << prefix2);
+  for (uint32_t i = 0; i < 10 ; ++i)
+    {
+      Ipv6Address ipv6address=Ipv6Address::MakeAutoconfiguredAddress(m_addresses[i], prefix2);
+      NS_LOG_INFO ("address = " <<ipv6address);
+    }
+}
+
--- a/examples/wscript	Thu Nov 06 15:04:25 2008 -0800
+++ b/examples/wscript	Fri Nov 07 11:36:15 2008 -0800
@@ -106,3 +106,7 @@
     obj = bld.create_ns3_program('csma-ping',
         ['csma', 'internet-stack', 'v4ping'])
     obj.source = 'csma-ping.cc'
+
+    obj = bld.create_ns3_program('test-ipv6',
+      ['point-to-point', 'internet-stack'])
+    obj.source = 'test-ipv6.cc'
--- a/src/devices/bridge/bridge-net-device.cc	Thu Nov 06 15:04:25 2008 -0800
+++ b/src/devices/bridge/bridge-net-device.cc	Fri Nov 07 11:36:15 2008 -0800
@@ -380,6 +380,10 @@
   NetDevice::DoDispose ();
 }
 
-
+Address BridgeNetDevice::GetMulticast (Ipv6Address addr) const
+{
+  NS_LOG_FUNCTION (this << addr);
+  return Mac48Address::GetMulticast (addr);
+}
 
 } // namespace ns3
--- a/src/devices/bridge/bridge-net-device.h	Thu Nov 06 15:04:25 2008 -0800
+++ b/src/devices/bridge/bridge-net-device.h	Fri Nov 07 11:36:15 2008 -0800
@@ -106,6 +106,7 @@
   virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb);
   virtual void SetPromiscReceiveCallback (NetDevice::PromiscReceiveCallback cb);
   virtual bool SupportsSendFrom () const;
+  virtual Address GetMulticast (Ipv6Address addr) const;
 
 protected:
   virtual void DoDispose (void);
--- a/src/devices/csma/csma-net-device.cc	Thu Nov 06 15:04:25 2008 -0800
+++ b/src/devices/csma/csma-net-device.cc	Fri Nov 07 11:36:15 2008 -0800
@@ -600,6 +600,20 @@
   NS_LOG_FUNCTION (packet << senderDevice);
   NS_LOG_LOGIC ("UID is " << packet->GetUid ());
 
+  /* IPv6 support*/
+  uint8_t mac[6];
+  Mac48Address multicast6AllNodes("33:33:00:00:00:01");
+  Mac48Address multicast6AllRouters("33:33:00:00:00:02");
+  Mac48Address multicast6AllHosts("33:33:00:00:00:03");
+  Mac48Address multicast6Node; /* multicast address addressed to our MAC address */
+
+  /* generate IPv6 multicast ethernet destination that nodes will accept */
+  GetAddress().CopyTo(mac);
+  mac[0]=0x33;
+  mac[1]=0x33;
+  /* mac[2]=0xff; */
+  multicast6Node.CopyFrom(mac);
+
   //
   // We never forward up packets that we sent. Real devices don't do this since
   // their receivers are disabled during send, so we don't. Drop the packet
@@ -672,7 +686,11 @@
           packetType = PACKET_BROADCAST;
           m_rxTrace (originalPacket);
         }
-      else if (header.GetDestination ().IsMulticast ())
+      else if (header.GetDestination ().IsMulticast () ||
+          header.GetDestination() == multicast6Node ||
+          header.GetDestination() == multicast6AllNodes ||
+          header.GetDestination() == multicast6AllRouters ||
+          header.GetDestination() == multicast6AllHosts)
         {
           packetType = PACKET_MULTICAST;          
           m_rxTrace (originalPacket);
@@ -922,6 +940,14 @@
   m_rxCallback = cb;
 }
 
+Address CsmaNetDevice::GetMulticast (Ipv6Address addr) const
+{
+  Mac48Address ad = Mac48Address::GetMulticast (addr);
+
+  NS_LOG_LOGIC("MAC IPv6 multicast address is " << ad);
+  return ad;
+}
+
   void 
 CsmaNetDevice::SetPromiscReceiveCallback (NetDevice::PromiscReceiveCallback cb)
 {
--- a/src/devices/csma/csma-net-device.h	Thu Nov 06 15:04:25 2008 -0800
+++ b/src/devices/csma/csma-net-device.h	Fri Nov 07 11:36:15 2008 -0800
@@ -392,6 +392,15 @@
    */
   virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb);
 
+  /**
+   * \brief Get the MAC multicast address corresponding
+   * to the IPv6 address provided.
+   * \param addr IPv6 address
+   * \return the MAC multicast address
+   * \warning Calling this method is invalid if IsMulticast returns not true.
+   */
+  virtual Address GetMulticast (Ipv6Address addr) const;
+
 
   virtual void SetPromiscReceiveCallback (PromiscReceiveCallback cb);
   virtual bool SupportsSendFrom (void) const;
--- a/src/devices/emu/emu-net-device.cc	Thu Nov 06 15:04:25 2008 -0800
+++ b/src/devices/emu/emu-net-device.cc	Fri Nov 07 11:36:15 2008 -0800
@@ -865,6 +865,17 @@
   return ad;
 }
 
+Address
+EmuNetDevice::GetMulticast (Ipv6Address addr) const
+{
+  NS_LOG_FUNCTION(this << addr);
+
+  Mac48Address ad = Mac48Address::GetMulticast (addr);
+  NS_LOG_LOGIC("MAC IPv6 multicast address is " << ad);
+
+  return ad;
+}
+
 bool 
 EmuNetDevice::IsPointToPoint (void) const
 {
--- a/src/devices/emu/emu-net-device.h	Thu Nov 06 15:04:25 2008 -0800
+++ b/src/devices/emu/emu-net-device.h	Fri Nov 07 11:36:15 2008 -0800
@@ -151,6 +151,15 @@
   virtual Address GetMulticast (Ipv4Address multicastGroup) const;
 
   /**
+   * \brief Get the MAC multicast address corresponding
+   * to the IPv6 address provided.
+   * \param addr IPv6 address
+   * \return the MAC multicast address
+   * \warning Calling this method is invalid if IsMulticast returns not true.
+   */
+  virtual Address GetMulticast (Ipv6Address addr) const;
+
+  /**
    * Is this a point to point link?
    * \returns false.
    */
--- a/src/devices/point-to-point/point-to-point-net-device.cc	Thu Nov 06 15:04:25 2008 -0800
+++ b/src/devices/point-to-point/point-to-point-net-device.cc	Fri Nov 07 11:36:15 2008 -0800
@@ -378,6 +378,13 @@
   return Mac48Address ("01:00:5e:00:00:00");
 }
 
+Address
+PointToPointNetDevice::GetMulticast (Ipv6Address addr) const
+{
+  NS_LOG_FUNCTION(this << addr);
+  return Mac48Address ("33:33:00:00:00:00");
+}
+
   bool 
 PointToPointNetDevice::IsPointToPoint (void) const
 {
--- a/src/devices/point-to-point/point-to-point-net-device.h	Thu Nov 06 15:04:25 2008 -0800
+++ b/src/devices/point-to-point/point-to-point-net-device.h	Fri Nov 07 11:36:15 2008 -0800
@@ -263,6 +263,8 @@
 
   virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb);
 
+  virtual Address GetMulticast (Ipv6Address addr) const;
+
   virtual void SetPromiscReceiveCallback (PromiscReceiveCallback cb);
   virtual bool SupportsSendFrom (void) const;
 
--- a/src/devices/wifi/wifi-net-device.cc	Thu Nov 06 15:04:25 2008 -0800
+++ b/src/devices/wifi/wifi-net-device.cc	Fri Nov 07 11:36:15 2008 -0800
@@ -257,6 +257,10 @@
 {
   return Mac48Address::GetMulticast (multicastGroup);
 }
+Address WifiNetDevice::GetMulticast (Ipv6Address addr) const
+{
+  return Mac48Address::GetMulticast (addr);
+}
 bool 
 WifiNetDevice::IsPointToPoint (void) const
 {
--- a/src/devices/wifi/wifi-net-device.h	Thu Nov 06 15:04:25 2008 -0800
+++ b/src/devices/wifi/wifi-net-device.h	Fri Nov 07 11:36:15 2008 -0800
@@ -100,6 +100,8 @@
   virtual bool NeedsArp (void) const;
   virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb);
 
+  virtual Address GetMulticast (Ipv6Address addr) const;
+
   virtual bool SendFrom(Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber);
   virtual void SetPromiscReceiveCallback (PromiscReceiveCallback cb);
   virtual bool SupportsSendFrom (void) const;
--- a/src/node/address-utils.cc	Thu Nov 06 15:04:25 2008 -0800
+++ b/src/node/address-utils.cc	Fri Nov 07 11:36:15 2008 -0800
@@ -25,6 +25,12 @@
 {
   i.WriteHtonU32 (ad.Get ());
 }
+void WriteTo (Buffer::Iterator &i, Ipv6Address ad)
+{
+  uint8_t buf[16];
+  ad.GetBytes(buf);
+  i.Write(buf, 16);
+}
 void WriteTo (Buffer::Iterator &i, const Address &ad)
 {
   uint8_t mac[Address::MAX_SIZE];
@@ -42,6 +48,12 @@
 {
   ad.Set (i.ReadNtohU32 ());
 }
+void ReadFrom (Buffer::Iterator &i, Ipv6Address &ad)
+{
+  uint8_t ipv6[16];
+  i.Read(ipv6, 16);
+  ad.Set (ipv6);
+}
 void ReadFrom (Buffer::Iterator &i, Address &ad, uint32_t len)
 {
   uint8_t mac[Address::MAX_SIZE];
--- a/src/node/address-utils.h	Thu Nov 06 15:04:25 2008 -0800
+++ b/src/node/address-utils.h	Fri Nov 07 11:36:15 2008 -0800
@@ -22,16 +22,19 @@
 
 #include "ns3/buffer.h"
 #include "ipv4-address.h"
+#include "ipv6-address.h"
 #include "address.h"
 #include "mac48-address.h"
 
 namespace ns3 {
 
 void WriteTo (Buffer::Iterator &i, Ipv4Address ad);
+void WriteTo (Buffer::Iterator &i, Ipv6Address ad);
 void WriteTo (Buffer::Iterator &i, const Address &ad);
 void WriteTo (Buffer::Iterator &i, Mac48Address ad);
 
 void ReadFrom (Buffer::Iterator &i, Ipv4Address &ad);
+void ReadFrom (Buffer::Iterator &i, Ipv6Address &ad);
 void ReadFrom (Buffer::Iterator &i, Address &ad, uint32_t len);
 void ReadFrom (Buffer::Iterator &i, Mac48Address &ad);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/icmp-socket.cc	Fri Nov 07 11:36:15 2008 -0800
@@ -0,0 +1,58 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 Louis Pasteur University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+#include "ns3/object.h"
+#include "ns3/log.h"
+#include "ns3/uinteger.h"
+#include "ns3/trace-source-accessor.h"
+#include "icmp-socket.h"
+
+NS_LOG_COMPONENT_DEFINE ("IcmpSocket");
+
+namespace ns3 {
+
+  NS_OBJECT_ENSURE_REGISTERED (IcmpSocket);
+
+  TypeId IcmpSocket::GetTypeId (void)
+  {
+    static TypeId tid = TypeId ("ns3::IcmpSocket")
+      .SetParent<Socket> ()
+      .AddAttribute ("RcvBufSize",
+          "IcmpSocket maximum receive buffer size (bytes)",
+          UintegerValue (0xffffffffl),
+          MakeUintegerAccessor (&IcmpSocket::GetRcvBufSize,
+            &IcmpSocket::SetRcvBufSize),
+          MakeUintegerChecker<uint32_t> ())
+      ;
+    return tid;
+  }
+
+  IcmpSocket::IcmpSocket (void)
+  {
+    NS_LOG_FUNCTION_NOARGS ();
+  }
+
+  IcmpSocket::~IcmpSocket (void)
+  {
+    NS_LOG_FUNCTION_NOARGS ();
+  }
+
+}; /* namespace ns3 */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/icmp-socket.h	Fri Nov 07 11:36:15 2008 -0800
@@ -0,0 +1,177 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 Louis Pasteur University
+ *
+ * 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
+ *
+ * Authors: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+#ifndef ICMP_SOCKET_H
+#define ICMP_SOCKET_H
+
+#include "socket.h"
+#include "ns3/traced-callback.h"
+#include "ns3/callback.h"
+#include "ns3/ptr.h"
+#include "ns3/object.h"
+
+namespace ns3 {
+
+class Node;
+class Packet;
+
+/**
+ * \brief (abstract) base class of all IcmpSockets (for IPv4 or IPv6).
+ *
+ * This class exists solely for hosting IcmpSocket attributes that can
+ * be reused across different implementations.
+ */
+class IcmpSocket : public Socket
+{
+  public:
+    /**
+     * \brief Get the UID of this class.
+     * \return UID
+     */
+    static TypeId GetTypeId (void);
+
+    /**
+     * \brief Constructor.
+     */
+    IcmpSocket (void);
+
+    /**
+     * \brief Destructor.
+     */
+    virtual ~IcmpSocket (void);
+
+    /**
+     * \brief Get the error.
+     * \return the error.
+     */
+    virtual enum Socket::SocketErrno GetErrno (void) const = 0;
+
+    /**
+     * \brief Get the node.
+     * \return the node
+     */
+    virtual Ptr<Node> GetNode (void) const = 0;
+
+    /**
+     * \brief Bind the socket.
+     * \return 0 if OK, -1 otherwise
+     */
+    virtual int Bind (void) = 0;
+
+    /**
+     * \brief Bind the socket on "addr".
+     * \param addr address
+     * \return 0 if OK, -1 otherwise
+     */
+    virtual int Bind (const Address &addr) = 0;
+
+    /**
+     * \brief Close the socket.
+     * \return 0 if OK, -1 otherwise
+     */
+    virtual int Close (void) = 0;
+
+    /**
+     * \brief Shutdown the socket on send.
+     * \return 0 if OK, -1 otherwise
+     */
+    virtual int ShutdownSend (void) = 0;
+
+    /**
+     * \brief Shutdown the socket on receive.
+     * \return 0 if OK, -1 otherwise
+     */
+    virtual int ShutdownRecv (void) = 0;
+
+    /**
+     * \brief Connect to another node.
+     * \param addr address
+     * \return 0 if OK, -1 otherwise
+     */
+    virtual int Connect (const Address &addr) = 0;
+
+    /**
+     * \brief Send a packet.
+     * \param p the packet to send
+     * \param flags flags
+     * \return 0 if OK, -1 otherwise
+     */		
+    virtual int Send (Ptr<Packet> p, uint32_t flags) = 0;
+
+    /**
+     * \brief Get the maximum message size available.
+     * \return maximum message size
+     * \warning size of a message that could be sent is limited by the link MTU.
+     */
+    virtual uint32_t GetTxAvailable (void) const = 0;
+
+    /**
+     * \brief Send a packet to a node.
+     * \param addr the address of the node
+     * \param flags flags
+     * \param p the packet to send
+     * \return 0 if OK, -1 otherwise
+     */
+    virtual int SendTo (Ptr<Packet> p, uint32_t flags, const Address &addr) = 0;
+
+    /**
+     * \brief Receive method.
+     * \param maxSize maximum size we want to return
+     * \param flags flags
+     * \return a packet with at maximum maxSize size
+     */
+    virtual Ptr<Packet> Recv (uint32_t maxSize, uint32_t flags) = 0;
+
+    /**
+     * \brief Receive method.
+     * \param maxSize maximum size we want to return
+     * \param flags flags
+     * \param fromAddress sender address
+     * \return a packet with at maximum maxSize size
+     */
+    virtual Ptr<Packet> RecvFrom (uint32_t maxSize, uint32_t flags, Address &fromAddress) = 0;
+
+    /**
+     * \brief Get the size we could receive.
+     * \return size we could receive at one moment
+     */
+    virtual uint32_t GetRxAvailable (void) const = 0;
+
+  private:
+    /**
+     * \brief Get the receive buffer size.
+     * \return receive buffer size
+     */
+    virtual uint32_t GetRcvBufSize (void) const = 0;
+
+    /**
+     * \brief Set the receive buffer size.
+     * \param rcvBufSize size to set
+     */
+    virtual void SetRcvBufSize (uint32_t rcvBufSize) = 0;
+
+    /* FIXME : add ICMP basic attribute for socket */
+    /* Indirect the attribute setting and getting through private virtual methods */
+};
+
+} /* namespace ns3 */
+
+#endif /* ICMP_SOCKET_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/inet6-socket-address.cc	Fri Nov 07 11:36:15 2008 -0800
@@ -0,0 +1,112 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007-2008 Louis Pasteur University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+#include "inet6-socket-address.h"
+#include "ns3/assert.h"
+
+namespace ns3 {
+
+Inet6SocketAddress::Inet6SocketAddress (Ipv6Address ipv6, uint16_t port)
+: m_ipv6(ipv6),
+  m_port(port)
+{
+}
+
+Inet6SocketAddress::Inet6SocketAddress (Ipv6Address ipv6)
+: m_ipv6(ipv6),
+  m_port(0)
+{
+}
+
+  Inet6SocketAddress::Inet6SocketAddress (const char* ipv6, uint16_t port)
+: m_ipv6(Ipv6Address(ipv6)),
+  m_port(port)
+{
+}
+
+  Inet6SocketAddress::Inet6SocketAddress (const char* ipv6)
+: m_ipv6(Ipv6Address(ipv6)),
+  m_port(0)
+{
+}
+
+  Inet6SocketAddress::Inet6SocketAddress (uint16_t port)
+: m_ipv6(Ipv6Address::GetAny()),
+  m_port(port)
+{
+}
+
+uint16_t Inet6SocketAddress::GetPort (void) const
+{
+  return m_port;
+}
+
+void Inet6SocketAddress::SetPort (uint16_t port)
+{
+  m_port=port;
+}
+
+Ipv6Address Inet6SocketAddress::GetIpv6 (void) const
+{
+  return m_ipv6;
+}
+
+void Inet6SocketAddress::SetIpv6 (Ipv6Address ipv6)
+{
+  m_ipv6=ipv6;
+}
+
+bool Inet6SocketAddress::IsMatchingType (const Address &addr)
+{
+  return addr.CheckCompatible(GetType(), 18); /* 16 (address) + 2  (port) */
+}
+
+Inet6SocketAddress::operator Address (void) const
+{
+  return ConvertTo();
+}
+
+Address Inet6SocketAddress::ConvertTo (void) const
+{
+  uint8_t buf[18];
+  m_ipv6.Serialize(buf);
+  buf[16]=m_port & 0xff;
+  buf[17]=(m_port >> 8) &0xff;
+  return Address(GetType(), buf, 18);
+}
+
+Inet6SocketAddress Inet6SocketAddress::ConvertFrom (const Address &addr)
+{
+  NS_ASSERT(addr.CheckCompatible(GetType(), 18));
+  uint8_t buf[18];
+  addr.CopyTo(buf);
+  Ipv6Address ipv6=Ipv6Address::Deserialize(buf);
+  uint16_t port= buf[16] | (buf[17] << 8);
+  return Inet6SocketAddress(ipv6, port);
+}
+
+uint8_t Inet6SocketAddress::GetType (void)
+{
+  static uint8_t type=Address::Register();
+  return type;
+}
+
+} /* namespace ns3 */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/inet6-socket-address.h	Fri Nov 07 11:36:15 2008 -0800
@@ -0,0 +1,140 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007-2008 Louis Pasteur University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+#ifndef INET6_SOCKET_ADDRESS_H 
+#define INET6_SOCKET_ADDRESS_H
+
+#include "address.h"
+#include "ipv6-address.h"
+#include <stdint.h>
+
+namespace ns3 {
+
+/**
+ * \class Inet6SocketAddress
+ * \brief An Inet6 address class.
+ */
+class Inet6SocketAddress
+{
+  public:
+    /**
+     * \brief Constructor.
+     * \param ipv6 the IPv6 address
+     * \param port the port
+     */
+    Inet6SocketAddress (Ipv6Address ipv6, uint16_t port);
+
+    /**
+     * \brief Constructor (the port is set to zero).
+     * \param ipv6 the IPv6 address
+     */
+    Inet6SocketAddress (Ipv6Address ipv6);
+
+    /**
+     * \brief Constructor (the address is set to "any").
+     * \param port the port
+     */
+    Inet6SocketAddress (uint16_t port);
+
+    /**
+     * \brief Constructor.
+     * \param ipv6 string which represents an IPv6 address
+     * \param port the port
+     */
+    Inet6SocketAddress (const char* ipv6, uint16_t port);
+
+    /**
+     * \brief Constructor.
+     * \param ipv6 string which represents an IPv6 address
+     */
+    Inet6SocketAddress (const char* ipv6);
+
+    /**
+     * \brief Get the port.
+     * \return the port
+     */
+    uint16_t GetPort (void) const;
+
+    /**
+     * \brief Set the port
+     * \param port the port
+     */
+    void SetPort (uint16_t port);
+
+    /**
+     * \brief Get the IPv6 address.
+     * \return the IPv6 address
+     */
+    Ipv6Address GetIpv6 (void) const;
+
+    /**
+     * \brief Set the IPv6 address.
+     * \param ipv6 the address
+     */
+    void SetIpv6 (Ipv6Address ipv6);
+
+    /**
+     * \brief If the address match.
+     * \param addr the address to test
+     * \return true if the address match, false otherwise
+     */
+    static bool IsMatchingType (const Address &addr);
+
+    /**
+     * \brief Get an Address instance which represents this
+     * Inet6SocketAddress instance.
+     */
+    operator Address (void) const;
+
+    /**
+     * \brief Convert the address to a InetSocketAddress.
+     * \param addr the address to convert
+     * \return an Inet6SocketAddress instance corresponding to address
+     */
+    static Inet6SocketAddress ConvertFrom (const Address &addr);
+
+  private:
+    /**
+     * \brief Convert to Address.
+     * \return Address instance
+     */
+    Address ConvertTo (void) const;
+
+    /**
+     * \brief Get the type.
+     * \return the type of Inet6SocketAddress
+     */
+    static uint8_t GetType (void);
+
+    /**
+     * \brief The IPv6 address.
+     */
+    Ipv6Address m_ipv6;
+
+    /**
+     * \brief The port.
+     */
+    uint16_t m_port;
+};
+
+} /* namespace ns3 */
+
+#endif /* INET6_SOCKET_ADDRESS_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/ipv6-address.cc	Fri Nov 07 11:36:15 2008 -0800
@@ -0,0 +1,686 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007-2008 Louis Pasteur University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+#include <string.h>
+
+#include "ns3/log.h"
+#include "ipv6-address.h"
+#include "ns3/assert.h"
+#include "mac48-address.h"
+
+#include <iomanip>
+
+NS_LOG_COMPONENT_DEFINE ("Ipv6Address");
+
+namespace ns3 {
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+  /**
+   * \brief Get a hash key.
+   * \param k the key
+   * \param length the length of the key
+   * \param level the previous hash, or an arbitrary value
+   * \return hash
+   * \note Adpated from Jens Jakobsen implementation (chillispot).
+   */
+  static uint32_t lookuphash (unsigned char* k, uint32_t length, uint32_t level)
+  {
+#define mix(a,b,c) \
+    { \
+      a -= b; a -= c; a ^= (c>>13); \
+      b -= c; b -= a; b ^= (a<<8); \
+      c -= a; c -= b; c ^= (b>>13); \
+      a -= b; a -= c; a ^= (c>>12);  \
+      b -= c; b -= a; b ^= (a<<16); \
+      c -= a; c -= b; c ^= (b>>5); \
+      a -= b; a -= c; a ^= (c>>3);  \
+      b -= c; b -= a; b ^= (a<<10); \
+      c -= a; c -= b; c ^= (b>>15); \
+    }
+
+    typedef uint32_t  ub4;   /* unsigned 4-byte quantities */
+    typedef unsigned  char ub1;   /* unsigned 1-byte quantities */
+    uint32_t a,b,c,len;
+
+    /* Set up the internal state */
+    len = length;
+    a = b = 0x9e3779b9;  /* the golden ratio; an arbitrary value */
+    c = level;           /* the previous hash value */
+
+    /*---------------------------------------- handle most of the key */
+    while (len >= 12)
+    {
+      a += (k[0] +((ub4)k[1]<<8) +((ub4)k[2]<<16) +((ub4)k[3]<<24));
+      b += (k[4] +((ub4)k[5]<<8) +((ub4)k[6]<<16) +((ub4)k[7]<<24));
+      c += (k[8] +((ub4)k[9]<<8) +((ub4)k[10]<<16)+((ub4)k[11]<<24));
+      mix(a,b,c);
+      k += 12; len -= 12;
+    }
+
+    /*------------------------------------- handle the last 11 bytes */
+    c += length;
+    switch(len)              /* all the case statements fall through */
+    {
+      case 11: c+=((ub4)k[10]<<24);
+      case 10: c+=((ub4)k[9]<<16);
+      case 9 : c+=((ub4)k[8]<<8);
+               /* the first byte of c is reserved for the length */
+      case 8 : b+=((ub4)k[7]<<24);
+      case 7 : b+=((ub4)k[6]<<16);
+      case 6 : b+=((ub4)k[5]<<8);
+      case 5 : b+=k[4];
+      case 4 : a+=((ub4)k[3]<<24);
+      case 3 : a+=((ub4)k[2]<<16);
+      case 2 : a+=((ub4)k[1]<<8);
+      case 1 : a+=k[0];
+               /* case 0: nothing left to add */
+    }
+    mix(a,b,c);
+    /*-------------------------------------------- report the result */
+    return c;
+  }
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * \brief Convert an IPv6 C-string into a 128-bit representation.
+ * \return 1 if OK, 0 if failure (bad format, ...)
+ * \note This function is strongly inspired by inet_pton6() from Paul Vixie.
+ * \todo Handle IPv6 address with decimal value for last four bytes.
+ */
+static int AsciiToIpv6Host (char const *address, uint8_t addr[16])
+{
+  static const char xdigits_l[] = "0123456789abcdef",
+               xdigits_u[] = "0123456789ABCDEF";
+  unsigned char tmp[16 /*NS_IN6ADDRSZ*/], *tp, *endp, *colonp;
+  const char *xdigits, *curtok;
+  int ch, seen_xdigits;
+  unsigned int val;
+
+  memset((tp = tmp), '\0', 16 /* NS_IN6ADDRSZ*/);
+  endp = tp + 16 /*NS_IN6ADDRSZ*/;
+  colonp = NULL;
+  /* Leading :: requires some special handling. */
+  if (*address == ':')
+    if (*++address != ':')
+      return (0);
+  curtok = address;
+  seen_xdigits = 0;
+  val = 0;
+  while ((ch = *address++) != '\0')
+  {
+    const char *pch;
+
+    if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
+      pch = strchr((xdigits = xdigits_u), ch);
+    if (pch != NULL)
+    {
+      val <<= 4;
+      val |= (pch - xdigits);
+      if (++seen_xdigits > 4)
+        return (0);
+      continue;
+    }
+    if (ch == ':')
+    {
+      curtok = address;
+      if (!seen_xdigits)
+      {
+        if (colonp)
+          return (0);
+        colonp = tp;
+        continue;
+      }
+      if (tp + 2 /*NS_INT16SZ*/ > endp)
+        return (0);
+      *tp++ = (unsigned char) (val >> 8) & 0xff;
+      *tp++ = (unsigned char) val & 0xff;
+      seen_xdigits = 0;
+      val = 0;
+      continue;
+    }
+
+    /* TODO Handle address like 2001::xxx.xxx.xxx.xxxx */
+#if 0
+    if (ch == '.' && ((tp + 4 /*NS_INADDRSZ*/) <= endp) &&
+        inet_pton4(curtok, tp) > 0)
+    {
+      tp += 4 /*NS_INADDRSZ*/;
+      seen_xdigits = 0;
+      break;/* '\0' was seen by inet_pton4(). */
+    }
+#endif
+    return (0);
+  }
+  if (seen_xdigits)
+  {
+    if (tp + 2/* NS_INT16SZ*/ > endp)
+      return (0);
+    *tp++ = (unsigned char) (val >> 8) & 0xff;
+    *tp++ = (unsigned char) val & 0xff;
+  }
+  if (colonp != NULL)
+  {
+    /*
+     * Since some memmove()'s erroneously fail to handle
+     * overlapping regions, we'll do the shift by hand.
+     */
+    const int n = tp - colonp;
+    int i;
+
+    if (tp == endp)
+      return (0);
+    for (i = 1; i <= n; i++)
+    {
+      endp[- i] = colonp[n - i];
+      colonp[n - i] = 0;
+    }
+    tp = endp;
+  }
+  if (tp != endp)
+    return (0);
+
+  /* memcpy(dst, tmp, NS_IN6ADDRSZ);  */
+  memcpy(addr, tmp, 16);
+  return (1);
+}
+
+Ipv6Address::Ipv6Address ()
+{
+  memset(m_address, 0x00, 16);
+}
+
+Ipv6Address::Ipv6Address (Ipv6Address const& addr)
+{
+  memcpy(m_address, addr.m_address, 16);
+}
+
+Ipv6Address::Ipv6Address (Ipv6Address const* addr)
+{
+  memcpy(m_address, addr->m_address, 16);
+}
+
+Ipv6Address::Ipv6Address (char const* address)
+{
+  AsciiToIpv6Host (address, m_address);
+}
+
+Ipv6Address::Ipv6Address (uint8_t address[16])
+{
+  /* 128 bit => 16 bytes */
+  memcpy(m_address, address, 16);
+}
+
+Ipv6Address::~Ipv6Address ()
+{
+  /* do nothing */
+}
+
+void Ipv6Address::Set (char const* address)
+{
+  AsciiToIpv6Host (address, m_address);
+}
+
+void Ipv6Address::Set (uint8_t address[16])
+{
+  /* 128 bit => 16 bytes */
+  memcpy(m_address, address, 16);
+}
+
+void Ipv6Address::Serialize (uint8_t buf[16]) const
+{
+  memcpy(buf, m_address, 16);
+}
+
+Ipv6Address Ipv6Address::Deserialize (const uint8_t buf[16])
+{
+  Ipv6Address ipv6((uint8_t*)buf);
+  return ipv6;
+}
+
+Ipv6Address Ipv6Address::MakeAutoconfiguredAddress (Mac48Address addr, Ipv6Address prefix)
+{
+  Ipv6Address ret;
+  uint8_t buf[16];
+  uint8_t buf2[16];
+
+  addr.CopyTo(buf);
+  prefix.GetBytes(buf2);
+
+  memcpy(buf2 + 8, buf, 3);
+  buf2[11] = 0xff;
+  buf2[12] = 0xfe;
+  memcpy(buf2 + 13, buf + 3, 3);
+  buf2[8] |= 0x02;
+
+  ret.Set(buf2);
+  return ret;
+}
+
+Ipv6Address Ipv6Address::MakeAutoconfiguredLinkLocalAddress (Mac48Address addr)
+{
+  Ipv6Address ret;
+  uint8_t buf[16];
+  uint8_t buf2[16];
+
+  addr.CopyTo(buf);
+
+  memset(buf2, 0x00, sizeof(buf2));
+  buf2[0] = 0xfe;
+  buf2[1] = 0x80;
+  memcpy(buf2 + 8, buf, 3);
+  buf2[11] = 0xff;
+  buf2[12] = 0xfe;
+  memcpy(buf2 + 13, buf + 3, 3);
+  buf2[8] |= 0x02;
+
+  ret.Set(buf2);
+  return ret;
+}
+
+Ipv6Address Ipv6Address::MakeSolicitedAddress (Ipv6Address addr)
+{
+  uint8_t buf[16];
+  uint8_t buf2[16];
+  Ipv6Address ret;
+
+  addr.Serialize(buf2);
+
+  memset(buf, 0x00, sizeof(buf));
+  buf[0] = 0xff;
+  buf[1] = 0x02;
+  buf[11] = 0x01;
+  buf[12] = 0xff;
+  buf[13] = buf2[13];
+  buf[14] = buf2[14];
+  buf[15] = buf2[15];
+
+  ret.Set(buf);
+  return ret;
+}
+
+void Ipv6Address::Print (std::ostream& os) const
+{
+  os << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[0]
+    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[1] << ":"
+    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[2] 
+    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[3] << ":"
+    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[4]
+    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[5] << ":"
+    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[6]
+    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[7] << ":"
+    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[8]
+    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[9] << ":"
+    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[10]
+    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[11] << ":"
+    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[12]
+    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[13] << ":"
+    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[14]
+    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[15];
+}
+
+bool Ipv6Address::IsLocalhost () const
+{
+  static Ipv6Address localhost("::1");
+  return (*this == localhost);
+}
+
+bool Ipv6Address::IsMulticast () const
+{
+  if(m_address[0] == 0xff)
+  {
+    return true;
+  }
+  return false;
+}
+
+Ipv6Address Ipv6Address::CombinePrefix (Ipv6Prefix const & prefix)
+{
+  Ipv6Address ipv6;
+  uint8_t addr[16];
+  uint8_t pref[16];
+  unsigned int i = 0;
+
+  memcpy(addr, m_address, 16);
+  ((Ipv6Prefix)prefix).GetBytes(pref);
+
+  /* a little bit ugly... */
+  for(i = 0 ; i < 16 ; i++)
+  {
+    addr[i] = addr[i] & pref[i];
+  }
+  ipv6.Set(addr);
+  return ipv6;
+}
+
+bool Ipv6Address::IsSolicitedMulticast () const
+{
+  uint8_t buf[16];
+
+  Serialize(buf);
+
+  if(buf[0] == 0xff && 
+      buf[1] == 0x02 &&
+      buf[11] == 0x01 &&
+      buf[12] == 0xff)
+  {
+    return true;
+  }
+  return false;
+}
+
+bool Ipv6Address::IsAllNodesMulticast () const
+{
+  static Ipv6Address allnodes("ff02::1");
+  return (*this == allnodes);
+}
+
+bool Ipv6Address::IsAllRoutersMulticast () const
+{
+  static Ipv6Address allrouters("ff02::2");
+  return (*this == allrouters);
+}
+
+bool Ipv6Address::IsAllHostsMulticast () const
+{
+  static Ipv6Address allhosts("ff02::3");
+  return (*this == allhosts);
+}
+
+bool Ipv6Address::IsAny () const
+{
+  static Ipv6Address any("::");
+  return (*this == any);
+}
+
+bool Ipv6Address::IsMatchingType (const Address& address)
+{
+  return address.CheckCompatible(GetType(), 16);
+}
+
+Ipv6Address::operator Address () const
+{
+  return ConvertTo ();
+}
+
+Address Ipv6Address::ConvertTo (void) const
+{
+  uint8_t buf[16];
+  Serialize (buf);
+  return Address(GetType(), buf, 16);
+}
+
+Ipv6Address Ipv6Address::ConvertFrom (const Address &address)
+{
+  NS_ASSERT (address.CheckCompatible (GetType (), 16));
+  uint8_t buf[16];
+  address.CopyTo (buf);
+  return Deserialize (buf);
+}
+
+uint8_t Ipv6Address::GetType (void)
+{
+  static uint8_t type = Address::Register();
+  return type;
+}
+
+Ipv6Address Ipv6Address::GetZero ()
+{
+  Ipv6Address zero("::");
+  return zero;
+}
+
+Ipv6Address Ipv6Address::GetAny ()
+{
+  Ipv6Address any("::");
+  return any;
+}
+
+Ipv6Address Ipv6Address::GetAllNodesMulticast ()
+{
+  Ipv6Address nmc("ff02::1");
+  return nmc;
+}
+
+Ipv6Address Ipv6Address::GetAllRoutersMulticast ()
+{
+  Ipv6Address rmc("ff02::2");
+  return rmc;
+}
+
+Ipv6Address Ipv6Address::GetAllHostsMulticast ()
+{
+  Ipv6Address hmc("ff02::3");
+  return hmc;
+}
+
+Ipv6Address Ipv6Address::GetLoopback ()
+{
+  static Ipv6Address loopback("::1");
+  return loopback;
+}
+
+void Ipv6Address::GetBytes (uint8_t buf[16]) const
+{
+  memcpy(buf, m_address, 16);
+}
+
+bool Ipv6Address::IsLinkLocal () const
+{
+  Ipv6Address linkLocal("fe80::0");
+  if(!IsMulticast() && ((Ipv6Address*)this)->CombinePrefix(Ipv6Prefix(64))==linkLocal)
+  {
+    return true;
+  }
+  return false;
+}
+
+bool Ipv6Address::IsEqual (const Ipv6Address& other) const
+{
+  if(!memcmp(m_address, other.m_address, 16))
+  {
+    return true;
+  }
+  return false;
+}
+
+std::ostream& operator << (std::ostream& os, Ipv6Address const& address)
+{
+  address.Print(os);
+  return os;
+}
+
+std::istream& operator >> (std::istream& is, Ipv6Address& address)
+{
+  std::string str;
+  is >> str;
+  address = Ipv6Address (str.c_str ());
+  return is;
+}
+
+Ipv6Prefix::Ipv6Prefix ()
+{
+  memset(m_prefix, 0x00, 16);
+}
+
+Ipv6Prefix::Ipv6Prefix (char const* prefix)
+{
+  AsciiToIpv6Host(prefix, m_prefix);
+}
+
+Ipv6Prefix::Ipv6Prefix (uint8_t prefix[16])
+{
+  memcpy(m_prefix, prefix, 16);
+}
+
+Ipv6Prefix::Ipv6Prefix (uint8_t prefix)
+{
+  unsigned int nb=0;
+  unsigned int mod=0;
+  unsigned int i=0;
+
+  memset(m_prefix, 0x00, 16);
+
+  NS_ASSERT(prefix <= 128);
+
+  nb = prefix / 8;
+  mod = prefix % 8;
+
+  memset(m_prefix, 0xff, nb);
+
+  if(mod)
+  {
+    m_prefix[nb] = 0xff << (8-mod);
+  }
+
+  if(nb < 16)
+  {
+    nb++;
+    for(i = nb; i < 16 ; i++)
+    {
+      m_prefix[i] = 0x00;
+    }
+  }
+}
+
+Ipv6Prefix::Ipv6Prefix (Ipv6Prefix const& prefix)
+{
+  memcpy(m_prefix, prefix.m_prefix, 16);
+}
+
+Ipv6Prefix::Ipv6Prefix (Ipv6Prefix const* prefix)
+{
+  memcpy(m_prefix, prefix->m_prefix, 16);
+}
+
+Ipv6Prefix::~Ipv6Prefix ()
+{
+  /* do nothing */
+}
+
+bool Ipv6Prefix::IsMatch (Ipv6Address a, Ipv6Address b) const
+{
+  uint8_t addrA[16];
+  uint8_t addrB[16];
+  unsigned int i = 0;
+
+  a.GetBytes(addrA);
+  b.GetBytes(addrB);
+
+  /* a little bit ugly... */
+  for(i = 0 ; i < 16 ; i++)
+  {
+    if((addrA[i] & m_prefix[i]) !=	(addrB[i] & m_prefix[i]))
+    {
+      return false;
+    }
+  }
+  return true;
+}
+
+void Ipv6Prefix::Print (std::ostream &os) const
+{
+  os << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[0]
+    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[1] << ":"
+    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[2]
+    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[3] << ":"
+    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[4]
+    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[5] << ":"
+    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[6]
+    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[7] << ":"
+    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[8]
+    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[9] << ":"
+    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[10]
+    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[11] << ":"
+    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[12]
+    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[13] << ":"
+    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[14]
+    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[15];
+}
+
+Ipv6Prefix Ipv6Prefix::GetLoopback ()
+{
+  Ipv6Prefix prefix((uint8_t)128);
+  return prefix;
+}
+
+Ipv6Prefix Ipv6Prefix::GetZero ()
+{
+  Ipv6Prefix prefix((uint8_t)0);
+  return prefix;
+}
+
+void Ipv6Prefix::GetBytes (uint8_t buf[16]) const
+{
+  memcpy(buf, m_prefix, 16);
+}
+
+bool Ipv6Prefix::IsEqual (const Ipv6Prefix& other) const
+{
+  if(!memcmp(m_prefix, other.m_prefix, 16))
+  {
+    return true;
+  }
+  return false;
+}
+
+std::ostream& operator<< (std::ostream& os, Ipv6Prefix const& prefix)
+{
+  prefix.Print (os);
+  return os;
+}
+
+std::istream& operator >> (std::istream& is, Ipv6Prefix& prefix)
+{
+  std::string str;
+  is >> str;
+  prefix = Ipv6Prefix (str.c_str ());
+  return is;
+}
+
+bool operator == (Ipv6Prefix const &a, Ipv6Prefix const &b)
+{
+  return a.IsEqual (b);
+}
+
+bool operator != (Ipv6Prefix const &a, Ipv6Prefix const &b)
+{
+  return !a.IsEqual (b);
+}
+
+size_t Ipv6AddressHash::operator() (Ipv6Address const &x) const
+{
+  uint8_t buf[16];
+
+  x.GetBytes(buf);
+
+  return lookuphash(buf, sizeof(buf), 0);
+}
+
+ATTRIBUTE_HELPER_CPP (Ipv6Address);
+ATTRIBUTE_HELPER_CPP (Ipv6Prefix);
+
+} /* namespace ns3 */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/ipv6-address.h	Fri Nov 07 11:36:15 2008 -0800
@@ -0,0 +1,427 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007-2008 Louis Pasteur University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+#ifndef IPV6_ADDRESS_H
+#define IPV6_ADDRESS_H
+
+#include <stdint.h>
+#include <string.h>
+
+#include <ostream>
+
+#include "address.h"
+#include "ns3/attribute-helper.h"
+
+namespace ns3 { 
+
+class Ipv6Prefix;
+class Mac48Address;
+
+/**
+ * \class Ipv6Address
+ * \brief Describes an IPv6 address.
+ * \see Ipv6Prefix
+ */
+class Ipv6Address
+{
+  public :
+    /**
+     * \brief Default constructor.
+     */
+    Ipv6Address ();
+
+    /**
+     * \brief Constructs an Ipv6Address by parsing the input C-string.
+     * \param address the C-string containing the IPv6 address (e.g. 2001:660:4701::1).
+     */
+    Ipv6Address (char const* address);
+
+    /**
+     * \brief Constructs an Ipv6Address by using the input 16 bytes.
+     * \param address the 128-bit address
+     * \warning the parameter must point on a 16 bytes integer array!
+     */
+    Ipv6Address (uint8_t address[16]);
+
+    /**
+     * \brief Copy constructor.
+     * \param addr Ipv6Address object
+     */
+    Ipv6Address (Ipv6Address const & addr);
+
+    /**
+     * \brief Copy constructor.
+     * \param addr Ipv6Address pointer
+     */
+    Ipv6Address (Ipv6Address const* addr);
+
+    /**
+     * \brief Destructor.
+     */
+    ~Ipv6Address ();
+
+    /**
+     * \brief Sets an Ipv6Address by parsing the input C-string.
+     * \param address the C-string containing the IPv6 address (e.g. 2001:660:4701::1).
+     */
+    void Set (char const* address);
+
+    /**
+     * \brief Set an Ipv6Address by using the input 16 bytes.
+     *
+     * \param address the 128-bit address
+     * \warning the parameter must point on a 16 bytes integer array!
+     */
+    void Set (uint8_t address[16]);
+
+    /**
+     * \brief Comparison operation between two Ipv6Addresses.
+     *
+     * \param other the IPv6 address to which to compare thisaddress
+     * \return true if the addresses are equal, false otherwise
+     */
+    bool IsEqual (const Ipv6Address& other) const;
+
+    /**
+     * \brief Serialize this address to a 16-byte buffer.
+     * \param buf the output buffer to which this address gets overwritter with this
+     * Ipv6Address
+     */
+    void Serialize (uint8_t buf[16]) const;
+
+    /**
+     * \brief Deserialize this address.
+     * \param buf buffer to read address from
+     * \return an Ipv6Address
+     */
+    static Ipv6Address Deserialize (const uint8_t buf[16]);
+
+    /**
+     * \brief Make the solicited IPv6 address.
+     * \param addr the IPv6 address
+     * \return Solicited IPv6 address
+     */
+    static Ipv6Address MakeSolicitedAddress (Ipv6Address addr);
+
+    /**
+     * \brief Make the autoconfigured IPv6 address with Mac48Address.
+     * \param addr the MAC address (48 bits).
+     * \param prefix the IPv6 prefix
+     * \return autoconfigured IPv6 address
+     */
+    static Ipv6Address MakeAutoconfiguredAddress (Mac48Address addr, Ipv6Address prefix);
+
+    /**
+     * \brief Make the autoconfigured link-local IPv6 address with Mac48Address.
+     * \param mac the MAC address (48 bits).
+     * \return autoconfigured link-local IPv6 address
+     */
+    static Ipv6Address MakeAutoconfiguredLinkLocalAddress (Mac48Address mac);
+
+    /**
+     * \brief Print this address to the given output stream.
+     *
+     * The print format is in the typical "2001:660:4701::1".
+     * \param os the output stream to which this Ipv6Address is printed
+     */
+    void Print (std::ostream& os) const;
+
+    /**
+     * \brief If the IPv6 address is localhost (::1).
+     * \return true if localhost, false otherwise
+     */
+    bool IsLocalhost () const;
+
+    /**
+     * \brief If the IPv6 address is multicast (ff00::/8).
+     * \return true if multicast, false otherwise
+     */
+    bool IsMulticast () const;
+
+    /**
+     * \brief If the IPv6 address is "all nodes multicast" (ff02::1/8).
+     * \return true if "all nodes multicast", false otherwise
+     */
+    bool IsAllNodesMulticast () const;
+
+    /**
+     * \brief If the IPv6 address is "all routers multicast" (ff02::2/8).
+     * \return true if "all routers multicast", false otherwise
+     */
+    bool IsAllRoutersMulticast () const;
+
+    /**
+     * \brief If the IPv6 address is "all hosts multicast" (ff02::3/8).
+     * \return true if "all hosts multicast", false otherwise
+     */
+    bool IsAllHostsMulticast () const;
+
+    /**
+     * \brief If the IPv6 address is a link-local address (fe80::/64).
+     * \return true if the address is link-local, false otherwise
+     */
+    bool IsLinkLocal () const;
+
+    /**
+     * \brief If the IPv6 address is a Solicited multicast address.
+     * \return true if it is, false otherwise
+     */
+    bool IsSolicitedMulticast () const;
+
+    /**
+     * \brief If the IPv6 address is the "Any" address.
+     * \return true if it is, false otherwise
+     */
+    bool IsAny () const;
+
+    /**
+     * \brief Combine this address with a prefix.
+     * \param prefix a IPv6 prefix
+     * \return an IPv6 address that is this address combined
+     * (bitwise AND) with a prefix, yielding an IPv6 network address.
+     */
+    Ipv6Address CombinePrefix (Ipv6Prefix const & prefix);
+
+    /**
+     * \brief If the Address matches the type.
+     * \param address other address
+     * \return true if the type matches, false otherwise
+     */
+    static bool IsMatchingType (const Address& address);
+
+    /**
+     * \brief Convert to Address object
+     */
+    operator Address () const;
+
+    /**
+     * \brief Convert the Address object into an Ipv6Address one.
+     * \return an Ipv6Address
+     */
+    static Ipv6Address ConvertFrom (const Address& address);
+
+    /**
+     * \brief Get the 0 (::) Ipv6Address.
+     * \return the :: Ipv6Address representation
+     */
+    static Ipv6Address GetZero ();
+
+    /**
+     * \brief Get the "any" (::) Ipv6Address.
+     * \return the "any" (::) Ipv6Address
+     */
+    static Ipv6Address GetAny ();
+
+    /**
+     * \brief Get the "all nodes multicast" address.
+     * \return the "ff02::2/8" Ipv6Address representation
+     */
+    static Ipv6Address GetAllNodesMulticast ();
+
+    /**
+     * \brief Get the "all routers multicast" address.
+     * \return the "ff02::2/8" Ipv6Address representation
+     */
+    static Ipv6Address GetAllRoutersMulticast ();
+
+    /**
+     * \brief Get the "all hosts multicast" address.
+     * \return the "ff02::3/8" Ipv6Address representation
+     */
+    static Ipv6Address GetAllHostsMulticast ();
+
+    /**
+     * \brief Get the loopback address.
+     * \return the "::1/128" Ipv6Address representation.
+     */
+    static Ipv6Address GetLoopback ();
+
+    /**
+     * \brief Get the bytes corresponding to the address.
+     * \param buf buffer to store the data
+     * \return bytes of the address
+     */
+    void GetBytes (uint8_t buf[16]) const;
+
+  private:
+    /**
+     * \brief convert the IPv6Address object to an Address object.
+     * \return the Address object corresponding to this object.
+     */
+    Address ConvertTo (void) const;
+
+    /**
+     * \brief Return the Type of address.
+     * \return type of address
+     */
+    static uint8_t GetType (void);
+
+    /**
+     * \brief The address representation on 128 bits (16 bytes).
+     */
+    uint8_t m_address[16];
+
+    friend bool operator == (Ipv6Address const &a, Ipv6Address const &b);
+    friend bool operator != (Ipv6Address const &a, Ipv6Address const &b);
+    friend bool operator < (Ipv6Address const &a, Ipv6Address const &b);
+};
+
+/**
+ * \class Ipv6Prefix
+ * \brief Describes an IPv6 prefix. It is just a bitmask like Ipv4Mask.
+ * \see Ipv6Address
+ */
+class Ipv6Prefix
+{
+  public:
+    /**
+     * \brief Default constructor.
+     */
+    Ipv6Prefix ();
+
+    /**
+     * \brief Constructs an Ipv6Prefix by using the input 16 bytes.
+     * \param prefix the 128-bit prefix
+     */
+    Ipv6Prefix (uint8_t prefix[16]);
+
+    /**
+     * \brief Constructs an Ipv6Prefix by using the input string.
+     * \param prefix the 128-bit prefix
+     */
+    Ipv6Prefix (char const* prefix);
+
+    /**
+     * \brief Constructs an Ipv6Prefix by using the input number of bits.
+     * \param prefix number of bits of the prefix (0 - 128)
+     * \note A valid number of bits is between 0 and 128).
+     */
+    Ipv6Prefix (uint8_t prefix);
+
+    /**
+     * \brief Copy constructor.
+     * \param prefix Ipv6Prefix object
+     */
+    Ipv6Prefix (Ipv6Prefix const& prefix);
+
+    /**
+     * \brief Copy constructor.
+     * \param prefix Ipv6Prefix pointer
+     */
+    Ipv6Prefix (Ipv6Prefix const* prefix);
+
+    /**
+     * \brief Destructor.
+     */
+    ~Ipv6Prefix ();
+
+    /**
+     * \brief If the Address match the type.
+     * \param a a first address
+     * \param b a second address
+     * \return true if the type match, false otherwise
+     */
+    bool IsMatch (Ipv6Address a, Ipv6Address b) const;
+
+    /**
+     * \brief Get the bytes corresponding to the prefix.
+     * \param buf buffer to store the data
+     */
+    void GetBytes (uint8_t buf[16]) const;
+
+    /**
+     * \brief Comparison operation between two Ipv6Prefix.
+     * \param other the IPv6 prefix to which to compare this prefix
+     * \return true if the prefixes are equal, false otherwise
+     */
+    bool IsEqual (const Ipv6Prefix& other) const;
+
+    /**
+     * \brief Print this address to the given output stream.
+     *
+     * The print format is in the typicall "2001:660:4701::1".
+     * \param os the output stream to which this Ipv6Address is printed
+     */
+    void Print (std::ostream &os) const;
+
+    /**
+     * \brief Get the loopback prefix ( /128).
+     * \return a Ipv6Prefix corresponding to loopback prefix
+     */
+    static Ipv6Prefix GetLoopback ();
+
+    /**
+     * \brief Get the zero prefix ( /0).
+     * \return an Ipv6Prefix
+     */
+    static Ipv6Prefix GetZero ();
+
+  private:
+    /**
+     * \brief The prefix representation.
+     */
+    uint8_t m_prefix[16];
+};
+
+/**
+ * \class ns3::Ipv6AddressValue
+ * \brief hold objects of type ns3::Ipv6Address
+ */
+ATTRIBUTE_HELPER_HEADER (Ipv6Address);
+
+/**
+ * \class ns3::Ipv6PrefixValue
+ * \brief hold objects of type ns3::Ipv6Prefix
+ */
+ATTRIBUTE_HELPER_HEADER (Ipv6Prefix);
+
+std::ostream& operator << (std::ostream& os, Ipv6Address const& address);
+std::ostream& operator<< (std::ostream& os, Ipv6Prefix const& prefix);
+std::istream & operator >> (std::istream &is, Ipv6Address &address);
+std::istream & operator >> (std::istream &is, Ipv6Prefix &prefix);
+
+inline bool operator == (const Ipv6Address& a, const Ipv6Address& b)
+{
+  return (!memcmp (a.m_address, b.m_address, 16));
+}
+
+inline bool operator != (const Ipv6Address& a, const Ipv6Address& b)
+{
+  return memcmp (a.m_address, b.m_address, 16);
+}
+
+inline bool operator < (const Ipv6Address& a, const Ipv6Address& b)
+{
+  return (memcmp (a.m_address, b.m_address, 16) < 0);
+}
+
+class Ipv6AddressHash : public std::unary_function<Ipv6Address, size_t>
+{
+  public:
+    size_t operator() (Ipv6Address const &x) const;
+};
+
+bool operator == (Ipv6Prefix const &a, Ipv6Prefix const &b);
+bool operator != (Ipv6Prefix const &a, Ipv6Prefix const &b);
+
+} /* namespace ns3 */
+
+#endif /* IPV6_ADDRESS_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/ipv6-header.cc	Fri Nov 07 11:36:15 2008 -0800
@@ -0,0 +1,187 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007-2008 Louis Pasteur University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+#include "ns3/assert.h"
+#include "ns3/log.h"
+#include "ns3/header.h"
+#include "address-utils.h"
+#include "ipv6-header.h"
+
+NS_LOG_COMPONENT_DEFINE ("Ipv6Header");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (Ipv6Header);
+
+Ipv6Header::Ipv6Header ()
+: m_version (6),
+  m_trafficClass (0),
+  m_flowLabel (1),
+  m_payloadLength (0),
+  m_nextHeader (0),
+  m_hopLimit (0)
+{
+
+  SetSourceAddress (Ipv6Address("::"));
+  SetDestinationAddress(Ipv6Address ("::"));
+}
+
+void Ipv6Header::SetTrafficClass (uint8_t traffic)
+{
+  m_trafficClass = traffic;
+}
+
+uint8_t Ipv6Header::GetTrafficClass () const
+{
+  return m_trafficClass;
+}
+
+void Ipv6Header::SetFlowLabel (uint32_t flow)
+{
+  m_flowLabel = flow;
+}
+
+uint32_t Ipv6Header::GetFlowLabel () const
+{
+  return m_flowLabel;
+}
+
+void Ipv6Header::SetPayloadLength (uint16_t len)
+{
+  m_payloadLength = len;
+}
+
+uint16_t Ipv6Header::GetPayloadLength () const
+{
+  return m_payloadLength;
+}
+
+void Ipv6Header::SetNextHeader (uint8_t next)
+{
+  m_nextHeader = next;
+}
+
+uint8_t Ipv6Header::GetNextHeader () const
+{
+  return m_nextHeader;
+}
+
+void Ipv6Header::SetHopLimit (uint8_t limit)
+{
+  m_hopLimit = limit;
+}
+
+uint8_t Ipv6Header::GetHopLimit () const
+{
+  return m_hopLimit;
+}
+
+void Ipv6Header::SetSourceAddress (Ipv6Address src)
+{
+  m_sourceAddress = src;
+}
+
+Ipv6Address Ipv6Header::GetSourceAddress () const
+{
+  return m_sourceAddress;
+}
+
+void Ipv6Header::SetDestinationAddress (Ipv6Address dst)
+{
+  m_destinationAddress = dst;
+}
+
+Ipv6Address Ipv6Header::GetDestinationAddress () const
+{
+  return m_destinationAddress;
+}
+
+TypeId Ipv6Header::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::Ipv6Header")
+    .SetParent<Header> ()
+    .AddConstructor<Ipv6Header> ()
+    ;
+  return tid;
+}
+
+TypeId Ipv6Header::GetInstanceTypeId (void) const
+{
+  return GetTypeId ();
+}
+
+void Ipv6Header::Print (std::ostream& os) const
+{
+  os << "("
+    "Version " << m_version << " "
+    << "Traffic class 0x" << std::hex << m_trafficClass << std::dec << " "
+    << "Flow Label 0x" << std::hex << m_flowLabel << std::dec << " "
+    << "Payload Length " << m_payloadLength << " "
+    << "Next Header " << std::dec << (uint32_t) m_nextHeader << " "
+    << "Hop Limit " << std::dec << (uint32_t)m_hopLimit << " )"
+    <<  m_sourceAddress << " > " <<  m_destinationAddress
+    ;
+}
+
+uint32_t Ipv6Header::GetSerializedSize () const
+{
+  return 10 * 4;
+}
+
+void Ipv6Header::Serialize (Buffer::Iterator start) const
+{
+  Buffer::Iterator i = start;
+  uint32_t vTcFl = 0; /* version, Traffic Class and Flow Label fields */
+
+  vTcFl= (6 << 28) | (m_trafficClass << 20) | (m_flowLabel);
+
+  i.WriteHtonU32(vTcFl);
+  i.WriteHtonU16(m_payloadLength);
+  i.WriteU8(m_nextHeader);
+  i.WriteU8(m_hopLimit);
+
+  WriteTo(i, m_sourceAddress);
+  WriteTo(i, m_destinationAddress);
+}
+
+uint32_t Ipv6Header::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+  uint32_t vTcFl = 0;
+
+  vTcFl = i.ReadNtohU32();
+  m_version = vTcFl >> 28;
+
+  NS_ASSERT((m_version) == 6);
+
+  m_trafficClass = (uint8_t)((vTcFl >> 20) & 0x000000ff);
+  m_flowLabel = vTcFl & 0xfff00000;
+  m_payloadLength = i.ReadNtohU16();
+  m_nextHeader = i.ReadU8();
+  m_hopLimit = i.ReadU8();
+
+  ReadFrom(i, m_sourceAddress);
+  ReadFrom(i, m_destinationAddress);
+
+  return GetSerializedSize();
+}
+
+} /* namespace ns3 */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/ipv6-header.h	Fri Nov 07 11:36:15 2008 -0800
@@ -0,0 +1,237 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007-2008 Louis Pasteur University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+#ifndef IPV6_HEADER_H
+#define IPV6_HEADER_H
+
+#include "ns3/header.h"
+#include "ns3/ipv6-address.h"
+
+namespace ns3 {
+
+/**
+ * \class Ipv6Header
+ * \brief Packet header for IPv6
+ */
+class Ipv6Header : public Header
+{
+  public:
+    /**
+     * \enum NextHeader_e
+     * \brief IPv6 next-header value
+     */
+    enum NextHeader_e
+    {
+      IPV6_EXT_HOP_BY_HOP=0,
+      IPV6_IPV4=4,
+      IPV6_TCP=6,
+      IPV6_UDP=17,
+      IPV6_IPV6=41,
+      IPV6_EXT_ROUTING=43,
+      IPV6_EXT_FRAGMENTATION=44,
+      IPV6_EXT_CONFIDENTIALITY=50,
+      IPV6_EXT_AUTHENTIFICATION,
+      IPV6_ICMPV6=58,
+      IPV6_EXT_END,
+      IPV6_EXT_DESTINATION,
+      IPV6_SCTP=135,
+      IPV6_EXT_MOBILITY=135,
+      IPV6_UDP_LITE,
+    };
+
+    /**
+     * \brief Get the type identifier.
+     * \return type identifier
+     */
+    static TypeId GetTypeId (void);
+
+    /**
+     * \brief Return the instance type identifier.
+     * \return instance type ID
+     */
+    virtual TypeId GetInstanceTypeId (void) const;
+
+    /**
+     * \brief Constructor.
+     */
+    Ipv6Header (void);
+
+    /**
+     * \brief Set the "Traffic class" field.
+     * \param traffic the 8-bit value
+     */
+    void SetTrafficClass (uint8_t traffic);
+
+    /**
+     * \brief Get the "Traffic class" field.
+     * \return the traffic value
+     */
+    uint8_t GetTrafficClass (void) const;
+
+    /**
+     * \brief Set the "Flow label" field.
+     * \param flow the 20-bit value
+     */
+    void SetFlowLabel (uint32_t flow);
+
+    /**
+     * \brief Get the "Flow label" field.
+     * \return the flow label value
+     */
+    uint32_t GetFlowLabel (void) const;
+
+    /**
+     * \brief Set the "Payload length" field.
+     * \param len the length of the payload in bytes
+     */
+    void SetPayloadLength (uint16_t len);
+
+    /**
+     * \brief Get the "Payload length" field.
+     * \return the payload length
+     */
+    uint16_t GetPayloadLength (void) const;
+
+    /**
+     * \brief Set the "Next header" field.
+     * \param next the next header number
+     */
+    void SetNextHeader (uint8_t next);
+
+    /**
+     * \brief Get the next header.
+     * \return the next header number
+     */
+    uint8_t GetNextHeader (void) const;
+
+    /**
+     * \brief Set the "Hop limit" field (TTL).
+     * \param limit the 8-bit value
+     */
+    void SetHopLimit (uint8_t limit);
+
+    /**
+     * \brief Get the "Hop limit" field (TTL).
+     * \return the hop limit value
+     */
+    uint8_t GetHopLimit (void) const;
+
+    /**
+     * \brief Set the "Source address" field.
+     * \param src the source address
+     */
+    void SetSourceAddress (Ipv6Address src);
+
+    /**
+     * \brief Get the "Source address" field.
+     * \return the source address
+     */
+    Ipv6Address GetSourceAddress (void) const;
+
+    /**
+     * \brief Set the "Destination address" field.
+     * \param dst the destination address
+     */
+    void SetDestinationAddress (Ipv6Address dst);
+
+    /**
+     * \brief Get the "Destination address" field.
+     * \return the destination address
+     */
+    Ipv6Address GetDestinationAddress (void) const;
+
+    /**
+     * \brief Get the name.
+     * \return the name
+     */
+    std::string GetName (void) const;
+
+    /**
+     * \brief Print some informations about the packet.
+     * \param os output stream
+     * \return info about this packet
+     */
+    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);
+
+  private:
+    /**
+     * \brief The version (always equal to 6).
+     */
+    uint32_t m_version : 4;
+    /**
+     * \brief The traffic class.
+     */
+    uint32_t m_trafficClass : 8;
+
+    /**
+     * \brief The flow label.
+     * \note This is 20-bit value.
+     */
+    uint32_t m_flowLabel : 20;
+
+    /**
+     * \brief The payload length.
+     */
+    uint16_t m_payloadLength;
+
+    /**
+     * \brief The Next header number.
+     */
+    uint8_t m_nextHeader;
+
+    /**
+     * \brief The Hop limit value.
+     */
+    uint8_t m_hopLimit;
+
+    /**
+     * \brief The source address.
+     */
+    Ipv6Address m_sourceAddress;
+
+    /**
+     * \brief The destination address.
+     */
+    Ipv6Address m_destinationAddress;
+};
+
+} /* namespace ns3 */
+
+#endif /* IPV6_HEADER_H */
+
--- a/src/node/mac48-address.cc	Thu Nov 06 15:04:25 2008 -0800
+++ b/src/node/mac48-address.cc	Fri Nov 07 11:36:15 2008 -0800
@@ -170,6 +170,12 @@
   static Mac48Address multicast = Mac48Address ("01:00:5e:00:00:00");
   return multicast;
 }
+Mac48Address
+Mac48Address::GetMulticast6Prefix (void)
+{
+  static Mac48Address multicast = Mac48Address ("33:33:00:00:00:00");
+  return multicast;
+}
 Mac48Address 
 Mac48Address::GetMulticast (Ipv4Address multicastGroup)
 {
@@ -206,6 +212,26 @@
   result.CopyFrom (etherBuffer);
   return result;
 }
+Mac48Address Mac48Address::GetMulticast(Ipv6Address addr)
+{
+  Mac48Address etherAddr = Mac48Address::GetMulticast6Prefix();
+  uint8_t etherBuffer[6];
+  uint8_t ipBuffer[16];
+
+  /* a MAC multicast IPv6 address is like 33:33 and the four low bytes */
+  /* for 2001:db8::2fff:fe11:ac10 => 33:33:FE:11:AC:10 */
+  etherAddr.CopyTo (etherBuffer);
+  addr.Serialize (ipBuffer);
+
+  etherBuffer[2] = ipBuffer[12];
+  etherBuffer[3] = ipBuffer[13];
+  etherBuffer[4] = ipBuffer[14];
+  etherBuffer[5] = ipBuffer[15];
+
+  etherAddr.CopyFrom (etherBuffer);
+
+  return etherAddr;
+}
 
 bool operator == (const Mac48Address &a, const Mac48Address &b)
 {
--- a/src/node/mac48-address.h	Thu Nov 06 15:04:25 2008 -0800
+++ b/src/node/mac48-address.h	Fri Nov 07 11:36:15 2008 -0800
@@ -25,6 +25,7 @@
 #include "ns3/attribute.h"
 #include "ns3/attribute-helper.h"
 #include "ipv4-address.h"
+#include "ipv6-address.h"
 
 namespace ns3 {
 
@@ -109,9 +110,21 @@
   static Mac48Address GetMulticast (Ipv4Address address);
 
   /**
+   * \brief Get multicast address from IPv6 address.
+   * \returns a multicast address
+   */
+  static Mac48Address GetMulticast (Ipv6Address address);
+
+  /**
    * \returns the multicast prefix (01:00:5e:00:00:00).
    */
   static Mac48Address GetMulticastPrefix (void);
+
+  /**
+   * \brief Get the multicast prefix for IPv6 (33:33:00:00:00:00).
+   * \returns a multicast address.
+   */
+  static Mac48Address GetMulticast6Prefix (void);
 private:
   /**
    * \returns a new Address instance
--- a/src/node/net-device.h	Thu Nov 06 15:04:25 2008 -0800
+++ b/src/node/net-device.h	Fri Nov 07 11:36:15 2008 -0800
@@ -28,6 +28,7 @@
 #include "ns3/ptr.h"
 #include "address.h"
 #include "ipv4-address.h"
+#include "ipv6-address.h"
 
 namespace ns3 {
 
@@ -173,6 +174,15 @@
    */
   virtual Address GetMulticast (Ipv4Address multicastGroup) const = 0;
   
+	/**
+   * \brief Get the MAC multicast address corresponding
+   * to the IPv6 address provided.
+   * \param addr IPv6 address
+   * \return the MAC multicast address
+   * \warning Calling this method is invalid if IsMulticast returns not true.
+   */
+  virtual Address GetMulticast (Ipv6Address addr) const = 0;
+
   /**
    * \return value of m_isPointToPoint flag
    */
--- a/src/node/simple-net-device.cc	Thu Nov 06 15:04:25 2008 -0800
+++ b/src/node/simple-net-device.cc	Fri Nov 07 11:36:15 2008 -0800
@@ -152,6 +152,12 @@
 {
   return Mac48Address::GetMulticast (multicastGroup);
 }
+
+Address SimpleNetDevice::GetMulticast (Ipv6Address addr) const
+{
+	return Mac48Address::GetMulticast (addr);
+}
+
 bool 
 SimpleNetDevice::IsPointToPoint (void) const
 {
--- a/src/node/simple-net-device.h	Thu Nov 06 15:04:25 2008 -0800
+++ b/src/node/simple-net-device.h	Fri Nov 07 11:36:15 2008 -0800
@@ -67,6 +67,9 @@
   virtual void SetNode (Ptr<Node> node);
   virtual bool NeedsArp (void) const;
   virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb);
+
+  virtual Address GetMulticast (Ipv6Address addr) const;
+
   virtual void SetPromiscReceiveCallback (PromiscReceiveCallback cb);
   virtual bool SupportsSendFrom (void) const;
 
--- a/src/node/wscript	Thu Nov 06 15:04:25 2008 -0800
+++ b/src/node/wscript	Fri Nov 07 11:36:15 2008 -0800
@@ -34,6 +34,10 @@
         'application.cc',
         'simple-channel.cc',
         'simple-net-device.cc',
+        'inet6-socket-address.cc',
+        'ipv6-address.cc',
+        'ipv6-header.cc',
+        'icmp-socket.cc',
         'ipv4-raw-socket-factory.cc',
         ]
 
@@ -70,5 +74,9 @@
         'application.h',
         'simple-channel.h',
         'simple-net-device.h',
+        'inet6-socket-address.h',
+        'ipv6-address.h',
+        'ipv6-header.h',
+        'icmp-socket.h',
         'ipv4-raw-socket-factory.h',
         ]