merge nsc phase one
authorCraig Dowell <craigdo@ee.washington.edu>
Tue, 02 Sep 2008 10:39:45 -0700
changeset 3581 048d80fcffde
parent 3576 f6abfdf47163 (current diff)
parent 3580 5818912ae9a3 (diff)
child 3583 b6cf80679b72
merge nsc phase one
examples/wscript
src/wscript
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/tcp-nsc-lfn.cc	Tue Sep 02 10:39:45 2008 -0700
@@ -0,0 +1,145 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * 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
+ *
+ */
+
+//
+// Network topology
+//
+//           6Mb/s, 500ms
+//       n0-----------------n1
+//
+// - a 'lossy' network with long delay
+// - TCP flow from n0 to n1 and from n1 to n0
+// - pcap traces generated as tcp-nsc-lfn-0-0.pcap and tcp-nsc-lfn-1-0.pcap
+//  Usage (e.g.): ./waf --run 'tcp-nsc-lfn --TCP_CONGESTION=hybla --runtime=30'
+
+#include <ctype.h>
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <cassert>
+
+#include "ns3/core-module.h"
+#include "ns3/common-module.h"
+#include "ns3/helper-module.h"
+#include "ns3/node-module.h"
+#include "ns3/global-route-manager.h"
+#include "ns3/simulator-module.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE ("TcpNscLfn");
+
+
+int main (int argc, char *argv[])
+{
+  RandomVariable::UseGlobalSeed (1, 1, 2, 3, 5, 8);
+
+  Config::SetDefault ("ns3::OnOffApplication::PacketSize", UintegerValue (4096));
+  Config::SetDefault ("ns3::OnOffApplication::DataRate", StringValue ("6Mbps"));
+
+  // cubic is the default congestion algorithm in Linux 2.6.26
+  std::string tcpCong = "cubic";
+  // this is the default error rate of our link, that is, the the probability of a single
+  // byte being 'corrupted' during transfer.
+  double errRate = 0.000001;
+  // how long the sender should be running, in seconds.
+  unsigned int runtime = 120;
+  // the name of the NSC stack library that should be used
+  std::string nscStack = "liblinux2.6.26.so";
+
+  CommandLine cmd;
+  // Here, we define additional command line options.
+  // This allows a user to override the defaults set above from the command line.
+  cmd.AddValue("TCP_CONGESTION", "Linux 2.6.26 Tcp Congestion control algorithm to use", tcpCong);
+  cmd.AddValue("error-rate", "Error rate to apply to link", errRate);
+  cmd.AddValue("runtime", "How long the applications should send data (default 120 seconds)", runtime);
+  cmd.AddValue("nscstack", "Set name of NSC stack (shared library) to use (default liblinux2.6.26.so)", nscStack);
+  cmd.Parse (argc, argv);
+
+  NodeContainer n;
+  n.Create (2);
+
+  PointToPointHelper p2p;
+  // create point-to-point link with a bandwidth of 6MBit/s and a large delay (0.5 seconds)
+  p2p.SetDeviceAttribute ("DataRate", DataRateValue (DataRate(6 * 1000 * 1000)));
+  p2p.SetChannelAttribute ("Delay", TimeValue (MilliSeconds(500)));
+
+  NetDeviceContainer p2pInterfaces = p2p.Install (n);
+  // The default MTU of the p2p link would be 65535, which doesn't work
+  // well with our default errRate (most packets would arrive corrupted).
+  p2pInterfaces.Get(0)->SetMtu(1500);
+  p2pInterfaces.Get(1)->SetMtu(1500);
+
+  InternetStackHelper internet;
+  // The next statement switches the nodes to 'NSC'-Mode.
+  // It disables the native ns-3 TCP model and loads the NSC library.
+  internet.SetNscStack (nscStack);
+  internet.Install (n);
+
+  if (tcpCong != "cubic") // make sure we only fail if both --nscstack and --TCP_CONGESTION are used
+    {
+      // This uses ns-3s attribute system to set the 'net.ipv4.tcp_congestion_control' sysctl of the
+      // stack.
+      // The same mechanism could be used to e.g. disable TCP timestamps:
+      // Config::Set ("/NodeList/*/$ns3::Ns3NscStack<linux2.6.26>/net.ipv4.tcp_timestamps", StringValue ("0"));
+      Config::Set ("/NodeList/*/$ns3::Ns3NscStack<linux2.6.26>/net.ipv4.tcp_congestion_control", StringValue (tcpCong));
+    }
+  Ipv4AddressHelper ipv4;
+  ipv4.SetBase ("10.0.0.0", "255.255.255.0");
+  Ipv4InterfaceContainer ipv4Interfaces = ipv4.Assign (p2pInterfaces);
+
+  DoubleValue rate(errRate);
+  RandomVariableValue u01(UniformVariable (0.0, 1.0));
+  Ptr<RateErrorModel> em1 = 
+      CreateObject<RateErrorModel> ("RanVar", u01, "ErrorRate", rate);
+  Ptr<RateErrorModel> em2 = 
+      CreateObject<RateErrorModel> ("RanVar", u01, "ErrorRate", rate);
+
+  // This enables the specified errRate on both link endpoints.
+  p2pInterfaces.Get(0)->SetAttribute("ReceiveErrorModel", PointerValue (em1));
+  p2pInterfaces.Get(1)->SetAttribute("ReceiveErrorModel", PointerValue (em2));
+
+  GlobalRouteManager::PopulateRoutingTables ();
+
+  uint16_t servPort = 8080;
+  PacketSinkHelper sinkHelper ("ns3::TcpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), servPort));
+  ApplicationContainer sinkApp = sinkHelper.Install (n);
+  sinkApp.Start (Seconds (0.0));
+  // this makes sure that the receiver will run one minute longer than the sender applicaton.
+  sinkApp.Stop (Seconds (runtime + 60.0));
+
+  // This sets up two TCP flows, one from A -> B, one from B -> A.
+  for (int i = 0, j = 1; i < 2; j--, i++)
+   {
+      Address remoteAddress(InetSocketAddress(ipv4Interfaces.GetAddress (i), servPort));
+      OnOffHelper clientHelper ("ns3::TcpSocketFactory", remoteAddress);
+      clientHelper.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
+      clientHelper.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
+      ApplicationContainer clientApp = clientHelper.Install(n.Get(j));
+      clientApp.Start (Seconds (1.0 + i));
+      clientApp.Stop (Seconds (runtime + 1.0 + i));
+    }
+
+  // This tells ns-3 to generate pcap traces.
+  PointToPointHelper::EnablePcapAll ("tcp-nsc-lfn");
+
+  Simulator::Stop (Seconds(900));
+  Simulator::Run ();
+  Simulator::Destroy ();
+
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/tcp-nsc-zoo.cc	Tue Sep 02 10:39:45 2008 -0700
@@ -0,0 +1,131 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * 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
+ *
+ */
+
+
+// Network topology
+//
+//       n0    n1   n2   n3
+//       |     |    |    |
+//       =================
+//              LAN
+//
+// - Pcap traces are saved as tcp-nsc-zoo-$n-0.pcap, where $n represents the node number
+// - TCP flows from n0 to n1, n2, n3, from n1 to n0, n2, n3, etc.
+//  Usage (e.g.): ./waf --run 'tcp-nsc-zoo --Nodes=5'
+
+#include <iostream>
+#include <string>
+
+#include "ns3/core-module.h"
+#include "ns3/helper-module.h"
+#include "ns3/node-module.h"
+#include "ns3/global-route-manager.h"
+#include "ns3/simulator-module.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE ("TcpNscZoo");
+
+// Simulates a diverse network with various stacks supported by NSC.
+int main(int argc, char *argv[])
+{
+  CsmaHelper csma;
+  unsigned int MaxNodes = 4;
+
+  Config::SetDefault ("ns3::OnOffApplication::PacketSize", UintegerValue (4096));
+  Config::SetDefault ("ns3::OnOffApplication::DataRate", StringValue ("1Mb/s"));
+  CommandLine cmd;
+  // this allows the user to raise the number of nodes using --Nodes=X command-line argument.
+  cmd.AddValue("Nodes", "Number of nodes in the network", MaxNodes);
+  cmd.Parse (argc, argv);
+
+  csma.SetChannelAttribute ("DataRate", DataRateValue (DataRate(100 * 1000 * 1000)));
+  csma.SetChannelAttribute ("Delay", TimeValue (MicroSeconds (200)));
+
+  NodeContainer n;
+  n.Create(MaxNodes);
+  NetDeviceContainer ethInterfaces = csma.Install (n);
+
+  InternetStackHelper internetStack;
+
+  internetStack.SetNscStack ("liblinux2.6.26.so");
+  // this switches nodes 0 and 1 to NSCs Linux 2.6.26 stack.
+  internetStack.Install (n.Get(0));
+  internetStack.Install (n.Get(1));
+  // this disables TCP SACK, wscale and timestamps on node 1 (the attributes represent sysctl-values).
+  Config::Set ("/NodeList/1/$ns3::Ns3NscStack<linux2.6.26>/net.ipv4.tcp_sack", StringValue ("0"));
+  Config::Set ("/NodeList/1/$ns3::Ns3NscStack<linux2.6.26>/net.ipv4.tcp_timestamps", StringValue ("0"));
+  Config::Set ("/NodeList/1/$ns3::Ns3NscStack<linux2.6.26>/net.ipv4.tcp_window_scaling", StringValue ("0"));
+  internetStack.Install (n.Get(2));
+  // the next statement doesn't change anything for the nodes 0, 1, and 2; since they
+  // already have a stack assigned.
+  internetStack.SetNscStack ("liblinux2.6.18.so");
+  // this switches node 3 to NSCs Linux 2.6.18 stack.
+  internetStack.Install (n.Get(3));
+  // and then agains disables sack/timestamps/wscale on node 3.
+  Config::Set ("/NodeList/3/$ns3::Ns3NscStack<linux2.6.18>/net.ipv4.tcp_sack", StringValue ("0"));
+  Config::Set ("/NodeList/3/$ns3::Ns3NscStack<linux2.6.18>/net.ipv4.tcp_timestamps", StringValue ("0"));
+  Config::Set ("/NodeList/3/$ns3::Ns3NscStack<linux2.6.18>/net.ipv4.tcp_window_scaling", StringValue ("0"));
+  // the freebsd stack is not yet built by default, so its commented out for now.
+  // internetStack.SetNscStack ("libfreebsd5.so");
+  for (unsigned int i =4; i < MaxNodes; i++)
+    {
+      internetStack.Install (n.Get(i));
+    }
+  Ipv4AddressHelper ipv4;
+
+  ipv4.SetBase ("10.0.0.0", "255.255.255.0");
+  Ipv4InterfaceContainer ipv4Interfaces = ipv4.Assign (ethInterfaces);
+
+  GlobalRouteManager::PopulateRoutingTables ();
+
+  uint16_t servPort = 8080;
+  PacketSinkHelper sinkHelper ("ns3::TcpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), servPort));
+  // start a sink client on all nodes
+  ApplicationContainer sinkApp = sinkHelper.Install (n);
+  sinkApp.Start (Seconds (1.0));
+  sinkApp.Stop (Seconds (30.0));
+
+  // This tells every node on the network to start a flow to all other nodes on the network ...
+  for (unsigned int i = 0 ; i < MaxNodes;i++)
+    {
+      for (unsigned int j = 0 ; j < MaxNodes;j++)
+        {
+          if (i == j)
+            {  // ...but we don't want a node to talk to itself.
+               continue;
+            }
+          Address remoteAddress(InetSocketAddress(ipv4Interfaces.GetAddress (j), servPort));
+          OnOffHelper clientHelper ("ns3::TcpSocketFactory", remoteAddress);
+          clientHelper.SetAttribute 
+            ("OnTime", RandomVariableValue (ConstantVariable (1)));
+          clientHelper.SetAttribute 
+            ("OffTime", RandomVariableValue (ConstantVariable (0)));
+          ApplicationContainer clientApp = clientHelper.Install(n.Get(i));
+          clientApp.Start (Seconds (j + 1.0)); /* delay startup depending on node number */
+          clientApp.Stop (Seconds (j + 10.0));
+	}
+    }
+
+  CsmaHelper::EnablePcapAll ("tcp-nsc-zoo");
+
+  Simulator::Stop (Seconds(1000));
+  Simulator::Run ();
+  Simulator::Destroy ();
+
+  return 0;
+}
--- a/examples/wscript	Tue Sep 02 10:12:14 2008 -0700
+++ b/examples/wscript	Tue Sep 02 10:39:45 2008 -0700
@@ -64,6 +64,14 @@
         ['point-to-point', 'internet-stack'])
     obj.source = 'tcp-errors.cc'
 
+    obj = bld.create_ns3_program('tcp-nsc-lfn',
+      ['point-to-point', 'internet-stack'])
+    obj.source = 'tcp-nsc-lfn.cc'
+
+    obj = bld.create_ns3_program('tcp-nsc-zoo',
+      ['csma', 'internet-stack'])
+    obj.source = 'tcp-nsc-zoo.cc'
+
     obj = bld.create_ns3_program('tcp-star-server',
         ['point-to-point', 'internet-stack'])
     obj.source = 'tcp-star-server.cc'
--- a/src/helper/internet-stack-helper.cc	Tue Sep 02 10:12:14 2008 -0700
+++ b/src/helper/internet-stack-helper.cc	Tue Sep 02 10:39:45 2008 -0700
@@ -33,6 +33,10 @@
 std::vector<InternetStackHelper::Trace> InternetStackHelper::m_traces;
 std::string InternetStackHelper::m_pcapBaseFilename;
 
+InternetStackHelper::InternetStackHelper() : m_nscLibrary("")
+{
+}
+
 void
 InternetStackHelper::Cleanup (void)
 {
@@ -48,6 +52,12 @@
   m_traces.clear ();
 }
 
+void
+InternetStackHelper::SetNscStack(const std::string soname)
+{
+  m_nscLibrary = soname;
+}
+
 void 
 InternetStackHelper::Install (NodeContainer c)
 {
@@ -59,8 +69,12 @@
           NS_FATAL_ERROR ("InternetStackHelper::Install(): Aggregating " 
              "an InternetStack to a node with an existing Ipv4 object");
           return;
-        } 
-      AddInternetStack (node);
+        }
+      if (m_nscLibrary != "")
+        AddNscInternetStack (node, m_nscLibrary);
+      else
+        AddInternetStack (node);
+
       Ptr<PacketSocketFactory> factory = CreateObject<PacketSocketFactory> ();
       node->AggregateObject (factory);
     }
--- a/src/helper/internet-stack-helper.h	Tue Sep 02 10:12:14 2008 -0700
+++ b/src/helper/internet-stack-helper.h	Tue Sep 02 10:39:45 2008 -0700
@@ -33,6 +33,8 @@
 class InternetStackHelper
 {
 public:
+  InternetStackHelper(void);
+
   /**
    * \param c the set of nodes
    *
@@ -45,6 +47,13 @@
   void Install (NodeContainer c);
 
   /**
+   * \param soname name of the shared library with the nsc tcp stack
+   * to use, e.g. 'liblinux2.6.26.so'. The empty string resets
+   * the InternetStackHelper to use the ns-3 models again.
+   */
+  void SetNscStack(std::string soname);
+
+  /**
    * \param filename filename prefix to use for pcap files.
    *
    * Enable pcap output on each protocol instance which is of the
@@ -60,6 +69,7 @@
   static void EnablePcapAll (std::string filename);
 
 private:
+  std::string m_nscLibrary;
   static void Cleanup (void);
   static void LogRxIp (std::string context, Ptr<const Packet> packet, uint32_t deviceId);
   static void LogTxIp (std::string context, Ptr<const Packet> packet, uint32_t deviceId);
--- a/src/internet-stack/internet-stack.cc	Tue Sep 02 10:12:14 2008 -0700
+++ b/src/internet-stack/internet-stack.cc	Tue Sep 02 10:39:45 2008 -0700
@@ -21,6 +21,7 @@
 #include "ns3/net-device.h"
 #include "ns3/callback.h"
 #include "ns3/node.h"
+#include "ns3/core-config.h"
 
 #include "ipv4-l4-demux.h"
 #include "udp-l4-protocol.h"
@@ -31,41 +32,105 @@
 #include "tcp-socket-factory-impl.h"
 #include "ipv4-impl.h"
 
+#ifdef NETWORK_SIMULATION_CRADLE
+#include "nsc-tcp-socket-factory-impl.h"
+#include "nsc-tcp-l4-protocol.h"
+#endif
+
 namespace ns3 {
 
-void 
+static void
+AddArpStack (Ptr<Node> node)
+{
+  Ptr<ArpL3Protocol> arp = CreateObject<ArpL3Protocol> ();
+  arp->SetNode (node);
+  node->AggregateObject (arp);
+}
+
+static void
+AddUdpStack(Ptr<Node> node, Ptr<Ipv4L4Demux> ipv4L4Demux)
+{
+  Ptr<UdpL4Protocol> udp = CreateObject<UdpL4Protocol> ();
+  udp->SetNode (node);
+  ipv4L4Demux->Insert (udp);
+  Ptr<UdpSocketFactoryImpl> udpFactory = CreateObject<UdpSocketFactoryImpl> ();
+  udpFactory->SetUdp (udp);
+  node->AggregateObject (udpFactory);
+}
+
+static void
+AddTcpStack(Ptr<Node> node, Ptr<Ipv4L4Demux> ipv4L4Demux)
+{
+  Ptr<TcpL4Protocol> tcp = CreateObject<TcpL4Protocol> ();
+  tcp->SetNode (node);
+  ipv4L4Demux->Insert (tcp);
+  Ptr<TcpSocketFactoryImpl> tcpFactory = CreateObject<TcpSocketFactoryImpl> ();
+  tcpFactory->SetTcp (tcp);
+  node->AggregateObject (tcpFactory);
+}
+
+static void
+AddIpv4Impl(Ptr<Node> node, Ptr<Ipv4L3Protocol> ipv4)
+{
+  Ptr<Ipv4Impl> ipv4Impl = CreateObject<Ipv4Impl> ();
+  ipv4Impl->SetIpv4 (ipv4);
+  node->AggregateObject (ipv4);
+  node->AggregateObject (ipv4Impl);
+}
+
+void
 AddInternetStack (Ptr<Node> node)
 {
+  AddArpStack(node);
   Ptr<Ipv4L3Protocol> ipv4 = CreateObject<Ipv4L3Protocol> ();
-  Ptr<ArpL3Protocol> arp = CreateObject<ArpL3Protocol> ();
   ipv4->SetNode (node);
-  arp->SetNode (node);
 
   Ptr<Ipv4L4Demux> ipv4L4Demux = CreateObject<Ipv4L4Demux> ();
-  Ptr<UdpL4Protocol> udp = CreateObject<UdpL4Protocol> ();
-  Ptr<TcpL4Protocol> tcp = CreateObject<TcpL4Protocol> ();
-
   ipv4L4Demux->SetNode (node);
-  udp->SetNode (node);
-  tcp->SetNode (node);
-
-  ipv4L4Demux->Insert (udp);
-  ipv4L4Demux->Insert (tcp);
 
-  Ptr<UdpSocketFactoryImpl> udpFactory = CreateObject<UdpSocketFactoryImpl> ();
-  Ptr<TcpSocketFactoryImpl> tcpFactory = CreateObject<TcpSocketFactoryImpl> ();
-  Ptr<Ipv4Impl> ipv4Impl = CreateObject<Ipv4Impl> ();
+  AddUdpStack (node, ipv4L4Demux);
+  AddTcpStack (node, ipv4L4Demux);
 
-  udpFactory->SetUdp (udp);
-  tcpFactory->SetTcp (tcp);
-  ipv4Impl->SetIpv4 (ipv4);
-
-  node->AggregateObject (ipv4);
-  node->AggregateObject (arp);
-  node->AggregateObject (ipv4Impl);
-  node->AggregateObject (udpFactory);
-  node->AggregateObject (tcpFactory);
+  AddIpv4Impl (node, ipv4);
   node->AggregateObject (ipv4L4Demux);
 }
 
+
+#ifdef NETWORK_SIMULATION_CRADLE
+static void
+AddNscStack(Ptr<Node> node, Ptr<Ipv4L4Demux> ipv4L4Demux, const std::string &soname)
+{
+  Ptr<NscTcpL4Protocol> tcp = CreateObject<NscTcpL4Protocol> ();
+  tcp->SetNscLibrary(soname);
+  tcp->SetNode (node);
+  ipv4L4Demux->Insert (tcp);
+  Ptr<NscTcpSocketFactoryImpl> tcpFactory = CreateObject<NscTcpSocketFactoryImpl> ();
+  tcpFactory->SetTcp (tcp);
+  node->AggregateObject (tcpFactory);
+}
+
+
+void
+AddNscInternetStack (Ptr<Node> node, const std::string &soname)
+{
+  AddArpStack(node);
+  Ptr<Ipv4L3Protocol> ipv4 = CreateObject<Ipv4L3Protocol> ();
+  ipv4->SetNode (node);
+
+  Ptr<Ipv4L4Demux> ipv4L4Demux = CreateObject<Ipv4L4Demux> ();
+  ipv4L4Demux->SetNode (node);
+
+  AddUdpStack (node, ipv4L4Demux);
+  AddNscStack (node, ipv4L4Demux, soname);
+
+  AddIpv4Impl (node, ipv4);
+  node->AggregateObject (ipv4L4Demux);
+}
+#else
+void
+AddNscInternetStack (Ptr<Node> node, const std::string &soname)
+{
+  NS_ASSERT_MSG(false, "ERROR: ns-3 was compiled without Network Simulation Cradle support");
+}
+#endif
 }//namespace ns3
--- a/src/internet-stack/internet-stack.h	Tue Sep 02 10:12:14 2008 -0700
+++ b/src/internet-stack/internet-stack.h	Tue Sep 02 10:39:45 2008 -0700
@@ -27,6 +27,7 @@
 class Node;
 
 void AddInternetStack (Ptr<Node> node);
+void AddNscInternetStack (Ptr<Node> node, const std::string &soname);
 
 }//namespace ns3
 
--- a/src/internet-stack/ipv4-end-point-demux.cc	Tue Sep 02 10:12:14 2008 -0700
+++ b/src/internet-stack/ipv4-end-point-demux.cc	Tue Sep 02 10:39:45 2008 -0700
@@ -169,6 +169,24 @@
 }
 
 /*
+ * return list of all available Endpoints
+ */
+Ipv4EndPointDemux::EndPoints
+Ipv4EndPointDemux::GetAllEndPoints (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  EndPoints ret;
+
+  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
+   {
+      Ipv4EndPoint* endP = *i;
+      ret.push_back(endP);
+    }
+  return ret;
+}
+
+
+/*
  * If we have an exact match, we return it.
  * Otherwise, if we find a generic match, we return it.
  * Otherwise, we return 0.
--- a/src/internet-stack/ipv4-end-point-demux.h	Tue Sep 02 10:12:14 2008 -0700
+++ b/src/internet-stack/ipv4-end-point-demux.h	Tue Sep 02 10:39:45 2008 -0700
@@ -48,6 +48,7 @@
   Ipv4EndPointDemux ();
   ~Ipv4EndPointDemux ();
 
+  EndPoints GetAllEndPoints (void);
   bool LookupPortLocal (uint16_t port);
   bool LookupLocal (Ipv4Address addr, uint16_t port);
   EndPoints Lookup (Ipv4Address daddr, 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/nsc-sysctl.cc	Tue Sep 02 10:39:45 2008 -0700
@@ -0,0 +1,154 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include "ns3/string.h"
+#include "nsc-sysctl.h"
+
+#include "nsc/sim/sim_interface.h"
+
+namespace ns3 {
+
+class NscStackStringAccessor : public AttributeAccessor
+{
+  public:
+  NscStackStringAccessor (std::string name) : m_name (name) {}
+
+  virtual bool Set (ObjectBase * object, const AttributeValue &val) const;
+  virtual bool Get (const ObjectBase * object, AttributeValue &val) const;
+  virtual bool HasGetter (void) const;
+  virtual bool HasSetter (void) const;
+  private:
+  std::string m_name;
+};
+
+bool NscStackStringAccessor::HasGetter(void) const
+{
+  return true;
+}
+
+bool NscStackStringAccessor::HasSetter(void) const
+{
+  return true;
+}
+
+
+bool NscStackStringAccessor::Set (ObjectBase * object, const AttributeValue & val) const
+{
+  const StringValue *value = dynamic_cast<const StringValue *> (&val);
+  if (value == 0)
+    {
+      return false;
+    }
+  Ns3NscStack *obj = dynamic_cast<Ns3NscStack *> (object);
+  if (obj == 0)
+    {
+      return false;
+    }
+  obj->Set (m_name, value->Get ());
+  return true;
+}
+
+bool NscStackStringAccessor::Get (const ObjectBase * object, AttributeValue &val) const
+{
+  StringValue *value = dynamic_cast<StringValue *> (&val);
+  if (value == 0)
+    {
+      return false;
+    }
+  const Ns3NscStack *obj = dynamic_cast<const Ns3NscStack *> (object);
+  if (obj == 0)
+    {
+      return false;
+    }
+  value->Set (obj->Get (m_name));
+  return true;
+}
+
+
+TypeId
+Ns3NscStack::GetInstanceTypeId (void) const
+{
+  if (m_stack == 0)
+    {
+      // if we have no stack, we are a normal NscStack without any attributes.
+      return GetTypeId ();
+    }
+  std::string name = "ns3::Ns3NscStack<";
+  name += m_stack->get_name ();
+  name += ">";
+  TypeId tid;
+  if (TypeId::LookupByNameFailSafe (name, &tid))
+    {
+      // if the relevant TypeId has already been registered, no need to do it again.
+      return tid;
+    }
+  else
+    {
+      // Now, we register a new TypeId for this stack which will look
+      // like a subclass of the Ns3NscStack. The class Ns3NscStack is effectively
+      // mutating into a subclass of itself from the point of view of the TypeId
+      // system _here_
+      tid = TypeId (name.c_str ());
+      tid.SetParent<Ns3NscStack> ();
+      char buf[256];
+      for (int i=0; m_stack->sysctl_getnum(i, buf, sizeof(buf)) > 0 ;i++)
+        {
+          char value[256];
+          if (m_stack->sysctl_get (buf, value, sizeof(value)) > 0)
+            {
+              tid.AddAttribute (buf, "Help text",
+                                StringValue (value),
+                                Create<NscStackStringAccessor> (buf),
+                                MakeStringChecker ());
+            }
+        }
+      return tid;
+    }
+}
+
+std::string
+Ns3NscStack::Get (std::string name) const
+{
+  char buf[512];
+  if (m_stack->sysctl_get (name.c_str (), buf, sizeof(buf)) <= 0)
+    { // name.c_str () is not a valid sysctl name, or internal NSC error (eg. error converting value)
+      return NULL;
+    }
+  return std::string(buf);
+}
+
+void
+Ns3NscStack::Set (std::string name, std::string value)
+{
+  int ret = m_stack->sysctl_set (name.c_str (), value.c_str ());
+  if (ret < 0)
+    {
+      NS_FATAL_ERROR ("setting " << name << " to " << value << "failed (retval " << ret << ")");
+    }
+}
+
+TypeId
+Ns3NscStack::Ns3NscStack::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::Ns3NscStack")
+  .SetParent<Object> ()
+  ;
+  return tid;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/nsc-sysctl.h	Tue Sep 02 10:39:45 2008 -0700
@@ -0,0 +1,44 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include <string>
+
+#include "ns3/attribute.h"
+#include "ns3/object.h"
+
+struct INetStack;
+
+namespace ns3 {
+
+// This object represents the underlying nsc stack,
+// which is aggregated to a Node object, and which provides access to the
+// sysctls of the nsc stack through attributes.
+class Ns3NscStack : public Object
+{
+public:
+  static TypeId GetTypeId (void);
+  virtual TypeId GetInstanceTypeId (void) const;
+  void SetStack (INetStack *stack) {m_stack = stack;}
+
+private:
+  friend class NscStackStringAccessor;
+  void Set (std::string name, std::string value);
+  std::string Get (std::string name) const;
+  INetStack *m_stack;
+};
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/nsc-tcp-l4-protocol.cc	Tue Sep 02 10:39:45 2008 -0700
@@ -0,0 +1,368 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * 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
+ *
+ * based on earlier integration work by Tom Henderson and Sam Jansen.
+ * 2008 Florian Westphal <fw@strlen.de>
+ */
+
+#include "ns3/assert.h"
+#include "ns3/log.h"
+#include "ns3/nstime.h"
+
+#include "ns3/packet.h"
+#include "ns3/node.h"
+
+#include "tcp-header.h"
+#include "ipv4-end-point-demux.h"
+#include "ipv4-end-point.h"
+#include "ipv4-l3-protocol.h"
+#include "nsc-tcp-l4-protocol.h"
+#include "nsc-tcp-socket-impl.h"
+#include "nsc-sysctl.h"
+
+#include "tcp-typedefs.h"
+
+#include <vector>
+#include <sstream>
+#include <dlfcn.h>
+#include <iomanip>
+
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+
+NS_LOG_COMPONENT_DEFINE ("NscTcpL4Protocol");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (NscTcpL4Protocol);
+
+/* see http://www.iana.org/assignments/protocol-numbers */
+const uint8_t NscTcpL4Protocol::PROT_NUMBER = 6;
+
+ObjectFactory
+NscTcpL4Protocol::GetDefaultRttEstimatorFactory (void)
+{
+  ObjectFactory factory;
+  factory.SetTypeId (RttMeanDeviation::GetTypeId ());
+  return factory;
+}
+
+TypeId 
+NscTcpL4Protocol::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::NscTcpL4Protocol")
+    .SetParent<Ipv4L4Protocol> ()
+
+    .AddAttribute ("RttEstimatorFactory",
+                   "How RttEstimator objects are created.",
+                   ObjectFactoryValue (GetDefaultRttEstimatorFactory ()),
+                   MakeObjectFactoryAccessor (&NscTcpL4Protocol::m_rttFactory),
+                   MakeObjectFactoryChecker ())
+    ;
+  return tid;
+}
+
+int external_rand()
+{
+    return 1; // TODO
+}
+
+NscTcpL4Protocol::NscTcpL4Protocol ()
+  : m_endPoints (new Ipv4EndPointDemux ()),
+    m_nscStack (0),
+    m_nscInterfacesSetUp(false),
+    m_softTimer (Timer::CANCEL_ON_DESTROY)
+{
+  m_dlopenHandle = NULL;
+  NS_LOG_FUNCTION_NOARGS ();
+  NS_LOG_LOGIC("Made a NscTcpL4Protocol "<<this);
+}
+
+NscTcpL4Protocol::~NscTcpL4Protocol ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  dlclose(m_dlopenHandle);
+}
+
+void
+NscTcpL4Protocol::SetNscLibrary(const std::string &soname)
+{
+  NS_ASSERT(!m_dlopenHandle);
+  m_dlopenHandle = dlopen(soname.c_str (), RTLD_NOW);
+  if (m_dlopenHandle == NULL)
+    NS_FATAL_ERROR (dlerror());
+}
+
+void 
+NscTcpL4Protocol::SetNode (Ptr<Node> node)
+{
+  m_node = node;
+
+  if (m_nscStack)
+    { // stack has already been loaded...
+      return;
+    }
+
+  NS_ASSERT(m_dlopenHandle);
+
+  FCreateStack create = (FCreateStack)dlsym(m_dlopenHandle, "nsc_create_stack");
+  NS_ASSERT(create);
+  m_nscStack = create(this, this, external_rand);
+  int hzval = m_nscStack->get_hz();
+
+  NS_ASSERT(hzval > 0);
+
+  m_softTimer.SetFunction (&NscTcpL4Protocol::SoftInterrupt, this);
+  m_softTimer.SetDelay (MilliSeconds (1000/hzval));
+  m_nscStack->init(hzval);
+  // This enables stack and NSC debug messages
+  // m_nscStack->set_diagnostic(1000);
+
+  Ptr<Ns3NscStack> nscStack = Create<Ns3NscStack> ();
+  nscStack->SetStack (m_nscStack);
+  node->AggregateObject (nscStack);
+
+  m_softTimer.Schedule ();
+}
+
+int 
+NscTcpL4Protocol::GetProtocolNumber (void) const
+{
+  return PROT_NUMBER;
+}
+int 
+NscTcpL4Protocol::GetVersion (void) const
+{
+  return 2;
+}
+
+void
+NscTcpL4Protocol::DoDispose (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  if (m_endPoints != 0)
+    {
+      delete m_endPoints;
+      m_endPoints = 0;
+    }
+  m_node = 0;
+  Ipv4L4Protocol::DoDispose ();
+}
+
+Ptr<Socket>
+NscTcpL4Protocol::CreateSocket (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  if (!m_nscInterfacesSetUp)
+  {
+    Ptr<Ipv4> ip = m_node->GetObject<Ipv4> ();
+
+    const uint32_t nInterfaces = ip->GetNInterfaces ();
+    // start from 1, ignore the loopback interface (HACK)
+
+    NS_ASSERT_MSG (nInterfaces <= 2, "nsc does not support multiple interfaces per node");
+
+    for (uint32_t i = 1; i < nInterfaces; i++)
+    {
+      Ipv4Address addr = ip->GetAddress(i);
+      Ipv4Mask mask = ip->GetNetworkMask(i);
+      uint16_t mtu = ip->GetMtu (i);
+
+      std::ostringstream addrOss, maskOss;
+
+      addr.Print(addrOss);
+      mask.Print(maskOss);
+
+      NS_LOG_LOGIC ("if_attach " << addrOss.str().c_str() << " " << maskOss.str().c_str() << " " << mtu);
+
+      std::string addrStr = addrOss.str();
+      std::string maskStr = maskOss.str();
+      const char* addrCStr = addrStr.c_str();
+      const char* maskCStr = maskStr.c_str();
+      m_nscStack->if_attach(addrCStr, maskCStr, mtu);
+
+      if (i == 1)
+      {
+        // We need to come up with a default gateway here. Can't guarantee this to be
+        // correct really...
+
+        uint8_t addrBytes[4];
+        addr.Serialize(addrBytes);
+
+        // XXX: this is all a bit of a horrible hack
+        //
+        // Just increment the last octet, this gives a decent chance of this being
+        // 'enough'.
+        //
+        // All we need is another address on the same network as the interface. This
+        // will force the stack to output the packet out of the network interface.
+        addrBytes[3]++;
+        addr.Deserialize(addrBytes);
+        addrOss.str("");
+        addr.Print(addrOss);
+        m_nscStack->add_default_gateway(addrOss.str().c_str());
+      }
+    }
+    m_nscInterfacesSetUp = true;
+  }
+
+  Ptr<RttEstimator> rtt = m_rttFactory.Create<RttEstimator> ();
+  Ptr<NscTcpSocketImpl> socket = CreateObject<NscTcpSocketImpl> ();
+  socket->SetNode (m_node);
+  socket->SetTcp (this);
+  socket->SetRtt (rtt);
+  return socket;
+}
+
+Ipv4EndPoint *
+NscTcpL4Protocol::Allocate (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_endPoints->Allocate ();
+}
+
+Ipv4EndPoint *
+NscTcpL4Protocol::Allocate (Ipv4Address address)
+{
+  NS_LOG_FUNCTION (this << address);
+  return m_endPoints->Allocate (address);
+}
+
+Ipv4EndPoint *
+NscTcpL4Protocol::Allocate (uint16_t port)
+{
+  NS_LOG_FUNCTION (this << port);
+  return m_endPoints->Allocate (port);
+}
+
+Ipv4EndPoint *
+NscTcpL4Protocol::Allocate (Ipv4Address address, uint16_t port)
+{
+  NS_LOG_FUNCTION (this << address << port);
+  return m_endPoints->Allocate (address, port);
+}
+
+Ipv4EndPoint *
+NscTcpL4Protocol::Allocate (Ipv4Address localAddress, uint16_t localPort,
+                         Ipv4Address peerAddress, uint16_t peerPort)
+{
+  NS_LOG_FUNCTION (this << localAddress << localPort << peerAddress << peerPort);
+  return m_endPoints->Allocate (localAddress, localPort,
+                                peerAddress, peerPort);
+}
+
+void 
+NscTcpL4Protocol::DeAllocate (Ipv4EndPoint *endPoint)
+{
+  NS_LOG_FUNCTION (this << endPoint);
+  // NSC m_endPoints->DeAllocate (endPoint);
+}
+
+void
+NscTcpL4Protocol::Receive (Ptr<Packet> packet,
+             Ipv4Address const &source,
+             Ipv4Address const &destination,
+             Ptr<Ipv4Interface> incomingInterface)
+{
+  NS_LOG_FUNCTION (this << packet << source << destination << incomingInterface);
+  Ipv4Header ipHeader;
+  uint32_t packetSize = packet->GetSize();
+
+  // The way things work at the moment, the IP header has been removed
+  // by the ns-3 IPv4 processing code. However, the NSC stack expects
+  // a complete IP packet, so we add the IP header back.
+  // Since the original header is already gone, we create a new one
+  // based on the information we have.
+  ipHeader.SetSource (source);
+  ipHeader.SetDestination (destination);
+  ipHeader.SetProtocol (PROT_NUMBER);
+  ipHeader.SetPayloadSize (packetSize);
+  ipHeader.SetTtl (1);
+  // all NSC stacks check the IP checksum
+  ipHeader.EnableChecksum ();
+
+  packet->AddHeader(ipHeader);
+  packetSize = packet->GetSize();
+
+  const uint8_t *data = const_cast<uint8_t *>(packet->PeekData());
+
+  // deliver complete packet to the NSC network stack
+  m_nscStack->if_receive_packet(0, data, packetSize);
+  wakeup ();
+}
+
+void NscTcpL4Protocol::SoftInterrupt (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_nscStack->timer_interrupt ();
+  m_nscStack->increment_ticks ();
+  m_softTimer.Schedule ();
+}
+
+void NscTcpL4Protocol::send_callback(const void* data, int datalen)
+{
+  Ptr<Packet> p;
+
+  NS_ASSERT(datalen > (int)sizeof(struct iphdr));
+
+  const uint8_t *rawdata = reinterpret_cast<const uint8_t *>(data);
+  rawdata += sizeof(struct iphdr);
+
+  const struct iphdr *ipHdr = reinterpret_cast<const struct iphdr *>(data);
+
+  // create packet, without IP header. The TCP header is not touched.
+  // Not using the IP header makes integration easier, but it destroys
+  // eg. ECN.
+  p = Create<Packet> (rawdata, datalen - sizeof(struct iphdr));
+
+  Ipv4Address saddr(ntohl(ipHdr->saddr));
+  Ipv4Address daddr(ntohl(ipHdr->daddr));
+
+  Ptr<Ipv4L3Protocol> ipv4 = m_node->GetObject<Ipv4L3Protocol> ();
+  if (ipv4 != 0)
+    {
+      ipv4->Send (p, saddr, daddr, PROT_NUMBER);
+    }
+  m_nscStack->if_send_finish(0);
+}
+
+void NscTcpL4Protocol::wakeup()
+{
+  // TODO
+  // this should schedule a timer to read from all tcp sockets now... this is
+  // an indication that data might be waiting on the socket
+
+  Ipv4EndPointDemux::EndPoints endPoints = m_endPoints->GetAllEndPoints ();
+  for (Ipv4EndPointDemux::EndPointsI endPoint = endPoints.begin ();
+       endPoint != endPoints.end (); endPoint++) {
+          // NSC HACK: (ab)use TcpSocket::ForwardUp for signalling
+          (*endPoint)->ForwardUp (NULL, Ipv4Address(), 0);
+  }
+}
+
+void NscTcpL4Protocol::gettime(unsigned int* sec, unsigned int* usec)
+{
+  // Only used by the Linux network stack, e.g. during ISN generation
+  // and in the kernel rng initialization routine. Also used in Linux
+  // printk output.
+  Time t = Simulator::Now ();
+  int64_t us = t.GetMicroSeconds ();
+  *sec = us / (1000*1000);
+  *usec = us - *sec * (1000*1000);
+}
+
+
+}; // namespace ns3
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/nsc-tcp-l4-protocol.h	Tue Sep 02 10:39:45 2008 -0700
@@ -0,0 +1,121 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * 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
+ */
+
+#ifndef NSC_TCP_L4_PROTOCOL_H
+#define NSC_TCP_L4_PROTOCOL_H
+
+#include <stdint.h>
+
+#include "ns3/packet.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/ptr.h"
+#include "ns3/object-factory.h"
+#include "ipv4-end-point-demux.h"
+#include "ipv4-l4-protocol.h"
+#include "ipv4-interface.h"
+
+#include "tcp-header.h"
+
+#include "ns3/timer.h"
+#include "nsc/sim/sim_interface.h"
+
+namespace ns3 {
+
+class Node;
+class Socket;
+class TcpHeader;
+/**
+ * \brief Nsc wrapper glue.
+ */
+class NscTcpL4Protocol : public Ipv4L4Protocol, ISendCallback, IInterruptCallback {
+public:
+  static const uint8_t PROT_NUMBER;
+  static TypeId GetTypeId (void);
+  /**
+   * \brief Constructor
+   */
+  NscTcpL4Protocol ();
+  virtual ~NscTcpL4Protocol ();
+
+  void SetNode (Ptr<Node> node);
+  void SetNscLibrary(const std::string &lib);
+
+  virtual int GetProtocolNumber (void) const;
+  virtual int GetVersion (void) const;
+
+  /**
+   * \return A smart Socket pointer to a NscTcpSocketImpl, allocated by this instance
+   * of the TCP protocol
+   */
+  Ptr<Socket> CreateSocket (void);
+
+  Ipv4EndPoint *Allocate (void);
+  Ipv4EndPoint *Allocate (Ipv4Address address);
+  Ipv4EndPoint *Allocate (uint16_t port);
+  Ipv4EndPoint *Allocate (Ipv4Address address, uint16_t port);
+  Ipv4EndPoint *Allocate (Ipv4Address localAddress, uint16_t localPort,
+                          Ipv4Address peerAddress, uint16_t peerPort);
+
+  void DeAllocate (Ipv4EndPoint *endPoint);
+
+  /**
+   * \brief Recieve a packet up the protocol stack
+   * \param p The Packet to dump the contents into
+   * \param source The source's Ipv4Address
+   * \param destination The destinations Ipv4Address
+   * \param incomingInterface The Ipv4Interface it was received on
+   */
+  virtual void Receive (Ptr<Packet> p,
+                       Ipv4Address const &source,
+                       Ipv4Address const &destination,
+                       Ptr<Ipv4Interface> incomingInterface);
+
+  // NSC callbacks.
+  // NSC invokes these hooks to interact with the simulator.
+  // In any case, these methods are only to be called by NSC.
+  //
+  // send_callback is invoked by NSCs 'ethernet driver' to re-inject
+  // a packet (i.e. an octet soup consisting of an IP Header, TCP Header
+  // and user payload, if any), into ns-3.
+  virtual void send_callback(const void *data, int datalen);
+  // This is called by the NSC stack whenever something of interest
+  // has happened, e.g. when data arrives on a socket, a listen socket
+  // has a new connection pending, etc.
+  virtual void wakeup();
+  // This is called by the Linux stack RNG initialization.
+  // Its also used by the cradle code to add a timestamp to
+  // printk/printf/debug output.
+  virtual void gettime(unsigned int *, unsigned int *);
+
+protected:
+  virtual void DoDispose (void);
+private:
+  Ptr<Node> m_node;
+  Ipv4EndPointDemux *m_endPoints;
+  ObjectFactory m_rttFactory;
+private:
+  void SoftInterrupt (void);
+  static ObjectFactory GetDefaultRttEstimatorFactory (void);
+  friend class NscTcpSocketImpl;
+  INetStack* m_nscStack;
+  void *m_dlopenHandle;
+  bool m_nscInterfacesSetUp;
+  Timer m_softTimer;
+};
+
+}; // namespace ns3
+
+#endif /* NSC_TCP_L4_PROTOCOL_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/nsc-tcp-socket-factory-impl.cc	Tue Sep 02 10:39:45 2008 -0700
@@ -0,0 +1,50 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * 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
+ */
+#include "nsc-tcp-socket-factory-impl.h"
+#include "nsc-tcp-l4-protocol.h"
+#include "ns3/socket.h"
+#include "ns3/assert.h"
+
+namespace ns3 {
+
+NscTcpSocketFactoryImpl::NscTcpSocketFactoryImpl ()
+  : m_tcp (0)
+{}
+NscTcpSocketFactoryImpl::~NscTcpSocketFactoryImpl ()
+{
+  NS_ASSERT (m_tcp == 0);
+}
+
+void 
+NscTcpSocketFactoryImpl::SetTcp (Ptr<NscTcpL4Protocol> tcp)
+{
+  m_tcp = tcp;
+}
+
+Ptr<Socket>
+NscTcpSocketFactoryImpl::CreateSocket (void)
+{
+  return m_tcp->CreateSocket ();
+}
+
+void 
+NscTcpSocketFactoryImpl::DoDispose (void)
+{
+  m_tcp = 0;
+  TcpSocketFactory::DoDispose ();
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/nsc-tcp-socket-factory-impl.h	Tue Sep 02 10:39:45 2008 -0700
@@ -0,0 +1,44 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * 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
+ */
+#ifndef NSC_TCP_SOCKET_FACTORY_IMPL_H
+#define NSC_TCP_SOCKET_FACTORY_IMPL_H
+
+#include "ns3/tcp-socket-factory.h"
+#include "ns3/ptr.h"
+
+namespace ns3 {
+
+class NscTcpL4Protocol;
+
+class NscTcpSocketFactoryImpl : public TcpSocketFactory
+{
+public:
+  NscTcpSocketFactoryImpl ();
+  virtual ~NscTcpSocketFactoryImpl ();
+
+  void SetTcp (Ptr<NscTcpL4Protocol> tcp);
+
+  virtual Ptr<Socket> CreateSocket (void);
+
+protected:
+  virtual void DoDispose (void);
+private:
+  Ptr<NscTcpL4Protocol> m_tcp;
+};
+
+} // namespace ns3
+
+#endif /* NSC_TCP_SOCKET_FACTORY_IMPL_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/nsc-tcp-socket-impl.cc	Tue Sep 02 10:39:45 2008 -0700
@@ -0,0 +1,842 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * 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
+ *
+ * based on tcp-socket-impl.cc, Author: Raj Bhattacharjea <raj.b@gatech.edu>
+ * Author: Florian Westphal <fw@strlen.de>
+ */
+
+#include "ns3/node.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/log.h"
+#include "ns3/ipv4.h"
+#include "ipv4-end-point.h"
+#include "ipv4-l4-demux.h"
+#include "nsc-tcp-l4-protocol.h"
+#include "nsc-tcp-socket-impl.h"
+#include "ns3/simulation-singleton.h"
+#include "tcp-typedefs.h"
+#include "ns3/simulator.h"
+#include "ns3/packet.h"
+#include "ns3/uinteger.h"
+#include "ns3/trace-source-accessor.h"
+
+#include <algorithm>
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+
+#include "nsc/sim/sim_errno.h"
+
+NS_LOG_COMPONENT_DEFINE ("NscTcpSocketImpl");
+
+using namespace std;
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (NscTcpSocketImpl);
+
+TypeId
+NscTcpSocketImpl::GetTypeId ()
+{
+  static TypeId tid = TypeId("ns3::NscTcpSocketImpl")
+    .SetParent<TcpSocket> ()
+    .AddTraceSource ("CongestionWindow",
+                     "The TCP connection's congestion window",
+                     MakeTraceSourceAccessor (&NscTcpSocketImpl::m_cWnd))
+    ;
+  return tid;
+}
+
+  NscTcpSocketImpl::NscTcpSocketImpl ()
+  : m_endPoint (0),
+    m_node (0),
+    m_tcp (0),
+    m_peerAddress ("0.0.0.0", 0),
+    m_errno (ERROR_NOTERROR),
+    m_shutdownSend (false),
+    m_shutdownRecv (false),
+    m_connected (false),
+    m_state (CLOSED),
+    m_closeOnEmpty (false),
+    m_txBufferSize (0),
+    m_rtt (0),
+    m_lastMeasuredRtt (Seconds(0.0))
+{
+  NS_LOG_FUNCTION (this);
+}
+
+NscTcpSocketImpl::NscTcpSocketImpl(const NscTcpSocketImpl& sock)
+  : TcpSocket(sock), //copy the base class callbacks
+    m_delAckMaxCount (sock.m_delAckMaxCount),
+    m_delAckTimeout (sock.m_delAckTimeout),
+    m_endPoint (0),
+    m_node (sock.m_node),
+    m_tcp (sock.m_tcp),
+    m_remoteAddress (sock.m_remoteAddress),
+    m_remotePort (sock.m_remotePort),
+    m_localAddress (sock.m_localAddress),
+    m_localPort (sock.m_localPort),
+    m_peerAddress (sock.m_peerAddress),
+    m_errno (sock.m_errno),
+    m_shutdownSend (sock.m_shutdownSend),
+    m_shutdownRecv (sock.m_shutdownRecv),
+    m_connected (sock.m_connected),
+    m_state (sock.m_state),
+    m_closeOnEmpty (sock.m_closeOnEmpty),
+    m_segmentSize (sock.m_segmentSize),
+    m_rxWindowSize (sock.m_rxWindowSize),
+    m_advertisedWindowSize (sock.m_advertisedWindowSize),
+    m_cWnd (sock.m_cWnd),
+    m_ssThresh (sock.m_ssThresh),
+    m_initialCWnd (sock.m_initialCWnd),
+    m_rtt (0),
+    m_lastMeasuredRtt (Seconds(0.0)),
+    m_cnTimeout (sock.m_cnTimeout),
+    m_cnCount (sock.m_cnCount),
+    m_rxAvailable (0),
+    m_nscTcpSocket (0),
+    m_sndBufSize (sock.m_sndBufSize)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  NS_LOG_LOGIC("Invoked the copy constructor");
+  //copy the pending data if necessary
+  if(!sock.m_txBuffer.empty () )
+    {
+      m_txBuffer = sock.m_txBuffer;
+    }
+  //copy the rtt if necessary
+  if (sock.m_rtt)
+    {
+      m_rtt = sock.m_rtt->Copy();
+    }
+  //can't "copy" the endpoint just yes, must do this when we know the peer info
+  //too; this is in SYN_ACK_TX
+}
+
+NscTcpSocketImpl::~NscTcpSocketImpl ()
+{
+  NS_LOG_FUNCTION(this);
+  m_node = 0;
+  if (m_endPoint != 0)
+    {
+      NS_ASSERT (m_tcp != 0);
+      /**
+       * Note that this piece of code is a bit tricky:
+       * when DeAllocate is called, it will call into
+       * Ipv4EndPointDemux::Deallocate which triggers
+       * a delete of the associated endPoint which triggers
+       * in turn a call to the method ::Destroy below
+       * will will zero the m_endPoint field.
+       */
+      NS_ASSERT (m_endPoint != 0);
+      m_tcp->DeAllocate (m_endPoint);
+      NS_ASSERT (m_endPoint == 0);
+    }
+  m_tcp = 0;
+}
+
+void
+NscTcpSocketImpl::SetNode (Ptr<Node> node)
+{
+  m_node = node;
+  // Initialize some variables 
+  m_cWnd = m_initialCWnd * m_segmentSize;
+  m_rxWindowSize = m_advertisedWindowSize;
+}
+
+void 
+NscTcpSocketImpl::SetTcp (Ptr<NscTcpL4Protocol> tcp)
+{
+  m_nscTcpSocket = tcp->m_nscStack->new_tcp_socket();
+  m_tcp = tcp;
+}
+void 
+NscTcpSocketImpl::SetRtt (Ptr<RttEstimator> rtt)
+{
+  m_rtt = rtt;
+}
+
+
+enum Socket::SocketErrno
+NscTcpSocketImpl::GetErrno (void) const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_errno;
+}
+
+Ptr<Node>
+NscTcpSocketImpl::GetNode (void) const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_node;
+}
+
+void 
+NscTcpSocketImpl::Destroy (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_node = 0;
+  m_endPoint = 0;
+  m_tcp = 0;
+}
+int
+NscTcpSocketImpl::FinishBind (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  if (m_endPoint == 0)
+    {
+      return -1;
+    }
+  m_endPoint->SetRxCallback (MakeCallback (&NscTcpSocketImpl::ForwardUp, Ptr<NscTcpSocketImpl>(this)));
+  m_endPoint->SetDestroyCallback (MakeCallback (&NscTcpSocketImpl::Destroy, Ptr<NscTcpSocketImpl>(this)));
+  m_localAddress = m_endPoint->GetLocalAddress ();
+  m_localPort = m_endPoint->GetLocalPort ();
+  return 0;
+}
+
+int
+NscTcpSocketImpl::Bind (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_endPoint = m_tcp->Allocate ();
+  return FinishBind ();
+}
+int 
+NscTcpSocketImpl::Bind (const Address &address)
+{
+  NS_LOG_FUNCTION (this<<address);
+  if (!InetSocketAddress::IsMatchingType (address))
+    {
+      return ERROR_INVAL;
+    }
+  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 ();
+      NS_LOG_LOGIC ("TcpSocketImpl "<<this<<" got an endpoint: "<<m_endPoint);
+    }
+  else if (ipv4 == Ipv4Address::GetAny () && port != 0)
+    {
+      m_endPoint = m_tcp->Allocate (port);
+      NS_LOG_LOGIC ("TcpSocketImpl "<<this<<" got an endpoint: "<<m_endPoint);
+    }
+  else if (ipv4 != Ipv4Address::GetAny () && port == 0)
+    {
+      m_endPoint = m_tcp->Allocate (ipv4);
+      NS_LOG_LOGIC ("TcpSocketImpl "<<this<<" got an endpoint: "<<m_endPoint);
+    }
+  else if (ipv4 != Ipv4Address::GetAny () && port != 0)
+    {
+      m_endPoint = m_tcp->Allocate (ipv4, port);
+      NS_LOG_LOGIC ("TcpSocketImpl "<<this<<" got an endpoint: "<<m_endPoint);
+    }
+
+  m_localPort = port;
+  return FinishBind ();
+}
+
+int 
+NscTcpSocketImpl::ShutdownSend (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_shutdownSend = true;
+  return 0;
+}
+int 
+NscTcpSocketImpl::ShutdownRecv (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_shutdownRecv = false;
+  return 0;
+}
+
+int
+NscTcpSocketImpl::Close (void)
+{
+  NS_LOG_FUNCTION (this << m_state);
+
+  if (m_state == CLOSED)
+    {
+      return -1;
+    }
+  if (!m_txBuffer.empty ())
+    { // App close with pending data must wait until all data transmitted
+      m_closeOnEmpty = true;
+      NS_LOG_LOGIC("Socket " << this << 
+                   " deferring close, state " << m_state);
+      return 0;
+    }
+
+  m_nscTcpSocket->disconnect();
+  m_state = CLOSED;
+  ShutdownSend ();
+  return 0;
+}
+
+int
+NscTcpSocketImpl::Connect (const Address & address)
+{
+  NS_LOG_FUNCTION (this << address);
+  if (m_endPoint == 0)
+    {
+      if (Bind () == -1)
+        {
+          NS_ASSERT (m_endPoint == 0);
+          return -1;
+        }
+      NS_ASSERT (m_endPoint != 0);
+    }
+  InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
+  m_remoteAddress = transport.GetIpv4 ();
+  m_remotePort = transport.GetPort ();
+
+  struct in_addr remoteAddr;
+  uint32_t addr32;
+
+  m_remoteAddress.Serialize((uint8_t*)&addr32);
+  remoteAddr.s_addr = addr32;
+
+  m_nscTcpSocket->connect(inet_ntoa(remoteAddr), m_remotePort);
+  m_state = SYN_SENT;
+  return 0;
+}
+
+int
+NscTcpSocketImpl::Send (const Ptr<Packet> p, uint32_t flags)
+{
+  NS_LOG_FUNCTION (this << p);
+
+  NS_ASSERT (p->GetSize () > 0);
+  if (m_state == ESTABLISHED || m_state == SYN_SENT || m_state == CLOSE_WAIT)
+  {
+    if (p->GetSize () > GetTxAvailable ())
+    {
+      m_errno = ERROR_MSGSIZE;
+      return -1;
+    }
+
+    bool txEmpty = m_txBuffer.empty();
+    if (m_state == ESTABLISHED)
+      {
+        if (txEmpty)
+          {
+            m_txBuffer.push(p);
+            m_txBufferSize += p->GetSize ();
+          }
+        if (!SendPendingData())
+          {
+             if (m_errno == ERROR_AGAIN)
+               {
+                 return txEmpty ? p->GetSize () : -1;
+               }
+             if (txEmpty)
+               {
+                  m_txBuffer.pop ();
+                  m_txBufferSize = 0;
+               }
+             return -1;
+          }
+      }
+      else
+      {  // SYN_SET -- Queue Data
+         m_txBuffer.push(p);
+         m_txBufferSize += p->GetSize ();
+      }
+    return p->GetSize ();
+  }
+  else
+  {
+    m_errno = ERROR_NOTCONN;
+    return -1;
+  }
+}
+
+int
+NscTcpSocketImpl::SendTo (Ptr<Packet> p, uint32_t flags, const Address &address)
+{
+  NS_LOG_FUNCTION (this << address << p);
+  if (!m_connected)
+    {
+      m_errno = ERROR_NOTCONN;
+      return -1;
+    }
+  else
+    {
+      return Send (p, flags); //drop the address according to BSD manpages
+    }
+}
+
+uint32_t
+NscTcpSocketImpl::GetTxAvailable (void) const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  if (m_txBufferSize != 0)
+    {
+      NS_ASSERT (m_txBufferSize <= m_sndBufSize);
+      return m_sndBufSize - m_txBufferSize;
+    }
+  else
+    {
+      return m_sndBufSize;
+    }
+}
+
+int
+NscTcpSocketImpl::Listen (uint32_t q)
+{
+  NS_LOG_FUNCTION (this << q);
+  m_nscTcpSocket->listen(m_localPort);
+  m_state = LISTEN;
+  return 0;
+}
+
+
+void
+NscTcpSocketImpl::NSCWakeup ()
+{
+  switch (m_state) {
+  case SYN_SENT:
+      if (!m_nscTcpSocket->is_connected())
+          break;
+      m_state = ESTABLISHED;
+      Simulator::ScheduleNow(&NscTcpSocketImpl::ConnectionSucceeded, this);
+      // fall through to schedule read/write events
+  case ESTABLISHED:
+      if (!m_txBuffer.empty ())
+          Simulator::ScheduleNow(&NscTcpSocketImpl::SendPendingData, this);
+      Simulator::ScheduleNow(&NscTcpSocketImpl::ReadPendingData, this);
+      break;
+  case LISTEN:
+      Simulator::ScheduleNow(&NscTcpSocketImpl::Accept, this);
+      break;
+  case CLOSED: break;
+  default:
+      NS_LOG_DEBUG (this << " invalid state: " << m_state);
+  }
+}
+
+Ptr<Packet>
+NscTcpSocketImpl::Recv (uint32_t maxSize, uint32_t flags)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  if (m_deliveryQueue.empty() )
+    {
+      return 0;
+    }
+  Ptr<Packet> p = m_deliveryQueue.front ();
+  if (p->GetSize () <= maxSize)
+    {
+      m_deliveryQueue.pop ();
+      m_rxAvailable -= p->GetSize ();
+    }
+  else
+    {
+      p = 0;
+    }
+  return p;
+}
+
+Ptr<Packet>
+NscTcpSocketImpl::RecvFrom (uint32_t maxSize, uint32_t flags,
+  Address &fromAddress)
+{
+  NS_LOG_FUNCTION (this << maxSize << flags);
+  Ptr<Packet> packet = Recv (maxSize, flags);
+  if (packet != 0)
+    {
+      SocketAddressTag tag;
+      bool found;
+      found = packet->FindFirstMatchingTag (tag);
+      NS_ASSERT (found);
+      fromAddress = tag.GetAddress ();
+    }
+  return packet;
+}
+
+uint32_t
+NscTcpSocketImpl::GetRxAvailable (void) const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  // We separately maintain this state to avoid walking the queue 
+  // every time this might be called
+  return m_rxAvailable;
+}
+
+void
+NscTcpSocketImpl::ForwardUp (Ptr<Packet> packet, Ipv4Address ipv4, uint16_t port)
+{
+  NSCWakeup();
+}
+
+void NscTcpSocketImpl::CompleteFork(void)
+{
+  // The address pairs (m_localAddress, m_localPort, m_remoteAddress, m_remotePort)
+  // are bogus, but this isn't important at the moment, because
+  // address <-> Socket handling is done by NSC internally.
+  // We only need to add the new ns-3 socket to the list of sockets, so
+  // we use plain Allocate() instead of Allocate(m_localAddress, ... )
+  uint8_t buf[4];
+  int port;
+  size_t buflen = sizeof(buf);
+
+  if (0 == m_nscTcpSocket->getpeername((void *) buf, &buflen, &port)) {
+    m_remotePort = ntohs(port);
+    m_remoteAddress = m_remoteAddress.Deserialize(buf);
+    m_peerAddress = InetSocketAddress(m_remoteAddress, m_remotePort);
+  }
+
+  m_endPoint = m_tcp->Allocate ();
+
+  //the cloned socket with be in listen state, so manually change state
+  NS_ASSERT(m_state == LISTEN);
+  m_state = ESTABLISHED;
+
+  buflen = sizeof(buf);
+  if (0 == m_nscTcpSocket->getsockname((void *) &buf, &buflen, &port))
+    m_localAddress = m_localAddress.Deserialize(buf);
+
+  NS_LOG_LOGIC ("NscTcpSocketImpl " << this << " accepted connection from " 
+                 << m_remoteAddress << ":" << m_remotePort
+                 << " to " << m_localAddress << ":" << m_localPort);
+  //equivalent to FinishBind
+  m_endPoint->SetRxCallback (MakeCallback (&NscTcpSocketImpl::ForwardUp, Ptr<NscTcpSocketImpl>(this)));
+  m_endPoint->SetDestroyCallback (MakeCallback (&NscTcpSocketImpl::Destroy, Ptr<NscTcpSocketImpl>(this)));
+
+  NotifyNewConnectionCreated (this, m_peerAddress);
+}
+
+void NscTcpSocketImpl::ConnectionSucceeded()
+{ // We would preferred to have scheduled an event directly to
+  // NotifyConnectionSucceeded, but (sigh) these are protected
+  // and we can get the address of it :(
+
+  uint8_t buf[4];
+  int port;
+  size_t buflen = sizeof(buf);
+  if (0 == m_nscTcpSocket->getsockname((void *) &buf, &buflen, &port)) {
+    m_localAddress = m_localAddress.Deserialize(buf);
+    m_localPort = ntohs(port);
+  }
+
+  NS_LOG_LOGIC ("NscTcpSocketImpl " << this << " connected to "
+                 << m_remoteAddress << ":" << m_remotePort
+                 << " from " << m_localAddress << ":" << m_localPort);
+  NotifyConnectionSucceeded();
+}
+
+
+bool NscTcpSocketImpl::Accept (void)
+{
+  if (m_state == CLOSED)
+    {  // Happens if application closes listening socket after Accept() was scheduled.
+      return false;
+    }
+  NS_ASSERT (m_state == LISTEN);
+
+  if (!m_nscTcpSocket->is_listening())
+    {
+      return false;
+    }
+  INetStreamSocket *newsock;
+  int res = m_nscTcpSocket->accept(&newsock);
+  if (res != 0)
+    {
+      return false;
+    }
+// We could obtain a fromAddress using getpeername, but we've already
+// finished the tcp handshake here, i.e. this is a new connection
+// and not a connection request.
+// if (!NotifyConnectionRequest(fromAddress))
+//   return true;
+
+  // Clone the socket
+  Ptr<NscTcpSocketImpl> newSock = Copy ();
+  newSock->m_nscTcpSocket = newsock;
+  NS_LOG_LOGIC ("Cloned a NscTcpSocketImpl " << newSock);
+
+  Simulator::ScheduleNow (&NscTcpSocketImpl::CompleteFork, newSock);
+  return true;
+}
+
+bool NscTcpSocketImpl::ReadPendingData (void)
+{
+  if (m_state != ESTABLISHED)
+    {
+      return false;
+    }
+  int len, err;
+  uint8_t buffer[8192];
+  len = sizeof(buffer);
+  m_errno = ERROR_NOTERROR;
+  err = m_nscTcpSocket->read_data(buffer, &len);
+  if (err == 0 && len == 0)
+    {
+      NS_LOG_LOGIC ("ReadPendingData got EOF from socket");
+      m_state = CLOSED;
+      return false;
+    }
+  m_errno = GetNativeNs3Errno(err);
+  switch (m_errno)
+    {
+      case ERROR_NOTERROR: break; // some data was sent
+      case ERROR_AGAIN: return false;
+      default:
+        NS_LOG_WARN ("Error (" << err << ") " <<
+                     "during read_data, ns-3 errno set to" << m_errno);
+        m_state = CLOSED;
+        return false;
+    }
+
+  Ptr<Packet> p =  Create<Packet> (buffer, len);
+
+  SocketAddressTag tag;
+
+  tag.SetAddress (m_peerAddress);
+  p->AddTag (tag);
+  m_deliveryQueue.push (p);
+  m_rxAvailable += p->GetSize ();
+
+  NotifyDataRecv ();
+  return true;
+}
+
+bool NscTcpSocketImpl::SendPendingData (void)
+{
+  NS_LOG_FUNCTION (this);
+  NS_LOG_LOGIC ("ENTERING SendPendingData");
+
+  if (m_txBuffer.empty ())
+    {
+      return false;
+    }
+
+  int ret;
+  size_t size, written = 0;
+
+  do {
+    Ptr<Packet> &p = m_txBuffer.front ();
+    size = p->GetSize ();
+    NS_ASSERT (size > 0);
+
+    m_errno = ERROR_NOTERROR;
+    ret = m_nscTcpSocket->send_data((const char *)p->PeekData (), size);
+    if (ret <= 0)
+      {
+        m_errno = GetNativeNs3Errno(ret);
+        if (m_errno != ERROR_AGAIN)
+          {
+            NS_LOG_WARN ("Error (" << ret << ") " <<
+                         "during send_data, ns-3 errno set to" << m_errno);
+          }
+        break;
+      }
+    written += ret;
+
+    NS_ASSERT (m_txBufferSize >= (size_t)ret);
+    m_txBufferSize -= ret;
+
+    if ((size_t)ret < size)
+      {
+        p->RemoveAtStart(ret);
+        break;
+      }
+
+    m_txBuffer.pop ();
+
+    if (m_txBuffer.empty ())
+      {
+        if (m_closeOnEmpty)
+          {
+            m_nscTcpSocket->disconnect();
+            m_state = CLOSED;
+          }
+        break;
+      }
+  } while ((size_t) ret == size);
+
+  if (written > 0)
+    {
+      Simulator::ScheduleNow(&NscTcpSocketImpl::NotifyDataSent, this, ret);
+      return true;
+    }
+  return false;
+}
+
+Ptr<NscTcpSocketImpl> NscTcpSocketImpl::Copy ()
+{
+  return CopyObject<NscTcpSocketImpl> (this);
+}
+
+void
+NscTcpSocketImpl::SetSndBufSize (uint32_t size)
+{
+  m_sndBufSize = size;
+}
+
+uint32_t
+NscTcpSocketImpl::GetSndBufSize (void) const
+{
+  return m_sndBufSize;
+}
+
+void
+NscTcpSocketImpl::SetRcvBufSize (uint32_t size)
+{
+  m_rcvBufSize = size;
+}
+
+uint32_t
+NscTcpSocketImpl::GetRcvBufSize (void) const
+{
+  return m_rcvBufSize;
+}
+
+void
+NscTcpSocketImpl::SetSegSize (uint32_t size)
+{
+  m_segmentSize = size;
+}
+
+uint32_t
+NscTcpSocketImpl::GetSegSize (void) const
+{
+  return m_segmentSize;
+}
+
+void
+NscTcpSocketImpl::SetAdvWin (uint32_t window)
+{
+  m_advertisedWindowSize = window;
+}
+
+uint32_t
+NscTcpSocketImpl::GetAdvWin (void) const
+{
+  return m_advertisedWindowSize;
+}
+
+void
+NscTcpSocketImpl::SetSSThresh (uint32_t threshold)
+{
+  m_ssThresh = threshold;
+}
+
+uint32_t
+NscTcpSocketImpl::GetSSThresh (void) const
+{
+  return m_ssThresh;
+}
+
+void
+NscTcpSocketImpl::SetInitialCwnd (uint32_t cwnd)
+{
+  m_initialCWnd = cwnd;
+}
+
+uint32_t
+NscTcpSocketImpl::GetInitialCwnd (void) const
+{
+  return m_initialCWnd;
+}
+
+void 
+NscTcpSocketImpl::SetConnTimeout (Time timeout)
+{
+  m_cnTimeout = timeout;
+}
+
+Time
+NscTcpSocketImpl::GetConnTimeout (void) const
+{
+  return m_cnTimeout;
+}
+
+void 
+NscTcpSocketImpl::SetConnCount (uint32_t count)
+{
+  m_cnCount = count;
+}
+
+uint32_t 
+NscTcpSocketImpl::GetConnCount (void) const
+{
+  return m_cnCount;
+}
+
+void 
+NscTcpSocketImpl::SetDelAckTimeout (Time timeout)
+{
+  m_delAckTimeout = timeout;
+}
+
+Time
+NscTcpSocketImpl::GetDelAckTimeout (void) const
+{
+  return m_delAckTimeout;
+}
+
+void
+NscTcpSocketImpl::SetDelAckMaxCount (uint32_t count)
+{
+  m_delAckMaxCount = count;
+}
+
+uint32_t
+NscTcpSocketImpl::GetDelAckMaxCount (void) const
+{
+  return m_delAckMaxCount;
+}
+
+enum Socket::SocketErrno
+NscTcpSocketImpl::GetNativeNs3Errno(int error) const
+{
+  enum nsc_errno err;
+
+  if (error >= 0)
+    {
+       return ERROR_NOTERROR;
+    }
+  err = (enum nsc_errno) error;
+  switch (err)
+    {
+      case NSC_EADDRINUSE: // fallthrough
+      case NSC_EADDRNOTAVAIL: return ERROR_AFNOSUPPORT;
+      case NSC_EINPROGRESS: // Altough nsc sockets are nonblocking, we pretend they're not.
+      case NSC_EAGAIN: return ERROR_AGAIN;
+      case NSC_EISCONN: // fallthrough
+      case NSC_EALREADY: return ERROR_ISCONN;
+      case NSC_ECONNREFUSED: return ERROR_NOROUTETOHOST; // XXX, better mapping?
+      case NSC_ECONNRESET: // for no, all of these fall through
+      case NSC_EHOSTDOWN:
+      case NSC_ENETUNREACH:
+      case NSC_EHOSTUNREACH: return ERROR_NOROUTETOHOST;
+      case NSC_EMSGSIZE: return ERROR_MSGSIZE;
+      case NSC_ENOTCONN: return ERROR_NOTCONN;
+      case NSC_ESHUTDOWN: return ERROR_SHUTDOWN;
+      case NSC_ETIMEDOUT: return ERROR_NOTCONN; // XXX - this mapping isn't correct
+      case NSC_ENOTDIR: // used by eg. sysctl(2). Shouldn't happen normally,
+                        // but is triggered by e.g. show_config().
+      case NSC_EUNKNOWN: return ERROR_INVAL; // Catches stacks that 'return -1' without real mapping
+    }
+  NS_ASSERT_MSG(0, "Unknown NSC error");
+  return ERROR_INVAL;
+}
+
+}//namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/nsc-tcp-socket-impl.h	Tue Sep 02 10:39:45 2008 -0700
@@ -0,0 +1,171 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * 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
+ */
+#ifndef NSC_TCP_SOCKET_IMPL_H
+#define NSC_TCP_SOCKET_IMPL_H
+
+#include <stdint.h>
+#include <queue>
+#include <vector>
+
+#include "ns3/callback.h"
+#include "ns3/traced-value.h"
+#include "ns3/tcp-socket.h"
+#include "ns3/ptr.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/event-id.h"
+#include "tcp-typedefs.h"
+#include "pending-data.h"
+#include "sequence-number.h"
+#include "rtt-estimator.h"
+
+#include "nsc/sim/sim_interface.h"
+
+namespace ns3 {
+
+class Ipv4EndPoint;
+class Node;
+class Packet;
+class NscTcpL4Protocol;
+class TcpHeader;
+
+class NscTcpSocketImpl : public TcpSocket
+{
+public:
+  static TypeId GetTypeId (void);
+  /**
+   * Create an unbound tcp socket.
+   */
+  NscTcpSocketImpl ();
+  NscTcpSocketImpl (const NscTcpSocketImpl& sock);
+  virtual ~NscTcpSocketImpl ();
+
+  void SetNode (Ptr<Node> node);
+  void SetTcp (Ptr<NscTcpL4Protocol> tcp);
+  void SetRtt (Ptr<RttEstimator> rtt);
+
+  virtual enum SocketErrno GetErrno (void) const;
+  virtual Ptr<Node> GetNode (void) const;
+  virtual int Bind (void);
+  virtual int Bind (const Address &address);
+  virtual int Close (void);
+  virtual int ShutdownSend (void);
+  virtual int ShutdownRecv (void);
+  virtual int Connect(const Address &address);
+  virtual int Listen(uint32_t queueLimit);
+  virtual uint32_t GetTxAvailable (void) const;
+  virtual int Send (Ptr<Packet> p, uint32_t flags);
+  virtual int SendTo(Ptr<Packet> p, uint32_t flags, const Address &toAddress);
+  virtual uint32_t GetRxAvailable (void) const;
+  virtual Ptr<Packet> Recv (uint32_t maxSize, uint32_t flags);
+  virtual Ptr<Packet> RecvFrom (uint32_t maxSize, uint32_t flags,
+    Address &fromAddress);
+
+private:
+  void NSCWakeup(void);
+  friend class Tcp;
+  // invoked by Tcp class
+  int FinishBind (void);
+  void ForwardUp (Ptr<Packet> p, Ipv4Address ipv4, uint16_t port);
+  void Destroy (void);
+  //methods for state
+  bool SendPendingData(void);
+  bool ReadPendingData(void);
+  bool Accept(void);
+  void CompleteFork(void);
+  void ConnectionSucceeded();
+
+  // Manage data tx/rx
+  // XXX This should be virtual and overridden
+  Ptr<NscTcpSocketImpl> Copy ();
+
+  // attribute related
+  virtual void SetSndBufSize (uint32_t size);
+  virtual uint32_t GetSndBufSize (void) const;
+  virtual void SetRcvBufSize (uint32_t size);
+  virtual uint32_t GetRcvBufSize (void) const;
+  virtual void SetSegSize (uint32_t size);
+  virtual uint32_t GetSegSize (void) const;
+  virtual void SetAdvWin (uint32_t window);
+  virtual uint32_t GetAdvWin (void) const;
+  virtual void SetSSThresh (uint32_t threshold);
+  virtual uint32_t GetSSThresh (void) const;
+  virtual void SetInitialCwnd (uint32_t cwnd);
+  virtual uint32_t GetInitialCwnd (void) const;
+  virtual void SetConnTimeout (Time timeout);
+  virtual Time GetConnTimeout (void) const;
+  virtual void SetConnCount (uint32_t count);
+  virtual uint32_t GetConnCount (void) const;
+  virtual void SetDelAckTimeout (Time timeout);
+  virtual Time GetDelAckTimeout (void) const;
+  virtual void SetDelAckMaxCount (uint32_t count);
+  virtual uint32_t GetDelAckMaxCount (void) const;
+
+  enum Socket::SocketErrno GetNativeNs3Errno(int err) const;
+  uint32_t m_delAckMaxCount;
+  Time m_delAckTimeout;
+
+  Ipv4EndPoint *m_endPoint;
+  Ptr<Node> m_node;
+  Ptr<NscTcpL4Protocol> m_tcp;
+  Ipv4Address m_remoteAddress;
+  uint16_t m_remotePort;
+  //these two are so that the socket/endpoint cloning works
+  Ipv4Address m_localAddress;
+  uint16_t m_localPort;
+  InetSocketAddress m_peerAddress;
+  enum SocketErrno m_errno;
+  bool m_shutdownSend;
+  bool m_shutdownRecv;
+  bool m_connected;
+  
+  //manage the state infomation
+  States_t m_state;
+  bool m_closeOnEmpty;
+
+  //needed to queue data when in SYN_SENT state
+  std::queue<Ptr<Packet> > m_txBuffer;
+  uint32_t m_txBufferSize;
+
+  // Window management
+  uint32_t                       m_segmentSize;          //SegmentSize
+  uint32_t                       m_rxWindowSize;
+  uint32_t                       m_advertisedWindowSize; //Window to advertise
+  TracedValue<uint32_t>          m_cWnd;                 //Congestion window
+  uint32_t                       m_ssThresh;             //Slow Start Threshold
+  uint32_t                       m_initialCWnd;          //Initial cWnd value
+
+  // Round trip time estimation
+  Ptr<RttEstimator> m_rtt;
+  Time m_lastMeasuredRtt;
+
+  // Timer-related members
+  Time              m_cnTimeout; 
+  uint32_t          m_cnCount;
+
+  // Temporary queue for delivering data to application
+  std::queue<Ptr<Packet> > m_deliveryQueue;
+  uint32_t m_rxAvailable;
+  INetStreamSocket* m_nscTcpSocket;
+
+  // Attributes
+  uint32_t m_sndBufSize;   // buffer limit for the outgoing queue
+  uint32_t m_rcvBufSize;   // maximum receive socket buffer size
+};
+
+}//namespace ns3
+
+#endif /* NSC_TCP_SOCKET_IMPL_H */
--- a/src/internet-stack/wscript	Tue Sep 02 10:12:14 2008 -0700
+++ b/src/internet-stack/wscript	Tue Sep 02 10:39:45 2008 -0700
@@ -1,4 +1,61 @@
 ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+import Params
+import os
+
+# Mercurial repository of the network simulation cradle
+NETWORK_SIMULATION_CRADLE_REPO = "https://secure.wand.net.nz/mercurial/nsc"
+def nsc_fetch():
+    def nsc_clone():
+        print "Retrieving nsc from " + NETWORK_SIMULATION_CRADLE_REPO
+        if os.system("hg version > /dev/null 2>&1") != 0:
+            Params.fatal("Mercurial not installed, http fallback not yet implemented")
+        if os.system("hg -q clone " + NETWORK_SIMULATION_CRADLE_REPO) != 0:
+            Params.fatal("hg -q clone %s failed" % NETWORK_SIMULATION_CRADLE_REPO)
+
+    def nsc_update():
+        if os.system("hg version > /dev/null 2>&1") != 0:
+            Params.warning("Mercurial not installed, not updating nsc source")
+
+        print "Pulling nsc updates from " + NETWORK_SIMULATION_CRADLE_REPO
+        if os.system("cd nsc && hg -q pull %s && hg -q update" % NETWORK_SIMULATION_CRADLE_REPO) != 0:
+            Params.warning("Updating nsc using mercurial failed")
+
+    if not os.path.exists("nsc"):
+        nsc_clone()
+    else:
+        nsc_update()
+
+def configure(conf):
+    # checks for flex and bison, which is needed to build NSCs globaliser
+    def check_nsc_buildutils():
+        import flex
+        import bison
+        conf.check_tool('flex bison')
+        e = conf.create_library_configurator()
+        e.mandatory = True
+        e.name = 'fl'
+        e.run()
+
+    if not Params.g_options.nsc:
+	return
+
+    check_nsc_buildutils()
+
+    arch = os.uname()[4]
+    ok = False
+    if arch == 'x86_64' or arch == 'i686' or arch == 'i586' or arch == 'i486' or arch == 'i386':
+        conf.env['NSC_ENABLED'] = 'yes'
+        conf.define('NETWORK_SIMULATION_CRADLE', 1)
+        conf.write_config_header('ns3/core-config.h')
+        e = conf.create_library_configurator()
+        e.mandatory = True
+        e.name = 'dl'
+        e.define = 'HAVE_DL'
+        e.uselib = 'DL'
+        e.run()
+        ok = True
+    conf.check_message('NSC supported architecture', arch, ok)
+    nsc_fetch()
 
 
 def build(bld):
@@ -43,3 +100,9 @@
         'ipv4-l3-protocol.h',
         'ipv4-static-routing.h',
         ]
+
+    if bld.env()['NSC_ENABLED']:
+        obj.source.append ('nsc-tcp-socket-impl.cc')
+        obj.source.append ('nsc-tcp-l4-protocol.cc')
+        obj.source.append ('nsc-tcp-socket-factory-impl.cc')
+        obj.source.append ('nsc-sysctl.cc')
--- a/src/wscript	Tue Sep 02 10:12:14 2008 -0700
+++ b/src/wscript	Tue Sep 02 10:39:45 2008 -0700
@@ -50,6 +50,7 @@
     conf.sub_config('core')
     conf.sub_config('simulator')
     conf.sub_config('contrib')
+    conf.sub_config('internet-stack')
 
     blddir = os.path.abspath(os.path.join(conf.m_blddir, conf.env.variant()))
     conf.env.append_value('NS3_MODULE_PATH', blddir)
--- a/wscript	Tue Sep 02 10:12:14 2008 -0700
+++ b/wscript	Tue Sep 02 10:39:45 2008 -0700
@@ -55,6 +55,8 @@
 #
 TRACEBALL_SUFFIX = ".tar.bz2"
 
+# directory that contains network simulation cradle source
+NSC_DIR = "nsc"
 
 def dist_hook():
     import tarfile
@@ -165,6 +167,10 @@
                    help=('For regression testing, only run/generate the indicated regression tests, '
                          'specified as a comma separated list of test names'),
                    dest='regression_tests', type="string")
+    opt.add_option('--nsc',
+                   help=('Enable Network Simulation Cradle to allow the use real-world network stacks'),
+                   action="store_true", default=False,
+                   dest='nsc')
 
     # options provided in a script in a subdirectory named "src"
     opt.sub_options('src')
@@ -193,6 +199,7 @@
     
 
 def configure(conf):
+    conf.env['NS3_BUILDDIR'] = conf.m_blddir
     conf.check_tool('compiler_cxx')
 
     # create the second environment, set the variant and set its name
@@ -304,6 +311,28 @@
     return stat >> 8
 
 
+def nsc_build(bld):
+    # XXX: Detect gcc major version(s) available to build supported stacks
+    kernels = [['linux-2.6.18', 'linux2.6.18'],
+               ['linux-2.6.26', 'linux2.6.26']]
+    for dir,name in kernels:
+        soname = 'lib' + name + '.so'
+        tmp = NSC_DIR + '/' + dir +'/' + soname
+        if not os.path.exists(tmp):
+            if os.system('cd ' + NSC_DIR + ' && python scons.py ' + dir) != 0:
+                Params.fatal("Building NSC stack failed")
+        builddir = os.path.abspath(os.path.join(bld.env()['NS3_BUILDDIR'], bld.env ().variant()))
+        if not os.path.exists(builddir + '/nsc'):
+            try:
+                os.symlink('../../' + NSC_DIR, builddir + '/nsc')
+            except:
+                Params.fatal("Error linkink " + builddir + '/nsc')
+        if not os.path.exists(builddir + '/' + soname):
+            try:
+                os.symlink('../../' + NSC_DIR + '/' + dir + '/' + soname, builddir +  '/' + soname)
+            except:
+                Params.fatal("Error linking " + builddir + '/' + soname)
+
 def build(bld):
     if Params.g_options.no_task_lines:
         import Runner
@@ -393,6 +422,9 @@
 
     bld.add_subdirs('bindings/python')
 
+    if env['NSC_ENABLED'] == 'yes':
+        nsc_build(bld)
+
 def get_command_template():
     if Params.g_options.valgrind:
         if Params.g_options.command_template: