Bug 1362 - ICMPv6 does not forward ICMPs to upper layers
authorGustavo J. A. M. Carneiro <gjc@inescporto.pt>
Wed, 21 Mar 2012 18:51:55 +0100
changeset 7790 47d6d575412c
parent 7789 c6120568876e
child 7791 21c3495394b4
Bug 1362 - ICMPv6 does not forward ICMPs to upper layers
RELEASE_NOTES
src/internet/model/icmpv6-l4-protocol.cc
src/internet/model/icmpv6-l4-protocol.h
src/internet/model/ipv6-end-point-demux.cc
src/internet/model/ipv6-end-point-demux.h
src/internet/model/ipv6-extension.cc
src/internet/model/ipv6-extension.h
src/internet/model/ipv6-l3-protocol.cc
src/internet/model/ipv6-list-routing.cc
src/internet/model/ipv6-list-routing.h
src/internet/model/ipv6-static-routing.cc
src/internet/model/ipv6-static-routing.h
src/internet/model/tcp-socket-base.cc
src/internet/test/ipv6-fragmentation-test.cc
src/internet/wscript
--- a/RELEASE_NOTES	Fri Mar 23 23:51:29 2012 -0700
+++ b/RELEASE_NOTES	Wed Mar 21 18:51:55 2012 +0100
@@ -32,6 +32,7 @@
  - bug 1357 - IPv6 fragmentation fails due to checks about malformed extensions
  - bug 1378 - UdpEchoClient::SetFill () does not set packet size correctly
  - bug 1351 and 1333 - TCP not able to take RTT samples on long delay network
+ - bug 1362 - ICMPv6 does not forward ICMPs to upper layers (and minor fixes to ICMPv6)
 
 Known issues
 ------------
--- a/src/internet/model/icmpv6-l4-protocol.cc	Fri Mar 23 23:51:29 2012 -0700
+++ b/src/internet/model/icmpv6-l4-protocol.cc	Wed Mar 21 18:51:55 2012 +0100
@@ -18,6 +18,7 @@
  * Author: Sebastien Vincent <[email protected]>
  *         David Gross <[email protected]>
  *         Mehdi Benamor <[email protected]>
+ *         Tommaso Pecorella <[email protected]>
  */
 
 #include "ns3/log.h"
@@ -34,8 +35,7 @@
 #include "icmpv6-l4-protocol.h"
 #include "ndisc-cache.h"
 
-namespace ns3
-{
+namespace ns3 {
 
 NS_OBJECT_ENSURE_REGISTERED (Icmpv6L4Protocol);
 
@@ -97,7 +97,7 @@
       cache = 0;
     }
   m_cacheList.clear ();
-  m_downTarget.Nullify();
+  m_downTarget.Nullify ();
 
   m_node = 0;
   IpL4Protocol::DoDispose ();
@@ -114,11 +114,11 @@
           Ptr<Ipv6L3Protocol> ipv6 = this->GetObject<Ipv6L3Protocol> ();
           if (ipv6 != 0)
             {
-              this->SetNode (node);
+              SetNode (node);
               ipv6->Insert (this);
               Ptr<Ipv6RawSocketFactoryImpl> rawFactory = CreateObject<Ipv6RawSocketFactoryImpl> ();
               ipv6->AggregateObject (rawFactory);
-              this->SetDownTarget6 (MakeCallback (&Ipv6L3Protocol::Send, ipv6));
+              SetDownTarget6 (MakeCallback (&Ipv6L3Protocol::Send, ipv6));
             }
         }
     }
@@ -162,9 +162,9 @@
 
   NS_ASSERT (ipv6);
 
-  if(!m_alwaysDad)
+  if (!m_alwaysDad)
     {
-      return; 
+      return;
     }
 
   /* TODO : disable multicast loopback to prevent NS probing to be received by the sender */
@@ -192,7 +192,7 @@
   uint8_t type;
   p->CopyData (&type, sizeof(type));
 
-  switch (type) 
+  switch (type)
     {
     case Icmpv6Header::ICMPV6_ND_ROUTER_SOLICITATION:
       if (ipv6->IsForwarding (ipv6->GetInterfaceForDevice (interface->GetDevice ())))
@@ -219,14 +219,21 @@
       HandleEchoRequest (p, src, dst, interface);
       break;
     case Icmpv6Header::ICMPV6_ECHO_REPLY:
+      // EchoReply does not contain any info about L4
+      // so we can not forward it up.
+      // TODO: implement request / reply consistency check.
       break;
     case Icmpv6Header::ICMPV6_ERROR_DESTINATION_UNREACHABLE:
+      HandleDestinationUnreachable (p, src, dst, interface);
       break;
     case Icmpv6Header::ICMPV6_ERROR_PACKET_TOO_BIG:
+      HandlePacketTooBig (p, src, dst, interface);
       break;
     case Icmpv6Header::ICMPV6_ERROR_TIME_EXCEEDED:
+      HandleTimeExceeded (p, src, dst, interface);
       break;
     case Icmpv6Header::ICMPV6_ERROR_PARAMETER_ERROR:
+      HandleParameterError (p, src, dst, interface);
       break;
     default:
       NS_LOG_LOGIC ("Unknown ICMPv6 message type=" << type);
@@ -236,6 +243,24 @@
   return IpL4Protocol::RX_OK;
 }
 
+void Icmpv6L4Protocol::Forward (Ipv6Address source, Icmpv6Header icmp,
+                                uint32_t info, Ipv6Header ipHeader,
+                                const uint8_t payload[8])
+{
+  Ptr<Ipv6L3Protocol> ipv6 = m_node->GetObject<Ipv6L3Protocol> ();
+
+  // TODO assuming the ICMP is carrying a extensionless IP packet
+
+  uint8_t nextHeader = ipHeader.GetNextHeader ();
+
+  Ptr<IpL4Protocol> l4 = ipv6->GetProtocol (nextHeader);
+  if (l4 != 0)
+    {
+      l4->ReceiveIcmp (source, ipHeader.GetHopLimit (), icmp.GetType (), icmp.GetCode (),
+                       info, ipHeader.GetSourceAddress (), ipHeader.GetDestinationAddress (), payload);
+    }
+}
+
 void Icmpv6L4Protocol::HandleEchoRequest (Ptr<Packet> packet, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface)
 {
   NS_LOG_FUNCTION (this << packet << src << dst << interface);
@@ -253,7 +278,7 @@
 }
 
 void Icmpv6L4Protocol::HandleRA (Ptr<Packet> packet, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface)
-{ 
+{
   NS_LOG_FUNCTION (this << packet << src << dst << interface);
   Ptr<Packet> p = packet->Copy ();
   Icmpv6RA raHeader;
@@ -276,7 +301,7 @@
         {
         case Icmpv6Header::ICMPV6_OPT_PREFIX:
           p->RemoveHeader (prefixHdr);
-          ipv6->AddAutoconfiguredAddress (ipv6->GetInterfaceForDevice (interface->GetDevice ()), prefixHdr.GetPrefix (), prefixHdr.GetPrefixLength (), 
+          ipv6->AddAutoconfiguredAddress (ipv6->GetInterfaceForDevice (interface->GetDevice ()), prefixHdr.GetPrefix (), prefixHdr.GetPrefixLength (),
                                           prefixHdr.GetFlags (), prefixHdr.GetValidTime (), prefixHdr.GetPreferredTime (), src);
           break;
         case Icmpv6Header::ICMPV6_OPT_MTU:
@@ -312,7 +337,7 @@
   NdiscCache::Entry* entry = 0;
   Ptr<NdiscCache> cache = FindCache (interface->GetDevice ());
 
-  /* check if we have this address in our cache */ 
+  /* check if we have this address in our cache */
   entry = cache->Lookup (src);
 
   if (!entry)
@@ -329,11 +354,11 @@
       if (entry->IsIncomplete ())
         {
           entry->StopRetransmitTimer ();
-          // mark it to reachable 
+          // mark it to reachable
           waiting = entry->MarkReachable (lla.GetAddress ());
           entry->StopReachableTimer ();
           entry->StartReachableTimer ();
-          // send out waiting packet 
+          // send out waiting packet
           for (std::list<Ptr<Packet> >::const_iterator it = waiting.begin (); it != waiting.end (); it++)
             {
               cache->GetInterface ()->Send (*it, src);
@@ -342,7 +367,7 @@
         }
       else
         {
-          if (entry->GetMacAddress ()!=lla.GetAddress ())
+          if (entry->GetMacAddress () != lla.GetAddress ())
             {
               entry->SetMacAddress (lla.GetAddress ());
               entry->MarkStale ();
@@ -497,7 +522,7 @@
 
   hardwareAddress = interface->GetDevice ()->GetAddress ();
   Ptr<Packet> p = ForgeNA (target.IsLinkLocal () ? interface->GetLinkLocalAddress ().GetAddress () : ifaddr.GetAddress (), src.IsAny () ? Ipv6Address::GetAllNodesMulticast () : src, &hardwareAddress, flags );
-  interface->Send (p,  src.IsAny () ? Ipv6Address::GetAllNodesMulticast () : src); 
+  interface->Send (p,  src.IsAny () ? Ipv6Address::GetAllNodesMulticast () : src);
 
   /* not a NS for us discard it */
 }
@@ -633,7 +658,7 @@
       entry->StopDelayTimer ();
 
       /* if the Flag O is clear and mac address differs from the cache */
-      if (!naHeader.GetFlagO () && lla.GetAddress ()!=entry->GetMacAddress ())
+      if (!naHeader.GetFlagO () && lla.GetAddress () != entry->GetMacAddress ())
         {
           if (entry->IsReachable ())
             {
@@ -656,7 +681,7 @@
                           waiting = entry->MarkReachable (lla.GetAddress ());
                           for (std::list<Ptr<Packet> >::const_iterator it = waiting.begin (); it != waiting.end (); it++)
                             {
-                              cache->GetInterface ()->Send (*it, src); 
+                              cache->GetInterface ()->Send (*it, src);
                             }
                           entry->ClearWaitingPacket ();
                         }
@@ -668,7 +693,7 @@
                   entry->StopReachableTimer ();
                   entry->StartReachableTimer ();
                 }
-              else if (lla.GetAddress ()!=entry->GetMacAddress ())
+              else if (lla.GetAddress () != entry->GetMacAddress ())
                 {
                   entry->MarkStale ();
                 }
@@ -723,7 +748,7 @@
           if (entry->IsIncomplete () || entry->GetMacAddress () != llOptionHeader.GetAddress ())
             {
               /* update entry to STALE */
-              if (entry->GetMacAddress ()!=llOptionHeader.GetAddress ())
+              if (entry->GetMacAddress () != llOptionHeader.GetAddress ())
                 {
                   entry->SetMacAddress (llOptionHeader.GetAddress ());
                   entry->MarkStale ();
@@ -750,6 +775,73 @@
     }
 }
 
+void Icmpv6L4Protocol::HandleDestinationUnreachable (Ptr<Packet> p, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface)
+{
+  NS_LOG_FUNCTION (this << *p << src << dst);
+  Ptr<Packet> pkt = p->Copy ();
+
+  Icmpv6DestinationUnreachable unreach;
+  pkt->RemoveHeader (unreach);
+  Ptr<Packet> origPkt = unreach.GetPacket ();
+
+  Ipv6Header ipHeader;
+  if ( origPkt->GetSerializedSize () > ipHeader.GetSerializedSize () )
+    {
+      origPkt->RemoveHeader (ipHeader);
+      uint8_t payload[8];
+      origPkt->CopyData (payload, 8);
+      Forward (src, unreach, unreach.GetCode (), ipHeader, payload);
+    }
+}
+
+void Icmpv6L4Protocol::HandleTimeExceeded (Ptr<Packet> p, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface)
+{
+  NS_LOG_FUNCTION (this << *p << src << dst);
+  Ptr<Packet> pkt = p->Copy ();
+
+  Icmpv6TimeExceeded timeexceeded;
+  pkt->RemoveHeader (timeexceeded);
+  Ptr<Packet> origPkt = timeexceeded.GetPacket ();
+  Ipv6Header ipHeader;
+  uint8_t payload[8];
+  origPkt->RemoveHeader (ipHeader);
+  origPkt->CopyData (payload, 8);
+
+  Forward (src, timeexceeded, timeexceeded.GetCode (), ipHeader, payload);
+}
+
+void Icmpv6L4Protocol::HandlePacketTooBig (Ptr<Packet> p, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface)
+{
+  NS_LOG_FUNCTION (this << *p << src << dst);
+  Ptr<Packet> pkt = p->Copy ();
+
+  Icmpv6TooBig tooBig;
+  pkt->RemoveHeader (tooBig);
+  Ptr<Packet> origPkt = tooBig.GetPacket ();
+
+  Ipv6Header ipHeader;
+  origPkt->RemoveHeader (ipHeader);
+  uint8_t payload[8];
+  origPkt->CopyData (payload, 8);
+  Forward (src, tooBig, tooBig.GetMtu (), ipHeader, payload);
+}
+
+void Icmpv6L4Protocol::HandleParameterError (Ptr<Packet> p, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface)
+{
+  NS_LOG_FUNCTION (this << *p << src << dst);
+  Ptr<Packet> pkt = p->Copy ();
+
+  Icmpv6ParameterError paramErr;
+  pkt->RemoveHeader (paramErr);
+  Ptr<Packet> origPkt = paramErr.GetPacket ();
+
+  Ipv6Header ipHeader;
+  origPkt->RemoveHeader (ipHeader);
+  uint8_t payload[8];
+  origPkt->CopyData (payload, 8);
+  Forward (src, paramErr, paramErr.GetCode (), ipHeader, payload);
+}
+
 void Icmpv6L4Protocol::SendMessage (Ptr<Packet> packet, Ipv6Address src, Ipv6Address dst, uint8_t ttl)
 {
   NS_LOG_FUNCTION (this << packet << src << dst << (uint32_t)ttl);
@@ -851,7 +943,7 @@
       dst = Ipv6Address::GetAllNodesMulticast ();
     }
 
-  NS_LOG_LOGIC ("Send NS ( from " << src << " to " << dst << " target " << target <<")");
+  NS_LOG_LOGIC ("Send NS ( from " << src << " to " << dst << " target " << target << ")");
 
   p->AddHeader (llOption);
   ns.CalculatePseudoHeaderChecksum (src, dst, p->GetSize () + ns.GetSerializedSize (), PROT_NUMBER);
@@ -930,7 +1022,7 @@
 
 void Icmpv6L4Protocol::SendErrorTimeExceeded (Ptr<Packet> malformedPacket, Ipv6Address dst, uint8_t code)
 {
-  NS_LOG_FUNCTION (this<< malformedPacket << dst << code);
+  NS_LOG_FUNCTION (this << malformedPacket << dst << code);
   Ptr<Packet> p = Create<Packet> ();
   uint32_t malformedPacketSize = malformedPacket->GetSize ();
   Icmpv6TimeExceeded header;
@@ -938,7 +1030,7 @@
   NS_LOG_LOGIC ("Send Time Exceeded ( to " << dst << " code " << (uint32_t)code << " )");
 
   /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
-  if (malformedPacketSize <= 1280 - 48) 
+  if (malformedPacketSize <= 1280 - 48)
     {
       header.SetPacket (malformedPacket);
     }
@@ -962,7 +1054,7 @@
   NS_LOG_LOGIC ("Send Parameter Error ( to " << dst << " code " << (uint32_t)code << " )");
 
   /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
-  if (malformedPacketSize <= 1280 -48 )
+  if (malformedPacketSize <= 1280 - 48 )
     {
       header.SetPacket (malformedPacket);
     }
@@ -992,7 +1084,7 @@
   if ((redirectedPacketSize % 8) != 0)
     {
       Ptr<Packet> pad = Create<Packet> (8 - (redirectedPacketSize % 8));
-      redirectedPacket->AddAtEnd (pad); 
+      redirectedPacket->AddAtEnd (pad);
     }
 
   if (redirHardwareTarget.GetLength ())
@@ -1081,7 +1173,7 @@
       dst = Ipv6Address::GetAllNodesMulticast ();
     }
 
-  NS_LOG_LOGIC ("Send NS ( from " << src << " to " << dst << " target " << target <<")");
+  NS_LOG_LOGIC ("Send NS ( from " << src << " to " << dst << " target " << target << ")");
 
   p->AddHeader (llOption);
   ns.CalculatePseudoHeaderChecksum (src, dst, p->GetSize () + ns.GetSerializedSize (), PROT_NUMBER);
@@ -1196,7 +1288,7 @@
       else
         {
           /* find source address that match destination */
-          addr = cache->GetInterface ()->GetAddressMatchingDestination (dst).GetAddress (); 
+          addr = cache->GetInterface ()->GetAddressMatchingDestination (dst).GetAddress ();
         }
 
       SendNS (addr, Ipv6Address::MakeSolicitedAddress (dst), dst, cache->GetDevice ()->GetAddress ());
@@ -1229,7 +1321,7 @@
         }
     }
 
-  /* for the moment, this function is always called, if we was victim of a DAD the address is INVALID 
+  /* for the moment, this function is always called, if we was victim of a DAD the address is INVALID
    * and we do not set it to PREFERRED
    */
   if (found && ifaddr.GetState () != Ipv6InterfaceAddress::INVALID)
@@ -1242,9 +1334,9 @@
        */
       Ptr<Ipv6> ipv6 = icmpv6->m_node->GetObject<Ipv6> ();
 
-      if (!ipv6->IsForwarding (ipv6->GetInterfaceForDevice (interface->GetDevice ())) && addr.IsLinkLocal ()) 
+      if (!ipv6->IsForwarding (ipv6->GetInterfaceForDevice (interface->GetDevice ())) && addr.IsLinkLocal ())
         {
-          /* XXX because all nodes start at the same time, there will be many of RS arround 1 second of simulation time 
+          /* XXX because all nodes start at the same time, there will be many of RS arround 1 second of simulation time
            * TODO Add random delays before sending RS
            */
           Simulator::Schedule (Seconds (0.0), &Icmpv6L4Protocol::SendRS, PeekPointer (icmpv6), ifaddr.GetAddress (), Ipv6Address::GetAllRoutersMulticast (), interface->GetDevice ()->GetAddress ());
--- a/src/internet/model/icmpv6-l4-protocol.h	Fri Mar 23 23:51:29 2012 -0700
+++ b/src/internet/model/icmpv6-l4-protocol.h	Wed Mar 21 18:51:55 2012 +0100
@@ -29,8 +29,7 @@
 #include "icmpv6-header.h"
 #include "ip-l4-protocol.h"
 
-namespace ns3
-{
+namespace ns3 {
 
 class NetDevice;
 class Node;
@@ -194,7 +193,7 @@
    * \brief Send a packet via ICMPv6.
    * \param packet the packet to send
    * \param dst destination address
-   * \param icmpv6Hdr ICMPv6 header (needed to calculate checksum 
+   * \param icmpv6Hdr ICMPv6 header (needed to calculate checksum
    * after source address is determined by routing stuff
    * \param ttl next hop limit
    */
@@ -202,8 +201,8 @@
 
   /**
    * \brief Do the Duplication Address Detection (DAD).
-   * It consists in sending a NS with our IPv6 as target. If 
-   * we received a NA with matched target address, we could not use 
+   * It consists in sending a NS with our IPv6 as target. If
+   * we received a NA with matched target address, we could not use
    * the address, else the address pass from TENTATIVE to PERMANENT.
    *
    * \param target target address
@@ -325,13 +324,20 @@
   /**
    * \brief Receive method.
    * \param p the packet
-   * \param src source address
-   * \param dst destination address
+   * \param header the IPv4 header
    * \param interface the interface from which the packet is coming
    */
   virtual enum IpL4Protocol::RxStatus Receive (Ptr<Packet> p,
                                                Ipv4Header const &header,
                                                Ptr<Ipv4Interface> interface);
+
+  /**
+   * \brief Receive method.
+   * \param p the packet
+   * \param src source address
+   * \param dst destination address
+   * \param interface the interface from which the packet is coming
+   */
   virtual enum IpL4Protocol::RxStatus Receive (Ptr<Packet> p,
                                                Ipv6Address &src, Ipv6Address &dst,
                                                Ptr<Ipv6Interface> interface);
@@ -396,7 +402,6 @@
   virtual void DoDispose ();
 
 private:
-
   typedef std::list<Ptr<NdiscCache> > CacheList;
 
   /**
@@ -415,6 +420,18 @@
   bool m_alwaysDad;
 
   /**
+   * \brief Notify an ICMPv6 reception to upper layers (if requested).
+   * \param source the ICMP source
+   * \param icmp the ICMP header
+   * \param info information about the ICMP
+   * \param ipHeader the IP header carried by the ICMP
+   * \param payload the data carried by the ICMP
+   */
+  void Forward (Ipv6Address source, Icmpv6Header icmp,
+                uint32_t info, Ipv6Header ipHeader,
+                const uint8_t payload[8]);
+
+  /**
    * \brief Receive Neighbor Solicitation method.
    * \param p the packet
    * \param src source address
@@ -469,6 +486,42 @@
   void HandleRedirection (Ptr<Packet> p, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface);
 
   /**
+   * \brief Receive Destination Unreachable method.
+   * \param p the packet
+   * \param src source address
+   * \param dst destination address
+   * \param interface the interface from which the packet is coming
+   */
+  void HandleDestinationUnreachable (Ptr<Packet> p, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface);
+
+  /**
+   * \brief Receive Time Exceeded method.
+   * \param p the packet
+   * \param src source address
+   * \param dst destination address
+   * \param interface the interface from which the packet is coming
+   */
+  void HandleTimeExceeded (Ptr<Packet> p, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface);
+
+  /**
+   * \brief Receive Packet Too Big method.
+   * \param p the packet
+   * \param src source address
+   * \param dst destination address
+   * \param interface the interface from which the packet is coming
+   */
+  void HandlePacketTooBig (Ptr<Packet> p, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface);
+
+  /**
+   * \brief Receive Parameter Error method.
+   * \param p the packet
+   * \param src source address
+   * \param dst destination address
+   * \param interface the interface from which the packet is coming
+   */
+  void HandleParameterError (Ptr<Packet> p, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface);
+
+  /**
    * \brief Link layer address option processing.
    * \param lla LLA option
    * \param src source address
--- a/src/internet/model/ipv6-end-point-demux.cc	Fri Mar 23 23:51:29 2012 -0700
+++ b/src/internet/model/ipv6-end-point-demux.cc	Wed Mar 21 18:51:55 2012 +0100
@@ -22,13 +22,14 @@
 #include "ipv6-end-point.h"
 #include "ns3/log.h"
 
-namespace ns3
-{
+namespace ns3 {
 
 NS_LOG_COMPONENT_DEFINE ("Ipv6EndPointDemux");
 
 Ipv6EndPointDemux::Ipv6EndPointDemux ()
-  : m_ephemeral (49152)
+  : m_ephemeral (49152),
+    m_portFirst (49152),
+    m_portLast (65535)
 {
   NS_LOG_FUNCTION_NOARGS ();
 }
@@ -36,7 +37,7 @@
 Ipv6EndPointDemux::~Ipv6EndPointDemux ()
 {
   NS_LOG_FUNCTION_NOARGS ();
-  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++) 
+  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
     {
       Ipv6EndPoint *endPoint = *i;
       delete endPoint;
@@ -47,9 +48,9 @@
 bool Ipv6EndPointDemux::LookupPortLocal (uint16_t port)
 {
   NS_LOG_FUNCTION (this << port);
-  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++) 
+  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
     {
-      if ((*i)->GetLocalPort  () == port) 
+      if ((*i)->GetLocalPort  () == port)
         {
           return true;
         }
@@ -60,10 +61,10 @@
 bool Ipv6EndPointDemux::LookupLocal (Ipv6Address addr, uint16_t port)
 {
   NS_LOG_FUNCTION (this << addr << port);
-  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++) 
+  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
     {
-      if ((*i)->GetLocalPort () == port &&
-          (*i)->GetLocalAddress () == addr) 
+      if ((*i)->GetLocalPort () == port
+          && (*i)->GetLocalAddress () == addr)
         {
           return true;
         }
@@ -75,7 +76,7 @@
 {
   NS_LOG_FUNCTION_NOARGS ();
   uint16_t port = AllocateEphemeralPort ();
-  if (port == 0) 
+  if (port == 0)
     {
       NS_LOG_WARN ("Ephemeral port allocation failed.");
       return 0;
@@ -90,7 +91,7 @@
 {
   NS_LOG_FUNCTION (this << address);
   uint16_t port = AllocateEphemeralPort ();
-  if (port == 0) 
+  if (port == 0)
     {
       NS_LOG_WARN ("Ephemeral port allocation failed.");
       return 0;
@@ -111,7 +112,7 @@
 Ipv6EndPoint* Ipv6EndPointDemux::Allocate (Ipv6Address address, uint16_t port)
 {
   NS_LOG_FUNCTION (this << address << port);
-  if (LookupLocal (address, port)) 
+  if (LookupLocal (address, port))
     {
       NS_LOG_WARN ("Duplicate address/port; failing.");
       return 0;
@@ -126,12 +127,12 @@
                                            Ipv6Address peerAddress, uint16_t peerPort)
 {
   NS_LOG_FUNCTION (this << localAddress << localPort << peerAddress << peerPort);
-  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++) 
+  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
     {
-      if ((*i)->GetLocalPort () == localPort &&
-          (*i)->GetLocalAddress () == localAddress &&
-          (*i)->GetPeerPort () == peerPort &&
-          (*i)->GetPeerAddress () == peerAddress) 
+      if ((*i)->GetLocalPort () == localPort
+          && (*i)->GetLocalAddress () == localAddress
+          && (*i)->GetPeerPort () == peerPort
+          && (*i)->GetPeerAddress () == peerAddress)
         {
           NS_LOG_WARN ("No way we can allocate this end-point.");
           /* no way we can allocate this end-point. */
@@ -150,7 +151,7 @@
 void Ipv6EndPointDemux::DeAllocate (Ipv6EndPoint *endPoint)
 {
   NS_LOG_FUNCTION_NOARGS ();
-  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++) 
+  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
     {
       if (*i == endPoint)
         {
@@ -166,7 +167,7 @@
  * Otherwise, if we find a generic match, we return it.
  * Otherwise, we return 0.
  */
-Ipv6EndPointDemux::EndPoints Ipv6EndPointDemux::Lookup (Ipv6Address daddr, uint16_t dport, 
+Ipv6EndPointDemux::EndPoints Ipv6EndPointDemux::Lookup (Ipv6Address daddr, uint16_t dport,
                                                         Ipv6Address saddr, uint16_t sport,
                                                         Ptr<Ipv6Interface> incomingInterface)
 {
@@ -178,14 +179,14 @@
   EndPoints retval4; /* Exact match on all 4 */
 
   NS_LOG_DEBUG ("Looking up endpoint for destination address " << daddr);
-  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++) 
+  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
     {
       Ipv6EndPoint* endP = *i;
       NS_LOG_DEBUG ("Looking at endpoint dport=" << endP->GetLocalPort ()
                                                  << " daddr=" << endP->GetLocalAddress ()
                                                  << " sport=" << endP->GetPeerPort ()
                                                  << " saddr=" << endP->GetPeerAddress ());
-      if (endP->GetLocalPort () != dport) 
+      if (endP->GetLocalPort () != dport)
         {
           NS_LOG_LOGIC ("Skipping endpoint " << &endP
                                              << " because endpoint dport "
@@ -203,7 +204,9 @@
 
       /* if no match here, keep looking */
       if (!(localAddressMatchesExact || localAddressMatchesWildCard))
-        continue; 
+        {
+          continue;
+        }
       bool remotePeerMatchesExact = endP->GetPeerPort () == sport;
       bool remotePeerMatchesWildCard = endP->GetPeerPort () == 0;
       bool remoteAddressMatchesExact = endP->GetPeerAddress () == saddr;
@@ -212,41 +215,54 @@
       /* If remote does not match either with exact or wildcard,i
          skip this one */
       if (!(remotePeerMatchesExact || remotePeerMatchesWildCard))
-        continue;
+        {
+          continue;
+        }
       if (!(remoteAddressMatchesExact || remoteAddressMatchesWildCard))
-        continue;
+        {
+          continue;
+        }
 
       /* Now figure out which return list to add this one to */
-      if (localAddressMatchesWildCard &&
-          remotePeerMatchesWildCard && 
-          remoteAddressMatchesWildCard)
+      if (localAddressMatchesWildCard
+          && remotePeerMatchesWildCard
+          && remoteAddressMatchesWildCard)
         { /* Only local port matches exactly */
           retval1.push_back (endP);
         }
-      if ((localAddressMatchesExact || (localAddressMatchesAllRouters))&&
-          remotePeerMatchesWildCard &&
-          remoteAddressMatchesWildCard)
+      if ((localAddressMatchesExact || (localAddressMatchesAllRouters))
+          && remotePeerMatchesWildCard
+          && remoteAddressMatchesWildCard)
         { /* Only local port and local address matches exactly */
           retval2.push_back (endP);
         }
-      if (localAddressMatchesWildCard &&
-          remotePeerMatchesExact &&
-          remoteAddressMatchesExact)
+      if (localAddressMatchesWildCard
+          && remotePeerMatchesExact
+          && remoteAddressMatchesExact)
         { /* All but local address */
           retval3.push_back (endP);
         }
-      if (localAddressMatchesExact &&
-          remotePeerMatchesExact &&
-          remoteAddressMatchesExact)
+      if (localAddressMatchesExact
+          && remotePeerMatchesExact
+          && remoteAddressMatchesExact)
         { /* All 4 match */
           retval4.push_back (endP);
         }
     }
 
   /* Here we find the most exact match */
-  if (!retval4.empty ()) return retval4;
-  if (!retval3.empty ()) return retval3;
-  if (!retval2.empty ()) return retval2;
+  if (!retval4.empty ())
+    {
+      return retval4;
+    }
+  if (!retval3.empty ())
+    {
+      return retval3;
+    }
+  if (!retval2.empty ())
+    {
+      return retval2;
+    }
   return retval1;  /* might be empty if no matches */
 }
 
@@ -264,8 +280,8 @@
           continue;
         }
 
-      if ((*i)->GetLocalAddress () == dst && (*i)->GetPeerPort () == sport &&
-          (*i)->GetPeerAddress () == src)
+      if ((*i)->GetLocalAddress () == dst && (*i)->GetPeerPort () == sport
+          && (*i)->GetPeerAddress () == src)
         {
           /* this is an exact match. */
           return *i;
@@ -294,19 +310,22 @@
 {
   NS_LOG_FUNCTION_NOARGS ();
   uint16_t port = m_ephemeral;
-  do 
+  int count = m_portLast - m_portFirst;
+  do
     {
-      port++;
-      if (port == 65535) 
+      if (count-- < 0)
         {
-          port = 49152;
+          return 0;
         }
-      if (!LookupPortLocal (port)) 
+      ++port;
+      if (port < m_portFirst || port > m_portLast)
         {
-          return port;
+          port = m_portFirst;
         }
-    } while (port != m_ephemeral);
-  return 0;
+    }
+  while (LookupPortLocal (port));
+  m_ephemeral = port;
+  return port;
 }
 
 Ipv6EndPointDemux::EndPoints Ipv6EndPointDemux::GetEndPoints () const
--- a/src/internet/model/ipv6-end-point-demux.h	Fri Mar 23 23:51:29 2012 -0700
+++ b/src/internet/model/ipv6-end-point-demux.h	Wed Mar 21 18:51:55 2012 +0100
@@ -26,8 +26,7 @@
 #include "ns3/ipv6-address.h"
 #include "ipv6-interface.h"
 
-namespace ns3
-{
+namespace ns3 {
 
 class Ipv6EndPoint;
 
@@ -91,21 +90,21 @@
    * \brief Allocate a Ipv6EndPoint.
    * \return an empty Ipv6EndPoint instance
    */
-  Ipv6EndPoint *Allocate (void);
+  Ipv6EndPoint * Allocate (void);
 
   /**
    * \brief Allocate a Ipv6EndPoint.
    * \param address IPv6 address
    * \return an Ipv6EndPoint instance
    */
-  Ipv6EndPoint *Allocate (Ipv6Address address);
+  Ipv6EndPoint * Allocate (Ipv6Address address);
 
   /**
    * \brief Allocate a Ipv6EndPoint.
    * \param port local port
    * \return an Ipv6EndPoint instance
    */
-  Ipv6EndPoint *Allocate (uint16_t port);
+  Ipv6EndPoint * Allocate (uint16_t port);
 
   /**
    * \brief Allocate a Ipv6EndPoint.
@@ -113,7 +112,7 @@
    * \param port local port
    * \return an Ipv6EndPoint instance
    */
-  Ipv6EndPoint *Allocate (Ipv6Address address, uint16_t port);
+  Ipv6EndPoint * Allocate (Ipv6Address address, uint16_t port);
 
   /**
    * \brief Allocate a Ipv6EndPoint.
@@ -123,7 +122,7 @@
    * \param peerPort peer port
    * \return an Ipv6EndPoint instance
    */
-  Ipv6EndPoint *Allocate (Ipv6Address localAddress, uint16_t localPort, Ipv6Address peerAddress, uint16_t peerPort);
+  Ipv6EndPoint * Allocate (Ipv6Address localAddress, uint16_t localPort, Ipv6Address peerAddress, uint16_t peerPort);
 
   /**
    * \brief Remove a end point.
@@ -150,6 +149,16 @@
   uint16_t m_ephemeral;
 
   /**
+   * \brief The first ephemeral port.
+   */
+  uint16_t m_portFirst;
+
+  /**
+   * \brief The last ephemeral port.
+   */
+  uint16_t m_portLast;
+
+  /**
    * \brief A list of IPv6 end points.
    */
   EndPoints m_endPoints;
--- a/src/internet/model/ipv6-extension.cc	Fri Mar 23 23:51:29 2012 -0700
+++ b/src/internet/model/ipv6-extension.cc	Wed Mar 21 18:51:55 2012 +0100
@@ -43,8 +43,7 @@
 
 NS_LOG_COMPONENT_DEFINE ("Ipv6Extension");
 
-namespace ns3
-{
+namespace ns3 {
 
 NS_OBJECT_ENSURE_REGISTERED (Ipv6Extension);
 
@@ -338,14 +337,17 @@
   std::pair<Ipv6Address, uint32_t> fragmentsId = std::make_pair<Ipv6Address, uint32_t> (src, identification);
   Ptr<Fragments> fragments;
 
+  Ipv6Header ipHeader = ipv6Header;
+  ipHeader.SetNextHeader (fragmentHeader.GetNextHeader ());
+
   MapFragments_t::iterator it = m_fragments.find (fragmentsId);
   if (it == m_fragments.end ())
     {
       fragments = Create<Fragments> ();
       m_fragments.insert (std::make_pair (fragmentsId, fragments));
-      EventId timeout = Simulator::Schedule (Seconds(60),
+      EventId timeout = Simulator::Schedule (Seconds (60),
                                              &Ipv6ExtensionFragment::HandleFragmentsTimeout, this,
-                                             fragmentsId, fragments, ipv6Header);
+                                             fragmentsId, fragments, ipHeader);
       fragments->SetTimeoutEventId (timeout);
     }
   else
@@ -365,11 +367,11 @@
   if (fragments->IsEntire ())
     {
       packet = fragments->GetPacket ();
-      fragments->CancelTimeout();
-      m_fragments.erase(fragmentsId);
+      fragments->CancelTimeout ();
+      m_fragments.erase (fragmentsId);
       isDropped = false;
     }
-  else 
+  else
     {
       // the fragment is not "dropped", but Ipv6L3Protocol::LocalDeliver must stop processing it.
       isDropped = true;
@@ -406,9 +408,9 @@
   Ptr<Ipv6Extension> extension = extensionDemux->GetExtension (nextHeader);
   uint8_t extensionHeaderLength;
 
-  while (moreHeader) 
+  while (moreHeader)
     {
-      if (nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP) 
+      if (nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
         {
           Ipv6ExtensionHopByHopHeader *hopbyhopHeader = new Ipv6ExtensionHopByHopHeader ();
           p->RemoveHeader (*hopbyhopHeader);
@@ -429,7 +431,7 @@
           unfragmentablePart.push_back (std::make_pair<Ipv6ExtensionHeader *, uint8_t> (hopbyhopHeader, Ipv6Header::IPV6_EXT_HOP_BY_HOP));
           unfragmentablePartSize += extensionHeaderLength;
         }
-      else if (nextHeader == Ipv6Header::IPV6_EXT_ROUTING) 
+      else if (nextHeader == Ipv6Header::IPV6_EXT_ROUTING)
         {
           uint8_t buf[2];
           p->CopyData (buf, sizeof(buf));
@@ -453,7 +455,7 @@
           unfragmentablePart.push_back (std::make_pair<Ipv6ExtensionHeader *, uint8_t> (routingHeader, Ipv6Header::IPV6_EXT_ROUTING));
           unfragmentablePartSize += extensionHeaderLength;
         }
-      else if (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION) 
+      else if (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION)
         {
           Ipv6ExtensionDestinationHeader *destinationHeader = new Ipv6ExtensionDestinationHeader ();
           p->RemoveHeader (*destinationHeader);
@@ -463,7 +465,7 @@
 
           uint8_t type;
           p->CopyData (&type, sizeof(type));
-          if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING 
+          if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING
                 || (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION && type == Ipv6Header::IPV6_EXT_ROUTING)))
             {
               moreHeader = false;
@@ -486,14 +488,14 @@
   uint32_t identification = (uint32_t) uvar.GetValue (0, (uint32_t)-1);
   uint16_t offset = 0;
 
-  do 
+  do
     {
       if (p->GetSize () > offset + maxFragmentablePartSize)
         {
           moreFragment = true;
           currentFragmentablePartSize = maxFragmentablePartSize;
         }
-      else 
+      else
         {
           moreFragment = false;
           currentFragmentablePartSize = p->GetSize () - offset;
@@ -516,15 +518,15 @@
         {
           if (it->second == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
             {
-              fragment->AddHeader (*dynamic_cast<Ipv6ExtensionHopByHopHeader *>(it->first));
+              fragment->AddHeader (*dynamic_cast<Ipv6ExtensionHopByHopHeader *> (it->first));
             }
           else if (it->second == Ipv6Header::IPV6_EXT_ROUTING)
             {
-              fragment->AddHeader (*dynamic_cast<Ipv6ExtensionLooseRoutingHeader *>(it->first));
+              fragment->AddHeader (*dynamic_cast<Ipv6ExtensionLooseRoutingHeader *> (it->first));
             }
           else if (it->second == Ipv6Header::IPV6_EXT_DESTINATION)
             {
-              fragment->AddHeader (*dynamic_cast<Ipv6ExtensionDestinationHeader *>(it->first));
+              fragment->AddHeader (*dynamic_cast<Ipv6ExtensionDestinationHeader *> (it->first));
             }
         }
 
@@ -534,7 +536,8 @@
       std::ostringstream oss;
       fragment->Print (oss);
       listFragments.push_back (fragment);
-    } while (moreFragment);
+    }
+  while (moreFragment);
 
   for (std::list<std::pair<Ipv6ExtensionHeader *, uint8_t> >::iterator it = unfragmentablePart.begin (); it != unfragmentablePart.end (); it++)
     {
@@ -549,17 +552,19 @@
 {
   Ptr<Packet> packet = fragments->GetPartialPacket ();
 
+  packet->AddHeader (ipHeader);
+
   // if we have at least 8 bytes, we can send an ICMP.
   if ( packet->GetSize () > 8 )
     {
 
-      Ptr<Icmpv6L4Protocol> icmp = GetNode()->GetObject<Icmpv6L4Protocol> ();
+      Ptr<Icmpv6L4Protocol> icmp = GetNode ()->GetObject<Icmpv6L4Protocol> ();
       icmp->SendErrorTimeExceeded (packet, ipHeader.GetSourceAddress (), Icmpv6Header::ICMPV6_FRAGTIME);
     }
   m_dropTrace (packet);
 
   // clear the buffers
-  m_fragments.erase(fragmentsId);
+  m_fragments.erase (fragmentsId);
 }
 
 Ipv6ExtensionFragment::Fragments::Fragments ()
@@ -591,7 +596,7 @@
   m_fragments.insert (it, std::make_pair<Ptr<Packet>, uint16_t> (fragment, fragmentOffset));
 }
 
-void Ipv6ExtensionFragment::Fragments::SetUnfragmentablePart (Ptr<Packet> unfragmentablePart) 
+void Ipv6ExtensionFragment::Fragments::SetUnfragmentablePart (Ptr<Packet> unfragmentablePart)
 {
   m_unfragmentable = unfragmentablePart;
 }
@@ -661,14 +666,14 @@
 
 void Ipv6ExtensionFragment::Fragments::SetTimeoutEventId (EventId event)
 {
-    m_timeoutEventId = event;
-    return;
+  m_timeoutEventId = event;
+  return;
 }
 
-void Ipv6ExtensionFragment::Fragments::CancelTimeout()
+void Ipv6ExtensionFragment::Fragments::CancelTimeout ()
 {
-    m_timeoutEventId.Cancel ();
-    return;
+  m_timeoutEventId.Cancel ();
+  return;
 }
 
 
@@ -727,7 +732,7 @@
 
   if (nextHeader)
     {
-      *nextHeader = routingNextHeader; 
+      *nextHeader = routingNextHeader;
     }
 
   Ptr<Icmpv6L4Protocol> icmpv6 = GetNode ()->GetObject<Ipv6L3Protocol> ()->GetIcmpv6 ();
@@ -918,7 +923,7 @@
   nextAddressIndex = nbAddress - segmentsLeft;
   nextAddress = routingHeader.GetRouterAddress (nextAddressIndex);
 
-  if (nextAddress.IsMulticast () || destAddress.IsMulticast ()) 
+  if (nextAddress.IsMulticast () || destAddress.IsMulticast ())
     {
       m_dropTrace (packet);
       isDropped = true;
@@ -941,10 +946,10 @@
   ipv6header.SetHopLimit (hopLimit - 1);
   p->AddHeader (routingHeader);
 
-  /* short-circuiting routing stuff 
-   * 
+  /* short-circuiting routing stuff
+   *
    * If we process this option,
-   * the packet was for us so we resend it to 
+   * the packet was for us so we resend it to
    * the new destination (modified in the header above).
    */
 
@@ -966,7 +971,7 @@
     }
 
   /* as we directly send packet, mark it as dropped */
-  isDropped = true; 
+  isDropped = true;
 
   return routingHeader.GetSerializedSize ();
 }
--- a/src/internet/model/ipv6-extension.h	Fri Mar 23 23:51:29 2012 -0700
+++ b/src/internet/model/ipv6-extension.h	Wed Mar 21 18:51:55 2012 +0100
@@ -35,8 +35,7 @@
 #include "ns3/traced-callback.h"
 
 
-namespace ns3
-{
+namespace ns3 {
 
 /**
  * \class Ipv6Extension
@@ -309,7 +308,7 @@
 
     /**
      * \brief If all fragments have been added.
-     * \returns true if the packet is entire 
+     * \returns true if the packet is entire
      */
     bool IsEntire () const;
 
--- a/src/internet/model/ipv6-l3-protocol.cc	Fri Mar 23 23:51:29 2012 -0700
+++ b/src/internet/model/ipv6-l3-protocol.cc	Wed Mar 21 18:51:55 2012 +0100
@@ -41,8 +41,7 @@
 #include "icmpv6-l4-protocol.h"
 #include "ndisc-cache.h"
 
-namespace ns3
-{
+namespace ns3 {
 
 NS_OBJECT_ENSURE_REGISTERED (Ipv6L3Protocol);
 
@@ -130,7 +129,7 @@
   m_routingProtocol->SetIpv6 (this);
 }
 
-Ptr<Ipv6RoutingProtocol> Ipv6L3Protocol::GetRoutingProtocol () const 
+Ptr<Ipv6RoutingProtocol> Ipv6L3Protocol::GetRoutingProtocol () const
 {
   NS_LOG_FUNCTION_NOARGS ();
   return m_routingProtocol;
@@ -175,7 +174,7 @@
   return 0;
 }
 
-uint32_t Ipv6L3Protocol::GetNInterfaces () const 
+uint32_t Ipv6L3Protocol::GetNInterfaces () const
 {
   NS_LOG_FUNCTION_NOARGS ();
   return m_nInterfaces;
@@ -183,7 +182,7 @@
 
 int32_t Ipv6L3Protocol::GetInterfaceForAddress (Ipv6Address address) const
 {
-  NS_LOG_FUNCTION (this << address); 
+  NS_LOG_FUNCTION (this << address);
   int32_t index = 0;
 
   for (Ipv6InterfaceList::const_iterator it = m_interfaces.begin (); it != m_interfaces.end (); it++)
@@ -193,7 +192,7 @@
 
       for (j = 0; j < max; j++)
         {
-          if ((*it)->GetAddress (j).GetAddress () == address) 
+          if ((*it)->GetAddress (j).GetAddress () == address)
             {
               return index;
             }
@@ -252,7 +251,7 @@
 
   Address addr = GetInterface (interface)->GetDevice ()->GetAddress ();
 
-  if (flags & (1<< 6)) /* auto flag */
+  if (flags & (1 << 6)) /* auto flag */
     {
       /* XXX : add other L2 address case */
       if (Mac48Address::IsMatchingType (addr))
@@ -282,7 +281,7 @@
       AddAddress (interface, address);
 
       /* add default router
-       * if a previous default route exists, the new ones is simply added 
+       * if a previous default route exists, the new ones is simply added
        */
       GetRoutingProtocol ()->NotifyAddRoute (Ipv6Address::GetAny (), Ipv6Prefix ((uint8_t)0), defaultRouter, interface, network);
 
@@ -304,7 +303,7 @@
 
   for (i = 0; i < max; i++)
     {
-      if (iface->GetAddress (i).GetAddress () == toFound) 
+      if (iface->GetAddress (i).GetAddress () == toFound)
         {
           RemoveAddress (interface, i);
           break;
@@ -369,14 +368,14 @@
   return false;
 }
 
-void Ipv6L3Protocol::SetMetric (uint32_t i, uint16_t metric) 
+void Ipv6L3Protocol::SetMetric (uint32_t i, uint16_t metric)
 {
   NS_LOG_FUNCTION (this << i << metric);
   Ptr<Ipv6Interface> interface = GetInterface (i);
   interface->SetMetric (metric);
 }
 
-uint16_t Ipv6L3Protocol::GetMetric (uint32_t i) const 
+uint16_t Ipv6L3Protocol::GetMetric (uint32_t i) const
 {
   NS_LOG_FUNCTION (this << i);
   Ptr<Ipv6Interface> interface = GetInterface (i);
@@ -635,12 +634,12 @@
   hdr = BuildHeader (source, destination, protocol, packet->GetSize (), ttl);
 
   //for link-local traffic, we need to determine the interface
-  if (source.IsLinkLocal () ||
-      destination.IsLinkLocal () ||
-      destination.IsAllNodesMulticast () ||
-      destination.IsAllRoutersMulticast () ||
-      destination.IsAllHostsMulticast () ||
-      destination.IsSolicitedMulticast ())
+  if (source.IsLinkLocal ()
+      || destination.IsLinkLocal ()
+      || destination.IsAllNodesMulticast ()
+      || destination.IsAllRoutersMulticast ()
+      || destination.IsAllHostsMulticast ()
+      || destination.IsSolicitedMulticast ())
     {
       int32_t index = GetInterfaceForAddress (source);
       NS_ASSERT (index >= 0);
@@ -707,7 +706,7 @@
       socket->ForwardUp (packet, hdr, device);
     }
 
-  Ptr<Ipv6ExtensionDemux> ipv6ExtensionDemux = m_node->GetObject<Ipv6ExtensionDemux>();
+  Ptr<Ipv6ExtensionDemux> ipv6ExtensionDemux = m_node->GetObject<Ipv6ExtensionDemux> ();
   Ptr<Ipv6Extension> ipv6Extension = 0;
   uint8_t nextHeader = hdr.GetNextHeader ();
   bool isDropped = false;
@@ -763,6 +762,12 @@
       // Router => drop
       if (m_ipForward)
         {
+          Ptr<Icmpv6L4Protocol> icmpv6 = GetIcmpv6 ();
+          if ( icmpv6 )
+            {
+              packet->AddHeader(ipHeader);
+              icmpv6->SendErrorTooBig (packet, ipHeader.GetSourceAddress (), dev->GetMtu ());
+            }
           return;
         }
 
@@ -771,7 +776,7 @@
       packet->AddHeader (ipHeader);
 
       // To get specific method GetFragments from Ipv6ExtensionFragmentation
-      Ipv6ExtensionFragment *ipv6Fragment = dynamic_cast<Ipv6ExtensionFragment *>(PeekPointer (ipv6ExtensionDemux->GetExtension (Ipv6Header::IPV6_EXT_FRAGMENTATION)));
+      Ipv6ExtensionFragment *ipv6Fragment = dynamic_cast<Ipv6ExtensionFragment *> (PeekPointer (ipv6ExtensionDemux->GetExtension (Ipv6Header::IPV6_EXT_FRAGMENTATION)));
       ipv6Fragment->GetFragments (packet, outInterface->GetDevice ()->GetMtu (), fragments);
     }
 
@@ -858,8 +863,8 @@
       NS_LOG_WARN ("TTL exceeded.  Drop.");
       m_dropTrace (ipHeader, packet, DROP_TTL_EXPIRED, m_node->GetObject<Ipv6> (), 0);
       // Do not reply to ICMPv6 or to multicast IPv6 address
-      if (ipHeader.GetNextHeader () != Icmpv6L4Protocol::PROT_NUMBER &&
-          ipHeader.GetDestinationAddress ().IsMulticast () == false)
+      if (ipHeader.GetNextHeader () != Icmpv6L4Protocol::PROT_NUMBER
+          && ipHeader.GetDestinationAddress ().IsMulticast () == false)
         {
           packet->AddHeader (ipHeader);
           GetIcmpv6 ()->SendErrorTimeExceeded (packet, ipHeader.GetSourceAddress (), Icmpv6Header::ICMPV6_HOPLIMIT);
@@ -869,12 +874,12 @@
 
   /* ICMPv6 Redirect */
 
-  /* if we forward to a machine on the same network as the source, 
-   * we send him an ICMPv6 redirect message to notify him that a short route 
+  /* if we forward to a machine on the same network as the source,
+   * we send him an ICMPv6 redirect message to notify him that a short route
    * exists.
    */
-  if ((!rtentry->GetGateway ().IsAny () && rtentry->GetGateway ().CombinePrefix (Ipv6Prefix (64)) == header.GetSourceAddress ().CombinePrefix (Ipv6Prefix (64))) ||
-      (rtentry->GetDestination ().CombinePrefix (Ipv6Prefix (64)) == header.GetSourceAddress ().CombinePrefix (Ipv6Prefix (64))))
+  if ((!rtentry->GetGateway ().IsAny () && rtentry->GetGateway ().CombinePrefix (Ipv6Prefix (64)) == header.GetSourceAddress ().CombinePrefix (Ipv6Prefix (64)))
+      || (rtentry->GetDestination ().CombinePrefix (Ipv6Prefix (64)) == header.GetSourceAddress ().CombinePrefix (Ipv6Prefix (64))))
     {
       NS_LOG_LOGIC ("ICMPv6 redirect!");
       Ptr<Icmpv6L4Protocol> icmpv6 = GetIcmpv6 ();
@@ -940,8 +945,8 @@
 {
   NS_LOG_FUNCTION (this << packet << ip << iif);
   Ptr<Packet> p = packet->Copy ();
-  Ptr<IpL4Protocol> protocol = 0; 
-  Ptr<Ipv6ExtensionDemux> ipv6ExtensionDemux = m_node->GetObject<Ipv6ExtensionDemux>();
+  Ptr<IpL4Protocol> protocol = 0;
+  Ptr<Ipv6ExtensionDemux> ipv6ExtensionDemux = m_node->GetObject<Ipv6ExtensionDemux> ();
   Ptr<Ipv6Extension> ipv6Extension = 0;
   Ipv6Address src = ip.GetSourceAddress ();
   Ipv6Address dst = ip.GetDestinationAddress ();
@@ -961,7 +966,8 @@
     }
 
   /* process all the extensions found and the layer 4 protocol */
-  do {
+  do
+    {
       /* it return 0 for non-extension (i.e. layer 4 protocol) */
       ipv6Extension = ipv6ExtensionDemux->GetExtension (nextHeader);
 
@@ -1030,7 +1036,8 @@
                 }
             }
         }
-    } while (ipv6Extension);
+    }
+  while (ipv6Extension);
 }
 
 void Ipv6L3Protocol::RouteInputError (Ptr<const Packet> p, const Ipv6Header& ipHeader, Socket::SocketErrno sockErrno)
--- a/src/internet/model/ipv6-list-routing.cc	Fri Mar 23 23:51:29 2012 -0700
+++ b/src/internet/model/ipv6-list-routing.cc	Wed Mar 21 18:51:55 2012 +0100
@@ -41,13 +41,13 @@
 }
 
 
-Ipv6ListRouting::Ipv6ListRouting () 
+Ipv6ListRouting::Ipv6ListRouting ()
   : m_ipv6 (0)
 {
   NS_LOG_FUNCTION_NOARGS ();
 }
 
-Ipv6ListRouting::~Ipv6ListRouting () 
+Ipv6ListRouting::~Ipv6ListRouting ()
 {
   NS_LOG_FUNCTION_NOARGS ();
 }
@@ -94,9 +94,9 @@
 }
 
 // Patterned after Linux ip_route_input and ip_route_input_slow
-bool 
-Ipv6ListRouting::RouteInput (Ptr<const Packet> p, const Ipv6Header &header, Ptr<const NetDevice> idev, 
-                             UnicastForwardCallback ucb, MulticastForwardCallback mcb, 
+bool
+Ipv6ListRouting::RouteInput (Ptr<const Packet> p, const Ipv6Header &header, Ptr<const NetDevice> idev,
+                             UnicastForwardCallback ucb, MulticastForwardCallback mcb,
                              LocalDeliverCallback lcb, ErrorCallback ecb)
 {
   bool retVal = false;
@@ -104,9 +104,9 @@
   NS_LOG_LOGIC ("RouteInput logic for node: " << m_ipv6->GetObject<Node> ()->GetId ());
 
   NS_ASSERT (m_ipv6 != 0);
-  // Check if input device supports IP 
+  // Check if input device supports IP
   NS_ASSERT (m_ipv6->GetInterfaceForDevice (idev) >= 0);
-  uint32_t iif = m_ipv6->GetInterfaceForDevice (idev); 
+  uint32_t iif = m_ipv6->GetInterfaceForDevice (idev);
   Ipv6Address dst = header.GetDestinationAddress ();
 
   // Multicast recognition; handle local delivery here
@@ -171,7 +171,7 @@
               lcb (p, header, iif);
               return true;
             }
-          NS_LOG_LOGIC ("Address "<< addr << " not a match");
+          NS_LOG_LOGIC ("Address " << addr << " not a match");
         }
     }
   // Check if input device supports IP forwarding
@@ -196,7 +196,7 @@
   return retVal;
 }
 
-void 
+void
 Ipv6ListRouting::NotifyInterfaceUp (uint32_t interface)
 {
   NS_LOG_FUNCTION (this << interface);
@@ -208,7 +208,7 @@
       (*rprotoIter).second->NotifyInterfaceUp (interface);
     }
 }
-void 
+void
 Ipv6ListRouting::NotifyInterfaceDown (uint32_t interface)
 {
   NS_LOG_FUNCTION (this << interface);
@@ -220,7 +220,7 @@
       (*rprotoIter).second->NotifyInterfaceDown (interface);
     }
 }
-void 
+void
 Ipv6ListRouting::NotifyAddAddress (uint32_t interface, Ipv6InterfaceAddress address)
 {
   NS_LOG_FUNCTION (this << interface << address);
@@ -232,7 +232,7 @@
       (*rprotoIter).second->NotifyAddAddress (interface, address);
     }
 }
-void 
+void
 Ipv6ListRouting::NotifyRemoveAddress (uint32_t interface, Ipv6InterfaceAddress address)
 {
   NS_LOG_FUNCTION (this << interface << address);
@@ -269,7 +269,7 @@
     }
 }
 
-void 
+void
 Ipv6ListRouting::SetIpv6 (Ptr<Ipv6> ipv6)
 {
   NS_LOG_FUNCTION (this << ipv6);
@@ -296,14 +296,14 @@
     }
 }
 
-uint32_t 
+uint32_t
 Ipv6ListRouting::GetNRoutingProtocols (void) const
 {
   NS_LOG_FUNCTION (this);
-  return m_routingProtocols.size (); 
+  return m_routingProtocols.size ();
 }
 
-Ptr<Ipv6RoutingProtocol> 
+Ptr<Ipv6RoutingProtocol>
 Ipv6ListRouting::GetRoutingProtocol (uint32_t index, int16_t& priority) const
 {
   NS_LOG_FUNCTION (index);
@@ -324,7 +324,7 @@
   return 0;
 }
 
-bool 
+bool
 Ipv6ListRouting::Compare (const Ipv6RoutingProtocolEntry& a, const Ipv6RoutingProtocolEntry& b)
 {
   return a.first > b.first;
--- a/src/internet/model/ipv6-list-routing.h	Fri Mar 23 23:51:29 2012 -0700
+++ b/src/internet/model/ipv6-list-routing.h	Wed Mar 21 18:51:55 2012 +0100
@@ -25,7 +25,7 @@
 namespace ns3 {
 
 /**
- * \ingroup internet 
+ * \ingroup internet
  * \defgroup ipv6ListRouting Ipv6 List Routing
  */
 
@@ -34,15 +34,15 @@
  * \class Ipv6ListRouting
  * \brief Hold list of Ipv6RoutingProtocol objects.
  *
- * This class is a specialization of Ipv6RoutingProtocol that allows 
- * other instances of Ipv6RoutingProtocol to be inserted in a 
+ * This class is a specialization of Ipv6RoutingProtocol that allows
+ * other instances of Ipv6RoutingProtocol to be inserted in a
  * prioritized list.  Routing protocols in the list are consulted one
  * by one, from highest to lowest priority, until a routing protocol
  * is found that will take the packet (this corresponds to a non-zero
  * return value to RouteOutput, or a return value of true to RouteInput).
- * The order by which routing protocols with the same priority value 
+ * The order by which routing protocols with the same priority value
  * are consulted is undefined.
- * 
+ *
  */
 class Ipv6ListRouting : public Ipv6RoutingProtocol
 {
@@ -78,7 +78,7 @@
   virtual uint32_t GetNRoutingProtocols (void) const;
 
   /**
-   * \brief Get pointer to routing protocol stored at index, 
+   * \brief Get pointer to routing protocol stored at index,
    *
    * The first protocol (index 0) the highest priority, the next one (index 1)
    * the second highest priority, and so on.  The priority parameter is an
@@ -86,7 +86,7 @@
    * \param index index of protocol to return
    * \param priority output parameter, set to the priority of the protocol
    * being returned
-   * \return pointer to routing protocol indexed by 
+   * \return pointer to routing protocol indexed by
    */
   virtual Ptr<Ipv6RoutingProtocol> GetRoutingProtocol (uint32_t index, int16_t& priority) const;
 
@@ -108,7 +108,7 @@
   /**
    * \brief Dispose this object.
    */
-  void DoDispose (void);
+  virtual void DoDispose (void);
 
 private:
   typedef std::pair<int16_t, Ptr<Ipv6RoutingProtocol> > Ipv6RoutingProtocolEntry;
--- a/src/internet/model/ipv6-static-routing.cc	Fri Mar 23 23:51:29 2012 -0700
+++ b/src/internet/model/ipv6-static-routing.cc	Wed Mar 21 18:51:55 2012 +0100
@@ -26,8 +26,7 @@
 #include "ipv6-static-routing.h"
 #include "ipv6-routing-table-entry.h"
 
-namespace ns3
-{
+namespace ns3 {
 
 NS_LOG_COMPONENT_DEFINE ("Ipv6StaticRouting");
 NS_OBJECT_ENSURE_REGISTERED (Ipv6StaticRouting);
@@ -56,7 +55,7 @@
 {
   NS_LOG_FUNCTION (this << ipv6);
   NS_ASSERT (m_ipv6 == 0 && ipv6 != 0);
-  uint32_t i = 0; 
+  uint32_t i = 0;
   m_ipv6 = ipv6;
 
   for (i = 0; i < m_ipv6->GetNInterfaces (); i++)
@@ -164,9 +163,9 @@
   for (MulticastRoutesI i = m_multicastRoutes.begin (); i != m_multicastRoutes.end (); i++)
     {
       Ipv6MulticastRoutingTableEntry *route = *i;
-      if (origin == route->GetOrigin () &&
-          group == route->GetGroup () &&
-          inputInterface == route->GetInputInterface ())
+      if (origin == route->GetOrigin ()
+          && group == route->GetGroup ()
+          && inputInterface == route->GetInputInterface ())
         {
           delete *i;
           m_multicastRoutes.erase (i);
@@ -222,8 +221,8 @@
   uint32_t shortestMetric = 0xffffffff;
 
   /* when sending on link-local multicast, there have to be interface specified */
-  if (dst == Ipv6Address::GetAllNodesMulticast () || dst.IsSolicitedMulticast () || 
-      dst == Ipv6Address::GetAllRoutersMulticast () || dst == Ipv6Address::GetAllHostsMulticast ())
+  if (dst == Ipv6Address::GetAllNodesMulticast () || dst.IsSolicitedMulticast ()
+      || dst == Ipv6Address::GetAllRoutersMulticast () || dst == Ipv6Address::GetAllHostsMulticast ())
     {
       NS_ASSERT_MSG (interface, "Try to send on link-local multicast address, and no interface index is given!");
       rtentry = Create<Ipv6Route> ();
@@ -294,7 +293,7 @@
         }
     }
 
-  if(rtentry)
+  if (rtentry)
     {
       NS_LOG_LOGIC ("Matching route via " << rtentry->GetDestination () << " (throught " << rtentry->GetGateway () << ") at the end");
     }
@@ -364,7 +363,7 @@
                     }
                 }
               return mrtentry;
-            } 
+            }
         }
     }
   return mrtentry;
@@ -474,8 +473,8 @@
   for (NetworkRoutesI it = m_networkRoutes.begin (); it != m_networkRoutes.end (); it++)
     {
       Ipv6RoutingTableEntry* rtentry = it->first;
-      if (network == rtentry->GetDest () && rtentry->GetInterface () == ifIndex && 
-          rtentry->GetPrefixToUse () == prefixToUse)
+      if (network == rtentry->GetDest () && rtentry->GetInterface () == ifIndex
+          && rtentry->GetPrefixToUse () == prefixToUse)
         {
           delete it->first;
           m_networkRoutes.erase (it);
@@ -568,7 +567,7 @@
               lcb (p, header, iif);
               return true;
             }
-          NS_LOG_LOGIC ("Address "<< addr << " not a match");
+          NS_LOG_LOGIC ("Address " << addr << " not a match");
         }
     }
   // Check if input device supports IP forwarding
@@ -599,8 +598,8 @@
 {
   for (uint32_t j = 0; j < m_ipv6->GetNAddresses (i); j++)
     {
-      if (m_ipv6->GetAddress (i, j).GetAddress () != Ipv6Address () &&
-          m_ipv6->GetAddress (i, j).GetPrefix () != Ipv6Prefix ())
+      if (m_ipv6->GetAddress (i, j).GetAddress () != Ipv6Address ()
+          && m_ipv6->GetAddress (i, j).GetPrefix () != Ipv6Prefix ())
         {
           if (m_ipv6->GetAddress (i, j).GetPrefix () == Ipv6Prefix (128))
             {
@@ -670,10 +669,10 @@
     {
       Ipv6RoutingTableEntry route = GetRoute (j);
 
-      if (route.GetInterface () == interface &&
-          route.IsNetwork () &&
-          route.GetDestNetwork () == networkAddress &&
-          route.GetDestNetworkPrefix () == networkMask)
+      if (route.GetInterface () == interface
+          && route.IsNetwork ()
+          && route.GetDestNetwork () == networkAddress
+          && route.GetDestNetworkPrefix () == networkMask)
         {
           RemoveRoute (j);
         }
@@ -716,7 +715,7 @@
             {
               delete j->first;
               m_networkRoutes.erase (j);
-            } 
+            }
         }
     }
   else
@@ -736,7 +735,7 @@
 
   if (dest == Ipv6Address::GetAllNodesMulticast () || dest == Ipv6Address::GetAllRoutersMulticast () || dest == Ipv6Address::GetAllHostsMulticast ())
     {
-      return ret; 
+      return ret;
     }
 
   /* useally IPv6 interfaces have one link-local address and one global address */
--- a/src/internet/model/ipv6-static-routing.h	Fri Mar 23 23:51:29 2012 -0700
+++ b/src/internet/model/ipv6-static-routing.h	Wed Mar 21 18:51:55 2012 +0100
@@ -31,8 +31,7 @@
 #include "ns3/ipv6-header.h"
 #include "ns3/ipv6-routing-protocol.h"
 
-namespace ns3
-{
+namespace ns3 {
 
 class Packet;
 class NetDevice;
@@ -241,7 +240,7 @@
   /**
    * \brief Dispose this object.
    */
-  void DoDispose ();
+  virtual void DoDispose ();
 
 private:
   typedef std::list<std::pair <Ipv6RoutingTableEntry *, uint32_t> > NetworkRoutes;
--- a/src/internet/model/tcp-socket-base.cc	Fri Mar 23 23:51:29 2012 -0700
+++ b/src/internet/model/tcp-socket-base.cc	Wed Mar 21 18:51:55 2012 +0100
@@ -105,7 +105,8 @@
     m_node (0),
     m_tcp (0),
     m_rtt (0),
-    m_nextTxSequence (0),       // Change this for non-zero initial sequence number
+    m_nextTxSequence (0),
+    // Change this for non-zero initial sequence number
     m_highTxMark (0),
     m_rxBuffer (0),
     m_txBuffer (0),
@@ -116,14 +117,16 @@
     m_shutdownSend (false),
     m_shutdownRecv (false),
     m_connected (false),
-    m_segmentSize (0),          // For attribute initialization consistency (quiet valgrind)
+    m_segmentSize (0),
+    // For attribute initialization consistency (quiet valgrind)
     m_rWnd (0)
 {
   NS_LOG_FUNCTION (this);
 }
 
 TcpSocketBase::TcpSocketBase (const TcpSocketBase& sock)
-  : TcpSocket (sock), //copy object::m_tid and socket::callbacks
+  : TcpSocket (sock),
+    //copy object::m_tid and socket::callbacks
     m_dupAckCount (sock.m_dupAckCount),
     m_delAckCount (0),
     m_delAckMaxCount (sock.m_delAckMaxCount),
@@ -246,10 +249,9 @@
 int
 TcpSocketBase::Bind (void)
 {
-  NS_LOG_FUNCTION_NOARGS ();
+  NS_LOG_FUNCTION (this);
   m_endPoint = m_tcp->Allocate ();
-  m_endPoint6 = m_tcp->Allocate6 ();
-  if (0 == m_endPoint || 0 == m_endPoint6)
+  if (0 == m_endPoint)
     {
       m_errno = ERROR_ADDRNOTAVAIL;
       return -1;
@@ -261,7 +263,15 @@
 int
 TcpSocketBase::Bind6 (void)
 {
-  return Bind ();
+  NS_LOG_FUNCTION (this);
+  m_endPoint6 = m_tcp->Allocate6 ();
+  if (0 == m_endPoint6)
+    {
+      m_errno = ERROR_ADDRNOTAVAIL;
+      return -1;
+    }
+  m_tcp->m_sockets.push_back (this);
+  return SetupCallback ();
 }
 
 /** Inherit from Socket class: Bind socket (with specific address) to an end-point in TcpL4Protocol */
@@ -341,7 +351,7 @@
   NS_LOG_FUNCTION (this << address);
 
   // If haven't do so, Bind() this socket first
-  if (InetSocketAddress::IsMatchingType (address))
+  if (InetSocketAddress::IsMatchingType (address) && m_endPoint6 == 0)
     {
       if (m_endPoint == 0)
         {
@@ -362,7 +372,7 @@
           return -1;
         }
     }
-  else if (Inet6SocketAddress::IsMatchingType (address) )
+  else if (Inet6SocketAddress::IsMatchingType (address)  && m_endPoint == 0)
     {
       // If we are operating on a v4-mapped address, translate the address to
       // a v4 address and re-call this function
@@ -371,7 +381,7 @@
       if (v6Addr.IsIpv4MappedAddress () == true)
         {
           Ipv4Address v4Addr = v6Addr.GetIpv4MappedAddress ();
-          return Connect(InetSocketAddress(v4Addr, transport.GetPort ()));
+          return Connect (InetSocketAddress (v4Addr, transport.GetPort ()));
         }
 
       if (m_endPoint6 == 0)
@@ -629,7 +639,7 @@
     }
   if (m_endPoint != 0)
     {
-      m_endPoint->SetRxCallback (MakeCallback (&TcpSocketBase::ForwardUp, Ptr<TcpSocketBase> (this))); 
+      m_endPoint->SetRxCallback (MakeCallback (&TcpSocketBase::ForwardUp, Ptr<TcpSocketBase> (this)));
       m_endPoint->SetDestroyCallback (MakeCallback (&TcpSocketBase::Destroy, Ptr<TcpSocketBase> (this)));
     }
   if (m_endPoint6 != 0)
@@ -712,8 +722,14 @@
 {
   NS_LOG_FUNCTION (this);
 
-  if (!m_closeNotified) NotifyNormalClose ();
-  if (m_state != TIME_WAIT) DeallocateEndPoint ();
+  if (!m_closeNotified)
+    {
+      NotifyNormalClose ();
+    }
+  if (m_state != TIME_WAIT)
+    {
+      DeallocateEndPoint ();
+    }
   m_closeNotified = true;
   NS_LOG_INFO (TcpStateName[m_state] << " -> CLOSED");
   CancelAllTimers ();
@@ -734,7 +750,7 @@
     { // In LAST_ACK and CLOSING states, it only wait for an ACK and the
       // sequence number must equals to m_rxBuffer.NextRxSequence ()
       return (m_rxBuffer.NextRxSequence () != head);
-    };
+    }
 
   // In all other cases, check if the sequence number is in range
   return (tail < m_rxBuffer.NextRxSequence () || m_rxBuffer.MaxRxSequence () <= head);
@@ -775,7 +791,7 @@
   TcpHeader tcpHeader;
   packet->RemoveHeader (tcpHeader);
   if (tcpHeader.GetFlags () & TcpHeader::ACK)
-    { 
+    {
       EstimateRtt (tcpHeader);
     }
   ReadOptions (tcpHeader);
@@ -789,12 +805,12 @@
   m_rWnd = tcpHeader.GetWindowSize ();
 
   // Discard fully out of range data packets
-  if (packet->GetSize () &&
-      OutOfRange (tcpHeader.GetSequenceNumber (), tcpHeader.GetSequenceNumber () + packet->GetSize ()))
+  if (packet->GetSize ()
+      && OutOfRange (tcpHeader.GetSequenceNumber (), tcpHeader.GetSequenceNumber () + packet->GetSize ()))
     {
       NS_LOG_LOGIC ("At state " << TcpStateName[m_state] <<
                     " received packet of seq [" << tcpHeader.GetSequenceNumber () <<
-                    ":" << tcpHeader.GetSequenceNumber () + packet->GetSize() <<
+                    ":" << tcpHeader.GetSequenceNumber () + packet->GetSize () <<
                     ") out of range [" << m_rxBuffer.NextRxSequence () << ":" <<
                     m_rxBuffer.MaxRxSequence () << ")");
       // Acknowledgement should be sent for all unacceptable packets (RFC793, p.69)
@@ -884,12 +900,12 @@
   m_rWnd = tcpHeader.GetWindowSize ();
 
   // Discard fully out of range packets
-  if (packet->GetSize () &&
-      OutOfRange (tcpHeader.GetSequenceNumber (), tcpHeader.GetSequenceNumber () + packet->GetSize ()))
+  if (packet->GetSize ()
+      && OutOfRange (tcpHeader.GetSequenceNumber (), tcpHeader.GetSequenceNumber () + packet->GetSize ()))
     {
       NS_LOG_LOGIC ("At state " << TcpStateName[m_state] <<
                     " received packet of seq [" << tcpHeader.GetSequenceNumber () <<
-                    ":" << tcpHeader.GetSequenceNumber () + packet->GetSize() <<
+                    ":" << tcpHeader.GetSequenceNumber () + packet->GetSize () <<
                     ") out of range [" << m_rxBuffer.NextRxSequence () << ":" <<
                     m_rxBuffer.MaxRxSequence () << ")");
       // Acknowledgement should be sent for all unacceptable packets (RFC793, p.69)
@@ -1045,11 +1061,17 @@
 
   // Fork a socket if received a SYN. Do nothing otherwise.
   // C.f.: the LISTEN part in tcp_v4_do_rcv() in tcp_ipv4.c in Linux kernel
-  if (tcpflags != TcpHeader::SYN) return;
+  if (tcpflags != TcpHeader::SYN)
+    {
+      return;
+    }
 
   // Call socket's notify function to let the server app know we got a SYN
   // If the server app refuses the connection, do nothing
-  if (!NotifyConnectionRequest (fromAddress)) return;
+  if (!NotifyConnectionRequest (fromAddress))
+    {
+      return;
+    }
   // Clone the socket, simulate fork
   Ptr<TcpSocketBase> newSock = Fork ();
   NS_LOG_LOGIC ("Cloned a TcpSocketBase " << newSock);
@@ -1108,7 +1130,7 @@
     { // Other in-sequence input
       if (tcpflags != TcpHeader::RST)
         { // When (1) rx of FIN+ACK; (2) rx of FIN; (3) rx of bad flags
-          NS_LOG_LOGIC ("Illegal flag " << std::hex << static_cast<uint32_t>(tcpflags) << std::dec << " received. Reset packet is sent.");
+          NS_LOG_LOGIC ("Illegal flag " << std::hex << static_cast<uint32_t> (tcpflags) << std::dec << " received. Reset packet is sent.");
           SendRST ();
         }
       CloseAndNotify ();
@@ -1125,9 +1147,9 @@
   // Extract the flags. PSH and URG are not honoured.
   uint8_t tcpflags = tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG);
 
-  if (tcpflags == 0 ||
-      (tcpflags == TcpHeader::ACK
-       && m_nextTxSequence + SequenceNumber32 (1) == tcpHeader.GetAckNumber ()))
+  if (tcpflags == 0
+      || (tcpflags == TcpHeader::ACK
+          && m_nextTxSequence + SequenceNumber32 (1) == tcpHeader.GetAckNumber ()))
     { // If it is bare data, accept it and move to ESTABLISHED state. This is
       // possibly due to ACK lost in 3WHS. If in-sequence ACK is received, the
       // handshake is completed nicely.
@@ -1221,8 +1243,8 @@
   else if (tcpflags == TcpHeader::ACK)
     { // Process the ACK, and if in FIN_WAIT_1, conditionally move to FIN_WAIT_2
       ReceivedAck (packet, tcpHeader);
-      if (m_state == FIN_WAIT_1 && m_txBuffer.Size () == 0 &&
-          tcpHeader.GetAckNumber () == m_highTxMark + SequenceNumber32 (1))
+      if (m_state == FIN_WAIT_1 && m_txBuffer.Size () == 0
+          && tcpHeader.GetAckNumber () == m_highTxMark + SequenceNumber32 (1))
         { // This ACK corresponds to the FIN sent
           NS_LOG_INFO ("FIN_WAIT_1 -> FIN_WAIT_2");
           m_state = FIN_WAIT_2;
@@ -1258,8 +1280,8 @@
         {
           NS_LOG_INFO ("FIN_WAIT_1 -> CLOSING");
           m_state = CLOSING;
-          if (m_txBuffer.Size () == 0 &&
-              tcpHeader.GetAckNumber () == m_highTxMark + SequenceNumber32 (1))
+          if (m_txBuffer.Size () == 0
+              && tcpHeader.GetAckNumber () == m_highTxMark + SequenceNumber32 (1))
             { // This ACK corresponds to the FIN sent
               TimeWait ();
             }
@@ -1267,9 +1289,12 @@
       else if (m_state == FIN_WAIT_2)
         {
           TimeWait ();
-        };
+        }
       SendEmptyPacket (TcpHeader::ACK);
-      if (!m_shutdownRecv) NotifyDataRecv ();
+      if (!m_shutdownRecv)
+        {
+          NotifyDataRecv ();
+        }
     }
 }
 
@@ -1348,11 +1373,11 @@
   NS_LOG_FUNCTION (this << tcpHeader);
 
   // Ignore all out of range packets
-  if (tcpHeader.GetSequenceNumber () < m_rxBuffer.NextRxSequence () ||
-      tcpHeader.GetSequenceNumber () > m_rxBuffer.MaxRxSequence ())
+  if (tcpHeader.GetSequenceNumber () < m_rxBuffer.NextRxSequence ()
+      || tcpHeader.GetSequenceNumber () > m_rxBuffer.MaxRxSequence ())
     {
       return;
-    };
+    }
   // For any case, remember the FIN position in rx buffer first
   m_rxBuffer.SetFinSequence (tcpHeader.GetSequenceNumber () + SequenceNumber32 (p->GetSize ()));
   NS_LOG_LOGIC ("Accepted FIN at seq " << tcpHeader.GetSequenceNumber () + SequenceNumber32 (p->GetSize ()));
@@ -1365,7 +1390,7 @@
   if (!m_rxBuffer.Finished ())
     {
       return;
-    };
+    }
 
   // Simultaneous close: Application invoked Close() when we are processing this FIN packet
   if (m_state == FIN_WAIT_1)
@@ -1770,8 +1795,11 @@
 TcpSocketBase::SendPendingData (bool withAck)
 {
   NS_LOG_FUNCTION (this << withAck);
-  if (m_txBuffer.Size () == 0) return false;  // Nothing to send
+  if (m_txBuffer.Size () == 0)
+    {
+      return false;                           // Nothing to send
 
+    }
   if (m_endPoint == 0 && m_endPoint6 == 0)
     {
       NS_LOG_INFO ("TcpSocketBase::SendPendingData: No endpoint; m_shutdownSend=" << m_shutdownSend);
@@ -1802,8 +1830,8 @@
         }
       // Nagle's algorithm (RFC896): Hold off sending if there is unacked data
       // in the buffer and the amount of data to send is less than one segment
-      if (!m_noDelay && UnAckDataCount () > 0 &&
-          m_txBuffer.SizeFromSequence (m_nextTxSequence) < m_segmentSize)
+      if (!m_noDelay && UnAckDataCount () > 0
+          && m_txBuffer.SizeFromSequence (m_nextTxSequence) < m_segmentSize)
         {
           NS_LOG_LOGIC ("Invoking Nagle's algorithm. Wait to send.");
           break;
@@ -1893,7 +1921,10 @@
   // Notify app to receive if necessary
   if (expectedSeq < m_rxBuffer.NextRxSequence ())
     { // NextRxSeq advanced, we have something to send to the app
-      if (!m_shutdownRecv) NotifyDataRecv ();
+      if (!m_shutdownRecv)
+        {
+          NotifyDataRecv ();
+        }
       // Handle exceptions
       if (m_closeNotified)
         {
@@ -1916,7 +1947,7 @@
   // (which should be ignored) is handled by m_rtt. Once timestamp option
   // is implemented, this function would be more elaborated.
   m_lastRtt = m_rtt->AckSeq (tcpHeader.GetAckNumber () );
-};
+}
 
 // Called by the ReceivedAck() when new ACK received and by ProcessSynRcvd()
 // when the three-way handshake completed. This cancels retransmission timer
@@ -1979,9 +2010,15 @@
   NS_LOG_FUNCTION (this);
   NS_LOG_LOGIC (this << " ReTxTimeout Expired at time " << Simulator::Now ().GetSeconds ());
   // If erroneous timeout in closed/timed-wait state, just return
-  if (m_state == CLOSED || m_state == TIME_WAIT) return;
+  if (m_state == CLOSED || m_state == TIME_WAIT)
+    {
+      return;
+    }
   // If all data are received (non-closing socket and nothing to send), just return
-  if (m_state <= ESTABLISHED && m_txBuffer.HeadSequence () >= m_highTxMark) return;
+  if (m_state <= ESTABLISHED && m_txBuffer.HeadSequence () >= m_highTxMark)
+    {
+      return;
+    }
 
   Retransmit ();
 }
@@ -2112,7 +2149,7 @@
   CancelAllTimers ();
   // Move from TIME_WAIT to CLOSED after 2*MSL. Max segment lifetime is 2 min
   // according to RFC793, p.28
-  m_timewaitEvent = Simulator::Schedule (Seconds (2*m_msl),
+  m_timewaitEvent = Simulator::Schedule (Seconds (2 * m_msl),
                                          &TcpSocketBase::CloseAndNotify, this);
 }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet/test/ipv6-fragmentation-test.cc	Wed Mar 21 18:51:55 2012 +0100
@@ -0,0 +1,430 @@
+/* -*-  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 <[email protected]>
+ */
+/**
+ * This is the test code for ipv6-l3protocol.cc (only the fragmentation and reassembly part).
+ */
+#define NS3_LOG_ENABLE 1
+
+#include "ns3/test.h"
+#include "ns3/config.h"
+#include "ns3/uinteger.h"
+#include "ns3/socket-factory.h"
+#include "ns3/ipv4-raw-socket-factory.h"
+#include "ns3/ipv6-raw-socket-factory.h"
+#include "ns3/udp-socket-factory.h"
+#include "ns3/simulator.h"
+#include "error-channel.h"
+#include "error-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/arp-l3-protocol.h"
+#include "ns3/ipv4-l3-protocol.h"
+#include "ns3/icmpv4-l4-protocol.h"
+#include "ns3/ipv4-list-routing.h"
+#include "ns3/ipv4-static-routing.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>
+
+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 Ipv6FragmentationTest : 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);
+  Ipv6FragmentationTest ();
+  ~Ipv6FragmentationTest ();
+
+  // 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);
+
+};
+
+
+Ipv6FragmentationTest::Ipv6FragmentationTest ()
+  : TestCase ("Verify the IPv6 layer 3 protocol fragmentation and reassembly")
+{
+  m_socketServer = 0;
+  m_data = 0;
+  m_dataSize = 0;
+}
+
+Ipv6FragmentationTest::~Ipv6FragmentationTest ()
+{
+  if ( m_data )
+    {
+      delete[] m_data;
+    }
+  m_data = 0;
+  m_dataSize = 0;
+}
+
+
+void
+Ipv6FragmentationTest::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::1"), 9);
+      m_socketServer->Bind (local);
+      Ptr<UdpSocket> udpSocket = DynamicCast<UdpSocket> (m_socketServer);
+    }
+
+  m_socketServer->SetRecvCallback (MakeCallback (&Ipv6FragmentationTest::HandleReadServer, this));
+}
+
+void
+Ipv6FragmentationTest::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
+Ipv6FragmentationTest::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::1"), 9));
+      CallbackValue cbValue = MakeCallback (&Ipv6FragmentationTest::HandleReadIcmpClient, this);
+      m_socketClient->SetAttribute ("IcmpCallback6", cbValue);
+    }
+
+  m_socketClient->SetRecvCallback (MakeCallback (&Ipv6FragmentationTest::HandleReadClient, this));
+}
+
+void
+Ipv6FragmentationTest::HandleReadClient (Ptr<Socket> socket)
+{
+  Ptr<Packet> packet;
+  Address from;
+  while ((packet = socket->RecvFrom (from)))
+    {
+      if (Inet6SocketAddress::IsMatchingType (from))
+        {
+          m_receivedPacketClient = packet->Copy ();
+        }
+    }
+}
+
+void
+Ipv6FragmentationTest::HandleReadIcmpClient (Ipv6Address icmpSource,
+                                             uint8_t icmpTtl, uint8_t icmpType,
+                                             uint8_t icmpCode, uint32_t icmpInfo)
+{
+  m_icmpType = icmpType;
+  m_icmpCode = icmpCode;
+}
+
+void
+Ipv6FragmentationTest::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> Ipv6FragmentationTest::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
+Ipv6FragmentationTest::DoRun (void)
+{
+  // set the arp cache to something quite high
+  // we shouldn't need because the NetDevice used doesn't need arp, but still
+  // Config::SetDefault ("ns3::ArpCache::PendingQueueSize", UintegerValue (100));
+//  LogComponentEnable ("ErrorNetDevice", LOG_LEVEL_ALL);
+// LogComponentEnableAll(LOG_LEVEL_ALL);
+// Create topology
+
+  // Receiver Node
+  Ptr<Node> serverNode = CreateObject<Node> ();
+  AddInternetStack (serverNode);
+  Ptr<ErrorNetDevice> serverDev;
+  Ptr<BinaryErrorModel> serverDevErrorModel = CreateObject<BinaryErrorModel> ();
+  {
+    serverDev = CreateObject<ErrorNetDevice> ();
+    serverDev->SetAddress (Mac48Address::ConvertFrom (Mac48Address::Allocate ()));
+    serverDev->SetMtu (1500);
+    serverDev->SetReceiveErrorModel (serverDevErrorModel);
+    serverDevErrorModel->Disable ();
+    serverNode->AddDevice (serverDev);
+    Ptr<Ipv6> ipv6 = serverNode->GetObject<Ipv6> ();
+    uint32_t netdev_idx = ipv6->AddInterface (serverDev);
+    Ipv6InterfaceAddress ipv6Addr = Ipv6InterfaceAddress (Ipv6Address ("2001::1"), Ipv6Prefix (32));
+    ipv6->AddAddress (netdev_idx, ipv6Addr);
+    ipv6->SetUp (netdev_idx);
+  }
+  StartServer (serverNode);
+
+  // Sender Node
+  Ptr<Node> clientNode = CreateObject<Node> ();
+  AddInternetStack (clientNode);
+  Ptr<ErrorNetDevice> clientDev;
+  Ptr<BinaryErrorModel> clientDevErrorModel = CreateObject<BinaryErrorModel> ();
+  {
+    clientDev = CreateObject<ErrorNetDevice> ();
+    clientDev->SetAddress (Mac48Address::ConvertFrom (Mac48Address::Allocate ()));
+    clientDev->SetMtu (1000);
+    clientDev->SetReceiveErrorModel (clientDevErrorModel);
+    clientDevErrorModel->Disable ();
+    clientNode->AddDevice (clientDev);
+    Ptr<Ipv6> ipv6 = clientNode->GetObject<Ipv6> ();
+    uint32_t netdev_idx = ipv6->AddInterface (clientDev);
+    Ipv6InterfaceAddress ipv6Addr = Ipv6InterfaceAddress (Ipv6Address ("2001::2"), Ipv6Prefix (32));
+    ipv6->AddAddress (netdev_idx, ipv6Addr);
+    ipv6->SetUp (netdev_idx);
+  }
+  StartClient (clientNode);
+
+  // link the two nodes
+  Ptr<ErrorChannel> channel = CreateObject<ErrorChannel> ();
+  serverDev->SetChannel (channel);
+  clientDev->SetChannel (channel);
+  channel->SetJumpingTime (Seconds (0.5));
+
+
+  // some small packets, some rather big ones
+  uint32_t packetSizes[5] = {1000, 2000, 5000, 10000, 65000};
+
+  // 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),
+                                      &Ipv6FragmentationTest::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),
+                                      &Ipv6FragmentationTest::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 errors, no delays.
+  // The reassembly procedure should fire a timeout after 30 seconds (as specified in the RFCs).
+  // Upon the timeout, the fragments received so far are discarded and an ICMP should be sent back
+  // to the sender (if the first fragment has been received).
+  // In this test case the first fragment is received, so we do expect an ICMP.
+  // Client -> Server : errors enabled
+  // Server -> Client : errors disabled (we want to have back the ICMP)
+  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),
+                                      &Ipv6FragmentationTest::SendClient, this);
+      Simulator::Run ();
+
+      uint16_t recvSize = m_receivedPacketServer->GetSize ();
+
+      NS_TEST_EXPECT_MSG_EQ ((recvSize == 0), true, "Server got a packet, something wrong");
+      NS_TEST_EXPECT_MSG_EQ ((m_icmpType == Icmpv6Header::ICMPV6_ERROR_TIME_EXCEEDED)
+                             && (m_icmpCode == Icmpv6Header::ICMPV6_FRAGTIME),
+                             true, "Client did not receive ICMPv6::TIME_EXCEEDED " << int(m_icmpType) << int(m_icmpCode) );
+    }
+
+
+  Simulator::Destroy ();
+}
+//-----------------------------------------------------------------------------
+class Ipv6FragmentationTestSuite : public TestSuite
+{
+public:
+  Ipv6FragmentationTestSuite () : TestSuite ("ipv6-fragmentation", UNIT)
+  {
+    AddTestCase (new Ipv6FragmentationTest);
+  }
+} g_ipv6fragmentationTestSuite;
+
+}; // namespace ns3
--- a/src/internet/wscript	Fri Mar 23 23:51:29 2012 -0700
+++ b/src/internet/wscript	Wed Mar 21 18:51:55 2012 +0100
@@ -206,6 +206,7 @@
         'test/udp-test.cc',
         'test/ipv6-address-generator-test-suite.cc',
         'test/ipv6-dual-stack-test-suite.cc',
+        'test/ipv6-fragmentation-test.cc',
         ]
 
     headers = bld.new_task_gen(features=['ns3header'])