Add support for IPv6 transport protocols
authorKen Renard <kdrenard2@gmail.com>
Mon, 20 Feb 2012 14:05:07 +0100
changeset 7717 cfa1741013dd
parent 7714 6ee8ada63117
child 7718 f6f55bda7d4f
Add support for IPv6 transport protocols
CHANGES.html
RELEASE_NOTES
examples/udp-client-server/udp-client-server.cc
examples/udp-client-server/udp-trace-client-server.cc
examples/udp/udp-echo.cc
src/applications/helper/udp-client-server-helper.cc
src/applications/helper/udp-client-server-helper.h
src/applications/helper/udp-echo-helper.cc
src/applications/helper/udp-echo-helper.h
src/applications/model/packet-sink.cc
src/applications/model/udp-client.cc
src/applications/model/udp-client.h
src/applications/model/udp-echo-client.cc
src/applications/model/udp-echo-client.h
src/applications/model/udp-echo-server.cc
src/applications/model/udp-echo-server.h
src/applications/model/udp-server.cc
src/applications/model/udp-server.h
src/applications/model/udp-trace-client.cc
src/applications/model/udp-trace-client.h
src/csma-layout/examples/csma-star.cc
src/csma-layout/model/csma-star-helper.cc
src/csma-layout/model/csma-star-helper.h
src/internet/doc/internet-stack.rst
src/internet/doc/ipv6.rst
src/internet/model/icmpv4-l4-protocol.cc
src/internet/model/icmpv4-l4-protocol.h
src/internet/model/icmpv6-l4-protocol.cc
src/internet/model/icmpv6-l4-protocol.h
src/internet/model/ip-l4-protocol.cc
src/internet/model/ip-l4-protocol.h
src/internet/model/ipv4-l3-protocol.cc
src/internet/model/ipv4-l3-protocol.h
src/internet/model/ipv4-l4-protocol.cc
src/internet/model/ipv4-l4-protocol.h
src/internet/model/ipv4-raw-socket-impl.cc
src/internet/model/ipv4-raw-socket-impl.h
src/internet/model/ipv4.h
src/internet/model/ipv6-end-point.cc
src/internet/model/ipv6-end-point.h
src/internet/model/ipv6-l3-protocol.cc
src/internet/model/ipv6-l3-protocol.h
src/internet/model/ipv6-l4-protocol.cc
src/internet/model/ipv6-l4-protocol.h
src/internet/model/ipv6-raw-socket-impl.cc
src/internet/model/ipv6-raw-socket-impl.h
src/internet/model/nsc-tcp-l4-protocol.cc
src/internet/model/nsc-tcp-l4-protocol.h
src/internet/model/nsc-tcp-socket-impl.cc
src/internet/model/nsc-tcp-socket-impl.h
src/internet/model/tcp-header.cc
src/internet/model/tcp-header.h
src/internet/model/tcp-l4-protocol.cc
src/internet/model/tcp-l4-protocol.h
src/internet/model/tcp-socket-base.cc
src/internet/model/tcp-socket-base.h
src/internet/model/udp-header.cc
src/internet/model/udp-header.h
src/internet/model/udp-l4-protocol.cc
src/internet/model/udp-l4-protocol.h
src/internet/model/udp-socket-impl.cc
src/internet/model/udp-socket-impl.h
src/internet/test/error-net-device.cc
src/internet/test/ipv6-dual-stack-test-suite.cc
src/internet/test/tcp-test.cc
src/internet/test/udp-test.cc
src/internet/wscript
src/netanim/examples/star-animation.cc
src/network/model/socket.h
src/network/utils/ipv6-address.cc
src/network/utils/ipv6-address.h
src/network/utils/packet-socket.cc
src/network/utils/packet-socket.h
src/point-to-point-layout/model/point-to-point-dumbbell.cc
src/point-to-point-layout/model/point-to-point-dumbbell.h
src/point-to-point-layout/model/point-to-point-grid.cc
src/point-to-point-layout/model/point-to-point-grid.h
src/point-to-point-layout/model/point-to-point-star.cc
src/point-to-point-layout/model/point-to-point-star.h
--- a/CHANGES.html	Sun Feb 19 16:22:51 2012 +0100
+++ b/CHANGES.html	Mon Feb 20 14:05:07 2012 +0100
@@ -51,6 +51,74 @@
 <li> The Ipv6RawSocketImpl "IcmpFilter" attribute has been removed. Six 
 new member functions have been added to enable the same functionality.
 </li>
+<li> IPv6 support for TCP and UDP has been implemented.  Socket functions
+that take an address [e.g. Send (), Connect (), Bind ()] can accept an
+ns3::Ipv6Address or a ns3::Address in addition to taking an ns3::Ipv4Address.
+(Note that the ns3::Address must contain a ns3::Ipv6Address or a ns3::Ipv4Address,
+otherwise these functions will return an error).
+Internally, the socket now stores the remote address as a type "ns3::Address"
+instead of a type "ns3::Ipv4Address".  The IPv6 Routing Header extension is not
+currently supported in ns3 and will not be reflected in the TCP and UDP checksum
+calculations per RFC 2460.  Also note that UDP checksums for IPv6 packets are
+required per RFC, but remain optional and disabled by default in ns3 (in the
+interest of performance).
+</li>
+<li>
+When calling Bind () on a socket without an address, the behavior remains the
+same: it will bind to the IPv4 "any" address (0.0.0.0).  In order to Bind () to
+the IPv6 "any" address in a similar fashion, use "Bind6 ()".
+</li>
+<li>
+The prototype for the RxCallback function in the Ipv6EndPoint was changed.
+It now includes the destination IPv6 address of the end point which was
+needed for TCP.  This lead to a small change in the UDP and ICMPv6 L4
+protocols as well.
+</li>
+</ul>
+
+<h2>Changes to build system:</h2>
+<ul>
+<li> The following files are removed:
+<pre>
+  src/internet/model/ipv4-l4-protocol.cc
+  src/internet/model/ipv4-l4-protocol.h
+  src/internet/model/ipv6-l4-protocol.cc
+  src/internet/model/ipv6-l4-protocol.h
+</pre>
+and replaced with:
+<pre>
+  src/internet/model/ip-l4-protocol.cc
+  src/internet/model/ip-l4-protocol.h
+</pre>
+</li>
+</ul>
+<h2>Changed behavior:</h2>
+<ul>
+<li> Dual-stacked IPv6 sockets are implemented.  An IPv6 socket can accept
+an IPv4 connection, returning the senders address as an IPv4-mapped address
+(IPV6_V6ONLY socket option is not implemented).
+</li>
+<li>
+The following examples/application/helpers were modified to support IPv6:
+<pre>
+csma-layout/examples/csma-star [*]
+netanim/examples/star-animation [*]
+point-to-point-layout/model/point-to-point-star.cc
+point-to-point-layout/model/point-to-point-grid.cc
+point-to-point-layout/model/point-to-point-dumbbell.cc
+examples/udp/udp-echo [*]
+examples/udp-client-server/udp-client-server [*]
+examples/udp-client-server/udp-trace-client-server [*]
+applications/helper/udp-echo-helper
+applications/model/udp-client
+applications/model/udp-echo-client
+applications/model/udp-echo-server
+applications/model/udp-server
+applications/model/udp-trace-client
+
+[*]  Added '--useIpv6' flag to switch between IPv4 and IPv6
+</pre>
+</li>
 </ul>
 
 <hr>
--- a/RELEASE_NOTES	Sun Feb 19 16:22:51 2012 +0100
+++ b/RELEASE_NOTES	Mon Feb 20 14:05:07 2012 +0100
@@ -21,6 +21,9 @@
 
 New user-visible features
 -------------------------
+- Dual-stacked IPv6 sockets are implemented. An IPv6 socket can accept an IPv4 
+  connection, returning the senders address as an IPv4-mapped address 
+  (IPV6_V6ONLY socket option is not implemented).
 
 Bugs fixed
 ----------
--- a/examples/udp-client-server/udp-client-server.cc	Sun Feb 19 16:22:51 2012 +0100
+++ b/examples/udp-client-server/udp-client-server.cc	Mon Feb 20 14:05:07 2012 +0100
@@ -43,6 +43,13 @@
   LogComponentEnable ("UdpClient", LOG_LEVEL_INFO);
   LogComponentEnable ("UdpServer", LOG_LEVEL_INFO);
 
+  bool useV6 = false;
+  Address serverAddress;
+
+  CommandLine cmd;
+  cmd.AddValue ("useIpv6", "Use Ipv6", useV6);
+  cmd.Parse (argc, argv);
+
 //
 // Explicitly create the nodes required by the topology (shown above).
 //
@@ -63,13 +70,24 @@
   csma.SetDeviceAttribute ("Mtu", UintegerValue (1400));
   NetDeviceContainer d = csma.Install (n);
 
-  Ipv4AddressHelper ipv4;
 //
 // We've got the "hardware" in place.  Now we need to add IP addresses.
 //
   NS_LOG_INFO ("Assign IP Addresses.");
-  ipv4.SetBase ("10.1.1.0", "255.255.255.0");
-  Ipv4InterfaceContainer i = ipv4.Assign (d);
+  if (useV6 == false)
+    {
+      Ipv4AddressHelper ipv4;
+      ipv4.SetBase ("10.1.1.0", "255.255.255.0");
+      Ipv4InterfaceContainer i = ipv4.Assign (d);
+      serverAddress = Address (i.GetAddress (1));
+    }
+  else
+    {
+      Ipv6AddressHelper ipv6;
+      ipv6.NewNetwork ("2001:0000:f00d:cafe::", 64);
+      Ipv6InterfaceContainer i6 = ipv6.Assign (d);
+      serverAddress = Address(i6.GetAddress (1,1));
+    }
 
   NS_LOG_INFO ("Create Applications.");
 //
@@ -88,7 +106,7 @@
   uint32_t MaxPacketSize = 1024;
   Time interPacketInterval = Seconds (0.05);
   uint32_t maxPacketCount = 320;
-  UdpClientHelper client (i.GetAddress (1), port);
+  UdpClientHelper client (serverAddress, port);
   client.SetAttribute ("MaxPackets", UintegerValue (maxPacketCount));
   client.SetAttribute ("Interval", TimeValue (interPacketInterval));
   client.SetAttribute ("PacketSize", UintegerValue (MaxPacketSize));
--- a/examples/udp-client-server/udp-trace-client-server.cc	Sun Feb 19 16:22:51 2012 +0100
+++ b/examples/udp-client-server/udp-trace-client-server.cc	Mon Feb 20 14:05:07 2012 +0100
@@ -42,6 +42,13 @@
   LogComponentEnable ("UdpTraceClient", LOG_LEVEL_INFO);
   LogComponentEnable ("UdpServer", LOG_LEVEL_INFO);
 
+  bool useV6 = false;
+  Address serverAddress;
+
+  CommandLine cmd;
+  cmd.AddValue ("useIpv6", "Use Ipv6", useV6);
+  cmd.Parse (argc, argv);
+
 //
 // Explicitly create the nodes required by the topology (shown above).
 //
@@ -62,13 +69,24 @@
   csma.SetDeviceAttribute ("Mtu", UintegerValue (1500));
   NetDeviceContainer d = csma.Install (n);
 
-  Ipv4AddressHelper ipv4;
 //
 // We've got the "hardware" in place.  Now we need to add IP addresses.
 //
   NS_LOG_INFO ("Assign IP Addresses.");
-  ipv4.SetBase ("10.1.1.0", "255.255.255.0");
-  Ipv4InterfaceContainer i = ipv4.Assign (d);
+  if (useV6 == false)
+    {
+      Ipv4AddressHelper ipv4;
+      ipv4.SetBase ("10.1.1.0", "255.255.255.0");
+      Ipv4InterfaceContainer i = ipv4.Assign (d);
+      serverAddress = Address (i.GetAddress (1));
+    }
+  else
+    {
+      Ipv6AddressHelper ipv6;
+      ipv6.NewNetwork ("2001:0000:f00d:cafe::", 64);
+      Ipv6InterfaceContainer i6 = ipv6.Assign (d);
+      serverAddress = Address(i6.GetAddress (1,1));
+    }
 
   NS_LOG_INFO ("Create Applications.");
 //
@@ -85,7 +103,7 @@
 // node one.
 //
   uint32_t MaxPacketSize = 1472;  // Back off 20 (IP) + 8 (UDP) bytes from MTU
-  UdpTraceClientHelper client (i.GetAddress (1), port,"");
+  UdpTraceClientHelper client (serverAddress, port,"");
   client.SetAttribute ("MaxPacketSize", UintegerValue (MaxPacketSize));
   apps = client.Install (n.Get (0));
   apps.Start (Seconds (2.0));
--- a/examples/udp/udp-echo.cc	Sun Feb 19 16:22:51 2012 +0100
+++ b/examples/udp/udp-echo.cc	Mon Feb 20 14:05:07 2012 +0100
@@ -51,7 +51,11 @@
 // Allow the user to override any of the defaults and the above Bind() at
 // run-time, via command-line arguments
 //
+  bool useV6 = false;
+  Address serverAddress;
+
   CommandLine cmd;
+  cmd.AddValue ("useIpv6", "Use Ipv6", useV6);
   cmd.Parse (argc, argv);
 //
 // Explicitly create the nodes required by the topology (shown above).
@@ -73,13 +77,24 @@
   csma.SetDeviceAttribute ("Mtu", UintegerValue (1400));
   NetDeviceContainer d = csma.Install (n);
 
-  Ipv4AddressHelper ipv4;
 //
 // We've got the "hardware" in place.  Now we need to add IP addresses.
 //
   NS_LOG_INFO ("Assign IP Addresses.");
-  ipv4.SetBase ("10.1.1.0", "255.255.255.0");
-  Ipv4InterfaceContainer i = ipv4.Assign (d);
+  if (useV6 == false)
+    {
+      Ipv4AddressHelper ipv4;
+      ipv4.SetBase ("10.1.1.0", "255.255.255.0");
+      Ipv4InterfaceContainer i = ipv4.Assign (d);
+      serverAddress = Address(i.GetAddress (1));
+    }
+  else
+    {
+      Ipv6AddressHelper ipv6;
+      ipv6.NewNetwork ("2001:0000:f00d:cafe::", 64);
+      Ipv6InterfaceContainer i6 = ipv6.Assign (d);
+      serverAddress = Address(i6.GetAddress (1,1));
+    }
 
   NS_LOG_INFO ("Create Applications.");
 //
@@ -98,7 +113,7 @@
   uint32_t packetSize = 1024;
   uint32_t maxPacketCount = 1;
   Time interPacketInterval = Seconds (1.);
-  UdpEchoClientHelper client (i.GetAddress (1), port);
+  UdpEchoClientHelper client (serverAddress, port);
   client.SetAttribute ("MaxPackets", UintegerValue (maxPacketCount));
   client.SetAttribute ("Interval", TimeValue (interPacketInterval));
   client.SetAttribute ("PacketSize", UintegerValue (packetSize));
--- a/src/applications/helper/udp-client-server-helper.cc	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/applications/helper/udp-client-server-helper.cc	Mon Feb 20 14:05:07 2012 +0100
@@ -68,10 +68,24 @@
 {
 }
 
+UdpClientHelper::UdpClientHelper (Address address, uint16_t port)
+{
+  m_factory.SetTypeId (UdpClient::GetTypeId ());
+  SetAttribute ("RemoteAddress", AddressValue (address));
+  SetAttribute ("RemotePort", UintegerValue (port));
+}
+
 UdpClientHelper::UdpClientHelper (Ipv4Address address, uint16_t port)
 {
   m_factory.SetTypeId (UdpClient::GetTypeId ());
-  SetAttribute ("RemoteAddress", Ipv4AddressValue (address));
+  SetAttribute ("RemoteAddress", AddressValue (Address(address)));
+  SetAttribute ("RemotePort", UintegerValue (port));
+}
+
+UdpClientHelper::UdpClientHelper (Ipv6Address address, uint16_t port)
+{
+  m_factory.SetTypeId (UdpClient::GetTypeId ());
+  SetAttribute ("RemoteAddress", AddressValue (Address(address)));
   SetAttribute ("RemotePort", UintegerValue (port));
 }
 
@@ -99,10 +113,26 @@
 {
 }
 
+UdpTraceClientHelper::UdpTraceClientHelper (Address address, uint16_t port, std::string filename)
+{
+  m_factory.SetTypeId (UdpTraceClient::GetTypeId ());
+  SetAttribute ("RemoteAddress", AddressValue (address));
+  SetAttribute ("RemotePort", UintegerValue (port));
+  SetAttribute ("TraceFilename", StringValue (filename));
+}
+
 UdpTraceClientHelper::UdpTraceClientHelper (Ipv4Address address, uint16_t port, std::string filename)
 {
   m_factory.SetTypeId (UdpTraceClient::GetTypeId ());
-  SetAttribute ("RemoteAddress", Ipv4AddressValue (address));
+  SetAttribute ("RemoteAddress", AddressValue (Address (address)));
+  SetAttribute ("RemotePort", UintegerValue (port));
+  SetAttribute ("TraceFilename", StringValue (filename));
+}
+
+UdpTraceClientHelper::UdpTraceClientHelper (Ipv6Address address, uint16_t port, std::string filename)
+{
+  m_factory.SetTypeId (UdpTraceClient::GetTypeId ());
+  SetAttribute ("RemoteAddress", AddressValue (Address (address)));
   SetAttribute ("RemotePort", UintegerValue (port));
   SetAttribute ("TraceFilename", StringValue (filename));
 }
--- a/src/applications/helper/udp-client-server-helper.h	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/applications/helper/udp-client-server-helper.h	Mon Feb 20 14:05:07 2012 +0100
@@ -100,6 +100,8 @@
    */
 
   UdpClientHelper (Ipv4Address ip, uint16_t port);
+  UdpClientHelper (Ipv6Address ip, uint16_t port);
+  UdpClientHelper (Address ip, uint16_t port);
 
   /**
    * Record an attribute to be set in each Application after it is is created.
@@ -150,7 +152,9 @@
    * \param port The port number of the remote udp server
    * \param filename the file from which packet traces will be loaded
    */
+  UdpTraceClientHelper (Address ip, uint16_t port, std::string filename);
   UdpTraceClientHelper (Ipv4Address ip, uint16_t port, std::string filename);
+  UdpTraceClientHelper (Ipv6Address ip, uint16_t port, std::string filename);
 
   /**
     * Record an attribute to be set in each Application after it is is created.
--- a/src/applications/helper/udp-echo-helper.cc	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/applications/helper/udp-echo-helper.cc	Mon Feb 20 14:05:07 2012 +0100
@@ -73,10 +73,24 @@
   return app;
 }
 
+UdpEchoClientHelper::UdpEchoClientHelper (Address address, uint16_t port)
+{
+  m_factory.SetTypeId (UdpEchoClient::GetTypeId ());
+  SetAttribute ("RemoteAddress", AddressValue (address));
+  SetAttribute ("RemotePort", UintegerValue (port));
+}
+
 UdpEchoClientHelper::UdpEchoClientHelper (Ipv4Address address, uint16_t port)
 {
   m_factory.SetTypeId (UdpEchoClient::GetTypeId ());
-  SetAttribute ("RemoteAddress", Ipv4AddressValue (address));
+  SetAttribute ("RemoteAddress", AddressValue (Address(address)));
+  SetAttribute ("RemotePort", UintegerValue (port));
+}
+
+UdpEchoClientHelper::UdpEchoClientHelper (Ipv6Address address, uint16_t port)
+{
+  m_factory.SetTypeId (UdpEchoClient::GetTypeId ());
+  SetAttribute ("RemoteAddress", AddressValue (Address(address)));
   SetAttribute ("RemotePort", UintegerValue (port));
 }
 
--- a/src/applications/helper/udp-echo-helper.h	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/applications/helper/udp-echo-helper.h	Mon Feb 20 14:05:07 2012 +0100
@@ -25,6 +25,7 @@
 #include "ns3/node-container.h"
 #include "ns3/object-factory.h"
 #include "ns3/ipv4-address.h"
+#include "ns3/ipv6-address.h"
 
 namespace ns3 {
 
@@ -106,7 +107,9 @@
    * \param ip The IP address of the remote udp echo server
    * \param port The port number of the remote udp echo server
    */
+  UdpEchoClientHelper (Address ip, uint16_t port);
   UdpEchoClientHelper (Ipv4Address ip, uint16_t port);
+  UdpEchoClientHelper (Ipv6Address ip, uint16_t port);
 
   /**
    * Record an attribute to be set in each Application after it is is created.
--- a/src/applications/model/packet-sink.cc	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/applications/model/packet-sink.cc	Mon Feb 20 14:05:07 2012 +0100
@@ -21,6 +21,7 @@
 #include "ns3/address-utils.h"
 #include "ns3/log.h"
 #include "ns3/inet-socket-address.h"
+#include "ns3/inet6-socket-address.h"
 #include "ns3/node.h"
 #include "ns3/socket.h"
 #include "ns3/udp-socket.h"
@@ -178,6 +179,17 @@
           m_totalRx += packet->GetSize ();
           NS_LOG_INFO (PrintStats (from, packet->GetSize (), m_totalRx));
         }
+      else if (Inet6SocketAddress::IsMatchingType (from))
+        {
+          m_totalRx += packet->GetSize ();
+          Inet6SocketAddress address = Inet6SocketAddress::ConvertFrom (from);
+          NS_LOG_INFO ("Received " << packet->GetSize () << " bytes from " <<
+                       address.GetIpv6 () << " [" << address << "]"
+                                   << " total Rx " << m_totalRx);
+          //cast address to void , to suppress 'address' set but not used 
+          //compiler warning in optimized builds
+          (void) address;
+        }
       m_rxTrace (packet, from);
     }
 }
--- a/src/applications/model/udp-client.cc	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/applications/model/udp-client.cc	Mon Feb 20 14:05:07 2012 +0100
@@ -22,6 +22,7 @@
 #include "ns3/ipv4-address.h"
 #include "ns3/nstime.h"
 #include "ns3/inet-socket-address.h"
+#include "ns3/inet6-socket-address.h"
 #include "ns3/socket.h"
 #include "ns3/simulator.h"
 #include "ns3/socket-factory.h"
@@ -54,10 +55,10 @@
                    MakeTimeChecker ())
     .AddAttribute (
       "RemoteAddress",
-      "The destination Ipv4Address of the outbound packets",
-      Ipv4AddressValue (),
-      MakeIpv4AddressAccessor (&UdpClient::m_peerAddress),
-      MakeIpv4AddressChecker ())
+      "The destination Address of the outbound packets",
+      AddressValue (),
+      MakeAddressAccessor (&UdpClient::m_peerAddress),
+      MakeAddressChecker ())
     .AddAttribute ("RemotePort", "The destination port of the outbound packets",
                    UintegerValue (100),
                    MakeUintegerAccessor (&UdpClient::m_peerPort),
@@ -87,6 +88,20 @@
 void
 UdpClient::SetRemote (Ipv4Address ip, uint16_t port)
 {
+  m_peerAddress = Address(ip);
+  m_peerPort = port;
+}
+
+void
+UdpClient::SetRemote (Ipv6Address ip, uint16_t port)
+{
+  m_peerAddress = Address(ip);
+  m_peerPort = port;
+}
+
+void
+UdpClient::SetRemote (Address ip, uint16_t port)
+{
   m_peerAddress = ip;
   m_peerPort = port;
 }
@@ -107,8 +122,16 @@
     {
       TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
       m_socket = Socket::CreateSocket (GetNode (), tid);
-      m_socket->Bind ();
-      m_socket->Connect (InetSocketAddress (m_peerAddress, m_peerPort));
+      if (Ipv4Address::IsMatchingType(m_peerAddress) == true)
+        {
+          m_socket->Bind ();
+          m_socket->Connect (InetSocketAddress (Ipv4Address::ConvertFrom(m_peerAddress), m_peerPort));
+        }
+      else if (Ipv6Address::IsMatchingType(m_peerAddress) == true)
+        {
+          m_socket->Bind6 ();
+          m_socket->Connect (Inet6SocketAddress (Ipv6Address::ConvertFrom(m_peerAddress), m_peerPort));
+        }
     }
 
   m_socket->SetRecvCallback (MakeNullCallback<void, Ptr<Socket> > ());
@@ -132,18 +155,29 @@
   Ptr<Packet> p = Create<Packet> (m_size-(8+4)); // 8+4 : the size of the seqTs header
   p->AddHeader (seqTs);
 
+  std::stringstream peerAddressStringStream;
+  if (Ipv4Address::IsMatchingType (m_peerAddress))
+    {
+      peerAddressStringStream << Ipv4Address::ConvertFrom (m_peerAddress);
+    }
+  else if (Ipv6Address::IsMatchingType (m_peerAddress))
+    {
+      peerAddressStringStream << Ipv6Address::ConvertFrom (m_peerAddress);
+    }
+
   if ((m_socket->Send (p)) >= 0)
     {
       ++m_sent;
       NS_LOG_INFO ("TraceDelay TX " << m_size << " bytes to "
-                                    << m_peerAddress << " Uid: " << p->GetUid ()
-                                    << " Time: " << (Simulator::Now ()).GetSeconds ());
+                                    << peerAddressStringStream.str () << " Uid: "
+                                    << p->GetUid () << " Time: "
+                                    << (Simulator::Now ()).GetSeconds ());
 
     }
   else
     {
       NS_LOG_INFO ("Error while sending " << m_size << " bytes to "
-                                          << m_peerAddress);
+                                          << peerAddressStringStream.str ());
     }
 
   if (m_sent < m_count)
--- a/src/applications/model/udp-client.h	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/applications/model/udp-client.h	Mon Feb 20 14:05:07 2012 +0100
@@ -56,6 +56,8 @@
    * \param port remote port
    */
   void SetRemote (Ipv4Address ip, uint16_t port);
+  void SetRemote (Ipv6Address ip, uint16_t port);
+  void SetRemote (Address ip, uint16_t port);
 
 protected:
   virtual void DoDispose (void);
@@ -74,7 +76,7 @@
 
   uint32_t m_sent;
   Ptr<Socket> m_socket;
-  Ipv4Address m_peerAddress;
+  Address m_peerAddress;
   uint16_t m_peerPort;
   EventId m_sendEvent;
 
--- a/src/applications/model/udp-echo-client.cc	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/applications/model/udp-echo-client.cc	Mon Feb 20 14:05:07 2012 +0100
@@ -17,8 +17,10 @@
  */
 #include "ns3/log.h"
 #include "ns3/ipv4-address.h"
+#include "ns3/ipv6-address.h"
 #include "ns3/nstime.h"
 #include "ns3/inet-socket-address.h"
+#include "ns3/inet6-socket-address.h"
 #include "ns3/socket.h"
 #include "ns3/simulator.h"
 #include "ns3/socket-factory.h"
@@ -49,10 +51,10 @@
                    MakeTimeAccessor (&UdpEchoClient::m_interval),
                    MakeTimeChecker ())
     .AddAttribute ("RemoteAddress", 
-                   "The destination Ipv4Address of the outbound packets",
-                   Ipv4AddressValue (),
-                   MakeIpv4AddressAccessor (&UdpEchoClient::m_peerAddress),
-                   MakeIpv4AddressChecker ())
+                   "The destination Address of the outbound packets",
+                   AddressValue (),
+                   MakeAddressAccessor (&UdpEchoClient::m_peerAddress),
+                   MakeAddressChecker ())
     .AddAttribute ("RemotePort", 
                    "The destination port of the outbound packets",
                    UintegerValue (0),
@@ -90,9 +92,23 @@
 }
 
 void 
+UdpEchoClient::SetRemote (Address ip, uint16_t port)
+{
+  m_peerAddress = ip;
+  m_peerPort = port;
+}
+
+void 
 UdpEchoClient::SetRemote (Ipv4Address ip, uint16_t port)
 {
-  m_peerAddress = ip;
+  m_peerAddress = Address (ip);
+  m_peerPort = port;
+}
+
+void 
+UdpEchoClient::SetRemote (Ipv6Address ip, uint16_t port)
+{
+  m_peerAddress = Address (ip);
   m_peerPort = port;
 }
 
@@ -112,8 +128,16 @@
     {
       TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
       m_socket = Socket::CreateSocket (GetNode (), tid);
-      m_socket->Bind ();
-      m_socket->Connect (InetSocketAddress (m_peerAddress, m_peerPort));
+      if (Ipv4Address::IsMatchingType(m_peerAddress) == true)
+        {
+          m_socket->Bind();
+          m_socket->Connect (InetSocketAddress (Ipv4Address::ConvertFrom(m_peerAddress), m_peerPort));
+        }
+      else if (Ipv6Address::IsMatchingType(m_peerAddress) == true)
+        {
+          m_socket->Bind6();
+          m_socket->Connect (Inet6SocketAddress (Ipv6Address::ConvertFrom(m_peerAddress), m_peerPort));
+        }
     }
 
   m_socket->SetRecvCallback (MakeCallback (&UdpEchoClient::HandleRead, this));
@@ -281,7 +305,16 @@
 
   ++m_sent;
 
-  NS_LOG_INFO ("Sent " << m_size << " bytes to " << m_peerAddress);
+  if (InetSocketAddress::IsMatchingType (m_peerAddress))
+    {
+      NS_LOG_INFO ("Sent " << m_size << " bytes to " <<
+                   InetSocketAddress::ConvertFrom (m_peerAddress));
+    }
+  else if (Inet6SocketAddress::IsMatchingType (m_peerAddress))
+    {
+      NS_LOG_INFO ("Sent " << m_size << " bytes to " <<
+                   Inet6SocketAddress::ConvertFrom (m_peerAddress));
+    }
 
   if (m_sent < m_count) 
     {
@@ -302,6 +335,11 @@
           NS_LOG_INFO ("Received " << packet->GetSize () << " bytes from " <<
                        InetSocketAddress::ConvertFrom (from).GetIpv4 ());
         }
+      else if (Inet6SocketAddress::IsMatchingType (from))
+        {
+          NS_LOG_INFO ("Received " << packet->GetSize () << " bytes from " <<
+                       Inet6SocketAddress::ConvertFrom (from).GetIpv6 ());
+        }
     }
 }
 
--- a/src/applications/model/udp-echo-client.h	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/applications/model/udp-echo-client.h	Mon Feb 20 14:05:07 2012 +0100
@@ -49,7 +49,9 @@
    * \param ip destination ipv4 address
    * \param port destination port
    */
+  void SetRemote (Address ip, uint16_t port);
   void SetRemote (Ipv4Address ip, uint16_t port);
+  void SetRemote (Ipv6Address ip, uint16_t port);
 
   /**
    * Set the data size of the packet (the number of bytes that are sent as data
@@ -142,7 +144,7 @@
 
   uint32_t m_sent;
   Ptr<Socket> m_socket;
-  Ipv4Address m_peerAddress;
+  Address m_peerAddress;
   uint16_t m_peerPort;
   EventId m_sendEvent;
   /// Callbacks for tracing the packet Tx events
--- a/src/applications/model/udp-echo-server.cc	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/applications/model/udp-echo-server.cc	Mon Feb 20 14:05:07 2012 +0100
@@ -18,9 +18,11 @@
 
 #include "ns3/log.h"
 #include "ns3/ipv4-address.h"
+#include "ns3/ipv6-address.h"
 #include "ns3/address-utils.h"
 #include "ns3/nstime.h"
 #include "ns3/inet-socket-address.h"
+#include "ns3/inet6-socket-address.h"
 #include "ns3/socket.h"
 #include "ns3/udp-socket.h"
 #include "ns3/simulator.h"
@@ -58,6 +60,7 @@
 {
   NS_LOG_FUNCTION_NOARGS ();
   m_socket = 0;
+  m_socket6 = 0;
 }
 
 void
@@ -88,12 +91,34 @@
             }
           else
             {
-              NS_FATAL_ERROR ("Error: joining multicast on a non-UDP socket");
+              NS_FATAL_ERROR ("Error: Failed to join multicast group");
+            }
+        }
+    }
+
+  if (m_socket6 == 0)
+    {
+      TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
+      m_socket6 = Socket::CreateSocket (GetNode (), tid);
+      Inet6SocketAddress local6 = Inet6SocketAddress (Ipv6Address::GetAny (), m_port);
+      m_socket6->Bind (local6);
+      if (addressUtils::IsMulticast (local6))
+        {
+          Ptr<UdpSocket> udpSocket = DynamicCast<UdpSocket> (m_socket6);
+          if (udpSocket)
+            {
+              // equivalent to setsockopt (MCAST_JOIN_GROUP)
+              udpSocket->MulticastJoinGroup (0, local6);
+            }
+          else
+            {
+              NS_FATAL_ERROR ("Error: Failed to join multicast group");
             }
         }
     }
 
   m_socket->SetRecvCallback (MakeCallback (&UdpEchoServer::HandleRead, this));
+  m_socket6->SetRecvCallback (MakeCallback (&UdpEchoServer::HandleRead, this));
 }
 
 void 
@@ -106,6 +131,11 @@
       m_socket->Close ();
       m_socket->SetRecvCallback (MakeNullCallback<void, Ptr<Socket> > ());
     }
+  if (m_socket6 != 0) 
+    {
+      m_socket6->Close ();
+      m_socket6->SetRecvCallback (MakeNullCallback<void, Ptr<Socket> > ());
+    }
 }
 
 void 
@@ -126,6 +156,17 @@
           NS_LOG_LOGIC ("Echoing packet");
           socket->SendTo (packet, 0, from);
         }
+      else if (Inet6SocketAddress::IsMatchingType (from))
+        {
+          NS_LOG_INFO ("Received " << packet->GetSize () << " bytes from " <<
+                       Inet6SocketAddress::ConvertFrom (from).GetIpv6 ());
+
+          packet->RemoveAllPacketTags ();
+          packet->RemoveAllByteTags ();
+
+          NS_LOG_LOGIC ("Echoing packet");
+          socket->SendTo (packet, 0, from);
+        }
     }
 }
 
--- a/src/applications/model/udp-echo-server.h	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/applications/model/udp-echo-server.h	Mon Feb 20 14:05:07 2012 +0100
@@ -59,6 +59,7 @@
 
   uint16_t m_port;
   Ptr<Socket> m_socket;
+  Ptr<Socket> m_socket6;
   Address m_local;
 };
 
--- a/src/applications/model/udp-server.cc	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/applications/model/udp-server.cc	Mon Feb 20 14:05:07 2012 +0100
@@ -23,6 +23,7 @@
 #include "ns3/ipv4-address.h"
 #include "ns3/nstime.h"
 #include "ns3/inet-socket-address.h"
+#include "ns3/inet6-socket-address.h"
 #include "ns3/socket.h"
 #include "ns3/simulator.h"
 #include "ns3/socket-factory.h"
@@ -121,6 +122,17 @@
 
   m_socket->SetRecvCallback (MakeCallback (&UdpServer::HandleRead, this));
 
+  if (m_socket6 == 0)
+    {
+      TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
+      m_socket6 = Socket::CreateSocket (GetNode (), tid);
+      Inet6SocketAddress local = Inet6SocketAddress (Ipv6Address::GetAny (),
+                                                   m_port);
+      m_socket6->Bind (local);
+    }
+
+  m_socket6->SetRecvCallback (MakeCallback (&UdpServer::HandleRead, this));
+
 }
 
 void
@@ -147,13 +159,26 @@
           SeqTsHeader seqTs;
           packet->RemoveHeader (seqTs);
           uint32_t currentSequenceNumber = seqTs.GetSeq ();
-          NS_LOG_INFO ("TraceDelay: RX " << packet->GetSize () <<
-                       " bytes from "<< InetSocketAddress::ConvertFrom (from).GetIpv4 () <<
-                       " Sequence Number: " << currentSequenceNumber <<
-                       " Uid: " << packet->GetUid () <<
-                       " TXtime: " << seqTs.GetTs () <<
-                       " RXtime: " << Simulator::Now () <<
-                       " Delay: " << Simulator::Now () - seqTs.GetTs ());
+          if (InetSocketAddress::IsMatchingType (from))
+            {
+              NS_LOG_INFO ("TraceDelay: RX " << packet->GetSize () <<
+                           " bytes from "<< InetSocketAddress::ConvertFrom (from).GetIpv4 () <<
+                           " Sequence Number: " << currentSequenceNumber <<
+                           " Uid: " << packet->GetUid () <<
+                           " TXtime: " << seqTs.GetTs () <<
+                           " RXtime: " << Simulator::Now () <<
+                           " Delay: " << Simulator::Now () - seqTs.GetTs ());
+            }
+          else if (Inet6SocketAddress::IsMatchingType (from))
+            {
+              NS_LOG_INFO ("TraceDelay: RX " << packet->GetSize () <<
+                           " bytes from "<< Inet6SocketAddress::ConvertFrom (from).GetIpv6 () <<
+                           " Sequence Number: " << currentSequenceNumber <<
+                           " Uid: " << packet->GetUid () <<
+                           " TXtime: " << seqTs.GetTs () <<
+                           " RXtime: " << Simulator::Now () <<
+                           " Delay: " << Simulator::Now () - seqTs.GetTs ());
+            }
 
           m_lossCounter.NotifyReceived (currentSequenceNumber);
           m_received++;
--- a/src/applications/model/udp-server.h	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/applications/model/udp-server.h	Mon Feb 20 14:05:07 2012 +0100
@@ -84,6 +84,7 @@
 
   uint16_t m_port;
   Ptr<Socket> m_socket;
+  Ptr<Socket> m_socket6;
   Address m_local;
   uint32_t m_received;
   PacketLossCounter m_lossCounter;
--- a/src/applications/model/udp-trace-client.cc	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/applications/model/udp-trace-client.cc	Mon Feb 20 14:05:07 2012 +0100
@@ -22,6 +22,7 @@
 #include "ns3/ipv4-address.h"
 #include "ns3/nstime.h"
 #include "ns3/inet-socket-address.h"
+#include "ns3/inet6-socket-address.h"
 #include "ns3/socket.h"
 #include "ns3/simulator.h"
 #include "ns3/socket-factory.h"
@@ -59,10 +60,10 @@
     .SetParent<Application> ()
     .AddConstructor<UdpTraceClient> ()
     .AddAttribute ("RemoteAddress",
-                   "The destination Ipv4Address of the outbound packets",
-                   Ipv4AddressValue (),
-                   MakeIpv4AddressAccessor (&UdpTraceClient::m_peerAddress),
-                   MakeIpv4AddressChecker ())
+                   "The destination Address of the outbound packets",
+                   AddressValue (),
+                   MakeAddressAccessor (&UdpTraceClient::m_peerAddress),
+                   MakeAddressChecker ())
     .AddAttribute ("RemotePort",
                    "The destination port of the outbound packets",
                    UintegerValue (100),
@@ -116,10 +117,26 @@
 }
 
 void
+UdpTraceClient::SetRemote (Address ip, uint16_t port)
+{
+  m_entries.clear ();
+  m_peerAddress = ip;
+  m_peerPort = port;
+}
+
+void
 UdpTraceClient::SetRemote (Ipv4Address ip, uint16_t port)
 {
   m_entries.clear ();
-  m_peerAddress = ip;
+  m_peerAddress = Address (ip);
+  m_peerPort = port;
+}
+
+void
+UdpTraceClient::SetRemote (Ipv6Address ip, uint16_t port)
+{
+  m_entries.clear ();
+  m_peerAddress = Address (ip);
   m_peerPort = port;
 }
 
@@ -223,8 +240,16 @@
     {
       TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
       m_socket = Socket::CreateSocket (GetNode (), tid);
-      m_socket->Bind ();
-      m_socket->Connect (InetSocketAddress (m_peerAddress, m_peerPort));
+      if (Ipv4Address::IsMatchingType(m_peerAddress) == true)
+        {
+          m_socket->Bind ();
+          m_socket->Connect (InetSocketAddress (Ipv4Address::ConvertFrom (m_peerAddress), m_peerPort));
+        }
+      else if (Ipv6Address::IsMatchingType(m_peerAddress) == true)
+        {
+          m_socket->Bind6 ();
+          m_socket->Connect (Inet6SocketAddress (Ipv6Address::ConvertFrom (m_peerAddress), m_peerPort));
+        }
     }
   m_socket->SetRecvCallback (MakeNullCallback<void, Ptr<Socket> > ());
   m_sendEvent = Simulator::Schedule (Seconds (0.0), &UdpTraceClient::Send, this);
@@ -255,16 +280,31 @@
   SeqTsHeader seqTs;
   seqTs.SetSeq (m_sent);
   p->AddHeader (seqTs);
+
+  std::stringstream addressString;
+  if (Ipv4Address::IsMatchingType(m_peerAddress) == true)
+    {
+      addressString << Ipv4Address::ConvertFrom (m_peerAddress);
+    }
+  else if (Ipv6Address::IsMatchingType(m_peerAddress) == true)
+    {
+      addressString << Ipv6Address::ConvertFrom (m_peerAddress);
+    }
+  else
+    {
+      addressString << m_peerAddress;
+    }
+
   if ((m_socket->Send (p)) >= 0)
     {
       ++m_sent;
       NS_LOG_INFO ("Sent " << size << " bytes to "
-                           << m_peerAddress);
+                           << addressString.str ());
     }
   else
     {
       NS_LOG_INFO ("Error while sending " << size << " bytes to "
-                                          << m_peerAddress);
+                                          << addressString.str ());
     }
 }
 
--- a/src/applications/model/udp-trace-client.h	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/applications/model/udp-trace-client.h	Mon Feb 20 14:05:07 2012 +0100
@@ -80,7 +80,9 @@
    * \param ip the destination ip address to which the stream will be sent
    * \param port the destination udp port to which the stream will be sent
    */
+  void SetRemote (Address ip, uint16_t port);
   void SetRemote (Ipv4Address ip, uint16_t port);
+  void SetRemote (Ipv6Address ip, uint16_t port);
 
   /**
    * \brief set the trace file to be used by the application
@@ -122,7 +124,7 @@
   };
   uint32_t m_sent;
   Ptr<Socket> m_socket;
-  Ipv4Address m_peerAddress;
+  Address m_peerAddress;
   uint16_t m_peerPort;
   EventId m_sendEvent;
   std::vector<struct TraceEntry> m_entries;
--- a/src/csma-layout/examples/csma-star.cc	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/csma-layout/examples/csma-star.cc	Mon Feb 20 14:05:07 2012 +0100
@@ -22,6 +22,7 @@
 #include "ns3/applications-module.h"
 #include "ns3/csma-module.h"
 #include "ns3/internet-module.h"
+#include "ns3/ipv6-address-generator.h"
 
 // Network topology (default)
 //
@@ -61,9 +62,13 @@
   // Default number of nodes in the star.  Overridable by command line argument.
   //
   uint32_t nSpokes = 7;
+  uint32_t useIpv6 = 0;
+  Ipv6Address ipv6AddressBase = Ipv6Address("2001::");
+  Ipv6Prefix ipv6AddressPrefix = Ipv6Prefix(64);
 
   CommandLine cmd;
   cmd.AddValue ("nSpokes", "Number of spoke nodes to place in the star", nSpokes);
+  cmd.AddValue ("useIpv6", "Use Ipv6", useIpv6);
   cmd.Parse (argc, argv);
 
   NS_LOG_INFO ("Build star topology.");
@@ -98,7 +103,14 @@
   internet.Install (fillNodes);
 
   NS_LOG_INFO ("Assign IP Addresses.");
-  star.AssignIpv4Addresses (Ipv4AddressHelper ("10.1.0.0", "255.255.255.0"));
+  if (useIpv6 == 0)
+    {
+      star.AssignIpv4Addresses (Ipv4AddressHelper ("10.1.0.0", "255.255.255.0"));
+    }
+  else
+    {
+      star.AssignIpv6Addresses (ipv6AddressBase, ipv6AddressPrefix);
+    }
 
   //
   // We assigned addresses to the logical hub and the first "drop" of the 
@@ -111,16 +123,31 @@
   // etc.
   //
   Ipv4AddressHelper address;
+  Ipv6AddressHelper address6;
   for(uint32_t i = 0; i < star.SpokeCount (); ++i)
     {
-      std::ostringstream subnet;
-      subnet << "10.1." << i << ".0";
-      NS_LOG_INFO ("Assign IP Addresses for CSMA subnet " << subnet.str ());
-      address.SetBase (subnet.str ().c_str (), "255.255.255.0", "0.0.0.3");
+      if (useIpv6 == 0)
+        {
+          std::ostringstream subnet;
+          subnet << "10.1." << i << ".0";
+          NS_LOG_INFO ("Assign IP Addresses for CSMA subnet " << subnet.str ());
+          address.SetBase (subnet.str ().c_str (), "255.255.255.0", "0.0.0.3");
 
-      for (uint32_t j = 0; j < nFill; ++j)
+          for (uint32_t j = 0; j < nFill; ++j)
+            {
+              address.Assign (fillDevices.Get (i * nFill + j));
+            }
+        }
+      else
         {
-          address.Assign (fillDevices.Get (i * nFill + j));
+          Ipv6AddressGenerator::Init (ipv6AddressBase, ipv6AddressPrefix);
+          Ipv6Address v6network = Ipv6AddressGenerator::GetNetwork (ipv6AddressPrefix);
+          address6.NewNetwork(v6network, ipv6AddressPrefix);
+
+          for (uint32_t j = 0; j < nFill; ++j)
+            {
+              address6.Assign(fillDevices.Get (i * nFill + j));
+            }
         }
     }
 
@@ -129,11 +156,23 @@
   // Create a packet sink on the star "hub" to receive packets.
   // 
   uint16_t port = 50000;
-  Address hubLocalAddress (InetSocketAddress (Ipv4Address::GetAny (), port));
-  PacketSinkHelper packetSinkHelper ("ns3::TcpSocketFactory", hubLocalAddress);
-  ApplicationContainer hubApp = packetSinkHelper.Install (star.GetHub ());
-  hubApp.Start (Seconds (1.0));
-  hubApp.Stop (Seconds (10.0));
+
+  if (useIpv6 == 0)
+    {
+      Address hubLocalAddress (InetSocketAddress (Ipv4Address::GetAny (), port));
+      PacketSinkHelper packetSinkHelper ("ns3::TcpSocketFactory", hubLocalAddress);
+      ApplicationContainer hubApp = packetSinkHelper.Install (star.GetHub ());
+      hubApp.Start (Seconds (1.0));
+      hubApp.Stop (Seconds (10.0));
+    }
+  else 
+    {
+      Address hubLocalAddress6 (Inet6SocketAddress (Ipv6Address::GetAny (), port));
+      PacketSinkHelper packetSinkHelper6 ("ns3::TcpSocketFactory", hubLocalAddress6);
+      ApplicationContainer hubApp6 = packetSinkHelper6.Install (star.GetHub ());
+      hubApp6.Start (Seconds (1.0));
+      hubApp6.Stop (Seconds (10.0));
+    }
 
   //
   // Create OnOff applications to send TCP to the hub, one on each spoke node.
@@ -146,8 +185,16 @@
 
   for (uint32_t i = 0; i < star.SpokeCount (); ++i)
     {
-      AddressValue remoteAddress (InetSocketAddress (star.GetHubIpv4Address (i), port));
-      onOffHelper.SetAttribute ("Remote", remoteAddress);
+      if (useIpv6 == 0)
+        {
+          AddressValue remoteAddress (InetSocketAddress (star.GetHubIpv4Address (i), port));
+          onOffHelper.SetAttribute ("Remote", remoteAddress);
+        }
+      else
+        {
+          AddressValue remoteAddress (Inet6SocketAddress (star.GetHubIpv6Address (i), port));
+          onOffHelper.SetAttribute ("Remote", remoteAddress);
+        }
       spokeApps.Add (onOffHelper.Install (star.GetSpokeNode (i)));
     }
 
@@ -166,7 +213,15 @@
 
   for (uint32_t i = 0; i < fillNodes.GetN (); ++i)
     {
-      AddressValue remoteAddress (InetSocketAddress (star.GetHubIpv4Address (i / nFill), port));
+      AddressValue remoteAddress;
+      if (useIpv6 == 0)
+        {
+          remoteAddress = AddressValue(InetSocketAddress (star.GetHubIpv4Address (i / nFill), port));
+        }
+      else
+        {
+          remoteAddress = AddressValue(Inet6SocketAddress (star.GetHubIpv6Address (i / nFill), port));
+        }
       onOffHelper.SetAttribute ("Remote", remoteAddress);
       fillApps.Add (onOffHelper.Install (fillNodes.Get (i)));
     }
@@ -178,7 +233,10 @@
   //
   // Turn on global static routing so we can actually be routed across the star.
   //
-  Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
+  if (useIpv6 == 0)
+    {
+      Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
+    }
 
   NS_LOG_INFO ("Enable pcap tracing.");
   //
--- a/src/csma-layout/model/csma-star-helper.cc	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/csma-layout/model/csma-star-helper.cc	Mon Feb 20 14:05:07 2012 +0100
@@ -83,6 +83,18 @@
   return m_spokeInterfaces.GetAddress (i);
 }
 
+Ipv6Address
+CsmaStarHelper::GetHubIpv6Address (uint32_t i) const
+{
+  return m_hubInterfaces6.GetAddress (i, 1);
+}
+
+Ipv6Address
+CsmaStarHelper::GetSpokeIpv6Address (uint32_t i) const
+{
+  return m_spokeInterfaces6.GetAddress (i, 1);
+}
+
 uint32_t
 CsmaStarHelper::SpokeCount () const
 {
@@ -107,4 +119,25 @@
     }
 }
 
+void 
+CsmaStarHelper::AssignIpv6Addresses (Ipv6Address network, Ipv6Prefix prefix)
+{
+  Ipv6AddressGenerator::Init(network, prefix);
+  Ipv6Address v6network;
+  Ipv6AddressHelper addressHelper;
+
+  for (uint32_t i = 0; i < m_spokes.GetN (); ++i)
+    {
+      v6network = Ipv6AddressGenerator::GetNetwork (prefix);
+      addressHelper.NewNetwork(v6network, prefix);
+
+      Ipv6InterfaceContainer ic = addressHelper.Assign (m_hubDevices.Get (i));
+      m_hubInterfaces6.Add (ic);
+      ic = addressHelper.Assign (m_spokeDevices.Get (i));
+      m_spokeInterfaces6.Add (ic);
+
+      Ipv6AddressGenerator::NextNetwork (prefix);
+    }
+}
+
 } // namespace ns3
--- a/src/csma-layout/model/csma-star-helper.h	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/csma-layout/model/csma-star-helper.h	Mon Feb 20 14:05:07 2012 +0100
@@ -23,8 +23,11 @@
 
 #include "csma-helper.h"
 #include "ipv4-address-helper.h"
+#include "ipv6-address-helper.h"
 #include "internet-stack-helper.h"
 #include "ipv4-interface-container.h"
+#include "ipv6-interface-container.h"
+#include "ipv6-address-generator.h"
 
 namespace ns3 {
 
@@ -92,6 +95,13 @@
   Ipv4Address GetHubIpv4Address (uint32_t i) const;
 
   /**
+   * \param i index into the hub interfaces
+   *
+   * \returns Ipv6Address according to indexed hub interface
+   */
+  Ipv6Address GetHubIpv6Address (uint32_t i) const;
+
+  /**
    * \param i index into the spoke interfaces
    *
    * \returns Ipv4Address according to indexed spoke interface
@@ -99,6 +109,13 @@
   Ipv4Address GetSpokeIpv4Address (uint32_t i) const;
 
   /**
+   * \param i index into the spoke interfaces
+   *
+   * \returns Ipv6Address according to indexed spoke interface
+   */
+  Ipv6Address GetSpokeIpv6Address (uint32_t i) const;
+
+  /**
    * \returns the total number of spokes in the star
    */
   uint32_t SpokeCount () const;
@@ -116,6 +133,13 @@
    */
   void AssignIpv4Addresses (Ipv4AddressHelper address);
 
+  /**
+   * \param network an IPv6 Address representing the network portion
+   *                of the Ipv6 Address
+   * \param prefix the prefix length
+   */
+  void AssignIpv6Addresses (Ipv6Address network, Ipv6Prefix prefix);
+
 private:
   NodeContainer m_hub;
   NetDeviceContainer m_hubDevices;
@@ -123,6 +147,8 @@
   NetDeviceContainer m_spokeDevices;
   Ipv4InterfaceContainer m_hubInterfaces;
   Ipv4InterfaceContainer m_spokeInterfaces;
+  Ipv6InterfaceContainer m_hubInterfaces6;
+  Ipv6InterfaceContainer m_spokeInterfaces6;
 };
 
 } // namespace ns3
--- a/src/internet/doc/internet-stack.rst	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/internet/doc/internet-stack.rst	Mon Feb 20 14:05:07 2012 +0100
@@ -70,7 +70,7 @@
 ~~~~~~~~~~~~~~~~~
 
 At the lowest layer, sitting above the NetDevices, are the "layer 3" protocols,
-including IPv4, IPv6 (in the future), and ARP. The class
+including IPv4, IPv6, and ARP. The class
 :cpp:class:`Ipv4L3Protocol` is an implementation class whose public interface is
 typically class :cpp:class:`Ipv4`, but the
 Ipv4L3Protocol public API is also used internally at present.
@@ -137,7 +137,12 @@
 
     Config::SetDefault ("ns3::ArpCache::PendingQueueSize", UintegerValue (MAX_BURST_SIZE/L2MTU*3));
 
-The IPv6 implementation follows a similar architecture.
+The IPv6 implementation follows a similar architecture.  Dual-stacked nodes (one with
+support for both IPv4 and IPv6) will allow an IPv6 socket to receive IPv4 connections
+as a standard dual-stacked system does.  A socket bound and listening to an IPv6 endpoint
+can receive an IPv4 connection and will return the remote address as an IPv4-mapped address.
+Support for the IPV6_V6ONLY socket option does not currently exist.
+
 
 Layer-4 protocols and sockets
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -156,8 +161,14 @@
 
 The above will query the node to get a pointer to its UDP socket factory, will
 create one such socket, and will use the socket with an API similar to the
-C-based sockets API, such as ``Connect ()`` and ``Send ()``.  See the chapter on
-|ns3| sockets for more information.  
+C-based sockets API, such as ``Connect ()`` and ``Send ()``.  The address passed
+to the ``Bind ()``, ``Connect ()``, or ``Send ()`` functions may be a
+:cpp:class:`Ipv4Address`, :cpp:class:`Ipv6Address`, or :cpp:class:`Address`.
+If a :cpp:class:`Address` is passed in and contains anything other than
+a :cpp:class:`Ipv4Address` or :cpp:class:`Ipv6Address`, these functions will
+return an error.  The ``Bind (void)`` and ``Bind6 (void)`` functions bind to
+"0.0.0.0" and "::" respectively.
+See the chapter on |ns3| sockets for more information.  
 
 We have described so far a socket factory (e.g. ``class Udp``) and a socket,
 which may be specialized (e.g., class :cpp:class:`UdpSocket`).  There are a few
--- a/src/internet/doc/ipv6.rst	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/internet/doc/ipv6.rst	Mon Feb 20 14:05:07 2012 +0100
@@ -5,6 +5,3 @@
 
 *Placeholder chapter*
 
-IPv6 models are being added to ns-3. A paper on the IPv6 models was published in
-WNS2 2008: `<http://lsiit.u-strasbg.fr/Publications/2008/VMM08/>`_.
-
--- a/src/internet/model/icmpv4-l4-protocol.cc	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/internet/model/icmpv4-l4-protocol.cc	Mon Feb 20 14:05:07 2012 +0100
@@ -22,7 +22,7 @@
 Icmpv4L4Protocol::GetTypeId (void)
 {
   static TypeId tid = TypeId ("ns3::Icmpv4L4Protocol")
-    .SetParent<Ipv4L4Protocol> ()
+    .SetParent<IpL4Protocol> ()
     .AddConstructor<Icmpv4L4Protocol> ()
   ;
   return tid;
@@ -180,7 +180,7 @@
                            const uint8_t payload[8])
 {
   Ptr<Ipv4L3Protocol> ipv4 = m_node->GetObject<Ipv4L3Protocol> ();
-  Ptr<Ipv4L4Protocol> l4 = ipv4->GetProtocol (ipHeader.GetProtocol ());
+  Ptr<IpL4Protocol> l4 = ipv4->GetProtocol (ipHeader.GetProtocol ());
   if (l4 != 0)
     {
       l4->ReceiveIcmp (source, ipHeader.GetTtl (), icmp.GetType (), icmp.GetCode (),
@@ -219,7 +219,7 @@
   Forward (source, icmp, 0, ipHeader, payload);
 }
 
-enum Ipv4L4Protocol::RxStatus
+enum IpL4Protocol::RxStatus
 Icmpv4L4Protocol::Receive (Ptr<Packet> p,
                            Ipv4Header const &header,
                            Ptr<Ipv4Interface> incomingInterface)
@@ -242,7 +242,16 @@
       NS_LOG_DEBUG (icmp << " " << *p);
       break;
     }
-  return Ipv4L4Protocol::RX_OK;
+  return IpL4Protocol::RX_OK;
+}
+enum IpL4Protocol::RxStatus
+Icmpv4L4Protocol::Receive (Ptr<Packet> p,
+                           Ipv6Address &src,
+                           Ipv6Address &dst,
+                           Ptr<Ipv6Interface> incomingInterface)
+{
+  NS_LOG_FUNCTION (this << p << src << dst << incomingInterface);
+  return IpL4Protocol::RX_ENDPOINT_UNREACH;
 }
 void 
 Icmpv4L4Protocol::DoDispose (void)
@@ -250,19 +259,30 @@
   NS_LOG_FUNCTION (this);
   m_node = 0;
   m_downTarget.Nullify ();
-  Ipv4L4Protocol::DoDispose ();
+  IpL4Protocol::DoDispose ();
 }
 
 void
-Icmpv4L4Protocol::SetDownTarget (Ipv4L4Protocol::DownTargetCallback callback)
+Icmpv4L4Protocol::SetDownTarget (IpL4Protocol::DownTargetCallback callback)
 {
   m_downTarget = callback;
 }
 
-Ipv4L4Protocol::DownTargetCallback
+void
+Icmpv4L4Protocol::SetDownTarget6 (IpL4Protocol::DownTargetCallback6 callback)
+{
+}
+
+IpL4Protocol::DownTargetCallback
 Icmpv4L4Protocol::GetDownTarget (void) const
 {
   return m_downTarget;
 }
 
+IpL4Protocol::DownTargetCallback6
+Icmpv4L4Protocol::GetDownTarget6 (void) const
+{
+  return (IpL4Protocol::DownTargetCallback6)NULL;
+}
+
 } // namespace ns3
--- a/src/internet/model/icmpv4-l4-protocol.h	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/internet/model/icmpv4-l4-protocol.h	Mon Feb 20 14:05:07 2012 +0100
@@ -1,7 +1,7 @@
 #ifndef ICMPV4_L4_PROTOCOL_H
 #define ICMPV4_L4_PROTOCOL_H
 
-#include "ipv4-l4-protocol.h"
+#include "ip-l4-protocol.h"
 #include "icmpv4.h"
 #include "ns3/ipv4-address.h"
 
@@ -11,7 +11,7 @@
 class Ipv4Interface;
 class Ipv4Route;
 
-class Icmpv4L4Protocol : public Ipv4L4Protocol
+class Icmpv4L4Protocol : public IpL4Protocol
 {
 public:
   static TypeId GetTypeId (void);
@@ -24,18 +24,24 @@
 
   static uint16_t GetStaticProtocolNumber (void);
   virtual int GetProtocolNumber (void) const;
-  virtual enum Ipv4L4Protocol::RxStatus Receive (Ptr<Packet> p,
+  virtual enum IpL4Protocol::RxStatus Receive (Ptr<Packet> p,
                                                  Ipv4Header const &header,
                                                  Ptr<Ipv4Interface> incomingInterface);
+  virtual enum IpL4Protocol::RxStatus Receive (Ptr<Packet> p,
+                                                 Ipv6Address &src,
+                                                 Ipv6Address &dst,
+                                                 Ptr<Ipv6Interface> incomingInterface);
 
   void SendDestUnreachFragNeeded (Ipv4Header header, Ptr<const Packet> orgData, uint16_t nextHopMtu);
   void SendTimeExceededTtl (Ipv4Header header, Ptr<const Packet> orgData);
   void SendDestUnreachPort (Ipv4Header header, Ptr<const Packet> orgData);
 
-  // From Ipv4L4Protocol
-  virtual void SetDownTarget (Ipv4L4Protocol::DownTargetCallback cb);
-  // From Ipv4L4Protocol
-  virtual Ipv4L4Protocol::DownTargetCallback GetDownTarget (void) const;
+  // From IpL4Protocol
+  virtual void SetDownTarget (IpL4Protocol::DownTargetCallback cb);
+  virtual void SetDownTarget6 (IpL4Protocol::DownTargetCallback6 cb);
+  // From IpL4Protocol
+  virtual IpL4Protocol::DownTargetCallback GetDownTarget (void) const;
+  virtual IpL4Protocol::DownTargetCallback6 GetDownTarget6 (void) const;
 protected:
   /*
    * This function will notify other components connected to the node that a new stack member is now connected
@@ -66,7 +72,7 @@
   virtual void DoDispose (void);
 
   Ptr<Node> m_node;
-  Ipv4L4Protocol::DownTargetCallback m_downTarget;
+  IpL4Protocol::DownTargetCallback m_downTarget;
 };
 
 } // namespace ns3
--- a/src/internet/model/icmpv6-l4-protocol.cc	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/internet/model/icmpv6-l4-protocol.cc	Mon Feb 20 14:05:07 2012 +0100
@@ -66,7 +66,7 @@
 TypeId Icmpv6L4Protocol::GetTypeId ()
 {
   static TypeId tid = TypeId ("ns3::Icmpv6L4Protocol")
-    .SetParent<Ipv6L4Protocol> ()
+    .SetParent<IpL4Protocol> ()
     .AddConstructor<Icmpv6L4Protocol> ()
     .AddAttribute ("DAD", "Always do DAD check.",
                    BooleanValue (true),
@@ -97,9 +97,10 @@
       cache = 0;
     }
   m_cacheList.clear ();
+  m_downTarget.Nullify();
 
   m_node = 0;
-  Ipv6L4Protocol::DoDispose ();
+  IpL4Protocol::DoDispose ();
 }
 
 void Icmpv6L4Protocol::NotifyNewAggregate ()
@@ -117,6 +118,7 @@
               ipv6->Insert (this);
               Ptr<Ipv6RawSocketFactoryImpl> rawFactory = CreateObject<Ipv6RawSocketFactoryImpl> ();
               ipv6->AggregateObject (rawFactory);
+              this->SetDownTarget6 (MakeCallback (&Ipv6L3Protocol::Send, ipv6));
             }
         }
     }
@@ -174,7 +176,13 @@
   interface->Send (p, Ipv6Address::MakeSolicitedAddress (target));
 }
 
-enum Ipv6L4Protocol::RxStatus_e Icmpv6L4Protocol::Receive (Ptr<Packet> packet, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface)
+enum IpL4Protocol::RxStatus Icmpv6L4Protocol::Receive (Ptr<Packet> packet, Ipv4Header const &header,  Ptr<Ipv4Interface> interface)
+{
+  NS_LOG_FUNCTION (this << packet << header);
+  return IpL4Protocol::RX_ENDPOINT_UNREACH;
+}
+
+enum IpL4Protocol::RxStatus Icmpv6L4Protocol::Receive (Ptr<Packet> packet, Ipv6Address &src, Ipv6Address &dst, Ptr<Ipv6Interface> interface)
 {
   NS_LOG_FUNCTION (this << packet << src << dst << interface);
   Ptr<Packet> p = packet->Copy ();
@@ -225,7 +233,7 @@
       break;
     }
 
-  return Ipv6L4Protocol::RX_OK;
+  return IpL4Protocol::RX_OK;
 }
 
 void Icmpv6L4Protocol::HandleEchoRequest (Ptr<Packet> packet, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface)
@@ -751,7 +759,7 @@
 
   tag.SetTtl (ttl);
   packet->AddPacketTag (tag);
-  ipv6->Send (packet, src, dst, PROT_NUMBER, 0);
+  m_downTarget (packet, src, dst, PROT_NUMBER, 0);
 }
 
 void Icmpv6L4Protocol::SendMessage (Ptr<Packet> packet, Ipv6Address dst, Icmpv6Header& icmpv6Hdr, uint8_t ttl)
@@ -777,7 +785,7 @@
 
       icmpv6Hdr.CalculatePseudoHeaderChecksum (src, dst, packet->GetSize () + icmpv6Hdr.GetSerializedSize (), PROT_NUMBER);
       packet->AddHeader (icmpv6Hdr);
-      ipv6->Send (packet, src, dst, PROT_NUMBER, route);
+      m_downTarget (packet, src, dst, PROT_NUMBER, route);
     }
   else
     {
@@ -1244,5 +1252,28 @@
     }
 }
 
+void
+Icmpv6L4Protocol::SetDownTarget (IpL4Protocol::DownTargetCallback callback)
+{
+}
+
+void
+Icmpv6L4Protocol::SetDownTarget6 (IpL4Protocol::DownTargetCallback6 callback)
+{
+  m_downTarget = callback;
+}
+
+IpL4Protocol::DownTargetCallback
+Icmpv6L4Protocol::GetDownTarget (void) const
+{
+  return (IpL4Protocol::DownTargetCallback)NULL;
+}
+
+IpL4Protocol::DownTargetCallback6
+Icmpv6L4Protocol::GetDownTarget6 (void) const
+{
+  return m_downTarget;
+}
+
 } /* namespace ns3 */
 
--- a/src/internet/model/icmpv6-l4-protocol.h	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/internet/model/icmpv6-l4-protocol.h	Mon Feb 20 14:05:07 2012 +0100
@@ -27,7 +27,7 @@
 
 #include "ns3/ipv6-address.h"
 #include "icmpv6-header.h"
-#include "ipv6-l4-protocol.h"
+#include "ip-l4-protocol.h"
 
 namespace ns3
 {
@@ -42,7 +42,7 @@
  * \class Icmpv6L4Protocol
  * \brief An implementation of the ICMPv6 protocol.
  */
-class Icmpv6L4Protocol : public Ipv6L4Protocol
+class Icmpv6L4Protocol : public IpL4Protocol
 {
 public:
   /**
@@ -329,7 +329,12 @@
    * \param dst destination address
    * \param interface the interface from which the packet is coming
    */
-  virtual enum Ipv6L4Protocol::RxStatus_e Receive (Ptr<Packet> p, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface);
+  virtual enum IpL4Protocol::RxStatus Receive (Ptr<Packet> p,
+                                               Ipv4Header const &header,
+                                               Ptr<Ipv4Interface> interface);
+  virtual enum IpL4Protocol::RxStatus Receive (Ptr<Packet> p,
+                                               Ipv6Address &src, Ipv6Address &dst,
+                                               Ptr<Ipv6Interface> interface);
 
   /**
    * \brief Function called when DAD timeout.
@@ -477,6 +482,16 @@
    * \param device the device
    */
   Ptr<NdiscCache> FindCache (Ptr<NetDevice> device);
+
+  // From IpL4Protocol
+  virtual void SetDownTarget (IpL4Protocol::DownTargetCallback cb);
+  virtual void SetDownTarget6 (IpL4Protocol::DownTargetCallback6 cb);
+  // From IpL4Protocol
+  virtual IpL4Protocol::DownTargetCallback GetDownTarget (void) const;
+  virtual IpL4Protocol::DownTargetCallback6 GetDownTarget6 (void) const;
+
+  IpL4Protocol::DownTargetCallback6 m_downTarget;
+
 };
 
 } /* namespace ns3 */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet/model/ip-l4-protocol.cc	Mon Feb 20 14:05:07 2012 +0100
@@ -0,0 +1,61 @@
+// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*-
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+//
+// 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: George F. Riley<riley@ece.gatech.edu>
+//
+
+// NS3 - Layer 4 Protocol base class
+// George F. Riley, Georgia Tech, Spring 2007
+
+#include "ip-l4-protocol.h"
+#include "ns3/uinteger.h"
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (IpL4Protocol);
+
+TypeId 
+IpL4Protocol::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::IpL4Protocol")
+    .SetParent<Object> ()
+    .AddAttribute ("ProtocolNumber", "The Ip protocol number.",
+                   UintegerValue (0),
+                   MakeUintegerAccessor (&IpL4Protocol::GetProtocolNumber),
+                   MakeUintegerChecker<int> ())
+  ;
+  return tid;
+}
+
+IpL4Protocol::~IpL4Protocol ()
+{
+}
+
+void
+IpL4Protocol::ReceiveIcmp (Ipv4Address icmpSource, uint8_t icmpTtl,
+                           uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo,
+                           Ipv4Address payloadSource,Ipv4Address payloadDestination,
+                           const uint8_t payload[8])
+{}
+void
+IpL4Protocol::ReceiveIcmp (Ipv6Address icmpSource, uint8_t icmpTtl,
+                           uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo,
+                           Ipv6Address payloadSource, Ipv6Address payloadDestination,
+                           const uint8_t payload[8])
+{}
+
+} //namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet/model/ip-l4-protocol.h	Mon Feb 20 14:05:07 2012 +0100
@@ -0,0 +1,127 @@
+// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*-
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+//
+// 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: George F. Riley<riley@ece.gatech.edu>
+//
+
+// NS3 - Layer 4 Protocol base class
+// George F. Riley, Georgia Tech, Spring 2007
+
+#ifndef IP_L4_PROTOCOL_H
+#define IP_L4_PROTOCOL_H
+
+#include "ns3/object.h"
+#include "ns3/callback.h"
+#include "ns3/ipv4-header.h"
+#include "ns3/ipv6-header.h"
+#include "ns3/ipv6-interface.h"
+
+namespace ns3 {
+
+class Packet;
+class Ipv4Address;
+class Ipv4Interface;
+class Ipv4Route;
+class Ipv6Route;
+
+/**
+ * \brief L4 Protocol abstract base class 
+ *
+ * This is an abstract base class for layer four protocols which use IP as
+ * the network layer.
+ */
+class IpL4Protocol : public Object
+{
+public:
+  enum RxStatus {
+    RX_OK,
+    RX_CSUM_FAILED,
+    RX_ENDPOINT_CLOSED,
+    RX_ENDPOINT_UNREACH
+  };
+
+  static TypeId GetTypeId (void);
+
+  virtual ~IpL4Protocol ();
+
+  /**
+   * \returns the protocol number of this protocol.
+   */
+  virtual int GetProtocolNumber (void) const = 0;
+
+  /**
+   * \param p packet to forward up
+   * \param header IPv4 Header information
+   * \param incomingInterface the Ipv4Interface on which the packet arrived
+   * 
+   * Called from lower-level layers to send the packet up
+   * in the stack. 
+   */
+  virtual enum RxStatus Receive (Ptr<Packet> p,
+                                 Ipv4Header const &header,
+                                 Ptr<Ipv4Interface> incomingInterface) = 0;
+  virtual enum RxStatus Receive (Ptr<Packet> p,
+                                 Ipv6Address &src,
+                                 Ipv6Address &dst,
+                                 Ptr<Ipv6Interface> incomingInterface) = 0;
+
+  /**
+   * \param icmpSource the source address of the icmp message
+   * \param icmpTtl the ttl of the icmp message
+   * \param icmpType the 'type' field of the icmp message
+   * \param icmpCode the 'code' field of the icmp message
+   * \param icmpInfo extra information dependent on the icmp message
+   *        generated by Icmpv4L4Protocol
+   * \param payloadSource the source address of the packet which triggered
+   *        the icmp message
+   * \param payloadDestination the destination address of the packet which
+   *        triggered the icmp message.
+   * \param payload the first 8 bytes of the udp header of the packet
+   *        which triggered the icmp message.
+   */
+  virtual void ReceiveIcmp (Ipv4Address icmpSource, uint8_t icmpTtl,
+                            uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo,
+                            Ipv4Address payloadSource, Ipv4Address payloadDestination,
+                            const uint8_t payload[8]);
+  virtual void ReceiveIcmp (Ipv6Address icmpSource, uint8_t icmpTtl,
+                            uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo,
+                            Ipv6Address payloadSource, Ipv6Address payloadDestination,
+                            const uint8_t payload[8]);
+
+  typedef Callback<void,Ptr<Packet>, Ipv4Address, Ipv4Address, uint8_t, Ptr<Ipv4Route> > DownTargetCallback;
+  typedef Callback<void,Ptr<Packet>, Ipv6Address, Ipv6Address, uint8_t, Ptr<Ipv6Route> > DownTargetCallback6;
+  /**
+   * This method allows a caller to set the current down target callback
+   * set for this L4 protocol
+   *
+   * \param cb current Callback for the L4 protocol
+   */
+  virtual void SetDownTarget (DownTargetCallback cb) = 0;
+  virtual void SetDownTarget6 (DownTargetCallback6 cb) = 0;
+  /**
+   * This method allows a caller to get the current down target callback
+   * set for this L4 protocol, for
+   *
+   * \return current Callback for the L4 protocol
+   */
+  virtual DownTargetCallback GetDownTarget (void) const = 0;
+  virtual DownTargetCallback6 GetDownTarget6 (void) const = 0;
+};
+
+} // Namespace ns3
+
+#endif
--- a/src/internet/model/ipv4-l3-protocol.cc	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/internet/model/ipv4-l3-protocol.cc	Mon Feb 20 14:05:07 2012 +0100
@@ -36,7 +36,6 @@
 #include "loopback-net-device.h"
 #include "arp-l3-protocol.h"
 #include "ipv4-l3-protocol.h"
-#include "ipv4-l4-protocol.h"
 #include "icmpv4-l4-protocol.h"
 #include "ipv4-interface.h"
 #include "ipv4-raw-socket-impl.h"
@@ -98,11 +97,11 @@
 }
 
 void
-Ipv4L3Protocol::Insert (Ptr<Ipv4L4Protocol> protocol)
+Ipv4L3Protocol::Insert (Ptr<IpL4Protocol> protocol)
 {
   m_protocols.push_back (protocol);
 }
-Ptr<Ipv4L4Protocol>
+Ptr<IpL4Protocol>
 Ipv4L3Protocol::GetProtocol (int protocolNumber) const
 {
   for (L4List_t::const_iterator i = m_protocols.begin (); i != m_protocols.end (); ++i)
@@ -115,7 +114,7 @@
   return 0;
 }
 void
-Ipv4L3Protocol::Remove (Ptr<Ipv4L4Protocol> protocol)
+Ipv4L3Protocol::Remove (Ptr<IpL4Protocol> protocol)
 {
   m_protocols.remove (protocol);
 }
@@ -512,7 +511,7 @@
 Ptr<Icmpv4L4Protocol> 
 Ipv4L3Protocol::GetIcmp (void) const
 {
-  Ptr<Ipv4L4Protocol> prot = GetProtocol (Icmpv4L4Protocol::GetStaticProtocolNumber ());
+  Ptr<IpL4Protocol> prot = GetProtocol (Icmpv4L4Protocol::GetStaticProtocolNumber ());
   if (prot != 0)
     {
       return prot->GetObject<Icmpv4L4Protocol> ();
@@ -863,22 +862,22 @@
 
   m_localDeliverTrace (ip, packet, iif);
 
-  Ptr<Ipv4L4Protocol> protocol = GetProtocol (ip.GetProtocol ());
+  Ptr<IpL4Protocol> protocol = GetProtocol (ip.GetProtocol ());
   if (protocol != 0)
     {
       // we need to make a copy in the unlikely event we hit the
       // RX_ENDPOINT_UNREACH codepath
       Ptr<Packet> copy = p->Copy ();
-      enum Ipv4L4Protocol::RxStatus status = 
+      enum IpL4Protocol::RxStatus status = 
         protocol->Receive (p, ip, GetInterface (iif));
       switch (status) {
-        case Ipv4L4Protocol::RX_OK:
+        case IpL4Protocol::RX_OK:
         // fall through
-        case Ipv4L4Protocol::RX_ENDPOINT_CLOSED:
+        case IpL4Protocol::RX_ENDPOINT_CLOSED:
         // fall through
-        case Ipv4L4Protocol::RX_CSUM_FAILED:
+        case IpL4Protocol::RX_CSUM_FAILED:
           break;
-        case Ipv4L4Protocol::RX_ENDPOINT_UNREACH:
+        case IpL4Protocol::RX_ENDPOINT_UNREACH:
           if (ip.GetDestination ().IsBroadcast () == true ||
               ip.GetDestination ().IsMulticast () == true)
             {
--- a/src/internet/model/ipv4-l3-protocol.h	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/internet/model/ipv4-l3-protocol.h	Mon Feb 20 14:05:07 2012 +0100
@@ -47,7 +47,7 @@
 class Node;
 class Socket;
 class Ipv4RawSocketImpl;
-class Ipv4L4Protocol;
+class IpL4Protocol;
 class Icmpv4L4Protocol;
 
 
@@ -117,7 +117,7 @@
    * a working L4 Protocol and returned from this method.
    * The caller does not get ownership of the returned pointer.
    */
-  void Insert (Ptr<Ipv4L4Protocol> protocol);
+  void Insert (Ptr<IpL4Protocol> protocol);
   /**
    * \param protocolNumber number of protocol to lookup
    *        in this L4 Demux
@@ -127,14 +127,14 @@
    * to forward packets up the stack to the right protocol.
    * It is also called from NodeImpl::GetUdp for example.
    */
-  Ptr<Ipv4L4Protocol> GetProtocol (int protocolNumber) const;
+  Ptr<IpL4Protocol> GetProtocol (int protocolNumber) const;
   /**
    * \param protocol protocol to remove from this demux.
    *
    * The input value to this method should be the value
    * returned from the Ipv4L4Protocol::Insert method.
    */
-  void Remove (Ptr<Ipv4L4Protocol> protocol);
+  void Remove (Ptr<IpL4Protocol> protocol);
 
   /**
    * \param ttl default ttl to use
@@ -292,7 +292,7 @@
 
   typedef std::vector<Ptr<Ipv4Interface> > Ipv4InterfaceList;
   typedef std::list<Ptr<Ipv4RawSocketImpl> > SocketList;
-  typedef std::list<Ptr<Ipv4L4Protocol> > L4List_t;
+  typedef std::list<Ptr<IpL4Protocol> > L4List_t;
 
   bool m_ipForward;
   bool m_weakEsModel;
--- a/src/internet/model/ipv4-l4-protocol.cc	Sun Feb 19 16:22:51 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-// -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*-
-//
-// Copyright (c) 2006 Georgia Tech Research Corporation
-//
-// 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: George F. Riley<riley@ece.gatech.edu>
-//
-
-// NS3 - Layer 4 Protocol base class
-// George F. Riley, Georgia Tech, Spring 2007
-
-#include "ipv4-l4-protocol.h"
-#include "ns3/uinteger.h"
-
-namespace ns3 {
-
-NS_OBJECT_ENSURE_REGISTERED (Ipv4L4Protocol);
-
-TypeId 
-Ipv4L4Protocol::GetTypeId (void)
-{
-  static TypeId tid = TypeId ("ns3::Ipv4L4Protocol")
-    .SetParent<Object> ()
-    .AddAttribute ("ProtocolNumber", "The Ipv4 protocol number.",
-                   UintegerValue (0),
-                   MakeUintegerAccessor (&Ipv4L4Protocol::GetProtocolNumber),
-                   MakeUintegerChecker<int> ())
-  ;
-  return tid;
-}
-
-Ipv4L4Protocol::~Ipv4L4Protocol ()
-{
-}
-
-void
-Ipv4L4Protocol::ReceiveIcmp (Ipv4Address icmpSource, uint8_t icmpTtl,
-                             uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo,
-                             Ipv4Address payloadSource,Ipv4Address payloadDestination,
-                             const uint8_t payload[8])
-{}
-
-} // namespace ns3
--- a/src/internet/model/ipv4-l4-protocol.h	Sun Feb 19 16:22:51 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,113 +0,0 @@
-// -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*-
-//
-// Copyright (c) 2006 Georgia Tech Research Corporation
-//
-// 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: George F. Riley<riley@ece.gatech.edu>
-//
-
-// NS3 - Layer 4 Protocol base class
-// George F. Riley, Georgia Tech, Spring 2007
-
-#ifndef IPV4_L4_PROTOCOL_H
-#define IPV4_L4_PROTOCOL_H
-
-#include "ns3/object.h"
-#include "ns3/callback.h"
-#include "ns3/ipv4-header.h"
-
-namespace ns3 {
-
-class Packet;
-class Ipv4Address;
-class Ipv4Interface;
-class Ipv4Route;
-
-/**
- * \brief L4 Protocol abstract base class 
- *
- * This is an abstract base class for layer four protocols which use IPv4 as
- * the network layer.
- */
-class Ipv4L4Protocol : public Object
-{
-public:
-  enum RxStatus {
-    RX_OK,
-    RX_CSUM_FAILED,
-    RX_ENDPOINT_CLOSED,
-    RX_ENDPOINT_UNREACH
-  };
-
-  static TypeId GetTypeId (void);
-
-  virtual ~Ipv4L4Protocol ();
-
-  /**
-   * \returns the protocol number of this protocol.
-   */
-  virtual int GetProtocolNumber (void) const = 0;
-
-  /**
-   * \param p packet to forward up
-   * \param header IPv4 Header information
-   * \param incomingInterface the Ipv4Interface on which the packet arrived
-   * 
-   * Called from lower-level layers to send the packet up
-   * in the stack. 
-   */
-  virtual enum RxStatus Receive (Ptr<Packet> p,
-                                 Ipv4Header const &header,
-                                 Ptr<Ipv4Interface> incomingInterface) = 0;
-
-  /**
-   * \param icmpSource the source address of the icmp message
-   * \param icmpTtl the ttl of the icmp message
-   * \param icmpType the 'type' field of the icmp message
-   * \param icmpCode the 'code' field of the icmp message
-   * \param icmpInfo extra information dependent on the icmp message
-   *        generated by Icmpv4L4Protocol
-   * \param payloadSource the source address of the packet which triggered
-   *        the icmp message
-   * \param payloadDestination the destination address of the packet which
-   *        triggered the icmp message.
-   * \param payload the first 8 bytes of the udp header of the packet
-   *        which triggered the icmp message.
-   */
-  virtual void ReceiveIcmp (Ipv4Address icmpSource, uint8_t icmpTtl,
-                            uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo,
-                            Ipv4Address payloadSource, Ipv4Address payloadDestination,
-                            const uint8_t payload[8]);
-
-  typedef Callback<void,Ptr<Packet>, Ipv4Address, Ipv4Address, uint8_t, Ptr<Ipv4Route> > DownTargetCallback;
-  /**
-   * This method allows a caller to set the current down target callback
-   * set for this L4 protocol
-   *
-   * \param cb current Callback for the L4 protocol
-   */
-  virtual void SetDownTarget (DownTargetCallback cb) = 0;
-  /**
-   * This method allows a caller to get the current down target callback
-   * set for this L4 protocol, for
-   *
-   * \return current Callback for the L4 protocol
-   */
-  virtual DownTargetCallback GetDownTarget (void) const = 0;
-};
-
-} // Namespace ns3
-
-#endif
--- a/src/internet/model/ipv4-raw-socket-impl.cc	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/internet/model/ipv4-raw-socket-impl.cc	Mon Feb 20 14:05:07 2012 +0100
@@ -116,6 +116,11 @@
   return 0;
 }
 int 
+Ipv4RawSocketImpl::Bind6 (void)
+{
+  return (-1);
+}
+int 
 Ipv4RawSocketImpl::GetSockName (Address &address) const
 {
   address = InetSocketAddress (m_src, 0);
--- a/src/internet/model/ipv4-raw-socket-impl.h	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/internet/model/ipv4-raw-socket-impl.h	Mon Feb 20 14:05:07 2012 +0100
@@ -27,6 +27,7 @@
   virtual Ptr<Node> GetNode (void) const;
   virtual int Bind (const Address &address);
   virtual int Bind ();
+  virtual int Bind6 ();
   virtual int GetSockName (Address &address) const; 
   virtual int Close (void);
   virtual int ShutdownSend (void);
--- a/src/internet/model/ipv4.h	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/internet/model/ipv4.h	Mon Feb 20 14:05:07 2012 +0100
@@ -24,7 +24,7 @@
 #include "ns3/object.h"
 #include "ns3/socket.h"
 #include "ns3/callback.h"
-#include "ns3/ipv4-l4-protocol.h"
+#include "ns3/ip-l4-protocol.h"
 #include "ns3/ipv4-address.h"
 #include "ipv4-route.h"
 #include "ipv4-interface-address.h"
@@ -149,7 +149,7 @@
    * Adds a protocol to an internal list of L4 protocols.
    *
    */
-  virtual void Insert (Ptr<Ipv4L4Protocol> protocol) = 0;
+  virtual void Insert (Ptr<IpL4Protocol> protocol) = 0;
 
   /**
    * \brief Determine whether address and interface corresponding to
--- a/src/internet/model/ipv6-end-point.cc	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/internet/model/ipv6-end-point.cc	Mon Feb 20 14:05:07 2012 +0100
@@ -81,7 +81,7 @@
   m_peerPort = port;
 }
 
-void Ipv6EndPoint::SetRxCallback (Callback<void, Ptr<Packet>, Ipv6Address, uint16_t> callback)
+void Ipv6EndPoint::SetRxCallback (Callback<void, Ptr<Packet>, Ipv6Address, Ipv6Address, uint16_t> callback)
 {
   m_rxCallback = callback;
 }
@@ -96,11 +96,11 @@
   m_destroyCallback = callback;
 }
 
-void Ipv6EndPoint::ForwardUp (Ptr<Packet> p, Ipv6Address addr, uint16_t port)
+void Ipv6EndPoint::ForwardUp (Ptr<Packet> p, Ipv6Address srcAddr, Ipv6Address dstAddr, uint16_t port)
 {
   if (!m_rxCallback.IsNull ())
     {
-      m_rxCallback (p, addr, port);
+      m_rxCallback (p, srcAddr, dstAddr, port);
     }
 }
 
@@ -114,9 +114,9 @@
     }
 }
 
-void Ipv6EndPoint::DoForwardUp (Ptr<Packet> p, Ipv6Address saddr, uint16_t sport)
+void Ipv6EndPoint::DoForwardUp (Ptr<Packet> p, Ipv6Address saddr, Ipv6Address daddr, uint16_t sport)
 {
-  m_rxCallback (p, saddr, sport);
+  m_rxCallback (p, saddr, daddr, sport);
 }
 
 void Ipv6EndPoint::DoForwardIcmp (Ipv6Address src, uint8_t ttl, uint8_t type, 
--- a/src/internet/model/ipv6-end-point.h	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/internet/model/ipv6-end-point.h	Mon Feb 20 14:05:07 2012 +0100
@@ -98,7 +98,7 @@
    * \brief Set the reception callback.
    * \param callback callback function
    */
-  void SetRxCallback (Callback<void, Ptr<Packet>, Ipv6Address, uint16_t> callback);
+  void SetRxCallback (Callback<void, Ptr<Packet>, Ipv6Address, Ipv6Address, uint16_t> callback);
 
   /**
    * \brief Set the ICMP callback.
@@ -115,10 +115,11 @@
   /**
    * \brief Forward the packet to the upper level.
    * \param p the packet
-   * \param addr source address
+   * \param srcAddr source address
+   * \param dstAddr source address
    * \param port source port
    */
-  void ForwardUp (Ptr<Packet> p, Ipv6Address addr, uint16_t port);
+  void ForwardUp (Ptr<Packet> p, Ipv6Address srcAddr, Ipv6Address dstAddr, uint16_t port);
 
   /**
    * \brief Function called from an L4Protocol implementation
@@ -137,9 +138,10 @@
    * \brief ForwardUp wrapper.
    * \param p packet
    * \param saddr source IPv6 address
+   * \param daddr dest IPv6 address
    * \param sport source port
    */
-  void DoForwardUp (Ptr<Packet> p, Ipv6Address saddr, uint16_t sport);
+  void DoForwardUp (Ptr<Packet> p, Ipv6Address saddr, Ipv6Address daddr, uint16_t sport);
 
   /**
    * \brief ForwardIcmp wrapper.
@@ -175,7 +177,7 @@
   /**
    * \brief The RX callback.
    */
-  Callback<void, Ptr<Packet>, Ipv6Address, uint16_t> m_rxCallback;
+  Callback<void, Ptr<Packet>, Ipv6Address, Ipv6Address, uint16_t> m_rxCallback;
 
   /**
    * \brief The ICMPv6 callback.
--- a/src/internet/model/ipv6-l3-protocol.cc	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/internet/model/ipv6-l3-protocol.cc	Mon Feb 20 14:05:07 2012 +0100
@@ -30,7 +30,6 @@
 
 #include "loopback-net-device.h"
 #include "ipv6-l3-protocol.h"
-#include "ipv6-l4-protocol.h"
 #include "ipv6-interface.h"
 #include "ipv6-raw-socket-impl.h"
 #include "ipv6-autoconfigured-prefix.h"
@@ -519,19 +518,19 @@
   SetupLoopback ();
 }
 
-void Ipv6L3Protocol::Insert (Ptr<Ipv6L4Protocol> protocol)
+void Ipv6L3Protocol::Insert (Ptr<IpL4Protocol> protocol)
 {
   NS_LOG_FUNCTION (this << protocol);
   m_protocols.push_back (protocol);
 }
 
-void Ipv6L3Protocol::Remove (Ptr<Ipv6L4Protocol> protocol)
+void Ipv6L3Protocol::Remove (Ptr<IpL4Protocol> protocol)
 {
   NS_LOG_FUNCTION (this << protocol);
   m_protocols.remove (protocol);
 }
 
-Ptr<Ipv6L4Protocol> Ipv6L3Protocol::GetProtocol (int protocolNumber) const
+Ptr<IpL4Protocol> Ipv6L3Protocol::GetProtocol (int protocolNumber) const
 {
   NS_LOG_FUNCTION (this << protocolNumber);
 
@@ -571,7 +570,7 @@
 Ptr<Icmpv6L4Protocol> Ipv6L3Protocol::GetIcmpv6 () const
 {
   NS_LOG_FUNCTION_NOARGS ();
-  Ptr<Ipv6L4Protocol> protocol = GetProtocol (Icmpv6L4Protocol::GetStaticProtocolNumber ());
+  Ptr<IpL4Protocol> protocol = GetProtocol (Icmpv6L4Protocol::GetStaticProtocolNumber ());
 
   if (protocol)
     {
@@ -941,7 +940,7 @@
 {
   NS_LOG_FUNCTION (this << packet << ip << iif);
   Ptr<Packet> p = packet->Copy ();
-  Ptr<Ipv6L4Protocol> protocol = 0; 
+  Ptr<IpL4Protocol> protocol = 0; 
   Ptr<Ipv6ExtensionDemux> ipv6ExtensionDemux = m_node->GetObject<Ipv6ExtensionDemux>();
   Ptr<Ipv6Extension> ipv6Extension = 0;
   Ipv6Address src = ip.GetSourceAddress ();
@@ -1009,15 +1008,17 @@
 
               /* L4 protocol */
               Ptr<Packet> copy = p->Copy ();
-              enum Ipv6L4Protocol::RxStatus_e status = protocol->Receive (p, ip.GetSourceAddress (), ip.GetDestinationAddress (), GetInterface (iif));
+              enum IpL4Protocol::RxStatus status = protocol->Receive (p, src, dst, GetInterface (iif));
 
               switch (status)
                 {
-                case Ipv6L4Protocol::RX_OK:
+                case IpL4Protocol::RX_OK:
+                  break;
+                case IpL4Protocol::RX_CSUM_FAILED:
                   break;
-                case Ipv6L4Protocol::RX_CSUM_FAILED:
+                case IpL4Protocol::RX_ENDPOINT_CLOSED:
                   break;
-                case Ipv6L4Protocol::RX_ENDPOINT_UNREACH:
+                case IpL4Protocol::RX_ENDPOINT_UNREACH:
                   if (ip.GetDestinationAddress ().IsMulticast ())
                     {
                       /* do not rely on multicast address */
--- a/src/internet/model/ipv6-l3-protocol.h	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/internet/model/ipv6-l3-protocol.h	Mon Feb 20 14:05:07 2012 +0100
@@ -34,7 +34,7 @@
 
 class Node;
 class Ipv6Interface;
-class Ipv6L4Protocol;
+class IpL4Protocol;
 class Ipv6Route;
 class Ipv6MulticastRoute;
 class Ipv6RawSocketImpl;
@@ -102,20 +102,20 @@
    * \brief Add an L4 protocol.
    * \param protocol L4 protocol
    */
-  void Insert (Ptr<Ipv6L4Protocol> protocol);
+  void Insert (Ptr<IpL4Protocol> protocol);
 
   /**
    * \brief Remove an L4 protocol.
    * \param protocol L4 protocol to remove
    */
-  void Remove (Ptr<Ipv6L4Protocol> protocol);
+  void Remove (Ptr<IpL4Protocol> protocol);
 
   /**
    * \brief Get L4 protocol by protocol number.
    * \param protocolNumber protocol number
    * \return corresponding Ipv6L4Protocol or 0 if not found
    */
-  Ptr<Ipv6L4Protocol> GetProtocol (int protocolNumber) const;
+  Ptr<IpL4Protocol> GetProtocol (int protocolNumber) const;
 
   /**
    * \brief Create raw IPv6 socket.
@@ -360,7 +360,7 @@
 
   typedef std::list<Ptr<Ipv6Interface> > Ipv6InterfaceList;
   typedef std::list<Ptr<Ipv6RawSocketImpl> > SocketList;
-  typedef std::list<Ptr<Ipv6L4Protocol> > L4List_t;
+  typedef std::list<Ptr<IpL4Protocol> > L4List_t;
 
   typedef std::list< Ptr<Ipv6AutoconfiguredPrefix> > Ipv6AutoconfiguredPrefixList;
   typedef std::list< Ptr<Ipv6AutoconfiguredPrefix> >::iterator Ipv6AutoconfiguredPrefixListI;
--- a/src/internet/model/ipv6-l4-protocol.cc	Sun Feb 19 16:22:51 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007-2009 Strasbourg 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/uinteger.h"
-
-#include "ipv6-l4-protocol.h"
-
-namespace ns3
-{
-
-NS_OBJECT_ENSURE_REGISTERED (Ipv6L4Protocol);
-
-TypeId Ipv6L4Protocol::GetTypeId ()
-{
-  static TypeId tid = TypeId ("ns3::Ipv6L4Protocol")
-    .SetParent<Object> ()
-    .AddAttribute ("ProtocolNumber", "The IPv6 protocol number.",
-                   UintegerValue (0),
-                   MakeUintegerAccessor (&Ipv6L4Protocol::GetProtocolNumber),
-                   MakeUintegerChecker<int> ())
-  ;
-  return tid;
-}
-
-Ipv6L4Protocol::~Ipv6L4Protocol ()
-{
-}
-
-void Ipv6L4Protocol::ReceiveIcmp (Ipv6Address icmpSource, uint8_t icmpTtl,
-                                  uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo,
-                                  Ipv6Address payloadSource, Ipv6Address payloadDestination,
-                                  const uint8_t* payload)
-{}
-
-} /* namespace ns3 */
-
--- a/src/internet/model/ipv6-l4-protocol.h	Sun Feb 19 16:22:51 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,109 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007-2009 Strasbourg 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_L4_PROTOCOL_H
-#define IPV6_L4_PROTOCOL_H
-
-#include "ns3/object.h"
-#include "ns3/ipv6-header.h"
-
-namespace ns3
-{
-
-class Packet;
-class Ipv6Address;
-class Ipv6Interface;
-
-/**
- * \class Ipv6L4Protocol
- * \brief IPv6 L4 protocol abstract class
- */
-class Ipv6L4Protocol : public Object
-{
-public:
-  /**
-   * \enum RxStatus_e
-   * \brief Status of receive.
-   */
-  enum RxStatus_e 
-  {
-    RX_OK, /**< Receive OK */
-    RX_CSUM_FAILED, /**< Checksum of layer 4 protocol failed */
-    RX_ENDPOINT_UNREACH /**< Destination unreachable */
-  };
-
-  /**
-   * \brief Get the type identifier.
-   * \return type identifier
-   */
-  static TypeId GetTypeId (void);
-
-  /**
-   * \brief Destructor.
-   */
-  virtual ~Ipv6L4Protocol ();
-
-  /**
-   * \brief Get the protocol number.
-   * \return protocol number
-   */
-  virtual int GetProtocolNumber () const = 0;
-
-  /**
-   * \brief Receive method.
-   *
-   * Called from lower-level layers to send the packet up
-   * in the stack.
-   * \param p packet to forward up
-   * \param src source address of packet received
-   * \param dst address of packet received
-   * \param incomingInterface the Ipv6Interface on which the packet arrived
-   * \return status (OK, destination unreachable or checksum failed)
-   */
-  virtual enum RxStatus_e Receive (Ptr<Packet> p, Ipv6Address const &src, 
-                                   Ipv6Address const &dst, 
-                                   Ptr<Ipv6Interface> incomingInterface) = 0;
-
-  /**
-   * \brief ICMPv6 receive method.
-   * \param icmpSource the source address of the ICMPv6 message
-   * \param icmpTtl the ttl of the ICMPv6 message
-   * \param icmpType the 'type' field of the ICMPv6 message
-   * \param icmpCode the 'code' field of the ICMPv6 message
-   * \param icmpInfo extra information dependent on the ICMPv6 message
-   *        generated by Icmpv6L4Protocol
-   * \param payloadSource the source address of the packet which triggered
-   *        the ICMPv6 message
-   * \param payloadDestination the destination address of the packet which
-   *        triggered the ICMPv6 message.
-   * \param payload the first 8 bytes of the UDP header of the packet
-   *        which triggered the ICMPv6 message.
-   */
-  virtual void ReceiveIcmp (Ipv6Address icmpSource, uint8_t icmpTtl,
-                            uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo,
-                            Ipv6Address payloadSource, Ipv6Address payloadDestination,
-                            const uint8_t* payload);
-
-};
-
-} /* namespace ns3 */
-
-#endif /* IPV6_L4_PROTOCOL_H */
-
--- a/src/internet/model/ipv6-raw-socket-impl.cc	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/internet/model/ipv6-raw-socket-impl.cc	Mon Feb 20 14:05:07 2012 +0100
@@ -122,6 +122,11 @@
   return 0;
 }
 
+int Ipv6RawSocketImpl::Bind6 ()
+{
+  return(Bind());
+}
+
 int Ipv6RawSocketImpl::GetSockName (Address& address) const
 {
   NS_LOG_FUNCTION_NOARGS ();
--- a/src/internet/model/ipv6-raw-socket-impl.h	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/internet/model/ipv6-raw-socket-impl.h	Mon Feb 20 14:05:07 2012 +0100
@@ -116,6 +116,7 @@
    * \return 0 if success, -1 otherwise
    */
   virtual int Bind ();
+  virtual int Bind6 ();
 
   /**
    * \brief Get socket address.
--- a/src/internet/model/nsc-tcp-l4-protocol.cc	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/internet/model/nsc-tcp-l4-protocol.cc	Mon Feb 20 14:05:07 2012 +0100
@@ -96,7 +96,7 @@
 NscTcpL4Protocol::GetTypeId (void)
 {
   static TypeId tid = TypeId ("ns3::NscTcpL4Protocol")
-    .SetParent<Ipv4L4Protocol> ()
+    .SetParent<IpL4Protocol> ()
     .AddConstructor<NscTcpL4Protocol>()
     .AddAttribute ("SocketList", "The list of sockets associated to this protocol.",
                    ObjectVectorValue (),
@@ -242,7 +242,7 @@
   delete m_nscInterface;
   m_nscInterface = 0;
   m_downTarget.Nullify ();
-  Ipv4L4Protocol::DoDispose ();
+  IpL4Protocol::DoDispose ();
 }
 
 Ptr<Socket>
@@ -301,7 +301,7 @@
   // NSC m_endPoints->DeAllocate (endPoint);
 }
 
-Ipv4L4Protocol::RxStatus
+IpL4Protocol::RxStatus
 NscTcpL4Protocol::Receive (Ptr<Packet> packet,
                            Ipv4Header const &header,
                            Ptr<Ipv4Interface> incomingInterface)
@@ -335,7 +335,13 @@
   delete[] buf;
 
   wakeup ();
-  return Ipv4L4Protocol::RX_OK;
+  return IpL4Protocol::RX_OK;
+}
+
+IpL4Protocol::RxStatus
+NscTcpL4Protocol::Receive(Ptr<Packet>, Ipv6Address&, Ipv6Address&, Ptr<Ipv6Interface>)
+{
+  return IpL4Protocol::RX_ENDPOINT_UNREACH;
 }
 
 void NscTcpL4Protocol::SoftInterrupt (void)
@@ -457,16 +463,27 @@
 }
 
 void
-NscTcpL4Protocol::SetDownTarget (Ipv4L4Protocol::DownTargetCallback callback)
+NscTcpL4Protocol::SetDownTarget (IpL4Protocol::DownTargetCallback callback)
 {
   m_downTarget = callback;
 }
 
-Ipv4L4Protocol::DownTargetCallback
+void
+NscTcpL4Protocol::SetDownTarget6 (IpL4Protocol::DownTargetCallback6 callback)
+{
+}
+
+IpL4Protocol::DownTargetCallback
 NscTcpL4Protocol::GetDownTarget (void) const
 {
   return m_downTarget;
 }
 
+IpL4Protocol::DownTargetCallback6
+NscTcpL4Protocol::GetDownTarget6 (void) const
+{
+  return (IpL4Protocol::DownTargetCallback6)0;
+}
+
 } // namespace ns3
 
--- a/src/internet/model/nsc-tcp-l4-protocol.h	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/internet/model/nsc-tcp-l4-protocol.h	Mon Feb 20 14:05:07 2012 +0100
@@ -24,7 +24,7 @@
 #include "ns3/ptr.h"
 #include "ns3/object-factory.h"
 #include "ns3/timer.h"
-#include "ipv4-l4-protocol.h"
+#include "ip-l4-protocol.h"
 
 struct INetStack;
 
@@ -43,7 +43,7 @@
  * 
  * \brief Nsc wrapper glue, to interface with the Ipv4 protocol underneath.
  */
-class NscTcpL4Protocol : public Ipv4L4Protocol {
+class NscTcpL4Protocol : public IpL4Protocol {
 public:
   static const uint8_t PROT_NUMBER;
   static TypeId GetTypeId (void);
@@ -80,14 +80,20 @@
    * \param header IPv4 Header information
    * \param incomingInterface The Ipv4Interface it was received on
    */
-  virtual Ipv4L4Protocol::RxStatus Receive (Ptr<Packet> p,
+  virtual IpL4Protocol::RxStatus Receive (Ptr<Packet> p,
                                             Ipv4Header const &header,
                                             Ptr<Ipv4Interface> incomingInterface);
+  virtual IpL4Protocol::RxStatus Receive (Ptr<Packet> p,
+                                                 Ipv6Address &src,
+                                                 Ipv6Address &dst,
+                                                 Ptr<Ipv6Interface> interface);
 
-  // From Ipv4L4Protocol
-  virtual void SetDownTarget (Ipv4L4Protocol::DownTargetCallback cb);
-  // From Ipv4L4Protocol
-  virtual Ipv4L4Protocol::DownTargetCallback GetDownTarget (void) const;
+  // From IpL4Protocol
+  virtual void SetDownTarget (IpL4Protocol::DownTargetCallback cb);
+  virtual void SetDownTarget6 (IpL4Protocol::DownTargetCallback6 cb);
+  // From IpL4Protocol
+  virtual IpL4Protocol::DownTargetCallback GetDownTarget (void) const;
+  virtual IpL4Protocol::DownTargetCallback6 GetDownTarget6 (void) const;
 protected:
   virtual void DoDispose (void);
   virtual void NotifyNewAggregate ();
@@ -123,7 +129,7 @@
   std::string m_nscLibrary;
   Timer m_softTimer;
   std::vector<Ptr<NscTcpSocketImpl> > m_sockets;
-  Ipv4L4Protocol::DownTargetCallback m_downTarget;
+  IpL4Protocol::DownTargetCallback m_downTarget;
 };
 
 } // namespace ns3
--- a/src/internet/model/nsc-tcp-socket-impl.cc	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/internet/model/nsc-tcp-socket-impl.cc	Mon Feb 20 14:05:07 2012 +0100
@@ -214,6 +214,13 @@
   m_endPoint = m_tcp->Allocate ();
   return FinishBind ();
 }
+int
+NscTcpSocketImpl::Bind6 ()
+{
+  NS_LOG_LOGIC ("NscTcpSocketImpl: ERROR_AFNOSUPPORT - Bind6 not supported".);
+  m_errno = ERROR_AFNOSUPPORT;
+  return (-1);
+}
 int 
 NscTcpSocketImpl::Bind (const Address &address)
 {
--- a/src/internet/model/nsc-tcp-socket-impl.h	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/internet/model/nsc-tcp-socket-impl.h	Mon Feb 20 14:05:07 2012 +0100
@@ -68,6 +68,7 @@
   virtual enum SocketType GetSocketType (void) const;
   virtual Ptr<Node> GetNode (void) const;
   virtual int Bind (void);
+  virtual int Bind6 (void);
   virtual int Bind (const Address &address);
   virtual int Close (void);
   virtual int ShutdownSend (void);
--- a/src/internet/model/tcp-header.cc	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/internet/model/tcp-header.cc	Mon Feb 20 14:05:07 2012 +0100
@@ -128,23 +128,67 @@
   m_protocol = protocol;
 }
 
+void 
+TcpHeader::InitializeChecksum (Ipv6Address source, 
+                               Ipv6Address destination,
+                               uint8_t protocol)
+{
+  m_source = source;
+  m_destination = destination;
+  m_protocol = protocol;
+}
+
+void 
+TcpHeader::InitializeChecksum (Address source, 
+                               Address destination,
+                               uint8_t protocol)
+{
+  m_source = source;
+  m_destination = destination;
+  m_protocol = protocol;
+}
+
 uint16_t
 TcpHeader::CalculateHeaderChecksum (uint16_t size) const
 {
-  Buffer buf = Buffer (12);
-  buf.AddAtStart (12);
+  /* Buffer size must be at least as large as the largest IP pseudo-header */
+  /* [per RFC2460, but without consideration for IPv6 extension hdrs]      */
+  /* Src address            16 bytes (more generally, Address::MAX_SIZE)   */
+  /* Dst address            16 bytes (more generally, Address::MAX_SIZE)   */
+  /* Upper layer pkt len    4 bytes                                        */
+  /* Zero                   3 bytes                                        */
+  /* Next header            1 byte                                         */
+
+  uint32_t maxHdrSz = (2 * Address::MAX_SIZE) + 8;
+  Buffer buf = Buffer (maxHdrSz);
+  buf.AddAtStart (maxHdrSz);
   Buffer::Iterator it = buf.Begin ();
+  uint32_t hdrSize = 0;
 
   WriteTo (it, m_source);
   WriteTo (it, m_destination);
-  it.WriteU8 (0); /* protocol */
-  it.WriteU8 (m_protocol); /* protocol */
-  it.WriteU8 (size >> 8); /* length */
-  it.WriteU8 (size & 0xff); /* length */
+  if (Ipv4Address::IsMatchingType(m_source))
+    {
+      it.WriteU8 (0); /* protocol */
+      it.WriteU8 (m_protocol); /* protocol */
+      it.WriteU8 (size >> 8); /* length */
+      it.WriteU8 (size & 0xff); /* length */
+      hdrSize = 12;
+    }
+  else
+    {
+      it.WriteU16 (0);
+      it.WriteU8 (size >> 8); /* length */
+      it.WriteU8 (size & 0xff); /* length */
+      it.WriteU16 (0);
+      it.WriteU8 (0);
+      it.WriteU8 (m_protocol); /* protocol */
+      hdrSize = 40;
+    }
 
   it = buf.Begin ();
   /* we don't CompleteChecksum ( ~ ) now */
-  return ~(it.CalculateIpChecksum (12));
+  return ~(it.CalculateIpChecksum (hdrSize));
 }
 
 bool
--- a/src/internet/model/tcp-header.h	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/internet/model/tcp-header.h	Mon Feb 20 14:05:07 2012 +0100
@@ -26,6 +26,7 @@
 #include "ns3/buffer.h"
 #include "ns3/tcp-socket-factory.h"
 #include "ns3/ipv4-address.h"
+#include "ns3/ipv6-address.h"
 #include "ns3/sequence-number.h"
 
 namespace ns3 {
@@ -132,6 +133,12 @@
   void InitializeChecksum (Ipv4Address source, 
                            Ipv4Address destination,
                            uint8_t protocol);
+  void InitializeChecksum (Ipv6Address source, 
+                           Ipv6Address destination,
+                           uint8_t protocol);
+  void InitializeChecksum (Address source, 
+                           Address destination,
+                           uint8_t protocol);
 
   typedef enum { NONE = 0, FIN = 1, SYN = 2, RST = 4, PSH = 8, ACK = 16, 
                  URG = 32, ECE = 64, CWR = 128} Flags_t;
@@ -160,8 +167,8 @@
   uint16_t m_windowSize;
   uint16_t m_urgentPointer;
 
-  Ipv4Address m_source;
-  Ipv4Address m_destination;
+  Address m_source;
+  Address m_destination;
   uint8_t m_protocol;
 
   uint16_t m_initialChecksum;
--- a/src/internet/model/tcp-l4-protocol.cc	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/internet/model/tcp-l4-protocol.cc	Mon Feb 20 14:05:07 2012 +0100
@@ -28,12 +28,17 @@
 #include "ns3/node.h"
 #include "ns3/simulator.h"
 #include "ns3/ipv4-route.h"
+#include "ns3/ipv6-route.h"
 
 #include "tcp-l4-protocol.h"
 #include "tcp-header.h"
 #include "ipv4-end-point-demux.h"
+#include "ipv6-end-point-demux.h"
 #include "ipv4-end-point.h"
+#include "ipv6-end-point.h"
 #include "ipv4-l3-protocol.h"
+#include "ipv6-l3-protocol.h"
+#include "ipv6-routing-protocol.h"
 #include "tcp-socket-factory-impl.h"
 #include "tcp-newreno.h"
 #include "rtt-estimator.h"
@@ -61,7 +66,7 @@
 TcpL4Protocol::GetTypeId (void)
 {
   static TypeId tid = TypeId ("ns3::TcpL4Protocol")
-    .SetParent<Ipv4L4Protocol> ()
+    .SetParent<IpL4Protocol> ()
     .AddConstructor<TcpL4Protocol> ()
     .AddAttribute ("RttEstimatorType",
                    "Type of RttEstimator objects.",
@@ -82,7 +87,7 @@
 }
 
 TcpL4Protocol::TcpL4Protocol ()
-  : m_endPoints (new Ipv4EndPointDemux ())
+  : m_endPoints (new Ipv4EndPointDemux ()), m_endPoints6 (new Ipv6EndPointDemux ())
 {
   NS_LOG_FUNCTION_NOARGS ();
   NS_LOG_LOGIC ("Made a TcpL4Protocol "<<this);
@@ -107,23 +112,36 @@
 void
 TcpL4Protocol::NotifyNewAggregate ()
 {
+  Ptr<Node> node = this->GetObject<Node> ();
+  Ptr<Ipv4> ipv4 = this->GetObject<Ipv4> ();
+  Ptr<Ipv6L3Protocol> ipv6 = node->GetObject<Ipv6L3Protocol> ();
+
   if (m_node == 0)
     {
-      Ptr<Node> node = this->GetObject<Node> ();
-      if (node != 0)
+      if ((node != 0) && (ipv4 != 0 || ipv6 != 0))
         {
-          Ptr<Ipv4> ipv4 = this->GetObject<Ipv4> ();
-          if (ipv4 != 0)
-            {
-              this->SetNode (node);
-              ipv4->Insert (this);
-              Ptr<TcpSocketFactoryImpl> tcpFactory = CreateObject<TcpSocketFactoryImpl> ();
-              tcpFactory->SetTcp (this);
-              node->AggregateObject (tcpFactory);
-              this->SetDownTarget (MakeCallback (&Ipv4::Send, ipv4));
-            }
+          this->SetNode (node);
+          Ptr<TcpSocketFactoryImpl> tcpFactory = CreateObject<TcpSocketFactoryImpl> ();
+          tcpFactory->SetTcp (this);
+          node->AggregateObject (tcpFactory);
         }
     }
+
+  // We set at least one of our 2 down targets to the IPv4/IPv6 send
+  // functions.  Since these functions have different prototypes, we
+  // need to keep track of whether we are connected to an IPv4 or
+  // IPv6 lower layer and call the appropriate one.
+  
+  if (ipv4 != 0)
+    {
+      ipv4->Insert(this);
+      this->SetDownTarget(MakeCallback(&Ipv4::Send, ipv4));
+    }
+  if (ipv6 != 0)
+    {
+      ipv6->Insert(this);
+      this->SetDownTarget6(MakeCallback(&Ipv6L3Protocol::Send, ipv6));
+    }
   Object::NotifyNewAggregate ();
 }
 
@@ -145,9 +163,16 @@
       m_endPoints = 0;
     }
 
+  if (m_endPoints6 != 0)
+    {
+      delete m_endPoints6;
+      m_endPoints6 = 0;
+    }
+
   m_node = 0;
   m_downTarget.Nullify ();
-  Ipv4L4Protocol::DoDispose ();
+  m_downTarget6.Nullify ();
+  IpL4Protocol::DoDispose ();
 }
 
 Ptr<Socket>
@@ -216,7 +241,51 @@
   m_endPoints->DeAllocate (endPoint);
 }
 
-enum Ipv4L4Protocol::RxStatus
+Ipv6EndPoint *
+TcpL4Protocol::Allocate6 (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_endPoints6->Allocate ();
+}
+
+Ipv6EndPoint *
+TcpL4Protocol::Allocate6 (Ipv6Address address)
+{
+  NS_LOG_FUNCTION (this << address);
+  return m_endPoints6->Allocate (address);
+}
+
+Ipv6EndPoint *
+TcpL4Protocol::Allocate6 (uint16_t port)
+{
+  NS_LOG_FUNCTION (this << port);
+  return m_endPoints6->Allocate (port);
+}
+
+Ipv6EndPoint *
+TcpL4Protocol::Allocate6 (Ipv6Address address, uint16_t port)
+{
+  NS_LOG_FUNCTION (this << address << port);
+  return m_endPoints6->Allocate (address, port);
+}
+
+Ipv6EndPoint *
+TcpL4Protocol::Allocate6 (Ipv6Address localAddress, uint16_t localPort,
+                          Ipv6Address peerAddress, uint16_t peerPort)
+{
+  NS_LOG_FUNCTION (this << localAddress << localPort << peerAddress << peerPort);
+  return m_endPoints6->Allocate (localAddress, localPort,
+                                 peerAddress, peerPort);
+}
+
+void
+TcpL4Protocol::DeAllocate (Ipv6EndPoint *endPoint)
+{
+  NS_LOG_FUNCTION (this << endPoint);
+  m_endPoints6->DeAllocate (endPoint);
+}
+
+enum IpL4Protocol::RxStatus
 TcpL4Protocol::Receive (Ptr<Packet> packet,
                         Ipv4Header const &ipHeader,
                         Ptr<Ipv4Interface> incomingInterface)
@@ -241,7 +310,7 @@
   if(!tcpHeader.IsChecksumOk ())
     {
       NS_LOG_INFO ("Bad checksum, dropping packet!");
-      return Ipv4L4Protocol::RX_CSUM_FAILED;
+      return IpL4Protocol::RX_CSUM_FAILED;
     }
 
   NS_LOG_LOGIC ("TcpL4Protocol "<<this<<" received a packet");
@@ -250,6 +319,15 @@
                          ipHeader.GetSource (), tcpHeader.GetSourcePort (),incomingInterface);
   if (endPoints.empty ())
     {
+      if (this->GetObject<Ipv6L3Protocol> () != 0)
+        {
+          NS_LOG_LOGIC ("  No Ipv4 endpoints matched on TcpL4Protocol, trying Ipv6 "<<this);
+          Ptr<Ipv6Interface> fakeInterface;
+          Ipv6Address src = Ipv6Address::MakeIpv4MappedAddress (ipHeader.GetSource ());
+          Ipv6Address dst = Ipv6Address::MakeIpv4MappedAddress (ipHeader.GetDestination ());
+          return (this->Receive (packet, src, dst, fakeInterface));
+        }
+
       NS_LOG_LOGIC ("  No endpoints matched on TcpL4Protocol "<<this);
       std::ostringstream oss;
       oss<<"  destination IP: ";
@@ -279,18 +357,100 @@
           header.SetSourcePort (tcpHeader.GetDestinationPort ());
           header.SetDestinationPort (tcpHeader.GetSourcePort ());
           SendPacket (rstPacket, header, ipHeader.GetDestination (), ipHeader.GetSource ());
-          return Ipv4L4Protocol::RX_ENDPOINT_CLOSED;
+          return IpL4Protocol::RX_ENDPOINT_CLOSED;
         }
       else
         {
-          return Ipv4L4Protocol::RX_ENDPOINT_CLOSED;
+          return IpL4Protocol::RX_ENDPOINT_CLOSED;
         }
     }
   NS_ASSERT_MSG (endPoints.size () == 1, "Demux returned more than one endpoint");
   NS_LOG_LOGIC ("TcpL4Protocol "<<this<<" forwarding up to endpoint/socket");
   (*endPoints.begin ())->ForwardUp (packet, ipHeader, tcpHeader.GetSourcePort (), 
                                     incomingInterface);
-  return Ipv4L4Protocol::RX_OK;
+  return IpL4Protocol::RX_OK;
+}
+
+enum IpL4Protocol::RxStatus
+TcpL4Protocol::Receive (Ptr<Packet> packet,
+                        Ipv6Address &src,
+                        Ipv6Address &dst,
+                        Ptr<Ipv6Interface> interface)
+{
+  NS_LOG_FUNCTION (this << packet << src << dst);
+
+  TcpHeader tcpHeader;
+
+  // If we are receving a v4-mapped packet, we will re-calculate the TCP checksum
+  // Is it worth checking every received "v6" packet to see if it is v4-mapped in
+  // order to avoid re-calculating TCP checksums for v4-mapped packets?
+
+  if(Node::ChecksumEnabled ())
+    {
+      tcpHeader.EnableChecksums ();
+      tcpHeader.InitializeChecksum (src, dst, PROT_NUMBER);
+    }
+
+  packet->PeekHeader (tcpHeader);
+
+  NS_LOG_LOGIC ("TcpL4Protocol " << this
+                                 << " receiving seq " << tcpHeader.GetSequenceNumber ()
+                                 << " ack " << tcpHeader.GetAckNumber ()
+                                 << " flags "<< std::hex << (int)tcpHeader.GetFlags () << std::dec
+                                 << " data size " << packet->GetSize ());
+
+  if(!tcpHeader.IsChecksumOk ())
+    {
+      NS_LOG_INFO ("Bad checksum, dropping packet!");
+      return IpL4Protocol::RX_CSUM_FAILED;
+    }
+
+  NS_LOG_LOGIC ("TcpL4Protocol "<<this<<" received a packet");
+  Ipv6EndPointDemux::EndPoints endPoints =
+    m_endPoints6->Lookup (dst, tcpHeader.GetDestinationPort (),
+                          src, tcpHeader.GetSourcePort (),interface);
+  if (endPoints.empty ())
+    {
+      NS_LOG_LOGIC ("  No IPv6 endpoints matched on TcpL4Protocol "<<this);
+      std::ostringstream oss;
+      oss<<"  destination IP: ";
+      dst.Print (oss);
+      oss<<" destination port: "<< tcpHeader.GetDestinationPort ()<<" source IP: ";
+      src.Print (oss);
+      oss<<" source port: "<<tcpHeader.GetSourcePort ();
+      NS_LOG_LOGIC (oss.str ());
+
+      if (!(tcpHeader.GetFlags () & TcpHeader::RST))
+        {
+          // build a RST packet and send
+          Ptr<Packet> rstPacket = Create<Packet> ();
+          TcpHeader header;
+          if (tcpHeader.GetFlags () & TcpHeader::ACK)
+            {
+              // ACK bit was set
+              header.SetFlags (TcpHeader::RST);
+              header.SetSequenceNumber (header.GetAckNumber ());
+            }
+          else
+            {
+              header.SetFlags (TcpHeader::RST | TcpHeader::ACK);
+              header.SetSequenceNumber (SequenceNumber32 (0));
+              header.SetAckNumber (header.GetSequenceNumber () + SequenceNumber32 (1));
+            }
+          header.SetSourcePort (tcpHeader.GetDestinationPort ());
+          header.SetDestinationPort (tcpHeader.GetSourcePort ());
+          SendPacket (rstPacket, header, dst, src);
+          return IpL4Protocol::RX_ENDPOINT_CLOSED;
+        }
+      else
+        {
+          return IpL4Protocol::RX_ENDPOINT_CLOSED;
+        }
+    }
+  NS_ASSERT_MSG (endPoints.size () == 1, "Demux returned more than one endpoint");
+  NS_LOG_LOGIC ("TcpL4Protocol "<<this<<" forwarding up to endpoint/socket");
+  (*endPoints.begin ())->ForwardUp (packet, src, dst, tcpHeader.GetSourcePort ());
+  return IpL4Protocol::RX_OK;
 }
 
 void
@@ -338,6 +498,50 @@
 }
 
 void
+TcpL4Protocol::Send (Ptr<Packet> packet,
+                     Ipv6Address saddr, Ipv6Address daddr,
+                     uint16_t sport, uint16_t dport, Ptr<NetDevice> oif)
+{
+  NS_LOG_FUNCTION (this << packet << saddr << daddr << sport << dport << oif);
+
+  TcpHeader tcpHeader;
+  tcpHeader.SetDestinationPort (dport);
+  tcpHeader.SetSourcePort (sport);
+  if(Node::ChecksumEnabled ())
+    {
+      tcpHeader.EnableChecksums ();
+    }
+  tcpHeader.InitializeChecksum (saddr,
+                                daddr,
+                                PROT_NUMBER);
+  tcpHeader.SetFlags (TcpHeader::ACK);
+  tcpHeader.SetAckNumber (SequenceNumber32 (0));
+
+  packet->AddHeader (tcpHeader);
+
+  Ptr<Ipv6L3Protocol> ipv6 = m_node->GetObject<Ipv6L3Protocol> ();
+  if (ipv6 != 0)
+    {
+      Ipv6Header header;
+      header.SetDestinationAddress (daddr);
+      header.SetNextHeader (PROT_NUMBER);
+      Socket::SocketErrno errno_;
+      Ptr<Ipv6Route> route;
+      Ptr<NetDevice> oif (0); //specify non-zero if bound to a source address
+      if (ipv6->GetRoutingProtocol () != 0)
+        {
+          route = ipv6->GetRoutingProtocol ()->RouteOutput (packet, header, oif, errno_);
+        }
+      else
+        {
+          NS_LOG_ERROR ("No IPV6 Routing Protocol");
+          route = 0;
+        }
+      ipv6->Send (packet, saddr, daddr, PROT_NUMBER, route);
+    }
+}
+
+void
 TcpL4Protocol::SendPacket (Ptr<Packet> packet, const TcpHeader &outgoing,
                            Ipv4Address saddr, Ipv4Address daddr, Ptr<NetDevice> oif)
 {
@@ -385,16 +589,79 @@
 }
 
 void
-TcpL4Protocol::SetDownTarget (Ipv4L4Protocol::DownTargetCallback callback)
+TcpL4Protocol::SendPacket (Ptr<Packet> packet, const TcpHeader &outgoing,
+                           Ipv6Address saddr, Ipv6Address daddr, Ptr<NetDevice> oif)
+{
+  NS_LOG_LOGIC ("TcpL4Protocol " << this
+                                 << " sending seq " << outgoing.GetSequenceNumber ()
+                                 << " ack " << outgoing.GetAckNumber ()
+                                 << " flags " << std::hex << (int)outgoing.GetFlags () << std::dec
+                                 << " data size " << packet->GetSize ());
+  NS_LOG_FUNCTION (this << packet << saddr << daddr << oif);
+  // XXX outgoingHeader cannot be logged
+
+  if (daddr.IsIpv4MappedAddress ())
+    {
+      return (SendPacket (packet, outgoing, saddr.GetIpv4MappedAddress(), daddr.GetIpv4MappedAddress(), oif));
+    }
+  TcpHeader outgoingHeader = outgoing;
+  outgoingHeader.SetLength (5); //header length in units of 32bit words
+  /* outgoingHeader.SetUrgentPointer (0); //XXX */
+  if(Node::ChecksumEnabled ())
+    {
+      outgoingHeader.EnableChecksums ();
+    }
+  outgoingHeader.InitializeChecksum (saddr, daddr, PROT_NUMBER);
+
+  packet->AddHeader (outgoingHeader);
+
+  Ptr<Ipv6L3Protocol> ipv6 = m_node->GetObject<Ipv6L3Protocol> ();
+  if (ipv6 != 0)
+    {
+      Ipv6Header header;
+      header.SetDestinationAddress (daddr);
+      header.SetSourceAddress (saddr);
+      header.SetNextHeader (PROT_NUMBER);
+      Socket::SocketErrno errno_;
+      Ptr<Ipv6Route> route;
+      if (ipv6->GetRoutingProtocol () != 0)
+        {
+          route = ipv6->GetRoutingProtocol ()->RouteOutput (packet, header, oif, errno_);
+        }
+      else
+        {
+          NS_LOG_ERROR ("No IPV6 Routing Protocol");
+          route = 0;
+        }
+      m_downTarget6 (packet, saddr, daddr, PROT_NUMBER, route);
+    }
+  else
+    NS_FATAL_ERROR ("Trying to use Tcp on a node without an Ipv6 interface");
+}
+
+void
+TcpL4Protocol::SetDownTarget (IpL4Protocol::DownTargetCallback callback)
 {
   m_downTarget = callback;
 }
 
-Ipv4L4Protocol::DownTargetCallback
+IpL4Protocol::DownTargetCallback
 TcpL4Protocol::GetDownTarget (void) const
 {
   return m_downTarget;
 }
 
+void
+TcpL4Protocol::SetDownTarget6 (IpL4Protocol::DownTargetCallback6 callback)
+{
+  m_downTarget6 = callback;
+}
+
+IpL4Protocol::DownTargetCallback6
+TcpL4Protocol::GetDownTarget6 (void) const
+{
+  return m_downTarget6;
+}
+
 } // namespace ns3
 
--- a/src/internet/model/tcp-l4-protocol.h	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/internet/model/tcp-l4-protocol.h	Mon Feb 20 14:05:07 2012 +0100
@@ -25,9 +25,10 @@
 
 #include "ns3/packet.h"
 #include "ns3/ipv4-address.h"
+#include "ns3/ipv6-address.h"
 #include "ns3/ptr.h"
 #include "ns3/object-factory.h"
-#include "ipv4-l4-protocol.h"
+#include "ip-l4-protocol.h"
 #include "ns3/net-device.h"
 
 namespace ns3 {
@@ -36,9 +37,11 @@
 class Socket;
 class TcpHeader;
 class Ipv4EndPointDemux;
+class Ipv6EndPointDemux;
 class Ipv4Interface;
 class TcpSocketBase;
 class Ipv4EndPoint;
+class Ipv6EndPoint;
 
 /**
  * \ingroup tcp
@@ -50,7 +53,7 @@
  * packets from IP, and forwards them up to the endpoints.
 */
 
-class TcpL4Protocol : public Ipv4L4Protocol {
+class TcpL4Protocol : public IpL4Protocol {
 public:
   static TypeId GetTypeId (void);
   static const uint8_t PROT_NUMBER;
@@ -77,8 +80,15 @@
   Ipv4EndPoint *Allocate (Ipv4Address address, uint16_t port);
   Ipv4EndPoint *Allocate (Ipv4Address localAddress, uint16_t localPort,
                           Ipv4Address peerAddress, uint16_t peerPort);
+  Ipv6EndPoint *Allocate6 (void);
+  Ipv6EndPoint *Allocate6 (Ipv6Address address);
+  Ipv6EndPoint *Allocate6 (uint16_t port);
+  Ipv6EndPoint *Allocate6 (Ipv6Address address, uint16_t port);
+  Ipv6EndPoint *Allocate6 (Ipv6Address localAddress, uint16_t localPort,
+                           Ipv6Address peerAddress, uint16_t peerPort);
 
   void DeAllocate (Ipv4EndPoint *endPoint);
+  void DeAllocate (Ipv6EndPoint *endPoint);
 
   /**
    * \brief Send a packet via TCP
@@ -92,20 +102,29 @@
   void Send (Ptr<Packet> packet,
              Ipv4Address saddr, Ipv4Address daddr, 
              uint16_t sport, uint16_t dport, Ptr<NetDevice> oif = 0);
+  void Send (Ptr<Packet> packet,
+             Ipv6Address saddr, Ipv6Address daddr, 
+             uint16_t sport, uint16_t dport, Ptr<NetDevice> oif = 0);
   /**
    * \brief Receive a packet up the protocol stack
    * \param p The Packet to dump the contents into
    * \param header IPv4 Header information
    * \param incomingInterface The Ipv4Interface it was received on
    */
-  virtual enum Ipv4L4Protocol::RxStatus Receive (Ptr<Packet> p,
+  virtual enum IpL4Protocol::RxStatus Receive (Ptr<Packet> p,
                                                  Ipv4Header const &header,
                                                  Ptr<Ipv4Interface> incomingInterface);
+  virtual enum IpL4Protocol::RxStatus Receive (Ptr<Packet> p,
+                                                 Ipv6Address &src,
+                                                 Ipv6Address &dst,
+                                                 Ptr<Ipv6Interface> interface);
 
-  // From Ipv4L4Protocol
-  virtual void SetDownTarget (Ipv4L4Protocol::DownTargetCallback cb);
-  // From Ipv4L4Protocol
-  virtual Ipv4L4Protocol::DownTargetCallback GetDownTarget (void) const;
+  // From IpL4Protocol
+  virtual void SetDownTarget (IpL4Protocol::DownTargetCallback cb);
+  virtual void SetDownTarget6 (IpL4Protocol::DownTargetCallback6 cb);
+  // From IpL4Protocol
+  virtual IpL4Protocol::DownTargetCallback GetDownTarget (void) const;
+  virtual IpL4Protocol::DownTargetCallback6 GetDownTarget6 (void) const;
 
 protected:
   virtual void DoDispose (void);
@@ -117,17 +136,21 @@
 private:
   Ptr<Node> m_node;
   Ipv4EndPointDemux *m_endPoints;
+  Ipv6EndPointDemux *m_endPoints6;
   TypeId m_rttTypeId;
   TypeId m_socketTypeId;
 private:
   friend class TcpSocketBase;
   void SendPacket (Ptr<Packet>, const TcpHeader &,
                    Ipv4Address, Ipv4Address, Ptr<NetDevice> oif = 0);
+  void SendPacket (Ptr<Packet>, const TcpHeader &,
+                   Ipv6Address, Ipv6Address, Ptr<NetDevice> oif = 0);
   TcpL4Protocol (const TcpL4Protocol &o);
   TcpL4Protocol &operator = (const TcpL4Protocol &o);
 
   std::vector<Ptr<TcpSocketBase> > m_sockets;
-  Ipv4L4Protocol::DownTargetCallback m_downTarget;
+  IpL4Protocol::DownTargetCallback m_downTarget;
+  IpL4Protocol::DownTargetCallback6 m_downTarget6;
 };
 
 } // namespace ns3
--- a/src/internet/model/tcp-socket-base.cc	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/internet/model/tcp-socket-base.cc	Mon Feb 20 14:05:07 2012 +0100
@@ -25,11 +25,15 @@
 #include "ns3/abort.h"
 #include "ns3/node.h"
 #include "ns3/inet-socket-address.h"
+#include "ns3/inet6-socket-address.h"
 #include "ns3/log.h"
 #include "ns3/ipv4.h"
+#include "ns3/ipv6.h"
 #include "ns3/ipv4-interface-address.h"
 #include "ns3/ipv4-route.h"
+#include "ns3/ipv6-route.h"
 #include "ns3/ipv4-routing-protocol.h"
+#include "ns3/ipv6-routing-protocol.h"
 #include "ns3/simulation-singleton.h"
 #include "ns3/simulator.h"
 #include "ns3/packet.h"
@@ -39,6 +43,8 @@
 #include "tcp-socket-base.h"
 #include "tcp-l4-protocol.h"
 #include "ipv4-end-point.h"
+#include "ipv6-end-point.h"
+#include "ipv6-l3-protocol.h"
 #include "tcp-header.h"
 #include "rtt-estimator.h"
 
@@ -95,6 +101,7 @@
   : m_dupAckCount (0),
     m_delAckCount (0),
     m_endPoint (0),
+    m_endPoint6 (0),
     m_node (0),
     m_tcp (0),
     m_rtt (0),
@@ -126,6 +133,7 @@
     m_persistTimeout (sock.m_persistTimeout),
     m_cnTimeout (sock.m_cnTimeout),
     m_endPoint (0),
+    m_endPoint6 (0),
     m_node (sock.m_node),
     m_tcp (sock.m_tcp),
     m_rtt (0),
@@ -180,6 +188,13 @@
       m_tcp->DeAllocate (m_endPoint);
       NS_ASSERT (m_endPoint == 0);
     }
+  if (m_endPoint6 != 0)
+    {
+      NS_ASSERT (m_tcp != 0);
+      NS_ASSERT (m_endPoint6 != 0);
+      m_tcp->DeAllocate (m_endPoint6);
+      NS_ASSERT (m_endPoint6 == 0);
+    }
   m_tcp = 0;
   CancelAllTimers ();
 }
@@ -233,7 +248,8 @@
 {
   NS_LOG_FUNCTION_NOARGS ();
   m_endPoint = m_tcp->Allocate ();
-  if (0 == m_endPoint)
+  m_endPoint6 = m_tcp->Allocate6 ();
+  if (0 == m_endPoint || 0 == m_endPoint6)
     {
       m_errno = ERROR_ADDRNOTAVAIL;
       return -1;
@@ -242,40 +258,76 @@
   return SetupCallback ();
 }
 
+int
+TcpSocketBase::Bind6 (void)
+{
+  return Bind ();
+}
+
 /** Inherit from Socket class: Bind socket (with specific address) to an end-point in TcpL4Protocol */
 int
 TcpSocketBase::Bind (const Address &address)
 {
   NS_LOG_FUNCTION (this << address);
-  if (!InetSocketAddress::IsMatchingType (address))
+  if (InetSocketAddress::IsMatchingType (address))
+    {
+      InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
+      Ipv4Address ipv4 = transport.GetIpv4 ();
+      uint16_t port = transport.GetPort ();
+      if (ipv4 == Ipv4Address::GetAny () && port == 0)
+        {
+          m_endPoint = m_tcp->Allocate ();
+        }
+      else if (ipv4 == Ipv4Address::GetAny () && port != 0)
+        {
+          m_endPoint = m_tcp->Allocate (port);
+        }
+      else if (ipv4 != Ipv4Address::GetAny () && port == 0)
+        {
+          m_endPoint = m_tcp->Allocate (ipv4);
+        }
+      else if (ipv4 != Ipv4Address::GetAny () && port != 0)
+        {
+          m_endPoint = m_tcp->Allocate (ipv4, port);
+        }
+      if (0 == m_endPoint)
+        {
+          m_errno = port ? ERROR_ADDRINUSE : ERROR_ADDRNOTAVAIL;
+          return -1;
+        }
+    }
+  else if (Inet6SocketAddress::IsMatchingType (address))
+    {
+      Inet6SocketAddress transport = Inet6SocketAddress::ConvertFrom (address);
+      Ipv6Address ipv6 = transport.GetIpv6 ();
+      uint16_t port = transport.GetPort ();
+      if (ipv6 == Ipv6Address::GetAny () && port == 0)
+        {
+          m_endPoint6 = m_tcp->Allocate6 ();
+        }
+      else if (ipv6 == Ipv6Address::GetAny () && port != 0)
+        {
+          m_endPoint6 = m_tcp->Allocate6 (port);
+        }
+      else if (ipv6 != Ipv6Address::GetAny () && port == 0)
+        {
+          m_endPoint6 = m_tcp->Allocate6 (ipv6);
+        }
+      else if (ipv6 != Ipv6Address::GetAny () && port != 0)
+        {
+          m_endPoint6 = m_tcp->Allocate6 (ipv6, port);
+        }
+      if (0 == m_endPoint6)
+        {
+          m_errno = port ? ERROR_ADDRINUSE : ERROR_ADDRNOTAVAIL;
+          return -1;
+        }
+    }
+  else
     {
       m_errno = ERROR_INVAL;
       return -1;
     }
-  InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
-  Ipv4Address ipv4 = transport.GetIpv4 ();
-  uint16_t port = transport.GetPort ();
-  if (ipv4 == Ipv4Address::GetAny () && port == 0)
-    {
-      m_endPoint = m_tcp->Allocate ();
-    }
-  else if (ipv4 == Ipv4Address::GetAny () && port != 0)
-    {
-      m_endPoint = m_tcp->Allocate (port);
-    }
-  else if (ipv4 != Ipv4Address::GetAny () && port == 0)
-    {
-      m_endPoint = m_tcp->Allocate (ipv4);
-    }
-  else if (ipv4 != Ipv4Address::GetAny () && port != 0)
-    {
-      m_endPoint = m_tcp->Allocate (ipv4, port);
-    }
-  if (0 == m_endPoint)
-    {
-      m_errno = port ? ERROR_ADDRINUSE : ERROR_ADDRNOTAVAIL;
-      return -1;
-    }
   m_tcp->m_sockets.push_back (this);
   NS_LOG_LOGIC ("TcpSocketBase " << this << " got an endpoint: " << m_endPoint);
 
@@ -289,22 +341,60 @@
   NS_LOG_FUNCTION (this << address);
 
   // If haven't do so, Bind() this socket first
-  if (m_endPoint == 0)
+  if (InetSocketAddress::IsMatchingType (address))
     {
-      if (Bind () == -1)
+      if (m_endPoint == 0)
         {
-          NS_ASSERT (m_endPoint == 0);
-          return -1; // Bind() failed
+          if (Bind () == -1)
+            {
+              NS_ASSERT (m_endPoint == 0);
+              return -1; // Bind() failed
+            }
+          NS_ASSERT (m_endPoint != 0);
+        }
+      InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
+      m_endPoint->SetPeer (transport.GetIpv4 (), transport.GetPort ());
+      m_endPoint6 = 0;
+
+      // Get the appropriate local address and port number from the routing protocol and set up endpoint
+      if (SetupEndpoint () != 0)
+        { // Route to destination does not exist
+          return -1;
         }
-      NS_ASSERT (m_endPoint != 0);
     }
+  else if (Inet6SocketAddress::IsMatchingType (address) )
+    {
+      // If we are operating on a v4-mapped address, translate the address to
+      // a v4 address and re-call this function
+      Inet6SocketAddress transport = Inet6SocketAddress::ConvertFrom (address);
+      Ipv6Address v6Addr = transport.GetIpv6 ();
+      if (v6Addr.IsIpv4MappedAddress () == true)
+        {
+          Ipv4Address v4Addr = v6Addr.GetIpv4MappedAddress ();
+          return Connect(InetSocketAddress(v4Addr, transport.GetPort ()));
+        }
 
-  InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
-  m_endPoint->SetPeer (transport.GetIpv4 (), transport.GetPort ());
+      if (m_endPoint6 == 0)
+        {
+          if (Bind6 () == -1)
+            {
+              NS_ASSERT (m_endPoint6 == 0);
+              return -1; // Bind() failed
+            }
+          NS_ASSERT (m_endPoint6 != 0);
+        }
+      m_endPoint6->SetPeer (v6Addr, transport.GetPort ());
+      m_endPoint = 0;
 
-  // Get the appropriate local address and port number from the routing protocol and set up endpoint
-  if (SetupEndpoint () != 0)
-    { // Route to destination does not exist
+      // Get the appropriate local address and port number from the routing protocol and set up endpoint
+      if (SetupEndpoint6 () != 0)
+        { // Route to destination does not exist
+          return -1;
+        }
+    }
+  else
+    {
+      m_errno = ERROR_INVAL;
       return -1;
     }
 
@@ -427,7 +517,14 @@
   if (outPacket != 0 && outPacket->GetSize () != 0)
     {
       SocketAddressTag tag;
-      tag.SetAddress (InetSocketAddress (m_endPoint->GetPeerAddress (), m_endPoint->GetPeerPort ()));
+      if (m_endPoint != 0)
+        {
+          tag.SetAddress (InetSocketAddress (m_endPoint->GetPeerAddress (), m_endPoint->GetPeerPort ()));
+        }
+      else if (m_endPoint6 != 0)
+        {
+          tag.SetAddress (Inet6SocketAddress (m_endPoint6->GetPeerAddress (), m_endPoint6->GetPeerPort ()));
+        }
       outPacket->AddPacketTag (tag);
     }
   return outPacket;
@@ -446,6 +543,10 @@
         {
           fromAddress = InetSocketAddress (m_endPoint->GetPeerAddress (), m_endPoint->GetPeerPort ());
         }
+      else if (m_endPoint6 != 0)
+        {
+          fromAddress = Inet6SocketAddress (m_endPoint6->GetPeerAddress (), m_endPoint6->GetPeerPort ());
+        }
       else
         {
           fromAddress = InetSocketAddress (Ipv4Address::GetZero (), 0);
@@ -479,9 +580,14 @@
     {
       address = InetSocketAddress (m_endPoint->GetLocalAddress (), m_endPoint->GetLocalPort ());
     }
+  else if (m_endPoint6 != 0)
+    {
+      address = Inet6SocketAddress (m_endPoint6->GetLocalAddress (), m_endPoint6->GetLocalPort ());
+    }
   else
     { // It is possible to call this method on a socket without a name
       // in which case, behavior is unspecified
+      // Should this return an InetSocketAddress or an Inet6SocketAddress?
       address = InetSocketAddress (Ipv4Address::GetZero (), 0);
     }
   return 0;
@@ -493,16 +599,21 @@
 {
   NS_LOG_FUNCTION (netdevice);
   Socket::BindToNetDevice (netdevice); // Includes sanity check
-  if (m_endPoint == 0)
+  if (m_endPoint == 0 && m_endPoint6 == 0)
     {
       if (Bind () == -1)
         {
-          NS_ASSERT (m_endPoint == 0);
+          NS_ASSERT ((m_endPoint == 0 && m_endPoint6 == 0));
           return;
         }
-      NS_ASSERT (m_endPoint != 0);
+      NS_ASSERT ((m_endPoint != 0 && m_endPoint6 != 0));
     }
-  m_endPoint->BindToNetDevice (netdevice);
+
+  if (m_endPoint != 0)
+    {
+      m_endPoint->BindToNetDevice (netdevice);
+    }
+  // No BindToNetDevice() for Ipv6EndPoint
   return;
 }
 
@@ -511,12 +622,22 @@
 TcpSocketBase::SetupCallback (void)
 {
   NS_LOG_FUNCTION (this);
-  if (m_endPoint == 0)
+
+  if (m_endPoint == 0 && m_endPoint6 == 0)
     {
       return -1;
     }
-  m_endPoint->SetRxCallback (MakeCallback (&TcpSocketBase::ForwardUp, Ptr<TcpSocketBase> (this)));
-  m_endPoint->SetDestroyCallback (MakeCallback (&TcpSocketBase::Destroy, Ptr<TcpSocketBase> (this)));
+  if (m_endPoint != 0)
+    {
+      m_endPoint->SetRxCallback (MakeCallback (&TcpSocketBase::ForwardUp, Ptr<TcpSocketBase> (this))); 
+      m_endPoint->SetDestroyCallback (MakeCallback (&TcpSocketBase::Destroy, Ptr<TcpSocketBase> (this)));
+    }
+  if (m_endPoint6 != 0)
+    {
+      m_endPoint6->SetRxCallback (MakeCallback (&TcpSocketBase::ForwardUp6, Ptr<TcpSocketBase> (this)));
+      m_endPoint6->SetDestroyCallback (MakeCallback (&TcpSocketBase::Destroy, Ptr<TcpSocketBase> (this)));
+    }
+
   return 0;
 }
 
@@ -629,6 +750,12 @@
   DoForwardUp (packet, header, port, incomingInterface);
 }
 
+void
+TcpSocketBase::ForwardUp6 (Ptr<Packet> packet, Ipv6Address saddr, Ipv6Address daddr, uint16_t port)
+{
+  DoForwardUp (packet, saddr, daddr, port);
+}
+
 /** The real function to handle the incoming packet from lower layers. This is
     wrapped by ForwardUp() so that this function can be overloaded by daughter
     classes. */
@@ -728,6 +855,101 @@
     }
 }
 
+void
+TcpSocketBase::DoForwardUp (Ptr<Packet> packet, Ipv6Address saddr, Ipv6Address daddr, uint16_t port)
+{
+  NS_LOG_LOGIC ("Socket " << this << " forward up " <<
+                m_endPoint6->GetPeerAddress () <<
+                ":" << m_endPoint6->GetPeerPort () <<
+                " to " << m_endPoint6->GetLocalAddress () <<
+                ":" << m_endPoint6->GetLocalPort ());
+  Address fromAddress = Inet6SocketAddress (saddr, port);
+  Address toAddress = Inet6SocketAddress (daddr, m_endPoint6->GetLocalPort ());
+
+  // Peel off TCP header and do validity checking
+  TcpHeader tcpHeader;
+  packet->RemoveHeader (tcpHeader);
+  if (tcpHeader.GetFlags () & TcpHeader::ACK)
+    {
+      EstimateRtt (tcpHeader);
+    }
+  ReadOptions (tcpHeader);
+
+  // Update Rx window size, i.e. the flow control window
+  if (m_rWnd.Get () == 0 && tcpHeader.GetWindowSize () != 0)
+    { // persist probes end
+      NS_LOG_LOGIC (this << " Leaving zerowindow persist state");
+      m_persistEvent.Cancel ();
+    }
+  m_rWnd = tcpHeader.GetWindowSize ();
+
+  // Discard fully out of range packets
+  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() <<
+                    ") out of range [" << m_rxBuffer.NextRxSequence () << ":" <<
+                    m_rxBuffer.MaxRxSequence () << ")");
+      // Acknowledgement should be sent for all unacceptable packets (RFC793, p.69)
+      if (m_state == ESTABLISHED && !(tcpHeader.GetFlags () & TcpHeader::RST))
+        {
+          SendEmptyPacket (TcpHeader::ACK);
+        }
+      return;
+    }
+
+  // TCP state machine code in different process functions
+  // C.f.: tcp_rcv_state_process() in tcp_input.c in Linux kernel
+  switch (m_state)
+    {
+    case ESTABLISHED:
+      ProcessEstablished (packet, tcpHeader);
+      break;
+    case LISTEN:
+      ProcessListen (packet, tcpHeader, fromAddress, toAddress);
+      break;
+    case TIME_WAIT:
+      // Do nothing
+      break;
+    case CLOSED:
+      // Send RST if the incoming packet is not a RST
+      if ((tcpHeader.GetFlags () & ~(TcpHeader::PSH | TcpHeader::URG)) != TcpHeader::RST)
+        { // Since m_endPoint is not configured yet, we cannot use SendRST here
+          TcpHeader h;
+          h.SetFlags (TcpHeader::RST);
+          h.SetSequenceNumber (m_nextTxSequence);
+          h.SetAckNumber (m_rxBuffer.NextRxSequence ());
+          h.SetSourcePort (tcpHeader.GetDestinationPort ());
+          h.SetDestinationPort (tcpHeader.GetSourcePort ());
+          h.SetWindowSize (AdvertisedWindowSize ());
+          AddOptions (h);
+          m_tcp->SendPacket (Create<Packet> (), h, daddr, saddr, m_boundnetdevice);
+        }
+      break;
+    case SYN_SENT:
+      ProcessSynSent (packet, tcpHeader);
+      break;
+    case SYN_RCVD:
+      ProcessSynRcvd (packet, tcpHeader, fromAddress, toAddress);
+      break;
+    case FIN_WAIT_1:
+    case FIN_WAIT_2:
+    case CLOSE_WAIT:
+      ProcessWait (packet, tcpHeader);
+      break;
+    case CLOSING:
+      ProcessClosing (packet, tcpHeader);
+      break;
+    case LAST_ACK:
+      ProcessLastAck (packet, tcpHeader);
+      break;
+    default: // mute compiler
+      break;
+    }
+}
+
 /** Received a packet upon ESTABLISHED state. This function is mimicking the
     role of tcp_rcv_established() in tcp_input.c in Linux kernel. */
 void
@@ -915,8 +1137,16 @@
       m_retxEvent.Cancel ();
       m_highTxMark = ++m_nextTxSequence;
       m_txBuffer.SetHeadSequence (m_nextTxSequence);
-      m_endPoint->SetPeer (InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
-                           InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
+      if (m_endPoint)
+        {
+          m_endPoint->SetPeer (InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
+                               InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
+        }
+      else if (m_endPoint6)
+        {
+          m_endPoint6->SetPeer (Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
+                                Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
+        }
       // Always respond to first data packet to speed up the connection.
       // Remove to get the behaviour of old NS-3 code.
       m_delAckCount = m_delAckMaxCount;
@@ -941,8 +1171,16 @@
           m_retxEvent.Cancel ();
           m_highTxMark = ++m_nextTxSequence;
           m_txBuffer.SetHeadSequence (m_nextTxSequence);
-          m_endPoint->SetPeer (InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
-                               InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
+          if (m_endPoint)
+            {
+              m_endPoint->SetPeer (InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
+                                   InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
+            }
+          else if (m_endPoint6)
+            {
+              m_endPoint6->SetPeer (Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
+                                    Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
+            }
           PeerClose (packet, tcpHeader);
         }
     }
@@ -951,8 +1189,16 @@
       if (tcpflags != TcpHeader::RST)
         { // When (1) rx of SYN+ACK; (2) rx of FIN; (3) rx of bad flags
           NS_LOG_LOGIC ("Illegal flag " << tcpflags << " received. Reset packet is sent.");
-          m_endPoint->SetPeer (InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
-                               InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
+          if (m_endPoint)
+            {
+              m_endPoint->SetPeer (InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
+                                   InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
+            }
+          else if (m_endPoint6)
+            {
+              m_endPoint6->SetPeer (Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
+                                    Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
+            }
           SendRST ();
         }
       CloseAndNotify ();
@@ -1178,13 +1424,17 @@
   NS_LOG_FUNCTION (this);
   m_node = 0;
   m_endPoint = 0;
-  std::vector<Ptr<TcpSocketBase> >::iterator it
-    = std::find (m_tcp->m_sockets.begin (), m_tcp->m_sockets.end (), this);
-  if (it != m_tcp->m_sockets.end ())
+  m_endPoint6 = 0;
+  if (m_tcp != 0)
     {
-      m_tcp->m_sockets.erase (it);
+      std::vector<Ptr<TcpSocketBase> >::iterator it
+        = std::find (m_tcp->m_sockets.begin (), m_tcp->m_sockets.end (), this);
+      if (it != m_tcp->m_sockets.end ())
+        {
+          m_tcp->m_sockets.erase (it);
+        }
+      m_tcp = 0;
     }
-  m_tcp = 0;
   NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " <<
                 (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ());
   CancelAllTimers ();
@@ -1199,7 +1449,7 @@
   TcpHeader header;
   SequenceNumber32 s = m_nextTxSequence;
 
-  if (m_endPoint == 0)
+  if (m_endPoint == 0 && m_endPoint6 == 0)
     {
       NS_LOG_WARN ("Failed to send empty packet due to null endpoint");
       return;
@@ -1216,8 +1466,16 @@
   header.SetFlags (flags);
   header.SetSequenceNumber (s);
   header.SetAckNumber (m_rxBuffer.NextRxSequence ());
-  header.SetSourcePort (m_endPoint->GetLocalPort ());
-  header.SetDestinationPort (m_endPoint->GetPeerPort ());
+  if (m_endPoint != 0)
+    {
+      header.SetSourcePort (m_endPoint->GetLocalPort ());
+      header.SetDestinationPort (m_endPoint->GetPeerPort ());
+    }
+  else
+    {
+      header.SetSourcePort (m_endPoint6->GetLocalPort ());
+      header.SetDestinationPort (m_endPoint6->GetPeerPort ());
+    }
   header.SetWindowSize (AdvertisedWindowSize ());
   AddOptions (header);
   m_rto = m_rtt->RetransmitTimeout ();
@@ -1239,7 +1497,16 @@
           m_cnCount--;
         }
     }
-  m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (), m_endPoint->GetPeerAddress (), m_boundnetdevice);
+  if (m_endPoint != 0)
+    {
+      m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (),
+                         m_endPoint->GetPeerAddress (), m_boundnetdevice);
+    }
+  else
+    {
+      m_tcp->SendPacket (p, header, m_endPoint6->GetLocalAddress (),
+                         m_endPoint6->GetPeerAddress (), m_boundnetdevice);
+    }
   if (flags & TcpHeader::ACK)
     { // If sending an ACK, cancel the delay ACK as well
       m_delAckEvent.Cancel ();
@@ -1281,6 +1548,19 @@
         }
       CancelAllTimers ();
     }
+  if (m_endPoint6 != 0)
+    {
+      m_endPoint6->SetDestroyCallback (MakeNullCallback<void> ());
+      m_tcp->DeAllocate (m_endPoint6);
+      m_endPoint6 = 0;
+      std::vector<Ptr<TcpSocketBase> >::iterator it
+        = std::find (m_tcp->m_sockets.begin (), m_tcp->m_sockets.end (), this);
+      if (it != m_tcp->m_sockets.end ())
+        {
+          m_tcp->m_sockets.erase (it);
+        }
+      CancelAllTimers ();
+    }
 }
 
 /** Configure the endpoint to a local address. Called by Connect() if Bind() didn't specify one. */
@@ -1314,6 +1594,36 @@
   return 0;
 }
 
+int
+TcpSocketBase::SetupEndpoint6 ()
+{
+  NS_LOG_FUNCTION (this);
+  Ptr<Ipv6L3Protocol> ipv6 = m_node->GetObject<Ipv6L3Protocol> ();
+  NS_ASSERT (ipv6 != 0);
+  if (ipv6->GetRoutingProtocol () == 0)
+    {
+      NS_FATAL_ERROR ("No Ipv6RoutingProtocol in the node");
+    }
+  // Create a dummy packet, then ask the routing function for the best output
+  // interface's address
+  Ipv6Header header;
+  header.SetDestinationAddress (m_endPoint6->GetPeerAddress ());
+  Socket::SocketErrno errno_;
+  Ptr<Ipv6Route> route;
+  Ptr<NetDevice> oif = m_boundnetdevice;
+  route = ipv6->GetRoutingProtocol ()->RouteOutput (Ptr<Packet> (), header, oif, errno_);
+  if (route == 0)
+    {
+      NS_LOG_LOGIC ("Route to " << m_endPoint6->GetPeerAddress () << " does not exist");
+      NS_LOG_ERROR (errno_);
+      m_errno = errno_;
+      return -1;
+    }
+  NS_LOG_LOGIC ("Route exists");
+  m_endPoint6->SetLocalAddress (route->GetSource ());
+  return 0;
+}
+
 /** This function is called only if a SYN received in LISTEN state. After
    TcpSocketBase cloned, allocate a new end point to handle the incoming
    connection and send a SYN+ACK to complete the handshake. */
@@ -1322,10 +1632,22 @@
                              const Address& fromAddress, const Address& toAddress)
 {
   // Get port and address from peer (connecting host)
-  m_endPoint = m_tcp->Allocate (InetSocketAddress::ConvertFrom (toAddress).GetIpv4 (),
-                                InetSocketAddress::ConvertFrom (toAddress).GetPort (),
-                                InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
-                                InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
+  if (InetSocketAddress::IsMatchingType (toAddress))
+    {
+      m_endPoint = m_tcp->Allocate (InetSocketAddress::ConvertFrom (toAddress).GetIpv4 (),
+                                    InetSocketAddress::ConvertFrom (toAddress).GetPort (),
+                                    InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (),
+                                    InetSocketAddress::ConvertFrom (fromAddress).GetPort ());
+      m_endPoint6 = 0;
+    }
+  else if (Inet6SocketAddress::IsMatchingType (toAddress))
+    {
+      m_endPoint6 = m_tcp->Allocate6 (Inet6SocketAddress::ConvertFrom (toAddress).GetIpv6 (),
+                                      Inet6SocketAddress::ConvertFrom (toAddress).GetPort (),
+                                      Inet6SocketAddress::ConvertFrom (fromAddress).GetIpv6 (),
+                                      Inet6SocketAddress::ConvertFrom (fromAddress).GetPort ());
+      m_endPoint = 0;
+    }
   m_tcp->m_sockets.push_back (this);
 
   // Change the cloned socket from LISTEN state to SYN_RCVD
@@ -1381,8 +1703,16 @@
   header.SetFlags (flags);
   header.SetSequenceNumber (seq);
   header.SetAckNumber (m_rxBuffer.NextRxSequence ());
-  header.SetSourcePort (m_endPoint->GetLocalPort ());
-  header.SetDestinationPort (m_endPoint->GetPeerPort ());
+  if (m_endPoint)
+    {
+      header.SetSourcePort (m_endPoint->GetLocalPort ());
+      header.SetDestinationPort (m_endPoint->GetPeerPort ());
+    }
+  else
+    {
+      header.SetSourcePort (m_endPoint6->GetLocalPort ());
+      header.SetDestinationPort (m_endPoint6->GetPeerPort ());
+    }
   header.SetWindowSize (AdvertisedWindowSize ());
   AddOptions (header);
   if (m_retxEvent.IsExpired () )
@@ -1394,8 +1724,16 @@
       m_retxEvent = Simulator::Schedule (m_rto, &TcpSocketBase::ReTxTimeout, this);
     }
   NS_LOG_LOGIC ("Send packet via TcpL4Protocol with flags 0x" << std::hex << static_cast<uint32_t> (flags) << std::dec);
-  m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (),
-                     m_endPoint->GetPeerAddress (), m_boundnetdevice);
+  if (m_endPoint)
+    {
+      m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (),
+                         m_endPoint->GetPeerAddress (), m_boundnetdevice);
+    }
+  else
+    {
+      m_tcp->SendPacket (p, header, m_endPoint6->GetLocalAddress (),
+                         m_endPoint6->GetPeerAddress (), m_boundnetdevice);
+    }
   m_rtt->SentSeq (seq, sz);       // notify the RTT
   // Notify the application of the data being sent unless this is a retransmit
   if (seq == m_nextTxSequence)
@@ -1415,7 +1753,8 @@
 {
   NS_LOG_FUNCTION (this << withAck);
   if (m_txBuffer.Size () == 0) return false;  // Nothing to send
-  if (m_endPoint == 0)
+
+  if (m_endPoint == 0 && m_endPoint6 == 0)
     {
       NS_LOG_INFO ("TcpSocketBase::SendPendingData: No endpoint; m_shutdownSend=" << m_shutdownSend);
       return false; // Is this the right way to handle this condition?
@@ -1438,7 +1777,7 @@
           m_errno = ERROR_SHUTDOWN;
           return false;
         }
-      // Stop sending if we need to wait for a larger Tx window
+      // Stop sending if we need to wait for a larger Tx window (prevent silly window syndrome)
       if (w < m_segmentSize && m_txBuffer.SizeFromSequence (m_nextTxSequence) > w)
         {
           break; // No more
@@ -1664,13 +2003,29 @@
   TcpHeader tcpHeader;
   tcpHeader.SetSequenceNumber (m_nextTxSequence);
   tcpHeader.SetAckNumber (m_rxBuffer.NextRxSequence ());
-  tcpHeader.SetSourcePort (m_endPoint->GetLocalPort ());
-  tcpHeader.SetDestinationPort (m_endPoint->GetPeerPort ());
   tcpHeader.SetWindowSize (AdvertisedWindowSize ());
+  if (m_endPoint != 0)
+    {
+      tcpHeader.SetSourcePort (m_endPoint->GetLocalPort ());
+      tcpHeader.SetDestinationPort (m_endPoint->GetPeerPort ());
+    }
+  else
+    {
+      tcpHeader.SetSourcePort (m_endPoint6->GetLocalPort ());
+      tcpHeader.SetDestinationPort (m_endPoint6->GetPeerPort ());
+    }
   AddOptions (tcpHeader);
 
-  m_tcp->SendPacket (p, tcpHeader, m_endPoint->GetLocalAddress (),
-                     m_endPoint->GetPeerAddress (), m_boundnetdevice);
+  if (m_endPoint != 0)
+    {
+      m_tcp->SendPacket (p, tcpHeader, m_endPoint->GetLocalAddress (),
+                         m_endPoint->GetPeerAddress (), m_boundnetdevice);
+    }
+  else
+    {
+      m_tcp->SendPacket (p, tcpHeader, m_endPoint6->GetLocalAddress (),
+                         m_endPoint6->GetPeerAddress (), m_boundnetdevice);
+    }
   NS_LOG_LOGIC ("Schedule persist timeout at time "
                 << Simulator::Now ().GetSeconds () << " to expire at time "
                 << (Simulator::Now () + m_persistTimeout).GetSeconds ());
--- a/src/internet/model/tcp-socket-base.h	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/internet/model/tcp-socket-base.h	Mon Feb 20 14:05:07 2012 +0100
@@ -38,6 +38,7 @@
 namespace ns3 {
 
 class Ipv4EndPoint;
+class Ipv6EndPoint;
 class Node;
 class Packet;
 class TcpL4Protocol;
@@ -81,6 +82,7 @@
   virtual enum SocketType GetSocketType (void) const; // returns socket type
   virtual Ptr<Node> GetNode (void) const;            // returns m_node
   virtual int Bind (void);    // Bind a socket by setting up endpoint in TcpL4Protocol
+  virtual int Bind6 (void);    // Bind a socket by setting up endpoint in TcpL4Protocol
   virtual int Bind (const Address &address);         // ... endpoint of specific addr or port
   virtual int Connect (const Address &address);      // Setup endpoint and call ProcessAction() to connect
   virtual int Listen (void);  // Verify the socket is in a correct state and call ProcessAction() to listen
@@ -128,11 +130,14 @@
   int DoConnect (void);            // Sending a SYN packet to make a connection if the state allows
   void ConnectionSucceeded (void); // Schedule-friendly wrapper for Socket::NotifyConnectionSucceeded()
   int SetupEndpoint (void);        // Configure m_endpoint for local addr for given remote addr
+  int SetupEndpoint6 (void);       // Configure m_endpoint6 for local addr for given remote addr
   void CompleteFork (Ptr<Packet>, const TcpHeader&, const Address& fromAddress, const Address& toAdress);
 
   // Helper functions: Transfer operation
   void ForwardUp (Ptr<Packet> packet, Ipv4Header header, uint16_t port, Ptr<Ipv4Interface> incomingInterface);
+  void ForwardUp6 (Ptr<Packet> packet, Ipv6Address saddr, Ipv6Address daddr, uint16_t port);
   virtual void DoForwardUp (Ptr<Packet> packet, Ipv4Header header, uint16_t port, Ptr<Ipv4Interface> incomingInterface); //Get a pkt from L3
+  virtual void DoForwardUp (Ptr<Packet> packet, Ipv6Address saddr, Ipv6Address daddr, uint16_t port); // Ipv6 version
   bool SendPendingData (bool withAck = false); // Send as much as the window allows
   uint32_t SendDataPacket (SequenceNumber32 seq, uint32_t maxSize, bool withAck); // Send a data packet
   void SendEmptyPacket (uint8_t flags); // Send a empty packet that carries a flag, e.g. ACK
@@ -202,6 +207,7 @@
 
   // Connections to other layers of TCP/IP
   Ipv4EndPoint*       m_endPoint;
+  Ipv6EndPoint*       m_endPoint6;
   Ptr<Node>           m_node;
   Ptr<TcpL4Protocol>  m_tcp;
 
--- a/src/internet/model/udp-header.cc	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/internet/model/udp-header.cc	Mon Feb 20 14:05:07 2012 +0100
@@ -70,9 +70,27 @@
 {
   return m_destinationPort;
 }
+void
+UdpHeader::InitializeChecksum (Address source,
+                               Address destination,
+                               uint8_t protocol)
+{
+  m_source = source;
+  m_destination = destination;
+  m_protocol = protocol;
+}
+void
+UdpHeader::InitializeChecksum (Ipv4Address source,
+                               Ipv4Address destination,
+                               uint8_t protocol)
+{
+  m_source = source;
+  m_destination = destination;
+  m_protocol = protocol;
+}
 void 
-UdpHeader::InitializeChecksum (Ipv4Address source, 
-                               Ipv4Address destination,
+UdpHeader::InitializeChecksum (Ipv6Address source, 
+                               Ipv6Address destination,
                                uint8_t protocol)
 {
   m_source = source;
@@ -82,20 +100,35 @@
 uint16_t
 UdpHeader::CalculateHeaderChecksum (uint16_t size) const
 {
-  Buffer buf = Buffer (12);
-  buf.AddAtStart (12);
+  Buffer buf = Buffer ((2 * Address::MAX_SIZE) + 8);
+  buf.AddAtStart ((2 * Address::MAX_SIZE) + 8);
   Buffer::Iterator it = buf.Begin ();
+  uint32_t hdrSize = 0;
 
   WriteTo (it, m_source);
   WriteTo (it, m_destination);
-  it.WriteU8 (0); /* protocol */
-  it.WriteU8 (m_protocol); /* protocol */
-  it.WriteU8 (size >> 8); /* length */
-  it.WriteU8 (size & 0xff); /* length */
+  if (Ipv4Address::IsMatchingType(m_source))
+    {
+      it.WriteU8 (0); /* protocol */
+      it.WriteU8 (m_protocol); /* protocol */
+      it.WriteU8 (size >> 8); /* length */
+      it.WriteU8 (size & 0xff); /* length */
+      hdrSize = 12;
+    }
+  else if (Ipv6Address::IsMatchingType(m_source))
+    {
+      it.WriteU16 (0);
+      it.WriteU8 (size >> 8); /* length */
+      it.WriteU8 (size & 0xff); /* length */
+      it.WriteU16 (0);
+      it.WriteU8 (0);
+      it.WriteU8 (m_protocol); /* protocol */
+      hdrSize = 40;
+    }
 
   it = buf.Begin ();
   /* we don't CompleteChecksum ( ~ ) now */
-  return ~(it.CalculateIpChecksum (12));
+  return ~(it.CalculateIpChecksum (hdrSize));
 }
 
 bool
--- a/src/internet/model/udp-header.h	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/internet/model/udp-header.h	Mon Feb 20 14:05:07 2012 +0100
@@ -25,6 +25,7 @@
 #include <string>
 #include "ns3/header.h"
 #include "ns3/ipv4-address.h"
+#include "ns3/ipv6-address.h"
 
 namespace ns3 {
 /**
@@ -79,10 +80,40 @@
    * If you want to use udp checksums, you should call this
    * method prior to adding the header to a packet.
    */
+  void InitializeChecksum (Address source, 
+                           Address destination,
+                           uint8_t protocol);
+
+  /**
+   * \param source the ip source to use in the underlying
+   *        ip packet.
+   * \param destination the ip destination to use in the
+   *        underlying ip packet.
+   * \param protocol the protocol number to use in the underlying
+   *        ip packet.
+   *
+   * If you want to use udp checksums, you should call this
+   * method prior to adding the header to a packet.
+   */
   void InitializeChecksum (Ipv4Address source, 
                            Ipv4Address destination,
                            uint8_t protocol);
 
+  /**
+   * \param source the ip source to use in the underlying
+   *        ip packet.
+   * \param destination the ip destination to use in the
+   *        underlying ip packet.
+   * \param protocol the protocol number to use in the underlying
+   *        ip packet.
+   *
+   * If you want to use udp checksums, you should call this
+   * method prior to adding the header to a packet.
+   */
+  void InitializeChecksum (Ipv6Address source, 
+                           Ipv6Address destination,
+                           uint8_t protocol);
+
   static TypeId GetTypeId (void);
   virtual TypeId GetInstanceTypeId (void) const;
   virtual void Print (std::ostream &os) const;
@@ -102,8 +133,8 @@
   uint16_t m_destinationPort;
   uint16_t m_payloadSize;
 
-  Ipv4Address m_source;
-  Ipv4Address m_destination;
+  Address m_source;
+  Address m_destination;
   uint8_t m_protocol;
   bool m_calcChecksum;
   bool m_goodChecksum;
--- a/src/internet/model/udp-l4-protocol.cc	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/internet/model/udp-l4-protocol.cc	Mon Feb 20 14:05:07 2012 +0100
@@ -24,14 +24,20 @@
 #include "ns3/node.h"
 #include "ns3/boolean.h"
 #include "ns3/object-vector.h"
+#include "ns3/ipv6.h"
 #include "ns3/ipv4-route.h"
+#include "ns3/ipv6-route.h"
+#include "ns3/ipv6-header.h"
 
 #include "udp-l4-protocol.h"
 #include "udp-header.h"
 #include "udp-socket-factory-impl.h"
 #include "ipv4-end-point-demux.h"
 #include "ipv4-end-point.h"
+#include "ipv6-end-point-demux.h"
+#include "ipv6-end-point.h"
 #include "ipv4-l3-protocol.h"
+#include "ipv6-l3-protocol.h"
 #include "udp-socket-impl.h"
 
 NS_LOG_COMPONENT_DEFINE ("UdpL4Protocol");
@@ -47,7 +53,7 @@
 UdpL4Protocol::GetTypeId (void)
 {
   static TypeId tid = TypeId ("ns3::UdpL4Protocol")
-    .SetParent<Ipv4L4Protocol> ()
+    .SetParent<IpL4Protocol> ()
     .AddConstructor<UdpL4Protocol> ()
     .AddAttribute ("SocketList", "The list of sockets associated to this protocol.",
                    ObjectVectorValue (),
@@ -58,7 +64,7 @@
 }
 
 UdpL4Protocol::UdpL4Protocol ()
-  : m_endPoints (new Ipv4EndPointDemux ())
+  : m_endPoints (new Ipv4EndPointDemux ()), m_endPoints6 (new Ipv6EndPointDemux ())
 {
   NS_LOG_FUNCTION_NOARGS ();
 }
@@ -82,23 +88,36 @@
 void
 UdpL4Protocol::NotifyNewAggregate ()
 {
+  Ptr<Node> node = this->GetObject<Node> ();
+  Ptr<Ipv4> ipv4 = this->GetObject<Ipv4> ();
+  Ptr<Ipv6L3Protocol> ipv6 = node->GetObject<Ipv6L3Protocol> ();
+
   if (m_node == 0)
     {
-      Ptr<Node> node = this->GetObject<Node> ();
-      if (node != 0)
+      if ((node != 0) && (ipv4 != 0 || ipv6 != 0))
         {
-          Ptr<Ipv4> ipv4 = this->GetObject<Ipv4> ();
-          if (ipv4 != 0)
-            {
-              this->SetNode (node);
-              ipv4->Insert (this);
-              Ptr<UdpSocketFactoryImpl> udpFactory = CreateObject<UdpSocketFactoryImpl> ();
-              udpFactory->SetUdp (this);
-              node->AggregateObject (udpFactory);
-              this->SetDownTarget (MakeCallback (&Ipv4::Send, ipv4));
-            }
+          this->SetNode (node);
+          Ptr<UdpSocketFactoryImpl> udpFactory = CreateObject<UdpSocketFactoryImpl> ();
+          udpFactory->SetUdp (this);
+          node->AggregateObject (udpFactory);
         }
     }
+  
+  // We set at least one of our 2 down targets to the IPv4/IPv6 send
+  // functions.  Since these functions have different prototypes, we
+  // need to keep track of whether we are connected to an IPv4 or
+  // IPv6 lower layer and call the appropriate one.
+  
+  if (ipv4 != 0)
+    {
+      ipv4->Insert (this);
+      this->SetDownTarget (MakeCallback (&Ipv4::Send, ipv4));
+    }
+  if (ipv6 != 0)
+    {
+      ipv6->Insert (this);
+      this->SetDownTarget6 (MakeCallback (&Ipv6L3Protocol::Send, ipv6));
+    }
   Object::NotifyNewAggregate ();
 }
 
@@ -124,12 +143,18 @@
       delete m_endPoints;
       m_endPoints = 0;
     }
+  if (m_endPoints6 != 0)
+    {
+      delete m_endPoints6;
+      m_endPoints6 = 0;
+    }
   m_node = 0;
   m_downTarget.Nullify ();
+  m_downTarget6.Nullify ();
 /*
  = MakeNullCallback<void,Ptr<Packet>, Ipv4Address, Ipv4Address, uint8_t, Ptr<Ipv4Route> > ();
 */
-  Ipv4L4Protocol::DoDispose ();
+  IpL4Protocol::DoDispose ();
 }
 
 Ptr<Socket>
@@ -186,6 +211,49 @@
   m_endPoints->DeAllocate (endPoint);
 }
 
+Ipv6EndPoint *
+UdpL4Protocol::Allocate6 (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_endPoints6->Allocate ();
+}
+
+Ipv6EndPoint *
+UdpL4Protocol::Allocate6 (Ipv6Address address)
+{
+  NS_LOG_FUNCTION (this << address);
+  return m_endPoints6->Allocate (address);
+}
+
+Ipv6EndPoint *
+UdpL4Protocol::Allocate6 (uint16_t port)
+{
+  NS_LOG_FUNCTION (this << port);
+  return m_endPoints6->Allocate (port);
+}
+
+Ipv6EndPoint *
+UdpL4Protocol::Allocate6 (Ipv6Address address, uint16_t port)
+{
+  NS_LOG_FUNCTION (this << address << port);
+  return m_endPoints6->Allocate (address, port);
+}
+Ipv6EndPoint *
+UdpL4Protocol::Allocate6 (Ipv6Address localAddress, uint16_t localPort,
+                         Ipv6Address peerAddress, uint16_t peerPort)
+{
+  NS_LOG_FUNCTION (this << localAddress << localPort << peerAddress << peerPort);
+  return m_endPoints6->Allocate (localAddress, localPort,
+                                peerAddress, peerPort);
+}
+
+void 
+UdpL4Protocol::DeAllocate (Ipv6EndPoint *endPoint)
+{
+  NS_LOG_FUNCTION (this << endPoint);
+  m_endPoints6->DeAllocate (endPoint);
+}
+
 void 
 UdpL4Protocol::ReceiveIcmp (Ipv4Address icmpSource, uint8_t icmpTtl,
                             uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo,
@@ -213,7 +281,34 @@
     }
 }
 
-enum Ipv4L4Protocol::RxStatus
+void 
+UdpL4Protocol::ReceiveIcmp (Ipv6Address icmpSource, uint8_t icmpTtl,
+                            uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo,
+                            Ipv6Address payloadSource,Ipv6Address payloadDestination,
+                            const uint8_t payload[8])
+{
+  NS_LOG_FUNCTION (this << icmpSource << icmpTtl << icmpType << icmpCode << icmpInfo 
+                        << payloadSource << payloadDestination);
+  uint16_t src, dst;
+  src = payload[0] << 8;
+  src |= payload[1];
+  dst = payload[2] << 8;
+  dst |= payload[3];
+
+  Ipv6EndPoint *endPoint = m_endPoints6->SimpleLookup (payloadSource, src, payloadDestination, dst);
+  if (endPoint != 0)
+    {
+      endPoint->ForwardIcmp (icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
+    }
+  else
+    {
+      NS_LOG_DEBUG ("no endpoint found source=" << payloadSource <<
+                    ", destination="<<payloadDestination<<
+                    ", src=" << src << ", dst=" << dst);
+    }
+}
+
+enum IpL4Protocol::RxStatus
 UdpL4Protocol::Receive (Ptr<Packet> packet,
                         Ipv4Header const &header,
                         Ptr<Ipv4Interface> interface)
@@ -227,12 +322,17 @@
 
   udpHeader.InitializeChecksum (header.GetSource (), header.GetDestination (), PROT_NUMBER);
 
-  packet->RemoveHeader (udpHeader);
+  // We only peek at the header for now (instead of removing it) so that it will be intact
+  // if we have to pass it to a IPv6 endpoint via:
+  // 
+  //   UdpL4Protocol::Receive (Ptr<Packet> packet, Ipv6Address &src, Ipv6Address &dst, ...)
+
+  packet->PeekHeader (udpHeader);
 
   if(!udpHeader.IsChecksumOk ())
     {
       NS_LOG_INFO ("Bad checksum : dropping packet!");
-      return Ipv4L4Protocol::RX_CSUM_FAILED;
+      return IpL4Protocol::RX_CSUM_FAILED;
     }
 
   NS_LOG_DEBUG ("Looking up dst " << header.GetDestination () << " port " << udpHeader.GetDestinationPort ()); 
@@ -241,16 +341,67 @@
                          header.GetSource (), udpHeader.GetSourcePort (), interface);
   if (endPoints.empty ())
     {
+      if (this->GetObject<Ipv6L3Protocol> () != 0)
+        {
+          NS_LOG_LOGIC ("  No Ipv4 endpoints matched on UdpL4Protocol, trying Ipv6 "<<this);
+          Ptr<Ipv6Interface> fakeInterface;
+          Ipv6Address src = Ipv6Address::MakeIpv4MappedAddress (header.GetSource ());
+          Ipv6Address dst = Ipv6Address::MakeIpv4MappedAddress (header.GetDestination ());
+          return (this->Receive (packet, src, dst, fakeInterface));
+        }
+
       NS_LOG_LOGIC ("RX_ENDPOINT_UNREACH");
-      return Ipv4L4Protocol::RX_ENDPOINT_UNREACH;
+      return IpL4Protocol::RX_ENDPOINT_UNREACH;
     }
+
+  packet->RemoveHeader(udpHeader);
   for (Ipv4EndPointDemux::EndPointsI endPoint = endPoints.begin ();
        endPoint != endPoints.end (); endPoint++)
     {
       (*endPoint)->ForwardUp (packet->Copy (), header, udpHeader.GetSourcePort (), 
                               interface);
     }
-  return Ipv4L4Protocol::RX_OK;
+  return IpL4Protocol::RX_OK;
+}
+
+enum IpL4Protocol::RxStatus
+UdpL4Protocol::Receive (Ptr<Packet> packet,
+                        Ipv6Address &src,
+                        Ipv6Address &dst,
+                        Ptr<Ipv6Interface> interface)
+{
+  NS_LOG_FUNCTION (this << packet << src << dst);
+  UdpHeader udpHeader;
+  if(Node::ChecksumEnabled ())
+    {
+      udpHeader.EnableChecksums ();
+    }
+
+  udpHeader.InitializeChecksum (src, dst, PROT_NUMBER);
+
+  packet->RemoveHeader (udpHeader);
+
+  if(!udpHeader.IsChecksumOk () && !src.IsIpv4MappedAddress ())
+    {
+      NS_LOG_INFO ("Bad checksum : dropping packet!");
+      return IpL4Protocol::RX_CSUM_FAILED;
+    }
+
+  NS_LOG_DEBUG ("Looking up dst " << dst << " port " << udpHeader.GetDestinationPort ()); 
+  Ipv6EndPointDemux::EndPoints endPoints =
+    m_endPoints6->Lookup (dst, udpHeader.GetDestinationPort (),
+                         src, udpHeader.GetSourcePort (), interface);
+  if (endPoints.empty ())
+    {
+      NS_LOG_LOGIC ("RX_ENDPOINT_UNREACH");
+      return IpL4Protocol::RX_ENDPOINT_UNREACH;
+    }
+  for (Ipv6EndPointDemux::EndPointsI endPoint = endPoints.begin ();
+       endPoint != endPoints.end (); endPoint++)
+    {
+      (*endPoint)->ForwardUp (packet->Copy (), src, dst, udpHeader.GetSourcePort ());
+    }
+  return IpL4Protocol::RX_OK;
 }
 
 void
@@ -300,16 +451,74 @@
 }
 
 void
-UdpL4Protocol::SetDownTarget (Ipv4L4Protocol::DownTargetCallback callback)
+UdpL4Protocol::Send (Ptr<Packet> packet,
+                     Ipv6Address saddr, Ipv6Address daddr,
+                     uint16_t sport, uint16_t dport)
+{
+  NS_LOG_FUNCTION (this << packet << saddr << daddr << sport << dport);
+
+  UdpHeader udpHeader;
+  if(Node::ChecksumEnabled ())
+    {
+      udpHeader.EnableChecksums ();
+      udpHeader.InitializeChecksum (saddr,
+                                    daddr,
+                                    PROT_NUMBER);
+    }
+  udpHeader.SetDestinationPort (dport);
+  udpHeader.SetSourcePort (sport);
+
+  packet->AddHeader (udpHeader);
+
+  m_downTarget6 (packet, saddr, daddr, PROT_NUMBER, 0);
+}
+
+void
+UdpL4Protocol::Send (Ptr<Packet> packet,
+                     Ipv6Address saddr, Ipv6Address daddr,
+                     uint16_t sport, uint16_t dport, Ptr<Ipv6Route> route)
+{
+  NS_LOG_FUNCTION (this << packet << saddr << daddr << sport << dport << route);
+
+  UdpHeader udpHeader;
+  if(Node::ChecksumEnabled ())
+    {
+      udpHeader.EnableChecksums ();
+      udpHeader.InitializeChecksum (saddr,
+                                    daddr,
+                                    PROT_NUMBER);
+    }
+  udpHeader.SetDestinationPort (dport);
+  udpHeader.SetSourcePort (sport);
+
+  packet->AddHeader (udpHeader);
+
+  m_downTarget6 (packet, saddr, daddr, PROT_NUMBER, route);
+}
+
+void
+UdpL4Protocol::SetDownTarget (IpL4Protocol::DownTargetCallback callback)
 {
   m_downTarget = callback;
 }
 
-Ipv4L4Protocol::DownTargetCallback
+IpL4Protocol::DownTargetCallback
 UdpL4Protocol::GetDownTarget (void) const
 {
   return m_downTarget;
 }
 
+void
+UdpL4Protocol::SetDownTarget6 (IpL4Protocol::DownTargetCallback6 callback)
+{
+  m_downTarget6 = callback;
+}
+
+IpL4Protocol::DownTargetCallback6
+UdpL4Protocol::GetDownTarget6 (void) const
+{
+  return m_downTarget6;
+}
+
 } // namespace ns3
 
--- a/src/internet/model/udp-l4-protocol.h	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/internet/model/udp-l4-protocol.h	Mon Feb 20 14:05:07 2012 +0100
@@ -25,8 +25,11 @@
 
 #include "ns3/packet.h"
 #include "ns3/ipv4-address.h"
+#include "ns3/ipv6-address.h"
 #include "ns3/ptr.h"
-#include "ipv4-l4-protocol.h"
+#include "ns3/ip-l4-protocol.h"
+#include "ipv6-interface.h"
+#include "ipv6-header.h"
 
 namespace ns3 {
 
@@ -34,13 +37,15 @@
 class Socket;
 class Ipv4EndPointDemux;
 class Ipv4EndPoint;
+class Ipv6EndPointDemux;
+class Ipv6EndPoint;
 class UdpSocketImpl;
 
 /**
  * \ingroup udp
  * \brief Implementation of the UDP protocol
  */
-class UdpL4Protocol : public Ipv4L4Protocol {
+class UdpL4Protocol : public IpL4Protocol {
 public:
   static TypeId GetTypeId (void);
   static const uint8_t PROT_NUMBER;
@@ -64,8 +69,15 @@
   Ipv4EndPoint *Allocate (Ipv4Address address, uint16_t port);
   Ipv4EndPoint *Allocate (Ipv4Address localAddress, uint16_t localPort,
                           Ipv4Address peerAddress, uint16_t peerPort);
+  Ipv6EndPoint *Allocate6 (void);
+  Ipv6EndPoint *Allocate6 (Ipv6Address address);
+  Ipv6EndPoint *Allocate6 (uint16_t port);
+  Ipv6EndPoint *Allocate6 (Ipv6Address address, uint16_t port);
+  Ipv6EndPoint *Allocate6 (Ipv6Address localAddress, uint16_t localPort,
+                          Ipv6Address peerAddress, uint16_t peerPort);
 
   void DeAllocate (Ipv4EndPoint *endPoint);
+  void DeAllocate (Ipv6EndPoint *endPoint);
 
   // called by UdpSocket.
   /**
@@ -82,6 +94,12 @@
   void Send (Ptr<Packet> packet,
              Ipv4Address saddr, Ipv4Address daddr, 
              uint16_t sport, uint16_t dport, Ptr<Ipv4Route> route);
+  void Send (Ptr<Packet> packet,
+             Ipv6Address saddr, Ipv6Address daddr, 
+             uint16_t sport, uint16_t dport);
+  void Send (Ptr<Packet> packet,
+             Ipv6Address saddr, Ipv6Address daddr, 
+             uint16_t sport, uint16_t dport, Ptr<Ipv6Route> route);
   /**
    * \brief Receive a packet up the protocol stack
    * \param p The Packet to dump the contents into
@@ -89,9 +107,13 @@
    * \param interface the interface from which the packet is coming.
    */
   // inherited from Ipv4L4Protocol
-  virtual enum Ipv4L4Protocol::RxStatus Receive (Ptr<Packet> p,
+  virtual enum IpL4Protocol::RxStatus Receive (Ptr<Packet> p,
                                                  Ipv4Header const &header,
                                                  Ptr<Ipv4Interface> interface);
+  virtual enum IpL4Protocol::RxStatus Receive (Ptr<Packet> p,
+                                                 Ipv6Address &src,
+                                                 Ipv6Address &dst,
+                                                 Ptr<Ipv6Interface> interface);
 
   /**
    * \brief Receive an ICMP packet
@@ -108,11 +130,17 @@
                             uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo,
                             Ipv4Address payloadSource,Ipv4Address payloadDestination,
                             const uint8_t payload[8]);
+  virtual void ReceiveIcmp (Ipv6Address icmpSource, uint8_t icmpTtl,
+                            uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo,
+                            Ipv6Address payloadSource,Ipv6Address payloadDestination,
+                            const uint8_t payload[8]);
 
-  // From Ipv4L4Protocol
-  virtual void SetDownTarget (Ipv4L4Protocol::DownTargetCallback cb);
-  // From Ipv4L4Protocol
-  virtual Ipv4L4Protocol::DownTargetCallback GetDownTarget (void) const;
+  // From IpL4Protocol
+  virtual void SetDownTarget (IpL4Protocol::DownTargetCallback cb);
+  virtual void SetDownTarget6 (IpL4Protocol::DownTargetCallback6 cb);
+  // From IpL4Protocol
+  virtual IpL4Protocol::DownTargetCallback GetDownTarget (void) const;
+  virtual IpL4Protocol::DownTargetCallback6 GetDownTarget6 (void) const;
 
 protected:
   virtual void DoDispose (void);
@@ -124,10 +152,12 @@
 private:
   Ptr<Node> m_node;
   Ipv4EndPointDemux *m_endPoints;
+  Ipv6EndPointDemux *m_endPoints6;
   UdpL4Protocol (const UdpL4Protocol &o);
   UdpL4Protocol &operator = (const UdpL4Protocol &o);
   std::vector<Ptr<UdpSocketImpl> > m_sockets;
-  Ipv4L4Protocol::DownTargetCallback m_downTarget;
+  IpL4Protocol::DownTargetCallback m_downTarget;
+  IpL4Protocol::DownTargetCallback6 m_downTarget6;
 };
 
 } // namespace ns3
--- a/src/internet/model/udp-socket-impl.cc	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/internet/model/udp-socket-impl.cc	Mon Feb 20 14:05:07 2012 +0100
@@ -21,16 +21,21 @@
 #include "ns3/log.h"
 #include "ns3/node.h"
 #include "ns3/inet-socket-address.h"
+#include "ns3/inet6-socket-address.h"
 #include "ns3/ipv4-route.h"
+#include "ns3/ipv6-route.h"
 #include "ns3/ipv4.h"
+#include "ns3/ipv6.h"
 #include "ns3/ipv4-header.h"
 #include "ns3/ipv4-routing-protocol.h"
+#include "ns3/ipv6-routing-protocol.h"
 #include "ns3/udp-socket-factory.h"
 #include "ns3/trace-source-accessor.h"
 #include "ns3/ipv4-packet-info-tag.h"
 #include "udp-socket-impl.h"
 #include "udp-l4-protocol.h"
 #include "ipv4-end-point.h"
+#include "ipv6-end-point.h"
 #include <limits>
 
 NS_LOG_COMPONENT_DEFINE ("UdpSocketImpl");
@@ -52,12 +57,17 @@
                    CallbackValue (),
                    MakeCallbackAccessor (&UdpSocketImpl::m_icmpCallback),
                    MakeCallbackChecker ())
+    .AddAttribute ("IcmpCallback6", "Callback invoked whenever an icmpv6 error is received on this socket.",
+                   CallbackValue (),
+                   MakeCallbackAccessor (&UdpSocketImpl::m_icmpCallback6),
+                   MakeCallbackChecker ())
   ;
   return tid;
 }
 
 UdpSocketImpl::UdpSocketImpl ()
   : m_endPoint (0),
+    m_endPoint6 (0),
     m_node (0),
     m_udp (0),
     m_errno (ERROR_NOTERROR),
@@ -142,14 +152,21 @@
 UdpSocketImpl::FinishBind (void)
 {
   NS_LOG_FUNCTION_NOARGS ();
-  if (m_endPoint == 0)
+  if (m_endPoint != 0)
     {
-      return -1;
+      m_endPoint->SetRxCallback (MakeCallback (&UdpSocketImpl::ForwardUp, Ptr<UdpSocketImpl> (this)));
+      m_endPoint->SetIcmpCallback (MakeCallback (&UdpSocketImpl::ForwardIcmp, Ptr<UdpSocketImpl> (this)));
+      m_endPoint->SetDestroyCallback (MakeCallback (&UdpSocketImpl::Destroy, Ptr<UdpSocketImpl> (this)));
+      return 0;
     }
-  m_endPoint->SetRxCallback (MakeCallback (&UdpSocketImpl::ForwardUp, Ptr<UdpSocketImpl> (this)));
-  m_endPoint->SetIcmpCallback (MakeCallback (&UdpSocketImpl::ForwardIcmp, Ptr<UdpSocketImpl> (this)));
-  m_endPoint->SetDestroyCallback (MakeCallback (&UdpSocketImpl::Destroy, Ptr<UdpSocketImpl> (this)));
-  return 0;
+  else if (m_endPoint6 != 0)
+    {
+      m_endPoint6->SetRxCallback (MakeCallback (&UdpSocketImpl::ForwardUp6, Ptr<UdpSocketImpl> (this)));
+      m_endPoint6->SetIcmpCallback (MakeCallback (&UdpSocketImpl::ForwardIcmp6, Ptr<UdpSocketImpl> (this)));
+      m_endPoint6->SetDestroyCallback (MakeCallback (&UdpSocketImpl::Destroy, Ptr<UdpSocketImpl> (this)));
+      return 0;
+    }
+  return -1;
 }
 
 int
@@ -160,36 +177,69 @@
   return FinishBind ();
 }
 
+int
+UdpSocketImpl::Bind6 (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_endPoint6 = m_udp->Allocate6 ();
+  return FinishBind ();
+}
+
 int 
 UdpSocketImpl::Bind (const Address &address)
 {
   NS_LOG_FUNCTION (this << address);
 
-  if (!InetSocketAddress::IsMatchingType (address))
+  if (InetSocketAddress::IsMatchingType (address))
+    {
+      InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
+      Ipv4Address ipv4 = transport.GetIpv4 ();
+      uint16_t port = transport.GetPort ();
+      if (ipv4 == Ipv4Address::GetAny () && port == 0)
+        {
+          m_endPoint = m_udp->Allocate ();
+        }
+      else if (ipv4 == Ipv4Address::GetAny () && port != 0)
+        {
+          m_endPoint = m_udp->Allocate (port);
+        }
+      else if (ipv4 != Ipv4Address::GetAny () && port == 0)
+        {
+          m_endPoint = m_udp->Allocate (ipv4);
+        }
+      else if (ipv4 != Ipv4Address::GetAny () && port != 0)
+        {
+          m_endPoint = m_udp->Allocate (ipv4, port);
+        }
+    }
+  else if (Inet6SocketAddress::IsMatchingType (address))
+    {
+      Inet6SocketAddress transport = Inet6SocketAddress::ConvertFrom (address);
+      Ipv6Address ipv6 = transport.GetIpv6 ();
+      uint16_t port = transport.GetPort ();
+      if (ipv6 == Ipv6Address::GetAny () && port == 0)
+        {
+          m_endPoint6 = m_udp->Allocate6 ();
+        }
+      else if (ipv6 == Ipv6Address::GetAny () && port != 0)
+        {
+          m_endPoint6 = m_udp->Allocate6 (port);
+        }
+      else if (ipv6 != Ipv6Address::GetAny () && port == 0)
+        {
+          m_endPoint6 = m_udp->Allocate6 (ipv6);
+        }
+      else if (ipv6 != Ipv6Address::GetAny () && port != 0)
+        {
+          m_endPoint6 = m_udp->Allocate6 (ipv6, port);
+        }
+    }
+  else
     {
       NS_LOG_ERROR ("Not IsMatchingType");
       m_errno = ERROR_INVAL;
       return -1;
     }
-  InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
-  Ipv4Address ipv4 = transport.GetIpv4 ();
-  uint16_t port = transport.GetPort ();
-  if (ipv4 == Ipv4Address::GetAny () && port == 0)
-    {
-      m_endPoint = m_udp->Allocate ();
-    }
-  else if (ipv4 == Ipv4Address::GetAny () && port != 0)
-    {
-      m_endPoint = m_udp->Allocate (port);
-    }
-  else if (ipv4 != Ipv4Address::GetAny () && port == 0)
-    {
-      m_endPoint = m_udp->Allocate (ipv4);
-    }
-  else if (ipv4 != Ipv4Address::GetAny () && port != 0)
-    {
-      m_endPoint = m_udp->Allocate (ipv4, port);
-    }
 
   return FinishBind ();
 }
@@ -228,11 +278,26 @@
 UdpSocketImpl::Connect (const Address & address)
 {
   NS_LOG_FUNCTION (this << address);
-  InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
-  m_defaultAddress = transport.GetIpv4 ();
-  m_defaultPort = transport.GetPort ();
-  m_connected = true;
-  NotifyConnectionSucceeded ();
+  if (InetSocketAddress::IsMatchingType(address) == true)
+    {
+      InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
+      m_defaultAddress = Address(transport.GetIpv4 ());
+      m_defaultPort = transport.GetPort ();
+      m_connected = true;
+      NotifyConnectionSucceeded ();
+    }
+  else if (Inet6SocketAddress::IsMatchingType(address) == true)
+    {
+      Inet6SocketAddress transport = Inet6SocketAddress::ConvertFrom (address);
+      m_defaultAddress = Address(transport.GetIpv6 ());
+      m_defaultPort = transport.GetPort ();
+      m_connected = true;
+      NotifyConnectionSucceeded ();
+    }
+  else
+    {
+      return -1;
+    }
 
   return 0;
 }
@@ -261,7 +326,7 @@
 UdpSocketImpl::DoSend (Ptr<Packet> p)
 {
   NS_LOG_FUNCTION (this << p);
-  if (m_endPoint == 0)
+  if ((m_endPoint == 0) && (InetSocketAddress::IsMatchingType(m_defaultAddress) == true))
     {
       if (Bind () == -1)
         {
@@ -270,13 +335,22 @@
         }
       NS_ASSERT (m_endPoint != 0);
     }
+  else if ((m_endPoint6 == 0) && (Inet6SocketAddress::IsMatchingType(m_defaultAddress) == true))
+    {
+      if (Bind6 () == -1)
+        {
+          NS_ASSERT (m_endPoint6 == 0);
+          return -1;
+        }
+      NS_ASSERT (m_endPoint6 != 0);
+    }
   if (m_shutdownSend)
     {
       m_errno = ERROR_SHUTDOWN;
       return -1;
     } 
 
-  return DoSendTo (p, m_defaultAddress, m_defaultPort);
+  return DoSendTo (p, (const Address)m_defaultAddress);
 }
 
 int
@@ -287,17 +361,40 @@
   if (!m_connected)
     {
       NS_LOG_LOGIC ("Not connected");
-      InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
-      Ipv4Address ipv4 = transport.GetIpv4 ();
-      uint16_t port = transport.GetPort ();
-      return DoSendTo (p, ipv4, port);
+      if (InetSocketAddress::IsMatchingType(address) == true)
+        {
+          InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
+          Ipv4Address ipv4 = transport.GetIpv4 ();
+          uint16_t port = transport.GetPort ();
+          return DoSendTo (p, ipv4, port);
+        }
+      else if (Inet6SocketAddress::IsMatchingType(address) == true)
+        {
+          Inet6SocketAddress transport = Inet6SocketAddress::ConvertFrom (address);
+          Ipv6Address ipv6 = transport.GetIpv6 ();
+          uint16_t port = transport.GetPort ();
+          return DoSendTo (p, ipv6, port);
+        }
+      else
+        {
+          return -1;
+        }
     }
   else
     {
       // connected UDP socket must use default addresses
       NS_LOG_LOGIC ("Connected");
-      return DoSendTo (p, m_defaultAddress, m_defaultPort);
+      if (Ipv4Address::IsMatchingType(m_defaultAddress))
+        {
+          return DoSendTo (p, Ipv4Address::ConvertFrom(m_defaultAddress), m_defaultPort);
+        }
+      else if (Ipv6Address::IsMatchingType(m_defaultAddress))
+        {
+          return DoSendTo (p, Ipv6Address::ConvertFrom(m_defaultAddress), m_defaultPort);
+        }
     }
+  m_errno = ERROR_AFNOSUPPORT;
+  return(-1);
 }
 
 int
@@ -483,6 +580,113 @@
   return 0;
 }
 
+int
+UdpSocketImpl::DoSendTo (Ptr<Packet> p, Ipv6Address dest, uint16_t port)
+{
+  NS_LOG_FUNCTION (this << p << dest << port);
+
+  if (dest.IsIpv4MappedAddress ())
+    {
+        return (DoSendTo(p, dest.GetIpv4MappedAddress (), port));
+    }
+  if (m_boundnetdevice)
+    {
+      NS_LOG_LOGIC ("Bound interface number " << m_boundnetdevice->GetIfIndex ());
+    }
+  if (m_endPoint6 == 0)
+    {
+      if (Bind6 () == -1)
+        {
+          NS_ASSERT (m_endPoint6 == 0);
+          return -1;
+        }
+      NS_ASSERT (m_endPoint6 != 0);
+    }
+  if (m_shutdownSend)
+    {
+      m_errno = ERROR_SHUTDOWN;
+      return -1;
+    }
+
+  if (p->GetSize () > GetTxAvailable () )
+    {
+      m_errno = ERROR_MSGSIZE;
+      return -1;
+    }
+
+  Ptr<Ipv6> ipv6 = m_node->GetObject<Ipv6> ();
+
+  // Locally override the IP TTL for this socket
+  // We cannot directly modify the TTL at this stage, so we set a Packet tag
+  // The destination can be either multicast, unicast/anycast, or
+  // either all-hosts broadcast or limited (subnet-directed) broadcast.
+  // For the latter two broadcast types, the TTL will later be set to one
+  // irrespective of what is set in these socket options.  So, this tagging
+  // may end up setting the TTL of a limited broadcast packet to be
+  // the same as a unicast, but it will be fixed further down the stack
+  if (m_ipMulticastTtl != 0 && dest.IsMulticast ())
+    {
+      SocketIpTtlTag tag;
+      tag.SetTtl (m_ipMulticastTtl);
+      p->AddPacketTag (tag);
+    }
+  else if (m_ipTtl != 0 && !dest.IsMulticast ())
+    {
+      SocketIpTtlTag tag;
+      tag.SetTtl (m_ipTtl);
+      p->AddPacketTag (tag);
+    }
+  // There is no analgous to an IPv4 broadcast address in IPv6.
+  // Instead, we use a set of link-local, site-local, and global
+  // multicast addresses.  The Ipv6 routing layers should all
+  // provide an interface-specific route to these addresses such
+  // that we can treat these multicast addresses as "not broadcast"
+
+  if (m_endPoint6->GetLocalAddress () != Ipv6Address::GetAny ())
+    {
+      m_udp->Send (p->Copy (), m_endPoint6->GetLocalAddress (), dest,
+                   m_endPoint6->GetLocalPort (), port, 0);
+      NotifyDataSent (p->GetSize ());
+      NotifySend (GetTxAvailable ());
+      return p->GetSize ();
+    }
+  else if (ipv6->GetRoutingProtocol () != 0)
+    {
+      Ipv6Header header;
+      header.SetDestinationAddress (dest);
+      header.SetNextHeader (UdpL4Protocol::PROT_NUMBER);
+      Socket::SocketErrno errno_;
+      Ptr<Ipv6Route> route;
+      Ptr<NetDevice> oif = m_boundnetdevice; //specify non-zero if bound to a specific device
+      // TBD-- we could cache the route and just check its validity
+      route = ipv6->GetRoutingProtocol ()->RouteOutput (p, header, oif, errno_); 
+      if (route != 0)
+        {
+          NS_LOG_LOGIC ("Route exists");
+          header.SetSourceAddress (route->GetSource ());
+          m_udp->Send (p->Copy (), header.GetSourceAddress (), header.GetDestinationAddress (),
+                       m_endPoint6->GetLocalPort (), port, route);
+          NotifyDataSent (p->GetSize ());
+          return p->GetSize ();
+        }
+      else 
+        {
+          NS_LOG_LOGIC ("No route to destination");
+          NS_LOG_ERROR (errno_);
+          m_errno = errno_;
+          return -1;
+        }
+    }
+  else
+    {
+      NS_LOG_ERROR ("ERROR_NOROUTETOHOST");
+      m_errno = ERROR_NOROUTETOHOST;
+      return -1;
+    }
+
+  return 0;
+}
+
 // XXX maximum message size for UDP broadcast is limited by MTU
 // size of underlying link; we are not checking that now.
 uint32_t
@@ -498,10 +702,21 @@
 UdpSocketImpl::SendTo (Ptr<Packet> p, uint32_t flags, const Address &address)
 {
   NS_LOG_FUNCTION (this << p << flags << address);
-  InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
-  Ipv4Address ipv4 = transport.GetIpv4 ();
-  uint16_t port = transport.GetPort ();
-  return DoSendTo (p, ipv4, port);
+  if (InetSocketAddress::IsMatchingType (address))
+    {
+      InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
+      Ipv4Address ipv4 = transport.GetIpv4 ();
+      uint16_t port = transport.GetPort ();
+      return DoSendTo (p, ipv4, port);
+    }
+  else if (Inet6SocketAddress::IsMatchingType (address))
+    {
+      Inet6SocketAddress transport = Inet6SocketAddress::ConvertFrom (address);
+      Ipv6Address ipv6 = transport.GetIpv6 ();
+      uint16_t port = transport.GetPort ();
+      return DoSendTo (p, ipv6, port);
+    }
+  return -1;
 }
 
 uint32_t
@@ -657,6 +872,38 @@
     }
 }
 
+void 
+UdpSocketImpl::ForwardUp6 (Ptr<Packet> packet, Ipv6Address saddr, Ipv6Address daddr, uint16_t port)
+{
+  NS_LOG_FUNCTION (this << packet << saddr << port);
+
+  if (m_shutdownRecv)
+    {
+      return;
+    }
+
+  if ((m_rxAvailable + packet->GetSize ()) <= m_rcvBufSize)
+    {
+      Address address = Inet6SocketAddress (saddr, port);
+      SocketAddressTag tag;
+      tag.SetAddress (address);
+      packet->AddPacketTag (tag);
+      m_deliveryQueue.push (packet);
+      m_rxAvailable += packet->GetSize ();
+      NotifyDataRecv ();
+    }
+  else
+    {
+      // In general, this case should not occur unless the
+      // receiving application reads data from this socket slowly
+      // in comparison to the arrival rate
+      //
+      // drop and trace packet
+      NS_LOG_WARN ("No receive buffer space available.  Drop.");
+      m_dropTrace (packet);
+    }
+}
+
 void
 UdpSocketImpl::ForwardIcmp (Ipv4Address icmpSource, uint8_t icmpTtl, 
                             uint8_t icmpType, uint8_t icmpCode,
@@ -670,6 +917,19 @@
     }
 }
 
+void
+UdpSocketImpl::ForwardIcmp6 (Ipv6Address icmpSource, uint8_t icmpTtl, 
+                            uint8_t icmpType, uint8_t icmpCode,
+                            uint32_t icmpInfo)
+{
+  NS_LOG_FUNCTION (this << icmpSource << (uint32_t)icmpTtl << (uint32_t)icmpType <<
+                   (uint32_t)icmpCode << icmpInfo);
+  if (!m_icmpCallback6.IsNull ())
+    {
+      m_icmpCallback6 (icmpSource, icmpTtl, icmpType, icmpCode, icmpInfo);
+    }
+}
+
 
 void 
 UdpSocketImpl::SetRcvBufSize (uint32_t size)
--- a/src/internet/model/udp-socket-impl.h	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/internet/model/udp-socket-impl.h	Mon Feb 20 14:05:07 2012 +0100
@@ -34,6 +34,7 @@
 namespace ns3 {
 
 class Ipv4EndPoint;
+class Ipv6EndPoint;
 class Node;
 class Packet;
 class UdpL4Protocol;
@@ -63,6 +64,7 @@
   virtual enum SocketType GetSocketType (void) const;
   virtual Ptr<Node> GetNode (void) const;
   virtual int Bind (void);
+  virtual int Bind6 (void);
   virtual int Bind (const Address &address);
   virtual int Close (void);
   virtual int ShutdownSend (void);
@@ -104,18 +106,24 @@
   int FinishBind (void);
   void ForwardUp (Ptr<Packet> p, Ipv4Header header, uint16_t port, 
                   Ptr<Ipv4Interface> incomingInterface);
+  void ForwardUp6 (Ptr<Packet> p, Ipv6Address saddr, Ipv6Address daddr, uint16_t port);
   void Destroy (void);
   int DoSend (Ptr<Packet> p);
   int DoSendTo (Ptr<Packet> p, const Address &daddr);
   int DoSendTo (Ptr<Packet> p, Ipv4Address daddr, uint16_t dport);
+  int DoSendTo (Ptr<Packet> p, Ipv6Address daddr, uint16_t dport);
   void ForwardIcmp (Ipv4Address icmpSource, uint8_t icmpTtl, 
                     uint8_t icmpType, uint8_t icmpCode,
                     uint32_t icmpInfo);
+  void ForwardIcmp6 (Ipv6Address icmpSource, uint8_t icmpTtl, 
+                     uint8_t icmpType, uint8_t icmpCode,
+                     uint32_t icmpInfo);
 
   Ipv4EndPoint *m_endPoint;
+  Ipv6EndPoint *m_endPoint6;
   Ptr<Node> m_node;
   Ptr<UdpL4Protocol> m_udp;
-  Ipv4Address m_defaultAddress;
+  Address m_defaultAddress;
   uint16_t m_defaultPort;
   TracedCallback<Ptr<const Packet> > m_dropTrace;
 
@@ -136,6 +144,7 @@
   bool m_ipMulticastLoop;
   bool m_mtuDiscover;
   Callback<void, Ipv4Address,uint8_t,uint8_t,uint8_t,uint32_t> m_icmpCallback;
+  Callback<void, Ipv6Address,uint8_t,uint8_t,uint8_t,uint32_t> m_icmpCallback6;
 };
 
 } // namespace ns3
--- a/src/internet/test/error-net-device.cc	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/internet/test/error-net-device.cc	Mon Feb 20 14:05:07 2012 +0100
@@ -61,7 +61,7 @@
 ErrorNetDevice::Receive (Ptr<Packet> packet, uint16_t protocol,
 			  Mac48Address to, Mac48Address from)
 {
-  NS_LOG_FUNCTION (packet << protocol << to << from);
+  NS_LOG_FUNCTION (packet << protocol << to << from << *packet);
   NetDevice::PacketType packetType;
 
   if (m_receiveErrorModel && m_receiveErrorModel->IsCorrupt (packet) )
@@ -194,7 +194,7 @@
 bool 
 ErrorNetDevice::Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
 {
-  NS_LOG_FUNCTION (packet << dest << protocolNumber);
+  NS_LOG_FUNCTION (packet << dest << protocolNumber << *packet);
   Mac48Address to = Mac48Address::ConvertFrom (dest);
   m_channel->Send (packet, protocolNumber, to, m_address, this);
   return true;
@@ -202,6 +202,7 @@
 bool 
 ErrorNetDevice::SendFrom(Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber)
 {
+  NS_LOG_FUNCTION (packet << source << dest << protocolNumber << *packet);
   Mac48Address to = Mac48Address::ConvertFrom (dest);
   Mac48Address from = Mac48Address::ConvertFrom (source);
   m_channel->Send (packet, protocolNumber, to, from, this);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet/test/ipv6-dual-stack-test-suite.cc	Mon Feb 20 14:05:07 2012 +0100
@@ -0,0 +1,312 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 Georgia Tech Research Corporation
+ * Copyright (c) 2009 INRIA
+ * 
+ * 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: Ken Renard <kenneth.d.renard.ctr@mail.mil>
+ *
+ */
+
+#include "ns3/test.h"
+#include "ns3/socket-factory.h"
+#include "ns3/tcp-socket-factory.h"
+#include "ns3/simulator.h"
+#include "ns3/simple-channel.h"
+#include "ns3/simple-net-device.h"
+#include "ns3/config.h"
+#include "ns3/ipv4-static-routing.h"
+#include "ns3/ipv4-list-routing.h"
+#include "ns3/ipv6-static-routing.h"
+#include "ns3/ipv6-list-routing.h"
+#include "ns3/node.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/inet6-socket-address.h"
+#include "ns3/uinteger.h"
+#include "ns3/log.h"
+
+#include "ns3/ipv4-end-point.h"
+#include "ns3/arp-l3-protocol.h"
+#include "ns3/ipv4-l3-protocol.h"
+#include "ns3/ipv6-l3-protocol.h"
+#include "ns3/icmpv4-l4-protocol.h"
+#include "ns3/icmpv6-l4-protocol.h"
+#include "ns3/udp-l4-protocol.h"
+#include "ns3/tcp-l4-protocol.h"
+
+#include <string>
+
+NS_LOG_COMPONENT_DEFINE ("Ipv6DualStackTestSuite");
+
+namespace ns3 {
+
+class DualStackTestCase : public TestCase
+{
+public:
+  DualStackTestCase ();
+private:
+  virtual void DoRun (void);
+  virtual void DoTeardown (void);
+
+  void SetUpSim ();
+  Ptr<Node> node0;
+  Ptr<Node> node1;
+
+  void ServerHandleConnectionCreated1 (Ptr<Socket> s, const Address & addr);
+  void ServerHandleConnectionCreated2 (Ptr<Socket> s, const Address & addr);
+  void ServerHandleConnectionCreated3 (Ptr<Socket> s, const Address & addr);
+  void ServerHandleConnectionCreated4 (Ptr<Socket> s, const Address & addr);
+
+  Ptr<Socket> server1;
+  Ptr<Socket> server2;
+  Ptr<Socket> server3;
+  Ptr<Socket> server4;
+
+  Ptr<Socket> source1;
+  Ptr<Socket> source2;
+  Ptr<Socket> source3;
+  Ptr<Socket> source4;
+
+  Address receivedAddr1;
+  Address receivedAddr2;
+  Address receivedAddr3;
+  Address receivedAddr4;
+};
+
+Ptr<Node>
+CreateDualStackNode ()
+{
+  Ptr<Node> node = CreateObject<Node> ();
+
+  //ARP
+  Ptr<ArpL3Protocol> arp = CreateObject<ArpL3Protocol> ();
+  node->AggregateObject (arp);
+
+  //IPV4
+  Ptr<Ipv4L3Protocol> ipv4 = CreateObject<Ipv4L3Protocol> ();
+  //Routing for Ipv4
+  Ptr<Ipv4ListRouting> ipv4Routing = CreateObject<Ipv4ListRouting> ();
+  ipv4->SetRoutingProtocol (ipv4Routing);
+  Ptr<Ipv4StaticRouting> ipv4staticRouting = CreateObject<Ipv4StaticRouting> ();
+  ipv4Routing->AddRoutingProtocol (ipv4staticRouting, 0);
+  node->AggregateObject (ipv4);
+
+  //ICMPv4
+  Ptr<Icmpv4L4Protocol> icmp = CreateObject<Icmpv4L4Protocol> ();
+  node->AggregateObject (icmp);
+
+  //UDP
+  Ptr<UdpL4Protocol> udp = CreateObject<UdpL4Protocol> ();
+  node->AggregateObject (udp);
+
+  //TCP
+  Ptr<TcpL4Protocol> tcp = CreateObject<TcpL4Protocol> ();
+  node->AggregateObject (tcp);
+
+  //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 ();
+
+  return node;
+}
+
+Ptr<SimpleNetDevice>
+AddSimpleNetDevice (Ptr<Node> node, Ipv4Address v4Addr, Ipv4Mask v4Mask,
+                    Ipv6Address v6Addr, Ipv6Prefix v6Prefix)
+{
+  Ptr<SimpleNetDevice> dev = CreateObject<SimpleNetDevice> ();
+  dev->SetAddress (Mac48Address::ConvertFrom (Mac48Address::Allocate ()));
+  node->AddDevice (dev);
+
+  Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
+  uint32_t ndid = ipv4->AddInterface (dev);
+  Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (v4Addr, v4Mask);
+  ipv4->AddAddress (ndid, ipv4Addr);
+  ipv4->SetUp (ndid);
+
+  Ptr<Ipv6> ipv6 = node->GetObject<Ipv6> ();
+  ndid = ipv6->AddInterface (dev);
+  Ipv6InterfaceAddress ipv6Addr = Ipv6InterfaceAddress (v6Addr, v6Prefix);
+  ipv6->AddAddress (ndid, ipv6Addr);
+  ipv6->SetUp (ndid);
+
+  return dev;
+}
+
+void
+DualStackTestCase::SetUpSim ()
+{
+  node0 = CreateDualStackNode ();
+  node1 = CreateDualStackNode ();
+
+  Ptr<SimpleNetDevice> dev0 = AddSimpleNetDevice(node0, Ipv4Address("10.0.0.1"),
+            Ipv4Mask(0xffffff00), Ipv6Address("2001::1"), Ipv6Prefix(64));
+  Ptr<SimpleNetDevice> dev1 = AddSimpleNetDevice(node1, Ipv4Address("10.0.0.2"),
+            Ipv4Mask(0xffffff00), Ipv6Address("2001::2"), Ipv6Prefix(64));
+
+  Ptr<SimpleChannel> channel = CreateObject<SimpleChannel> ();
+  dev0->SetChannel (channel);
+  dev1->SetChannel (channel);
+
+  Ptr<SocketFactory> sockFactory0 = node0->GetObject<TcpSocketFactory> ();
+  Ptr<SocketFactory> sockFactory1 = node1->GetObject<TcpSocketFactory> ();
+
+  server1 = sockFactory0->CreateSocket ();
+  server2 = sockFactory0->CreateSocket ();
+  server3 = sockFactory0->CreateSocket ();
+  server4 = sockFactory0->CreateSocket ();
+
+  source1 = sockFactory1->CreateSocket ();
+  source2 = sockFactory1->CreateSocket ();
+  source3 = sockFactory1->CreateSocket ();
+  source4 = sockFactory1->CreateSocket ();
+
+  return;
+}
+
+void
+DualStackTestCase::ServerHandleConnectionCreated1 (Ptr<Socket> s, const Address & addr)
+{
+  receivedAddr1 = addr;
+  return;
+}
+
+void
+DualStackTestCase::ServerHandleConnectionCreated2 (Ptr<Socket> s, const Address & addr)
+{
+  receivedAddr2 = addr;
+  return;
+}
+
+void
+DualStackTestCase::ServerHandleConnectionCreated3 (Ptr<Socket> s, const Address & addr)
+{
+  receivedAddr3 = addr;
+  return;
+}
+
+void
+DualStackTestCase::ServerHandleConnectionCreated4 (Ptr<Socket> s, const Address & addr)
+{
+  receivedAddr4 = addr;
+  return;
+}
+
+
+DualStackTestCase::DualStackTestCase ()
+  : TestCase ("DualStackTestCase")
+{
+  receivedAddr1 = Address ();
+  receivedAddr2 = Address ();
+  receivedAddr3 = Address ();
+  receivedAddr4 = Address ();
+}
+
+void
+DualStackTestCase::DoRun (void)
+{
+  SetUpSim ();
+
+  uint16_t port1 = 5000;
+  uint16_t port2 = 5001;
+  uint16_t port3 = 5002;
+  uint16_t port4 = 5003;
+
+  /* Server 1: listen on 0.0.0.0 for IPv4 connection */
+  server1->Bind (InetSocketAddress(Ipv4Address::GetAny(), port1));
+  server1->Listen ();
+  server1->SetAcceptCallback (MakeNullCallback<bool, Ptr< Socket >, const Address &> (),
+                 MakeCallback (&DualStackTestCase::ServerHandleConnectionCreated1, this));
+
+  /* Server 2: listen on 0.0.0.0 for IPv4 connection - should reject IPv6 */
+  server2->Bind (InetSocketAddress(Ipv4Address::GetAny(), port2));
+  server2->Listen ();
+  server2->SetAcceptCallback (MakeNullCallback<bool, Ptr< Socket >, const Address &> (),
+                 MakeCallback (&DualStackTestCase::ServerHandleConnectionCreated2, this));
+
+  /* Server 3: listen on :: for IPv4 (mapped into IPv6 address) connection */
+  server3->Bind (Inet6SocketAddress(Ipv6Address::GetAny(), port3));
+  server3->Listen ();
+  server3->SetAcceptCallback (MakeNullCallback<bool, Ptr< Socket >, const Address &> (),
+                 MakeCallback (&DualStackTestCase::ServerHandleConnectionCreated3, this));
+
+  /* Server 4: listen on :: for IPv6 connection */
+  server4->Bind (Inet6SocketAddress(Ipv6Address::GetAny(), port4));
+  server4->Listen ();
+  server4->SetAcceptCallback (MakeNullCallback<bool, Ptr< Socket >, const Address &> (),
+                 MakeCallback (&DualStackTestCase::ServerHandleConnectionCreated4, this));
+
+
+  /* Source 1: connect to server 1 via IPv4 */
+  source1->Connect(InetSocketAddress(Ipv4Address("10.0.0.1"), port1));
+
+  /* Source 2: connect to server 2 via IPv6 */
+  source2->Connect(Inet6SocketAddress(Ipv6Address("2001::1"), port2));
+
+  /* Source 3: connect to server 3 via IPv4 */
+  source3->Connect(InetSocketAddress(Ipv4Address("10.0.0.1"), port3));
+
+  /* Source 4: connect to server 4 via IPv6 */
+  source4->Connect(Inet6SocketAddress(Ipv6Address("2001::1"), port4));
+
+  Simulator::Run();
+
+  /* Server 1: should have connection from Ipv4 address of Node 1 */
+  NS_TEST_EXPECT_MSG_EQ (InetSocketAddress::IsMatchingType(receivedAddr1), true, "Accepted address is of proper type");
+  NS_TEST_EXPECT_MSG_EQ(InetSocketAddress::ConvertFrom(receivedAddr1).GetIpv4 (), Ipv4Address("10.0.0.2"), "Accepted address is correct");
+
+  /* Server 2: should have no connection */
+  NS_TEST_EXPECT_MSG_EQ(receivedAddr2.IsInvalid(), true, "IPv4 socket correctly ignored IPv6 connection");
+
+  /* Server 3: should have connection from Ipv4-mapped IPv6 address of Node 1 */
+  NS_TEST_EXPECT_MSG_EQ (Inet6SocketAddress::IsMatchingType(receivedAddr3), true, "Accepted address is of proper type");
+  NS_TEST_EXPECT_MSG_EQ(Inet6SocketAddress::ConvertFrom(receivedAddr3).GetIpv6 (), Ipv6Address("::ffff:0a00:0002"), "Accepted address is correct");
+
+  /* Server 4: should have connection from IPv6 address of Node 1 */
+  NS_TEST_EXPECT_MSG_EQ (Inet6SocketAddress::IsMatchingType(receivedAddr4), true, "Accepted address is of proper type");
+  NS_TEST_EXPECT_MSG_EQ(Inet6SocketAddress::ConvertFrom(receivedAddr4).GetIpv6 (), Ipv6Address("2001::2"), "Accepted address is correct");
+}
+
+void
+DualStackTestCase::DoTeardown (void)
+{
+}
+
+
+static class Ipv6DualStackTestSuite : public TestSuite
+{
+public:
+  Ipv6DualStackTestSuite ()
+    : TestSuite ("ipv6-dual-stack", UNIT)
+  {
+    AddTestCase (new DualStackTestCase());
+  }
+} g_ipv6DualStackTestSuite;
+
+} // namespace ns3
--- a/src/internet/test/tcp-test.cc	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/internet/test/tcp-test.cc	Mon Feb 20 14:05:07 2012 +0100
@@ -30,15 +30,20 @@
 #include "ns3/config.h"
 #include "ns3/ipv4-static-routing.h"
 #include "ns3/ipv4-list-routing.h"
+#include "ns3/ipv6-static-routing.h"
+#include "ns3/ipv6-list-routing.h"
 #include "ns3/node.h"
 #include "ns3/inet-socket-address.h"
+#include "ns3/inet6-socket-address.h"
 #include "ns3/uinteger.h"
 #include "ns3/log.h"
 
 #include "ns3/ipv4-end-point.h"
 #include "ns3/arp-l3-protocol.h"
 #include "ns3/ipv4-l3-protocol.h"
+#include "ns3/ipv6-l3-protocol.h"
 #include "ns3/icmpv4-l4-protocol.h"
+#include "ns3/icmpv6-l4-protocol.h"
 #include "ns3/udp-l4-protocol.h"
 #include "ns3/tcp-l4-protocol.h"
 
@@ -55,14 +60,18 @@
                uint32_t sourceWriteSize,
                uint32_t sourceReadSize,
                uint32_t serverWriteSize,
-               uint32_t serverReadSize);
+               uint32_t serverReadSize,
+               bool useIpv6);
 private:
   virtual void DoRun (void);
   virtual void DoTeardown (void);
   void SetupDefaultSim (void);
+  void SetupDefaultSim6 (void);
 
   Ptr<Node> CreateInternetNode (void);
+  Ptr<Node> CreateInternetNode6 (void);
   Ptr<SimpleNetDevice> AddSimpleNetDevice (Ptr<Node> node, const char* ipaddr, const char* netmask);
+  Ptr<SimpleNetDevice> AddSimpleNetDevice6 (Ptr<Node> node, Ipv6Address ipaddr, Ipv6Prefix prefix);
   void ServerHandleConnectionCreated (Ptr<Socket> s, const Address & addr);
   void ServerHandleRecv (Ptr<Socket> sock);
   void ServerHandleSend (Ptr<Socket> sock, uint32_t available);
@@ -81,18 +90,21 @@
   uint8_t *m_sourceTxPayload;
   uint8_t *m_sourceRxPayload;
   uint8_t* m_serverRxPayload;
+
+  bool m_useIpv6;
 };
 
 static std::string Name (std::string str, uint32_t totalStreamSize,
                          uint32_t sourceWriteSize,
                          uint32_t serverReadSize,
                          uint32_t serverWriteSize,
-                         uint32_t sourceReadSize)
+                         uint32_t sourceReadSize,
+                         bool useIpv6)
 {
   std::ostringstream oss;
   oss << str << " total=" << totalStreamSize << " sourceWrite=" << sourceWriteSize 
       << " sourceRead=" << sourceReadSize << " serverRead=" << serverReadSize
-      << " serverWrite=" << serverWriteSize;
+      << " serverWrite=" << serverWriteSize << " useIpv6=" << useIpv6;
   return oss.str ();
 }
 
@@ -109,18 +121,21 @@
                           uint32_t sourceWriteSize,
                           uint32_t sourceReadSize,
                           uint32_t serverWriteSize,
-                          uint32_t serverReadSize)
+                          uint32_t serverReadSize,
+                          bool useIpv6)
   : TestCase (Name ("Send string data from client to server and back", 
                     totalStreamSize, 
                     sourceWriteSize,
                     serverReadSize,
                     serverWriteSize,
-                    sourceReadSize)),
+                    sourceReadSize,
+                    useIpv6)),
     m_totalBytes (totalStreamSize),
     m_sourceWriteSize (sourceWriteSize),
     m_sourceReadSize (sourceReadSize),
     m_serverWriteSize (serverWriteSize),
-    m_serverReadSize (serverReadSize)
+    m_serverReadSize (serverReadSize),
+    m_useIpv6 (useIpv6)
 {
 }
 
@@ -142,7 +157,14 @@
   memset (m_sourceRxPayload, 0, m_totalBytes);
   memset (m_serverRxPayload, 0, m_totalBytes);
 
-  SetupDefaultSim ();
+  if (m_useIpv6 == true)
+    {
+      SetupDefaultSim6 ();
+    }
+  else
+    {
+      SetupDefaultSim ();
+    }
 
   Simulator::Run ();
 
@@ -326,6 +348,83 @@
   source->Connect (serverremoteaddr);
 }
 
+void
+TcpTestCase::SetupDefaultSim6 (void)
+{
+  Ipv6Prefix prefix = Ipv6Prefix(64);
+  Ipv6Address ipaddr0 = Ipv6Address("2001:0100:f00d:cafe::1");
+  Ipv6Address ipaddr1 = Ipv6Address("2001:0100:f00d:cafe::2");
+  Ptr<Node> node0 = CreateInternetNode6 ();
+  Ptr<Node> node1 = CreateInternetNode6 ();
+  Ptr<SimpleNetDevice> dev0 = AddSimpleNetDevice6 (node0, ipaddr0, prefix);
+  Ptr<SimpleNetDevice> dev1 = AddSimpleNetDevice6 (node1, ipaddr1, prefix);
+
+  Ptr<SimpleChannel> channel = CreateObject<SimpleChannel> ();
+  dev0->SetChannel (channel);
+  dev1->SetChannel (channel);
+
+  Ptr<SocketFactory> sockFactory0 = node0->GetObject<TcpSocketFactory> ();
+  Ptr<SocketFactory> sockFactory1 = node1->GetObject<TcpSocketFactory> ();
+
+  Ptr<Socket> server = sockFactory0->CreateSocket ();
+  Ptr<Socket> source = sockFactory1->CreateSocket ();
+
+  uint16_t port = 50000;
+  Inet6SocketAddress serverlocaladdr (Ipv6Address::GetAny (), port);
+  Inet6SocketAddress serverremoteaddr (ipaddr0, port);
+
+  server->Bind (serverlocaladdr);
+  server->Listen ();
+  server->SetAcceptCallback (MakeNullCallback<bool, Ptr< Socket >, const Address &> (),
+                             MakeCallback (&TcpTestCase::ServerHandleConnectionCreated,this));
+
+  source->SetRecvCallback (MakeCallback (&TcpTestCase::SourceHandleRecv, this));
+  source->SetSendCallback (MakeCallback (&TcpTestCase::SourceHandleSend, this));
+
+  source->Connect (serverremoteaddr);
+}
+
+Ptr<Node>
+TcpTestCase::CreateInternetNode6 ()
+{
+  Ptr<Node> node = CreateObject<Node> ();
+  //IPV6
+  Ptr<Ipv6L3Protocol> ipv6 = CreateObject<Ipv6L3Protocol> ();
+  //Routing for Ipv6
+  Ptr<Ipv6ListRouting> ipv6Routing = CreateObject<Ipv6ListRouting> ();
+  ipv6->SetRoutingProtocol (ipv6Routing);
+  Ptr<Ipv6StaticRouting> ipv6staticRouting = CreateObject<Ipv6StaticRouting> ();
+  ipv6Routing->AddRoutingProtocol (ipv6staticRouting, 0);
+  node->AggregateObject (ipv6);
+  //ICMP
+  Ptr<Icmpv6L4Protocol> icmp = CreateObject<Icmpv6L4Protocol> ();
+  node->AggregateObject (icmp);
+  //Ipv6 Extensions
+  ipv6->RegisterExtensions ();
+  ipv6->RegisterOptions ();
+  //UDP
+  Ptr<UdpL4Protocol> udp = CreateObject<UdpL4Protocol> ();
+  node->AggregateObject (udp);
+  //TCP
+  Ptr<TcpL4Protocol> tcp = CreateObject<TcpL4Protocol> ();
+  node->AggregateObject (tcp);
+  return node;
+}
+
+Ptr<SimpleNetDevice>
+TcpTestCase::AddSimpleNetDevice6 (Ptr<Node> node, Ipv6Address ipaddr, Ipv6Prefix prefix)
+{
+  Ptr<SimpleNetDevice> dev = CreateObject<SimpleNetDevice> ();
+  dev->SetAddress (Mac48Address::ConvertFrom (Mac48Address::Allocate ()));
+  node->AddDevice (dev);
+  Ptr<Ipv6> ipv6 = node->GetObject<Ipv6> ();
+  uint32_t ndid = ipv6->AddInterface (dev);
+  Ipv6InterfaceAddress ipv6Addr = Ipv6InterfaceAddress (ipaddr, prefix);
+  ipv6->AddAddress (ndid, ipv6Addr);
+  ipv6->SetUp (ndid);
+  return dev;
+}
+
 static class TcpTestSuite : public TestSuite
 {
 public:
@@ -336,9 +435,13 @@
     // 2) source write size, 3) source read size
     // 4) server write size, and 5) server read size
     // with units of bytes
-    AddTestCase (new TcpTestCase (13, 200, 200, 200, 200));
-    AddTestCase (new TcpTestCase (13, 1, 1, 1, 1));
-    AddTestCase (new TcpTestCase (100000, 100, 50, 100, 20));
+    AddTestCase (new TcpTestCase (13, 200, 200, 200, 200, false));
+    AddTestCase (new TcpTestCase (13, 1, 1, 1, 1, false));
+    AddTestCase (new TcpTestCase (100000, 100, 50, 100, 20, false));
+
+    AddTestCase (new TcpTestCase (13, 200, 200, 200, 200, true));
+    AddTestCase (new TcpTestCase (13, 1, 1, 1, 1, true));
+    AddTestCase (new TcpTestCase (100000, 100, 50, 100, 20, true));
   }
 
 } g_tcpTestSuite;
--- a/src/internet/test/udp-test.cc	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/internet/test/udp-test.cc	Mon Feb 20 14:05:07 2012 +0100
@@ -34,14 +34,19 @@
 #include "ns3/log.h"
 #include "ns3/node.h"
 #include "ns3/inet-socket-address.h"
+#include "ns3/inet6-socket-address.h"
 
 #include "ns3/arp-l3-protocol.h"
 #include "ns3/ipv4-l3-protocol.h"
+#include "ns3/ipv6-l3-protocol.h"
 #include "ns3/icmpv4-l4-protocol.h"
+#include "ns3/icmpv6-l4-protocol.h"
 #include "ns3/udp-l4-protocol.h"
 #include "ns3/tcp-l4-protocol.h"
 #include "ns3/ipv4-list-routing.h"
 #include "ns3/ipv4-static-routing.h"
+#include "ns3/ipv6-list-routing.h"
+#include "ns3/ipv6-static-routing.h"
 
 #include <string>
 #include <limits>
@@ -72,6 +77,31 @@
   node->AggregateObject (tcp);
 }
 
+static void
+AddInternetStack6 (Ptr<Node> node)
+{
+  //IPV6
+  Ptr<Ipv6L3Protocol> ipv6 = CreateObject<Ipv6L3Protocol> ();
+  //Routing for Ipv6
+  Ptr<Ipv6ListRouting> ipv6Routing = CreateObject<Ipv6ListRouting> ();
+  ipv6->SetRoutingProtocol (ipv6Routing);
+  Ptr<Ipv6StaticRouting> ipv6staticRouting = CreateObject<Ipv6StaticRouting> ();
+  ipv6Routing->AddRoutingProtocol (ipv6staticRouting, 0);
+  node->AggregateObject (ipv6);
+  //ICMP
+  Ptr<Icmpv6L4Protocol> icmp = CreateObject<Icmpv6L4Protocol> ();
+  node->AggregateObject (icmp);
+  //Ipv6 Extensions
+  ipv6->RegisterExtensions ();
+  ipv6->RegisterOptions ();
+  //UDP
+  Ptr<UdpL4Protocol> udp = CreateObject<UdpL4Protocol> ();
+  node->AggregateObject (udp);
+  //TCP
+  Ptr<TcpL4Protocol> tcp = CreateObject<TcpL4Protocol> ();
+  node->AggregateObject (tcp);
+}
+
 
 class UdpSocketLoopbackTest : public TestCase
 {
@@ -114,6 +144,50 @@
   NS_TEST_EXPECT_MSG_EQ (m_receivedPacket->GetSize (), 246, "first socket should not receive it (it is bound specifically to the second interface's address");
 }
 
+class Udp6SocketLoopbackTest : public TestCase
+{
+public:
+  Udp6SocketLoopbackTest ();
+  virtual void DoRun (void);
+
+  void ReceivePkt (Ptr<Socket> socket);
+  Ptr<Packet> m_receivedPacket;
+};
+
+Udp6SocketLoopbackTest::Udp6SocketLoopbackTest ()
+  : TestCase ("UDP6 loopback test") 
+{
+}
+
+void Udp6SocketLoopbackTest::ReceivePkt (Ptr<Socket> socket)
+{
+  uint32_t availableData;
+  availableData = socket->GetRxAvailable ();
+  m_receivedPacket = socket->Recv (std::numeric_limits<uint32_t>::max (), 0);
+  NS_ASSERT (availableData == m_receivedPacket->GetSize ());
+  //cast availableData to void, to suppress 'availableData' set but not used
+  //compiler warning
+  (void) availableData;
+}
+
+void
+Udp6SocketLoopbackTest::DoRun ()
+{
+  Ptr<Node> rxNode = CreateObject<Node> ();
+  AddInternetStack6 (rxNode);
+
+  Ptr<SocketFactory> rxSocketFactory = rxNode->GetObject<UdpSocketFactory> ();
+  Ptr<Socket> rxSocket = rxSocketFactory->CreateSocket ();
+  rxSocket->Bind (Inet6SocketAddress (Ipv6Address::GetAny (), 80));
+  rxSocket->SetRecvCallback (MakeCallback (&Udp6SocketLoopbackTest::ReceivePkt, this));
+
+  Ptr<Socket> txSocket = rxSocketFactory->CreateSocket ();
+  txSocket->SendTo (Create<Packet> (246), 0, Inet6SocketAddress ("::1", 80));
+  Simulator::Run ();
+  Simulator::Destroy ();
+  NS_TEST_EXPECT_MSG_EQ (m_receivedPacket->GetSize (), 246, "first socket should not receive it (it is bound specifically to the second interface's address");
+}
+
 class UdpSocketImplTest : public TestCase
 {
   Ptr<Packet> m_receivedPacket;
@@ -311,6 +385,190 @@
 
 }
 
+class Udp6SocketImplTest : public TestCase
+{
+  Ptr<Packet> m_receivedPacket;
+  Ptr<Packet> m_receivedPacket2;
+  void DoSendData (Ptr<Socket> socket, std::string to);
+  void SendData (Ptr<Socket> socket, std::string to);
+
+public:
+  virtual void DoRun (void);
+  Udp6SocketImplTest ();
+
+  void ReceivePacket (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from);
+  void ReceivePacket2 (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from);
+  void ReceivePkt (Ptr<Socket> socket);
+  void ReceivePkt2 (Ptr<Socket> socket);
+};
+
+Udp6SocketImplTest::Udp6SocketImplTest ()
+  : TestCase ("UDP6 socket implementation")
+{
+}
+
+void Udp6SocketImplTest::ReceivePacket (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from)
+{
+  m_receivedPacket = packet;
+}
+
+void Udp6SocketImplTest::ReceivePacket2 (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from)
+{
+  m_receivedPacket2 = packet;
+}
+
+void Udp6SocketImplTest::ReceivePkt (Ptr<Socket> socket)
+{
+  uint32_t availableData;
+  availableData = socket->GetRxAvailable ();
+  m_receivedPacket = socket->Recv (std::numeric_limits<uint32_t>::max (), 0);
+  NS_ASSERT (availableData == m_receivedPacket->GetSize ());
+  //cast availableData to void, to suppress 'availableData' set but not used
+  //compiler warning
+  (void) availableData;
+}
+
+void Udp6SocketImplTest::ReceivePkt2 (Ptr<Socket> socket)
+{
+  uint32_t availableData;
+  availableData = socket->GetRxAvailable ();
+  m_receivedPacket2 = socket->Recv (std::numeric_limits<uint32_t>::max (), 0);
+  NS_ASSERT (availableData == m_receivedPacket2->GetSize ());
+  //cast availableData to void, to suppress 'availableData' set but not used
+  //compiler warning
+  (void) availableData;
+}
+
+void
+Udp6SocketImplTest::DoSendData (Ptr<Socket> socket, std::string to)
+{
+  Address realTo = Inet6SocketAddress (Ipv6Address (to.c_str ()), 1234);
+  NS_TEST_EXPECT_MSG_EQ (socket->SendTo (Create<Packet> (123), 0, realTo),
+                         123, "XXX");
+}
+
+void
+Udp6SocketImplTest::SendData (Ptr<Socket> socket, std::string to)
+{
+  m_receivedPacket = Create<Packet> ();
+  m_receivedPacket2 = Create<Packet> ();
+  Simulator::ScheduleWithContext (socket->GetNode ()->GetId (), Seconds (0),
+                                  &Udp6SocketImplTest::DoSendData, this, socket, to);
+  Simulator::Run ();
+}
+
+void
+Udp6SocketImplTest::DoRun (void)
+{
+  // Create topology
+
+  // Receiver Node
+  Ptr<Node> rxNode = CreateObject<Node> ();
+  AddInternetStack6 (rxNode);
+  Ptr<SimpleNetDevice> rxDev1, rxDev2;
+  { // first interface
+    rxDev1 = CreateObject<SimpleNetDevice> ();
+    rxDev1->SetAddress (Mac48Address::ConvertFrom (Mac48Address::Allocate ()));
+    rxNode->AddDevice (rxDev1);
+    Ptr<Ipv6> ipv6 = rxNode->GetObject<Ipv6> ();
+    uint32_t netdev_idx = ipv6->AddInterface (rxDev1);
+    Ipv6InterfaceAddress ipv6Addr = Ipv6InterfaceAddress (Ipv6Address ("2001:0100::1"), Ipv6Prefix (64));
+    ipv6->AddAddress (netdev_idx, ipv6Addr);
+    ipv6->SetUp (netdev_idx);
+  }
+  { // second interface
+    rxDev2 = CreateObject<SimpleNetDevice> ();
+    rxDev2->SetAddress (Mac48Address::ConvertFrom (Mac48Address::Allocate ()));
+    rxNode->AddDevice (rxDev2);
+    Ptr<Ipv6> ipv6 = rxNode->GetObject<Ipv6> ();
+    uint32_t netdev_idx = ipv6->AddInterface (rxDev2);
+    Ipv6InterfaceAddress ipv6Addr = Ipv6InterfaceAddress (Ipv6Address ("2001:0100:1::1"), Ipv6Prefix (64));
+    ipv6->AddAddress (netdev_idx, ipv6Addr);
+    ipv6->SetUp (netdev_idx);
+  }
+
+  // Sender Node
+  Ptr<Node> txNode = CreateObject<Node> ();
+  AddInternetStack6 (txNode);
+  Ptr<SimpleNetDevice> txDev1;
+  {
+    txDev1 = CreateObject<SimpleNetDevice> ();
+    txDev1->SetAddress (Mac48Address::ConvertFrom (Mac48Address::Allocate ()));
+    txNode->AddDevice (txDev1);
+    Ptr<Ipv6> ipv6 = txNode->GetObject<Ipv6> ();
+    uint32_t netdev_idx = ipv6->AddInterface (txDev1);
+    Ipv6InterfaceAddress ipv6Addr = Ipv6InterfaceAddress (Ipv6Address ("2001:0100::2"), Ipv6Prefix (64));
+    ipv6->AddAddress (netdev_idx, ipv6Addr);
+    ipv6->SetUp (netdev_idx);
+  }
+  Ptr<SimpleNetDevice> txDev2;
+  {
+    txDev2 = CreateObject<SimpleNetDevice> ();
+    txDev2->SetAddress (Mac48Address::ConvertFrom (Mac48Address::Allocate ()));
+    txNode->AddDevice (txDev2);
+    Ptr<Ipv6> ipv6 = txNode->GetObject<Ipv6> ();
+    uint32_t netdev_idx = ipv6->AddInterface (txDev2);
+    Ipv6InterfaceAddress ipv6Addr = Ipv6InterfaceAddress (Ipv6Address ("2001:0100:1::2"), Ipv6Prefix (64));
+    ipv6->AddAddress (netdev_idx, ipv6Addr);
+    ipv6->SetUp (netdev_idx);
+  }
+
+  // link the two nodes
+  Ptr<SimpleChannel> channel1 = CreateObject<SimpleChannel> ();
+  rxDev1->SetChannel (channel1);
+  txDev1->SetChannel (channel1);
+
+  Ptr<SimpleChannel> channel2 = CreateObject<SimpleChannel> ();
+  rxDev2->SetChannel (channel2);
+  txDev2->SetChannel (channel2);
+
+
+  // Create the UDP sockets
+  Ptr<SocketFactory> rxSocketFactory = rxNode->GetObject<UdpSocketFactory> ();
+  Ptr<Socket> rxSocket = rxSocketFactory->CreateSocket ();
+  NS_TEST_EXPECT_MSG_EQ (rxSocket->Bind (Inet6SocketAddress (Ipv6Address ("2001:0100::1"), 1234)), 0, "trivial");
+  rxSocket->SetRecvCallback (MakeCallback (&Udp6SocketImplTest::ReceivePkt, this));
+
+  Ptr<Socket> rxSocket2 = rxSocketFactory->CreateSocket ();
+  rxSocket2->SetRecvCallback (MakeCallback (&Udp6SocketImplTest::ReceivePkt2, this));
+  NS_TEST_EXPECT_MSG_EQ (rxSocket2->Bind (Inet6SocketAddress (Ipv6Address ("2001:0100:1::1"), 1234)), 0, "trivial");
+
+  Ptr<SocketFactory> txSocketFactory = txNode->GetObject<UdpSocketFactory> ();
+  Ptr<Socket> txSocket = txSocketFactory->CreateSocket ();
+  txSocket->SetAllowBroadcast (true);
+  // ------ Now the tests ------------
+
+  // Unicast test
+  SendData (txSocket, "2001:0100::1");
+  NS_TEST_EXPECT_MSG_EQ (m_receivedPacket->GetSize (), 123, "trivial");
+  NS_TEST_EXPECT_MSG_EQ (m_receivedPacket2->GetSize (), 0, "second interface should receive it");
+
+  m_receivedPacket->RemoveAllByteTags ();
+  m_receivedPacket2->RemoveAllByteTags ();
+
+  // Simple Link-local multicast test
+
+  // When receiving broadcast packets, all sockets sockets bound to
+  // the address/port should receive a copy of the same packet -- if
+  // the socket address matches.
+  rxSocket2->Dispose ();
+  rxSocket2 = rxSocketFactory->CreateSocket ();
+  rxSocket2->SetRecvCallback (MakeCallback (&Udp6SocketImplTest::ReceivePkt2, this));
+  NS_TEST_EXPECT_MSG_EQ (rxSocket2->Bind (Inet6SocketAddress (Ipv6Address ("::"), 1234)), 0, "trivial");
+
+  txSocket->BindToNetDevice (txDev1);
+  SendData (txSocket, "ff02::1");
+  NS_TEST_EXPECT_MSG_EQ (m_receivedPacket->GetSize (), 0, "first socket should not receive it (it is bound specifically to the second interface's address");
+  NS_TEST_EXPECT_MSG_EQ (m_receivedPacket2->GetSize (), 123, "recv2: ff02::1");
+
+  m_receivedPacket->RemoveAllByteTags ();
+  m_receivedPacket2->RemoveAllByteTags ();
+
+  Simulator::Destroy ();
+
+}
+
+
 //-----------------------------------------------------------------------------
 class UdpTestSuite : public TestSuite
 {
@@ -319,6 +577,8 @@
   {
     AddTestCase (new UdpSocketImplTest);
     AddTestCase (new UdpSocketLoopbackTest);
+    AddTestCase (new Udp6SocketImplTest);
+    AddTestCase (new Udp6SocketLoopbackTest);
   }
 } g_udpTestSuite;
 
--- a/src/internet/wscript	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/internet/wscript	Mon Feb 20 14:05:07 2012 +0100
@@ -94,7 +94,7 @@
     # bridge and mpi dependencies are due to global routing
     obj = bld.create_ns3_module('internet', ['bridge', 'mpi', 'network', 'core'])
     obj.source = [
-        'model/ipv4-l4-protocol.cc',
+        'model/ip-l4-protocol.cc',
         'model/udp-header.cc',
         'model/tcp-header.cc',
         'model/ipv4-interface.cc',
@@ -122,7 +122,6 @@
         'model/ipv6-l3-protocol.cc',
         'model/ipv6-end-point.cc',
         'model/ipv6-end-point-demux.cc',
-        'model/ipv6-l4-protocol.cc',
         'model/ipv6-raw-socket-factory-impl.cc',
         'model/ipv6-raw-socket-impl.cc',
         'model/ipv6-autoconfigured-prefix.cc',
@@ -206,6 +205,7 @@
         'test/tcp-test.cc',
         'test/udp-test.cc',
         'test/ipv6-address-generator-test-suite.cc',
+        'test/ipv6-dual-stack-test-suite.cc',
         ]
 
     headers = bld.new_task_gen(features=['ns3header'])
@@ -226,11 +226,10 @@
         'model/udp-l4-protocol.h',
         'model/tcp-l4-protocol.h',
         'model/icmpv4-l4-protocol.h',
-        'model/ipv4-l4-protocol.h',
+        'model/ip-l4-protocol.h',
         'model/arp-header.h',
         'model/arp-cache.h',
         'model/icmpv6-l4-protocol.h',
-        'model/ipv6-l4-protocol.h',
         'model/ipv6-interface.h',
         'model/ndisc-cache.h',
         'model/loopback-net-device.h',
--- a/src/netanim/examples/star-animation.cc	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/netanim/examples/star-animation.cc	Mon Feb 20 14:05:07 2012 +0100
@@ -56,10 +56,14 @@
   //
   uint32_t nSpokes = 8;
   std::string animFile = "star-animation.xml";
+  uint8_t useIpv6 = 0;
+  Ipv6Address ipv6AddressBase = Ipv6Address("2001::");
+  Ipv6Prefix ipv6AddressPrefix = Ipv6Prefix(64);
 
   CommandLine cmd;
   cmd.AddValue ("nSpokes", "Number of spoke nodes to place in the star", nSpokes);
   cmd.AddValue ("animFile",  "File Name for Animation Output", animFile);
+  cmd.AddValue ("useIpv6",   "use Ipv6", useIpv6);
 
   cmd.Parse (argc, argv);
 
@@ -74,14 +78,29 @@
   star.InstallStack (internet);
 
   NS_LOG_INFO ("Assign IP Addresses.");
-  star.AssignIpv4Addresses (Ipv4AddressHelper ("10.1.1.0", "255.255.255.0"));
+  if (useIpv6 == 0)
+    {
+      star.AssignIpv4Addresses (Ipv4AddressHelper ("10.1.1.0", "255.255.255.0"));
+    }
+  else
+    {
+      star.AssignIpv6Addresses (ipv6AddressBase, ipv6AddressPrefix);
+    }
 
   NS_LOG_INFO ("Create applications.");
   //
   // Create a packet sink on the star "hub" to receive packets.
   // 
   uint16_t port = 50000;
-  Address hubLocalAddress (InetSocketAddress (Ipv4Address::GetAny (), port));
+  Address hubLocalAddress;
+  if (useIpv6 == 0)
+    {
+      hubLocalAddress = InetSocketAddress (Ipv4Address::GetAny (), port);
+    }
+  else
+    {
+      hubLocalAddress = Inet6SocketAddress (Ipv6Address::GetAny (), port);
+    }
   PacketSinkHelper packetSinkHelper ("ns3::TcpSocketFactory", hubLocalAddress);
   ApplicationContainer hubApp = packetSinkHelper.Install (star.GetHub ());
   hubApp.Start (Seconds (1.0));
@@ -98,7 +117,15 @@
 
   for (uint32_t i = 0; i < star.SpokeCount (); ++i)
     {
-      AddressValue remoteAddress (InetSocketAddress (star.GetHubIpv4Address (i), port));
+      AddressValue remoteAddress;
+      if (useIpv6 == 0)
+        {
+          remoteAddress = AddressValue(InetSocketAddress (star.GetHubIpv4Address (i), port));
+        }
+      else
+        {
+          remoteAddress = AddressValue(Inet6SocketAddress (star.GetHubIpv6Address (i), port));
+        }
       onOffHelper.SetAttribute ("Remote", remoteAddress);
       spokeApps.Add (onOffHelper.Install (star.GetSpokeNode (i)));
     }
@@ -109,7 +136,10 @@
   //
   // Turn on global static routing so we can actually be routed across the star.
   //
-  Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
+  if (useIpv6 == 0)
+    {
+      Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
+    }
 
   // Set the bounding box for animation
   star.BoundingBox (1, 1, 100, 100);
--- a/src/network/model/socket.h	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/network/model/socket.h	Mon Feb 20 14:05:07 2012 +0100
@@ -202,20 +202,25 @@
    */
   void SetRecvCallback (Callback<void, Ptr<Socket> >);
   /** 
+   * \brief Allocate a local endpoint for this socket.
    * \param address the address to try to allocate
    * \returns 0 on success, -1 on failure.
    *
-   * Allocate a local endpoint for this socket.
    */
   virtual int Bind (const Address &address) = 0;
 
   /** 
-   * Allocate a local endpoint for this socket.
-   *
+   * \brief Allocate a local IPv4 endpoint for this socket.
    * \returns 0 on success, -1 on failure.
    */
   virtual int Bind () = 0;
 
+  /**
+   * \brief Allocate a local IPv6 endpoint for this socket.
+   * \returns 0 on success, -1 on failure.
+   */
+  virtual int Bind6 () = 0;
+
   /** 
    * \brief Close a socket.
    * \returns zero on success, -1 on failure.
--- a/src/network/utils/ipv6-address.cc	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/network/utils/ipv6-address.cc	Mon Feb 20 14:05:07 2012 +0100
@@ -301,6 +301,24 @@
   return ipv6;
 }
 
+Ipv6Address Ipv6Address::MakeIpv4MappedAddress(Ipv4Address addr)
+{
+  uint8_t buf[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                      0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 };
+  addr.Serialize (&buf[12]);
+  return (Ipv6Address (buf));
+}
+
+Ipv4Address Ipv6Address::GetIpv4MappedAddress() const
+{
+    uint8_t buf[16];
+    Ipv4Address v4Addr;
+
+    Serialize (buf);
+    v4Addr = Ipv4Address::Deserialize (&buf[12]);
+    return (v4Addr);
+}
+
 Ipv6Address Ipv6Address::MakeAutoconfiguredAddress (Mac48Address addr, Ipv6Address prefix)
 {
   Ipv6Address ret;
@@ -398,6 +416,26 @@
   return false;
 }
 
+bool Ipv6Address::IsLinkLocalMulticast () const
+{
+  if (m_address[0] == 0xff && m_address[1] == 0x02)
+    {
+      return true;
+    }
+  return false;
+}
+
+bool Ipv6Address::IsIpv4MappedAddress ()
+{
+  uint8_t v4MappedPrefix[12] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                 0x00, 0x00, 0xff, 0xff };
+  if (memcmp(m_address, v4MappedPrefix, sizeof(v4MappedPrefix)) == 0)
+    {
+      return (true);
+    }
+  return (false);
+}
+
 Ipv6Address Ipv6Address::CombinePrefix (Ipv6Prefix const& prefix)
 {
   Ipv6Address ipv6;
--- a/src/network/utils/ipv6-address.h	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/network/utils/ipv6-address.h	Mon Feb 20 14:05:07 2012 +0100
@@ -28,6 +28,7 @@
 
 #include "ns3/attribute-helper.h"
 #include "ns3/address.h"
+#include "ns3/ipv4-address.h"
 
 namespace ns3 { 
 
@@ -122,6 +123,19 @@
   static Ipv6Address MakeSolicitedAddress (Ipv6Address addr);
 
   /**
+   * \brief Make the Ipv4-mapped IPv6 address.
+   * \param addr the IPv4 address
+   * \return Ipv4-mapped IPv6 address
+   */
+  static Ipv6Address MakeIpv4MappedAddress (Ipv4Address addr);
+
+  /**
+   * \brief Return the Ipv4 address.
+   * \return Ipv4 address
+   */
+  Ipv4Address GetIpv4MappedAddress () const;
+
+  /**
    * \brief Make the autoconfigured IPv6 address with Mac48Address.
    * \param addr the MAC address (48 bits).
    * \param prefix the IPv6 prefix
@@ -157,6 +171,12 @@
   bool IsMulticast () const;
 
   /**
+   * \brief If the IPv6 address is link-local multicast (ff02::/16).
+   * \return true if link-local multicast, false otherwise
+   */
+  bool IsLinkLocalMulticast () const;
+
+  /**
    * \brief If the IPv6 address is "all nodes multicast" (ff02::1/8).
    * \return true if "all nodes multicast", false otherwise
    */
@@ -208,6 +228,12 @@
   static bool IsMatchingType (const Address& address);
 
   /**
+   * \brief If the address is an IPv4-mapped address
+   * \return true if address is an IPv4-mapped address, otherwise false.
+   */
+  bool IsIpv4MappedAddress();
+
+  /**
    * \brief Convert to Address object
    */
   operator Address () const;
--- a/src/network/utils/packet-socket.cc	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/network/utils/packet-socket.cc	Mon Feb 20 14:05:07 2012 +0100
@@ -113,6 +113,12 @@
 }
 
 int
+PacketSocket::Bind6 (void)
+{
+  return(Bind());
+}
+
+int
 PacketSocket::Bind (const Address &address)
 { 
   NS_LOG_FUNCTION (this << address);
--- a/src/network/utils/packet-socket.h	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/network/utils/packet-socket.h	Mon Feb 20 14:05:07 2012 +0100
@@ -89,6 +89,7 @@
   virtual enum SocketType GetSocketType (void) const;
   virtual Ptr<Node> GetNode (void) const;
   virtual int Bind (void);
+  virtual int Bind6 (void);
   virtual int Bind (const Address & address);
   virtual int Close (void);
   virtual int ShutdownSend (void);
--- a/src/point-to-point-layout/model/point-to-point-dumbbell.cc	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/point-to-point-layout/model/point-to-point-dumbbell.cc	Mon Feb 20 14:05:07 2012 +0100
@@ -29,6 +29,7 @@
 #include "ns3/node-list.h"
 #include "ns3/point-to-point-net-device.h"
 #include "ns3/vector.h"
+#include "ns3/ipv6-address-generator.h"
 
 NS_LOG_COMPONENT_DEFINE ("PointToPointDumbbellHelper");
 
@@ -100,6 +101,16 @@
   return m_rightLeafInterfaces.GetAddress (i);
 }
 
+Ipv6Address PointToPointDumbbellHelper::GetLeftIpv6Address (uint32_t i) const
+{
+  return m_leftLeafInterfaces6.GetAddress (i, 1);
+}
+
+Ipv6Address PointToPointDumbbellHelper::GetRightIpv6Address (uint32_t i) const
+{
+  return m_rightLeafInterfaces6.GetAddress (i, 1);
+}
+
 uint32_t  PointToPointDumbbellHelper::LeftCount () const
 { // Number of left side nodes
   return m_leftLeaf.GetN ();
@@ -147,6 +158,52 @@
     }
 }
 
+void PointToPointDumbbellHelper::AssignIpv6Addresses (Ipv6Address addrBase, Ipv6Prefix prefix)
+{
+  // Assign the router network
+  Ipv6AddressGenerator::Init (addrBase, prefix);
+  Ipv6Address v6network;
+  Ipv6AddressHelper addressHelper;
+  
+  v6network = Ipv6AddressGenerator::GetNetwork (prefix);
+  addressHelper.NewNetwork (v6network, prefix);
+  m_routerInterfaces6 = addressHelper.Assign (m_routerDevices);
+  Ipv6AddressGenerator::NextNetwork (prefix);
+
+  // Assign to left side
+  for (uint32_t i = 0; i < LeftCount (); ++i)
+    {
+      v6network = Ipv6AddressGenerator::GetNetwork (prefix);
+      addressHelper.NewNetwork (v6network, prefix);
+
+      NetDeviceContainer ndc;
+      ndc.Add (m_leftLeafDevices.Get (i));
+      ndc.Add (m_leftRouterDevices.Get (i));
+      Ipv6InterfaceContainer ifc = addressHelper.Assign (ndc);
+      Ipv6InterfaceContainer::Iterator it = ifc.Begin ();
+      m_leftLeafInterfaces6.Add ((*it).first, (*it).second);
+      it++;
+      m_leftRouterInterfaces6.Add ((*it).first, (*it).second);
+      Ipv6AddressGenerator::NextNetwork (prefix);
+    }
+  // Assign to right side
+  for (uint32_t i = 0; i < RightCount (); ++i)
+    {
+      v6network = Ipv6AddressGenerator::GetNetwork (prefix);
+      addressHelper.NewNetwork (v6network, prefix);
+
+      NetDeviceContainer ndc;
+      ndc.Add (m_rightLeafDevices.Get (i));
+      ndc.Add (m_rightRouterDevices.Get (i));
+      Ipv6InterfaceContainer ifc = addressHelper.Assign (ndc);
+      Ipv6InterfaceContainer::Iterator it = ifc.Begin ();
+      m_rightLeafInterfaces6.Add ((*it).first, (*it).second);
+      it++;
+      m_rightRouterInterfaces6.Add ((*it).first, (*it).second);
+      Ipv6AddressGenerator::NextNetwork (prefix);
+    }
+}
+
 
 void PointToPointDumbbellHelper::BoundingBox (double ulx, double uly, // Upper left x/y
                                               double lrx, double lry) // Lower right y
--- a/src/point-to-point-layout/model/point-to-point-dumbbell.h	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/point-to-point-layout/model/point-to-point-dumbbell.h	Mon Feb 20 14:05:07 2012 +0100
@@ -25,8 +25,10 @@
 
 #include "point-to-point-helper.h"
 #include "ipv4-address-helper.h"
+#include "ipv6-address-helper.h"
 #include "internet-stack-helper.h"
 #include "ipv4-interface-container.h"
+#include "ipv6-interface-container.h"
 
 namespace ns3 {
 
@@ -101,6 +103,16 @@
   Ipv4Address GetRightIpv4Address (uint32_t i) const; // Get right leaf address
 
   /**
+   * \returns an Ipv6Address of the i'th left leaf
+   */
+  Ipv6Address GetLeftIpv6Address (uint32_t i ) const; // Get left leaf address
+
+  /**
+   * \returns an Ipv6Address of the i'th right leaf
+   */
+  Ipv6Address GetRightIpv6Address (uint32_t i) const; // Get right leaf address
+
+  /**
    * \returns total number of left side leaf nodes
    */
   uint32_t  LeftCount () const;
@@ -131,6 +143,13 @@
                                  Ipv4AddressHelper routerIp);
 
   /**
+   * \param network an IPv6 address representing the network portion
+   *                of the IPv6 Address
+   * \param prefix the prefix length
+   */
+  void      AssignIpv6Addresses (Ipv6Address network, Ipv6Prefix prefix);
+
+  /**
    * Sets up the node canvas locations for every node in the dumbbell.
    * This is needed for use with the animation interface
    *
@@ -155,6 +174,11 @@
   Ipv4InterfaceContainer m_rightLeafInterfaces;
   Ipv4InterfaceContainer m_rightRouterInterfaces;
   Ipv4InterfaceContainer m_routerInterfaces;
+  Ipv6InterfaceContainer m_leftLeafInterfaces6;
+  Ipv6InterfaceContainer m_leftRouterInterfaces6;
+  Ipv6InterfaceContainer m_rightLeafInterfaces6;
+  Ipv6InterfaceContainer m_rightRouterInterfaces6;
+  Ipv6InterfaceContainer m_routerInterfaces6;
 };
 
 } // namespace ns3
--- a/src/point-to-point-layout/model/point-to-point-grid.cc	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/point-to-point-layout/model/point-to-point-grid.cc	Mon Feb 20 14:05:07 2012 +0100
@@ -24,6 +24,7 @@
 #include "ns3/string.h"
 #include "ns3/vector.h"
 #include "ns3/log.h"
+#include "ns3/ipv6-address-generator.h"
 
 NS_LOG_COMPONENT_DEFINE ("PointToPointGridHelper");
 
@@ -131,6 +132,56 @@
 }
 
 void
+PointToPointGridHelper::AssignIpv6Addresses(Ipv6Address addrBase, Ipv6Prefix prefix)
+{
+  Ipv6AddressGenerator::Init(addrBase, prefix);
+  Ipv6Address v6network;
+  Ipv6AddressHelper addrHelper;
+
+  // Assign addresses to all row devices in the grid.
+  // These devices are stored in a vector.  Each row 
+  // of the grid has all the row devices in one entry 
+  // of the vector.  These entries come in pairs.
+  for (uint32_t i = 0; i < m_rowDevices.size (); ++i)
+    {
+      Ipv6InterfaceContainer rowInterfaces; 
+      NetDeviceContainer rowContainer = m_rowDevices[i];
+      for (uint32_t j = 0; j < rowContainer.GetN (); j+=2)
+        {
+          v6network = Ipv6AddressGenerator::GetNetwork (prefix);
+          addrHelper.NewNetwork(v6network, prefix);
+          Ipv6InterfaceContainer ic = addrHelper.Assign (rowContainer.Get (j));
+          rowInterfaces.Add (ic);
+          ic = addrHelper.Assign (rowContainer.Get (j+1));
+          rowInterfaces.Add (ic);
+          Ipv6AddressGenerator::NextNetwork (prefix);
+        }
+      m_rowInterfaces6.push_back (rowInterfaces);
+    }
+
+  // Assign addresses to all col devices in the grid.
+  // These devices are stored in a vector.  Each col 
+  // of the grid has all the col devices in one entry 
+  // of the vector.  These entries come in pairs.
+  for (uint32_t i = 0; i < m_colDevices.size (); ++i)
+    {
+      Ipv6InterfaceContainer colInterfaces; 
+      NetDeviceContainer colContainer = m_colDevices[i];
+      for (uint32_t j = 0; j < colContainer.GetN (); j+=2)
+        {
+          v6network = Ipv6AddressGenerator::GetNetwork (prefix);
+          addrHelper.NewNetwork(v6network, prefix);
+          Ipv6InterfaceContainer ic = addrHelper.Assign (colContainer.Get (j));
+          colInterfaces.Add (ic);
+          ic = addrHelper.Assign (colContainer.Get (j+1));
+          colInterfaces.Add (ic);
+          Ipv6AddressGenerator::NextNetwork (prefix);
+        }
+      m_colInterfaces6.push_back (colInterfaces);
+    }
+}
+
+void
 PointToPointGridHelper::BoundingBox (double ulx, double uly,
                                      double lrx, double lry)
 {
@@ -214,4 +265,30 @@
     }
 }
 
+Ipv6Address
+PointToPointGridHelper::GetIpv6Address (uint32_t row, uint32_t col)
+{
+  if (row > m_nodes.size () - 1 ||
+      col > m_nodes.at (row).GetN () - 1)
+    {
+      NS_FATAL_ERROR ("Index out of bounds in PointToPointGridHelper::GetIpv4Address.");
+    }
+
+  // Right now this just gets one of the addresses of the
+  // specified node.  The exact device can't be specified.
+  // If you picture the grid, the address returned is the
+  // address of the left (row) device of all nodes, with
+  // the exception of the left-most nodes in the grid;
+  // in which case the right (row) device address is
+  // returned
+  if (col == 0)
+    {
+      return (m_rowInterfaces6.at (row)).GetAddress (0, 1);
+    }
+  else
+    {
+      return (m_rowInterfaces6.at (row)).GetAddress ((2*col)-1, 1);
+    }
+}
+
 } // namespace ns3
--- a/src/point-to-point-layout/model/point-to-point-grid.h	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/point-to-point-layout/model/point-to-point-grid.h	Mon Feb 20 14:05:07 2012 +0100
@@ -24,7 +24,9 @@
 #include "internet-stack-helper.h"
 #include "point-to-point-helper.h"
 #include "ipv4-address-helper.h"
+#include "ipv6-address-helper.h"
 #include "ipv4-interface-container.h"
+#include "ipv6-interface-container.h"
 #include "net-device-container.h"
 
 namespace ns3 {
@@ -85,6 +87,24 @@
   Ipv4Address GetIpv4Address (uint32_t row, uint32_t col);
 
   /**
+   * This returns an Ipv6 address at the node specified by 
+   * the (row, col) address.  Technically, a node will have 
+   * multiple interfaces in the grid; therefore, it also has 
+   * multiple Ipv6 addresses.  This method only returns one of 
+   * the addresses. If you picture the grid, the address returned 
+   * is the left row device of all the nodes, except the left-most 
+   * grid nodes, which returns the right row device.
+   *
+   * \param row the row address of the node desired
+   *
+   * \param col the column address of the node desired
+   *
+   * \returns Ipv6Address of one of the interfaces of the node 
+   *          specified by the (row, col) address
+   */
+  Ipv6Address GetIpv6Address (uint32_t row, uint32_t col);
+
+  /**
    * \param stack an InternetStackHelper which is used to install 
    *              on every node in the grid
    */
@@ -102,6 +122,15 @@
   void AssignIpv4Addresses (Ipv4AddressHelper rowIp, Ipv4AddressHelper colIp);
 
   /**
+   * Assigns Ipv6 addresses to all the row and column interfaces
+   *
+   * \param network an IPv6 address representing the network portion
+   *                of the IPv6 Address
+   * \param prefix the prefix length
+   */
+  void AssignIpv6Addresses (Ipv6Address network, Ipv6Prefix prefix);
+
+  /**
    * Sets up the node canvas locations for every node in the grid.
    * This is needed for use with the animation interface
    *
@@ -119,6 +148,8 @@
   std::vector<NetDeviceContainer> m_colDevices;
   std::vector<Ipv4InterfaceContainer> m_rowInterfaces;
   std::vector<Ipv4InterfaceContainer> m_colInterfaces;
+  std::vector<Ipv6InterfaceContainer> m_rowInterfaces6;
+  std::vector<Ipv6InterfaceContainer> m_colInterfaces6;
   std::vector<NodeContainer> m_nodes;
 };
 
--- a/src/point-to-point-layout/model/point-to-point-star.cc	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/point-to-point-layout/model/point-to-point-star.cc	Mon Feb 20 14:05:07 2012 +0100
@@ -25,6 +25,7 @@
 #include "ns3/node-list.h"
 #include "ns3/point-to-point-net-device.h"
 #include "ns3/vector.h"
+#include "ns3/ipv6-address-generator.h"
 
 NS_LOG_COMPONENT_DEFINE ("PointToPointStarHelper");
 
@@ -72,6 +73,18 @@
   return m_spokeInterfaces.GetAddress (i);
 }
 
+Ipv6Address
+PointToPointStarHelper::GetHubIpv6Address (uint32_t i) const
+{
+  return m_hubInterfaces6.GetAddress (i, 1);
+}
+
+Ipv6Address
+PointToPointStarHelper::GetSpokeIpv6Address (uint32_t i) const
+{
+  return m_spokeInterfaces6.GetAddress (i, 1);
+}
+
 uint32_t
 PointToPointStarHelper::SpokeCount () const
 {
@@ -97,6 +110,27 @@
 }
 
 void 
+PointToPointStarHelper::AssignIpv6Addresses (Ipv6Address addrBase, Ipv6Prefix prefix)
+{
+  Ipv6AddressGenerator::Init (addrBase, prefix);
+  Ipv6Address v6network;
+  Ipv6AddressHelper addressHelper;
+
+  for (uint32_t i = 0; i < m_spokes.GetN (); ++i)
+    {
+      v6network = Ipv6AddressGenerator::GetNetwork (prefix);
+      addressHelper.NewNetwork(v6network, prefix);
+
+      Ipv6InterfaceContainer ic = addressHelper.Assign (m_hubDevices.Get (i));
+      m_hubInterfaces6.Add (ic);
+      ic = addressHelper.Assign (m_spokeDevices.Get (i));
+      m_spokeInterfaces6.Add (ic);
+
+      Ipv6AddressGenerator::NextNetwork (prefix);
+    }
+}
+
+void 
 PointToPointStarHelper::BoundingBox (double ulx, double uly,
                                      double lrx, double lry)
 {
--- a/src/point-to-point-layout/model/point-to-point-star.h	Sun Feb 19 16:22:51 2012 +0100
+++ b/src/point-to-point-layout/model/point-to-point-star.h	Mon Feb 20 14:05:07 2012 +0100
@@ -23,8 +23,10 @@
 
 #include "point-to-point-helper.h"
 #include "ipv4-address-helper.h"
+#include "ipv6-address-helper.h"
 #include "internet-stack-helper.h"
 #include "ipv4-interface-container.h"
+#include "ipv6-interface-container.h"
 
 namespace ns3 {
 
@@ -87,6 +89,20 @@
   Ipv4Address GetSpokeIpv4Address (uint32_t i) const;
 
   /**
+   * \param i index into the hub interfaces
+   *
+   * \returns Ipv6Address according to indexed hub interface
+   */
+  Ipv6Address GetHubIpv6Address (uint32_t i) const;
+
+  /**
+   * \param i index into the spoke interfaces
+   *
+   * \returns Ipv6Address according to indexed spoke interface
+   */
+  Ipv6Address GetSpokeIpv6Address (uint32_t i) const;
+
+  /**
    * \returns the total number of spokes in the star
    */
   uint32_t SpokeCount () const;
@@ -105,6 +121,13 @@
   void AssignIpv4Addresses (Ipv4AddressHelper address);
 
   /**
+   * \param network an IPv6 address representing the network portion
+   *                of the IPv6 Address
+   * \param prefix the prefix length
+   */
+  void AssignIpv6Addresses (Ipv6Address network, Ipv6Prefix prefix);
+
+  /**
    * Sets up the node canvas locations for every node in the star. 
    * This is needed for use with the animation interface
    *
@@ -122,6 +145,8 @@
   NetDeviceContainer m_spokeDevices;
   Ipv4InterfaceContainer m_hubInterfaces;
   Ipv4InterfaceContainer m_spokeInterfaces;
+  Ipv6InterfaceContainer m_hubInterfaces6;
+  Ipv6InterfaceContainer m_spokeInterfaces6;
 };
 
 } // namespace ns3