merge with HEAD
authorMathieu Lacage <mathieu.lacage@sophia.inria.fr>
Tue Sep 02 10:45:06 2008 -0700 (18 months ago)
changeset 3583b6cf80679b72
parent 3582 96fa2a7b5f88
parent 3581 048d80fcffde
child 3584 4eb48239b4dc
merge with HEAD
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/examples/tcp-nsc-lfn.cc	Tue Sep 02 10:45:06 2008 -0700
     1.3 @@ -0,0 +1,145 @@
     1.4 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
     1.5 +/*
     1.6 + * This program is free software; you can redistribute it and/or modify
     1.7 + * it under the terms of the GNU General Public License version 2 as
     1.8 + * published by the Free Software Foundation;
     1.9 + *
    1.10 + * This program is distributed in the hope that it will be useful,
    1.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1.13 + * GNU General Public License for more details.
    1.14 + *
    1.15 + * You should have received a copy of the GNU General Public License
    1.16 + * along with this program; if not, write to the Free Software
    1.17 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    1.18 + *
    1.19 + */
    1.20 +
    1.21 +//
    1.22 +// Network topology
    1.23 +//
    1.24 +//           6Mb/s, 500ms
    1.25 +//       n0-----------------n1
    1.26 +//
    1.27 +// - a 'lossy' network with long delay
    1.28 +// - TCP flow from n0 to n1 and from n1 to n0
    1.29 +// - pcap traces generated as tcp-nsc-lfn-0-0.pcap and tcp-nsc-lfn-1-0.pcap
    1.30 +//  Usage (e.g.): ./waf --run 'tcp-nsc-lfn --TCP_CONGESTION=hybla --runtime=30'
    1.31 +
    1.32 +#include <ctype.h>
    1.33 +#include <iostream>
    1.34 +#include <fstream>
    1.35 +#include <string>
    1.36 +#include <cassert>
    1.37 +
    1.38 +#include "ns3/core-module.h"
    1.39 +#include "ns3/common-module.h"
    1.40 +#include "ns3/helper-module.h"
    1.41 +#include "ns3/node-module.h"
    1.42 +#include "ns3/global-route-manager.h"
    1.43 +#include "ns3/simulator-module.h"
    1.44 +
    1.45 +using namespace ns3;
    1.46 +
    1.47 +NS_LOG_COMPONENT_DEFINE ("TcpNscLfn");
    1.48 +
    1.49 +
    1.50 +int main (int argc, char *argv[])
    1.51 +{
    1.52 +  RandomVariable::UseGlobalSeed (1, 1, 2, 3, 5, 8);
    1.53 +
    1.54 +  Config::SetDefault ("ns3::OnOffApplication::PacketSize", UintegerValue (4096));
    1.55 +  Config::SetDefault ("ns3::OnOffApplication::DataRate", StringValue ("6Mbps"));
    1.56 +
    1.57 +  // cubic is the default congestion algorithm in Linux 2.6.26
    1.58 +  std::string tcpCong = "cubic";
    1.59 +  // this is the default error rate of our link, that is, the the probability of a single
    1.60 +  // byte being 'corrupted' during transfer.
    1.61 +  double errRate = 0.000001;
    1.62 +  // how long the sender should be running, in seconds.
    1.63 +  unsigned int runtime = 120;
    1.64 +  // the name of the NSC stack library that should be used
    1.65 +  std::string nscStack = "liblinux2.6.26.so";
    1.66 +
    1.67 +  CommandLine cmd;
    1.68 +  // Here, we define additional command line options.
    1.69 +  // This allows a user to override the defaults set above from the command line.
    1.70 +  cmd.AddValue("TCP_CONGESTION", "Linux 2.6.26 Tcp Congestion control algorithm to use", tcpCong);
    1.71 +  cmd.AddValue("error-rate", "Error rate to apply to link", errRate);
    1.72 +  cmd.AddValue("runtime", "How long the applications should send data (default 120 seconds)", runtime);
    1.73 +  cmd.AddValue("nscstack", "Set name of NSC stack (shared library) to use (default liblinux2.6.26.so)", nscStack);
    1.74 +  cmd.Parse (argc, argv);
    1.75 +
    1.76 +  NodeContainer n;
    1.77 +  n.Create (2);
    1.78 +
    1.79 +  PointToPointHelper p2p;
    1.80 +  // create point-to-point link with a bandwidth of 6MBit/s and a large delay (0.5 seconds)
    1.81 +  p2p.SetDeviceAttribute ("DataRate", DataRateValue (DataRate(6 * 1000 * 1000)));
    1.82 +  p2p.SetChannelAttribute ("Delay", TimeValue (MilliSeconds(500)));
    1.83 +
    1.84 +  NetDeviceContainer p2pInterfaces = p2p.Install (n);
    1.85 +  // The default MTU of the p2p link would be 65535, which doesn't work
    1.86 +  // well with our default errRate (most packets would arrive corrupted).
    1.87 +  p2pInterfaces.Get(0)->SetMtu(1500);
    1.88 +  p2pInterfaces.Get(1)->SetMtu(1500);
    1.89 +
    1.90 +  InternetStackHelper internet;
    1.91 +  // The next statement switches the nodes to 'NSC'-Mode.
    1.92 +  // It disables the native ns-3 TCP model and loads the NSC library.
    1.93 +  internet.SetNscStack (nscStack);
    1.94 +  internet.Install (n);
    1.95 +
    1.96 +  if (tcpCong != "cubic") // make sure we only fail if both --nscstack and --TCP_CONGESTION are used
    1.97 +    {
    1.98 +      // This uses ns-3s attribute system to set the 'net.ipv4.tcp_congestion_control' sysctl of the
    1.99 +      // stack.
   1.100 +      // The same mechanism could be used to e.g. disable TCP timestamps:
   1.101 +      // Config::Set ("/NodeList/*/$ns3::Ns3NscStack<linux2.6.26>/net.ipv4.tcp_timestamps", StringValue ("0"));
   1.102 +      Config::Set ("/NodeList/*/$ns3::Ns3NscStack<linux2.6.26>/net.ipv4.tcp_congestion_control", StringValue (tcpCong));
   1.103 +    }
   1.104 +  Ipv4AddressHelper ipv4;
   1.105 +  ipv4.SetBase ("10.0.0.0", "255.255.255.0");
   1.106 +  Ipv4InterfaceContainer ipv4Interfaces = ipv4.Assign (p2pInterfaces);
   1.107 +
   1.108 +  DoubleValue rate(errRate);
   1.109 +  RandomVariableValue u01(UniformVariable (0.0, 1.0));
   1.110 +  Ptr<RateErrorModel> em1 = 
   1.111 +      CreateObject<RateErrorModel> ("RanVar", u01, "ErrorRate", rate);
   1.112 +  Ptr<RateErrorModel> em2 = 
   1.113 +      CreateObject<RateErrorModel> ("RanVar", u01, "ErrorRate", rate);
   1.114 +
   1.115 +  // This enables the specified errRate on both link endpoints.
   1.116 +  p2pInterfaces.Get(0)->SetAttribute("ReceiveErrorModel", PointerValue (em1));
   1.117 +  p2pInterfaces.Get(1)->SetAttribute("ReceiveErrorModel", PointerValue (em2));
   1.118 +
   1.119 +  GlobalRouteManager::PopulateRoutingTables ();
   1.120 +
   1.121 +  uint16_t servPort = 8080;
   1.122 +  PacketSinkHelper sinkHelper ("ns3::TcpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), servPort));
   1.123 +  ApplicationContainer sinkApp = sinkHelper.Install (n);
   1.124 +  sinkApp.Start (Seconds (0.0));
   1.125 +  // this makes sure that the receiver will run one minute longer than the sender applicaton.
   1.126 +  sinkApp.Stop (Seconds (runtime + 60.0));
   1.127 +
   1.128 +  // This sets up two TCP flows, one from A -> B, one from B -> A.
   1.129 +  for (int i = 0, j = 1; i < 2; j--, i++)
   1.130 +   {
   1.131 +      Address remoteAddress(InetSocketAddress(ipv4Interfaces.GetAddress (i), servPort));
   1.132 +      OnOffHelper clientHelper ("ns3::TcpSocketFactory", remoteAddress);
   1.133 +      clientHelper.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
   1.134 +      clientHelper.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
   1.135 +      ApplicationContainer clientApp = clientHelper.Install(n.Get(j));
   1.136 +      clientApp.Start (Seconds (1.0 + i));
   1.137 +      clientApp.Stop (Seconds (runtime + 1.0 + i));
   1.138 +    }
   1.139 +
   1.140 +  // This tells ns-3 to generate pcap traces.
   1.141 +  PointToPointHelper::EnablePcapAll ("tcp-nsc-lfn");
   1.142 +
   1.143 +  Simulator::Stop (Seconds(900));
   1.144 +  Simulator::Run ();
   1.145 +  Simulator::Destroy ();
   1.146 +
   1.147 +  return 0;
   1.148 +}
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/examples/tcp-nsc-zoo.cc	Tue Sep 02 10:45:06 2008 -0700
     2.3 @@ -0,0 +1,131 @@
     2.4 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
     2.5 +/*
     2.6 + * This program is free software; you can redistribute it and/or modify
     2.7 + * it under the terms of the GNU General Public License version 2 as
     2.8 + * published by the Free Software Foundation;
     2.9 + *
    2.10 + * This program is distributed in the hope that it will be useful,
    2.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    2.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    2.13 + * GNU General Public License for more details.
    2.14 + *
    2.15 + * You should have received a copy of the GNU General Public License
    2.16 + * along with this program; if not, write to the Free Software
    2.17 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    2.18 + *
    2.19 + */
    2.20 +
    2.21 +
    2.22 +// Network topology
    2.23 +//
    2.24 +//       n0    n1   n2   n3
    2.25 +//       |     |    |    |
    2.26 +//       =================
    2.27 +//              LAN
    2.28 +//
    2.29 +// - Pcap traces are saved as tcp-nsc-zoo-$n-0.pcap, where $n represents the node number
    2.30 +// - TCP flows from n0 to n1, n2, n3, from n1 to n0, n2, n3, etc.
    2.31 +//  Usage (e.g.): ./waf --run 'tcp-nsc-zoo --Nodes=5'
    2.32 +
    2.33 +#include <iostream>
    2.34 +#include <string>
    2.35 +
    2.36 +#include "ns3/core-module.h"
    2.37 +#include "ns3/helper-module.h"
    2.38 +#include "ns3/node-module.h"
    2.39 +#include "ns3/global-route-manager.h"
    2.40 +#include "ns3/simulator-module.h"
    2.41 +
    2.42 +using namespace ns3;
    2.43 +
    2.44 +NS_LOG_COMPONENT_DEFINE ("TcpNscZoo");
    2.45 +
    2.46 +// Simulates a diverse network with various stacks supported by NSC.
    2.47 +int main(int argc, char *argv[])
    2.48 +{
    2.49 +  CsmaHelper csma;
    2.50 +  unsigned int MaxNodes = 4;
    2.51 +
    2.52 +  Config::SetDefault ("ns3::OnOffApplication::PacketSize", UintegerValue (4096));
    2.53 +  Config::SetDefault ("ns3::OnOffApplication::DataRate", StringValue ("1Mb/s"));
    2.54 +  CommandLine cmd;
    2.55 +  // this allows the user to raise the number of nodes using --Nodes=X command-line argument.
    2.56 +  cmd.AddValue("Nodes", "Number of nodes in the network", MaxNodes);
    2.57 +  cmd.Parse (argc, argv);
    2.58 +
    2.59 +  csma.SetChannelAttribute ("DataRate", DataRateValue (DataRate(100 * 1000 * 1000)));
    2.60 +  csma.SetChannelAttribute ("Delay", TimeValue (MicroSeconds (200)));
    2.61 +
    2.62 +  NodeContainer n;
    2.63 +  n.Create(MaxNodes);
    2.64 +  NetDeviceContainer ethInterfaces = csma.Install (n);
    2.65 +
    2.66 +  InternetStackHelper internetStack;
    2.67 +
    2.68 +  internetStack.SetNscStack ("liblinux2.6.26.so");
    2.69 +  // this switches nodes 0 and 1 to NSCs Linux 2.6.26 stack.
    2.70 +  internetStack.Install (n.Get(0));
    2.71 +  internetStack.Install (n.Get(1));
    2.72 +  // this disables TCP SACK, wscale and timestamps on node 1 (the attributes represent sysctl-values).
    2.73 +  Config::Set ("/NodeList/1/$ns3::Ns3NscStack<linux2.6.26>/net.ipv4.tcp_sack", StringValue ("0"));
    2.74 +  Config::Set ("/NodeList/1/$ns3::Ns3NscStack<linux2.6.26>/net.ipv4.tcp_timestamps", StringValue ("0"));
    2.75 +  Config::Set ("/NodeList/1/$ns3::Ns3NscStack<linux2.6.26>/net.ipv4.tcp_window_scaling", StringValue ("0"));
    2.76 +  internetStack.Install (n.Get(2));
    2.77 +  // the next statement doesn't change anything for the nodes 0, 1, and 2; since they
    2.78 +  // already have a stack assigned.
    2.79 +  internetStack.SetNscStack ("liblinux2.6.18.so");
    2.80 +  // this switches node 3 to NSCs Linux 2.6.18 stack.
    2.81 +  internetStack.Install (n.Get(3));
    2.82 +  // and then agains disables sack/timestamps/wscale on node 3.
    2.83 +  Config::Set ("/NodeList/3/$ns3::Ns3NscStack<linux2.6.18>/net.ipv4.tcp_sack", StringValue ("0"));
    2.84 +  Config::Set ("/NodeList/3/$ns3::Ns3NscStack<linux2.6.18>/net.ipv4.tcp_timestamps", StringValue ("0"));
    2.85 +  Config::Set ("/NodeList/3/$ns3::Ns3NscStack<linux2.6.18>/net.ipv4.tcp_window_scaling", StringValue ("0"));
    2.86 +  // the freebsd stack is not yet built by default, so its commented out for now.
    2.87 +  // internetStack.SetNscStack ("libfreebsd5.so");
    2.88 +  for (unsigned int i =4; i < MaxNodes; i++)
    2.89 +    {
    2.90 +      internetStack.Install (n.Get(i));
    2.91 +    }
    2.92 +  Ipv4AddressHelper ipv4;
    2.93 +
    2.94 +  ipv4.SetBase ("10.0.0.0", "255.255.255.0");
    2.95 +  Ipv4InterfaceContainer ipv4Interfaces = ipv4.Assign (ethInterfaces);
    2.96 +
    2.97 +  GlobalRouteManager::PopulateRoutingTables ();
    2.98 +
    2.99 +  uint16_t servPort = 8080;
   2.100 +  PacketSinkHelper sinkHelper ("ns3::TcpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), servPort));
   2.101 +  // start a sink client on all nodes
   2.102 +  ApplicationContainer sinkApp = sinkHelper.Install (n);
   2.103 +  sinkApp.Start (Seconds (1.0));
   2.104 +  sinkApp.Stop (Seconds (30.0));
   2.105 +
   2.106 +  // This tells every node on the network to start a flow to all other nodes on the network ...
   2.107 +  for (unsigned int i = 0 ; i < MaxNodes;i++)
   2.108 +    {
   2.109 +      for (unsigned int j = 0 ; j < MaxNodes;j++)
   2.110 +        {
   2.111 +          if (i == j)
   2.112 +            {  // ...but we don't want a node to talk to itself.
   2.113 +               continue;
   2.114 +            }
   2.115 +          Address remoteAddress(InetSocketAddress(ipv4Interfaces.GetAddress (j), servPort));
   2.116 +          OnOffHelper clientHelper ("ns3::TcpSocketFactory", remoteAddress);
   2.117 +          clientHelper.SetAttribute 
   2.118 +            ("OnTime", RandomVariableValue (ConstantVariable (1)));
   2.119 +          clientHelper.SetAttribute 
   2.120 +            ("OffTime", RandomVariableValue (ConstantVariable (0)));
   2.121 +          ApplicationContainer clientApp = clientHelper.Install(n.Get(i));
   2.122 +          clientApp.Start (Seconds (j + 1.0)); /* delay startup depending on node number */
   2.123 +          clientApp.Stop (Seconds (j + 10.0));
   2.124 +	}
   2.125 +    }
   2.126 +
   2.127 +  CsmaHelper::EnablePcapAll ("tcp-nsc-zoo");
   2.128 +
   2.129 +  Simulator::Stop (Seconds(1000));
   2.130 +  Simulator::Run ();
   2.131 +  Simulator::Destroy ();
   2.132 +
   2.133 +  return 0;
   2.134 +}
     3.1 --- a/examples/wscript	Tue Sep 02 10:44:28 2008 -0700
     3.2 +++ b/examples/wscript	Tue Sep 02 10:45:06 2008 -0700
     3.3 @@ -64,6 +64,14 @@
     3.4          ['point-to-point', 'internet-stack'])
     3.5      obj.source = 'tcp-errors.cc'
     3.6  
     3.7 +    obj = bld.create_ns3_program('tcp-nsc-lfn',
     3.8 +      ['point-to-point', 'internet-stack'])
     3.9 +    obj.source = 'tcp-nsc-lfn.cc'
    3.10 +
    3.11 +    obj = bld.create_ns3_program('tcp-nsc-zoo',
    3.12 +      ['csma', 'internet-stack'])
    3.13 +    obj.source = 'tcp-nsc-zoo.cc'
    3.14 +
    3.15      obj = bld.create_ns3_program('tcp-star-server',
    3.16          ['point-to-point', 'internet-stack'])
    3.17      obj.source = 'tcp-star-server.cc'
     4.1 --- a/src/helper/internet-stack-helper.cc	Tue Sep 02 10:44:28 2008 -0700
     4.2 +++ b/src/helper/internet-stack-helper.cc	Tue Sep 02 10:45:06 2008 -0700
     4.3 @@ -33,6 +33,10 @@
     4.4  std::vector<InternetStackHelper::Trace> InternetStackHelper::m_traces;
     4.5  std::string InternetStackHelper::m_pcapBaseFilename;
     4.6  
     4.7 +InternetStackHelper::InternetStackHelper() : m_nscLibrary("")
     4.8 +{
     4.9 +}
    4.10 +
    4.11  void
    4.12  InternetStackHelper::Cleanup (void)
    4.13  {
    4.14 @@ -48,6 +52,12 @@
    4.15    m_traces.clear ();
    4.16  }
    4.17  
    4.18 +void
    4.19 +InternetStackHelper::SetNscStack(const std::string soname)
    4.20 +{
    4.21 +  m_nscLibrary = soname;
    4.22 +}
    4.23 +
    4.24  void 
    4.25  InternetStackHelper::Install (NodeContainer c)
    4.26  {
    4.27 @@ -59,8 +69,12 @@
    4.28            NS_FATAL_ERROR ("InternetStackHelper::Install(): Aggregating " 
    4.29               "an InternetStack to a node with an existing Ipv4 object");
    4.30            return;
    4.31 -        } 
    4.32 -      AddInternetStack (node);
    4.33 +        }
    4.34 +      if (m_nscLibrary != "")
    4.35 +        AddNscInternetStack (node, m_nscLibrary);
    4.36 +      else
    4.37 +        AddInternetStack (node);
    4.38 +
    4.39        Ptr<PacketSocketFactory> factory = CreateObject<PacketSocketFactory> ();
    4.40        node->AggregateObject (factory);
    4.41      }
     5.1 --- a/src/helper/internet-stack-helper.h	Tue Sep 02 10:44:28 2008 -0700
     5.2 +++ b/src/helper/internet-stack-helper.h	Tue Sep 02 10:45:06 2008 -0700
     5.3 @@ -33,6 +33,8 @@
     5.4  class InternetStackHelper
     5.5  {
     5.6  public:
     5.7 +  InternetStackHelper(void);
     5.8 +
     5.9    /**
    5.10     * \param c the set of nodes
    5.11     *
    5.12 @@ -45,6 +47,13 @@
    5.13    void Install (NodeContainer c);
    5.14  
    5.15    /**
    5.16 +   * \param soname name of the shared library with the nsc tcp stack
    5.17 +   * to use, e.g. 'liblinux2.6.26.so'. The empty string resets
    5.18 +   * the InternetStackHelper to use the ns-3 models again.
    5.19 +   */
    5.20 +  void SetNscStack(std::string soname);
    5.21 +
    5.22 +  /**
    5.23     * \param filename filename prefix to use for pcap files.
    5.24     *
    5.25     * Enable pcap output on each protocol instance which is of the
    5.26 @@ -60,6 +69,7 @@
    5.27    static void EnablePcapAll (std::string filename);
    5.28  
    5.29  private:
    5.30 +  std::string m_nscLibrary;
    5.31    static void Cleanup (void);
    5.32    static void LogRxIp (std::string context, Ptr<const Packet> packet, uint32_t deviceId);
    5.33    static void LogTxIp (std::string context, Ptr<const Packet> packet, uint32_t deviceId);
     6.1 --- a/src/internet-stack/internet-stack.cc	Tue Sep 02 10:44:28 2008 -0700
     6.2 +++ b/src/internet-stack/internet-stack.cc	Tue Sep 02 10:45:06 2008 -0700
     6.3 @@ -21,6 +21,7 @@
     6.4  #include "ns3/net-device.h"
     6.5  #include "ns3/callback.h"
     6.6  #include "ns3/node.h"
     6.7 +#include "ns3/core-config.h"
     6.8  
     6.9  #include "ipv4-l4-demux.h"
    6.10  #include "udp-l4-protocol.h"
    6.11 @@ -31,41 +32,105 @@
    6.12  #include "tcp-socket-factory-impl.h"
    6.13  #include "ipv4-impl.h"
    6.14  
    6.15 +#ifdef NETWORK_SIMULATION_CRADLE
    6.16 +#include "nsc-tcp-socket-factory-impl.h"
    6.17 +#include "nsc-tcp-l4-protocol.h"
    6.18 +#endif
    6.19 +
    6.20  namespace ns3 {
    6.21  
    6.22 -void 
    6.23 +static void
    6.24 +AddArpStack (Ptr<Node> node)
    6.25 +{
    6.26 +  Ptr<ArpL3Protocol> arp = CreateObject<ArpL3Protocol> ();
    6.27 +  arp->SetNode (node);
    6.28 +  node->AggregateObject (arp);
    6.29 +}
    6.30 +
    6.31 +static void
    6.32 +AddUdpStack(Ptr<Node> node, Ptr<Ipv4L4Demux> ipv4L4Demux)
    6.33 +{
    6.34 +  Ptr<UdpL4Protocol> udp = CreateObject<UdpL4Protocol> ();
    6.35 +  udp->SetNode (node);
    6.36 +  ipv4L4Demux->Insert (udp);
    6.37 +  Ptr<UdpSocketFactoryImpl> udpFactory = CreateObject<UdpSocketFactoryImpl> ();
    6.38 +  udpFactory->SetUdp (udp);
    6.39 +  node->AggregateObject (udpFactory);
    6.40 +}
    6.41 +
    6.42 +static void
    6.43 +AddTcpStack(Ptr<Node> node, Ptr<Ipv4L4Demux> ipv4L4Demux)
    6.44 +{
    6.45 +  Ptr<TcpL4Protocol> tcp = CreateObject<TcpL4Protocol> ();
    6.46 +  tcp->SetNode (node);
    6.47 +  ipv4L4Demux->Insert (tcp);
    6.48 +  Ptr<TcpSocketFactoryImpl> tcpFactory = CreateObject<TcpSocketFactoryImpl> ();
    6.49 +  tcpFactory->SetTcp (tcp);
    6.50 +  node->AggregateObject (tcpFactory);
    6.51 +}
    6.52 +
    6.53 +static void
    6.54 +AddIpv4Impl(Ptr<Node> node, Ptr<Ipv4L3Protocol> ipv4)
    6.55 +{
    6.56 +  Ptr<Ipv4Impl> ipv4Impl = CreateObject<Ipv4Impl> ();
    6.57 +  ipv4Impl->SetIpv4 (ipv4);
    6.58 +  node->AggregateObject (ipv4);
    6.59 +  node->AggregateObject (ipv4Impl);
    6.60 +}
    6.61 +
    6.62 +void
    6.63  AddInternetStack (Ptr<Node> node)
    6.64  {
    6.65 +  AddArpStack(node);
    6.66    Ptr<Ipv4L3Protocol> ipv4 = CreateObject<Ipv4L3Protocol> ();
    6.67 -  Ptr<ArpL3Protocol> arp = CreateObject<ArpL3Protocol> ();
    6.68    ipv4->SetNode (node);
    6.69 -  arp->SetNode (node);
    6.70  
    6.71    Ptr<Ipv4L4Demux> ipv4L4Demux = CreateObject<Ipv4L4Demux> ();
    6.72 -  Ptr<UdpL4Protocol> udp = CreateObject<UdpL4Protocol> ();
    6.73 -  Ptr<TcpL4Protocol> tcp = CreateObject<TcpL4Protocol> ();
    6.74 +  ipv4L4Demux->SetNode (node);
    6.75  
    6.76 -  ipv4L4Demux->SetNode (node);
    6.77 -  udp->SetNode (node);
    6.78 -  tcp->SetNode (node);
    6.79 +  AddUdpStack (node, ipv4L4Demux);
    6.80 +  AddTcpStack (node, ipv4L4Demux);
    6.81  
    6.82 -  ipv4L4Demux->Insert (udp);
    6.83 -  ipv4L4Demux->Insert (tcp);
    6.84 -
    6.85 -  Ptr<UdpSocketFactoryImpl> udpFactory = CreateObject<UdpSocketFactoryImpl> ();
    6.86 -  Ptr<TcpSocketFactoryImpl> tcpFactory = CreateObject<TcpSocketFactoryImpl> ();
    6.87 -  Ptr<Ipv4Impl> ipv4Impl = CreateObject<Ipv4Impl> ();
    6.88 -
    6.89 -  udpFactory->SetUdp (udp);
    6.90 -  tcpFactory->SetTcp (tcp);
    6.91 -  ipv4Impl->SetIpv4 (ipv4);
    6.92 -
    6.93 -  node->AggregateObject (ipv4);
    6.94 -  node->AggregateObject (arp);
    6.95 -  node->AggregateObject (ipv4Impl);
    6.96 -  node->AggregateObject (udpFactory);
    6.97 -  node->AggregateObject (tcpFactory);
    6.98 +  AddIpv4Impl (node, ipv4);
    6.99    node->AggregateObject (ipv4L4Demux);
   6.100  }
   6.101  
   6.102 +
   6.103 +#ifdef NETWORK_SIMULATION_CRADLE
   6.104 +static void
   6.105 +AddNscStack(Ptr<Node> node, Ptr<Ipv4L4Demux> ipv4L4Demux, const std::string &soname)
   6.106 +{
   6.107 +  Ptr<NscTcpL4Protocol> tcp = CreateObject<NscTcpL4Protocol> ();
   6.108 +  tcp->SetNscLibrary(soname);
   6.109 +  tcp->SetNode (node);
   6.110 +  ipv4L4Demux->Insert (tcp);
   6.111 +  Ptr<NscTcpSocketFactoryImpl> tcpFactory = CreateObject<NscTcpSocketFactoryImpl> ();
   6.112 +  tcpFactory->SetTcp (tcp);
   6.113 +  node->AggregateObject (tcpFactory);
   6.114 +}
   6.115 +
   6.116 +
   6.117 +void
   6.118 +AddNscInternetStack (Ptr<Node> node, const std::string &soname)
   6.119 +{
   6.120 +  AddArpStack(node);
   6.121 +  Ptr<Ipv4L3Protocol> ipv4 = CreateObject<Ipv4L3Protocol> ();
   6.122 +  ipv4->SetNode (node);
   6.123 +
   6.124 +  Ptr<Ipv4L4Demux> ipv4L4Demux = CreateObject<Ipv4L4Demux> ();
   6.125 +  ipv4L4Demux->SetNode (node);
   6.126 +
   6.127 +  AddUdpStack (node, ipv4L4Demux);
   6.128 +  AddNscStack (node, ipv4L4Demux, soname);
   6.129 +
   6.130 +  AddIpv4Impl (node, ipv4);
   6.131 +  node->AggregateObject (ipv4L4Demux);
   6.132 +}
   6.133 +#else
   6.134 +void
   6.135 +AddNscInternetStack (Ptr<Node> node, const std::string &soname)
   6.136 +{
   6.137 +  NS_ASSERT_MSG(false, "ERROR: ns-3 was compiled without Network Simulation Cradle support");
   6.138 +}
   6.139 +#endif
   6.140  }//namespace ns3
     7.1 --- a/src/internet-stack/internet-stack.h	Tue Sep 02 10:44:28 2008 -0700
     7.2 +++ b/src/internet-stack/internet-stack.h	Tue Sep 02 10:45:06 2008 -0700
     7.3 @@ -27,6 +27,7 @@
     7.4  class Node;
     7.5  
     7.6  void AddInternetStack (Ptr<Node> node);
     7.7 +void AddNscInternetStack (Ptr<Node> node, const std::string &soname);
     7.8  
     7.9  }//namespace ns3
    7.10  
     8.1 --- a/src/internet-stack/ipv4-end-point-demux.cc	Tue Sep 02 10:44:28 2008 -0700
     8.2 +++ b/src/internet-stack/ipv4-end-point-demux.cc	Tue Sep 02 10:45:06 2008 -0700
     8.3 @@ -169,6 +169,24 @@
     8.4  }
     8.5  
     8.6  /*
     8.7 + * return list of all available Endpoints
     8.8 + */
     8.9 +Ipv4EndPointDemux::EndPoints
    8.10 +Ipv4EndPointDemux::GetAllEndPoints (void)
    8.11 +{
    8.12 +  NS_LOG_FUNCTION_NOARGS ();
    8.13 +  EndPoints ret;
    8.14 +
    8.15 +  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++)
    8.16 +   {
    8.17 +      Ipv4EndPoint* endP = *i;
    8.18 +      ret.push_back(endP);
    8.19 +    }
    8.20 +  return ret;
    8.21 +}
    8.22 +
    8.23 +
    8.24 +/*
    8.25   * If we have an exact match, we return it.
    8.26   * Otherwise, if we find a generic match, we return it.
    8.27   * Otherwise, we return 0.
     9.1 --- a/src/internet-stack/ipv4-end-point-demux.h	Tue Sep 02 10:44:28 2008 -0700
     9.2 +++ b/src/internet-stack/ipv4-end-point-demux.h	Tue Sep 02 10:45:06 2008 -0700
     9.3 @@ -48,6 +48,7 @@
     9.4    Ipv4EndPointDemux ();
     9.5    ~Ipv4EndPointDemux ();
     9.6  
     9.7 +  EndPoints GetAllEndPoints (void);
     9.8    bool LookupPortLocal (uint16_t port);
     9.9    bool LookupLocal (Ipv4Address addr, uint16_t port);
    9.10    EndPoints Lookup (Ipv4Address daddr, 
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/src/internet-stack/nsc-sysctl.cc	Tue Sep 02 10:45:06 2008 -0700
    10.3 @@ -0,0 +1,154 @@
    10.4 +/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
    10.5 +/*
    10.6 + * This program is free software; you can redistribute it and/or modify
    10.7 + * it under the terms of the GNU General Public License version 2 as
    10.8 + * published by the Free Software Foundation;
    10.9 + *
   10.10 + * This program is distributed in the hope that it will be useful,
   10.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   10.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   10.13 + * GNU General Public License for more details.
   10.14 + *
   10.15 + * You should have received a copy of the GNU General Public License
   10.16 + * along with this program; if not, write to the Free Software
   10.17 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   10.18 + *
   10.19 + * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
   10.20 + */
   10.21 +
   10.22 +#include "ns3/string.h"
   10.23 +#include "nsc-sysctl.h"
   10.24 +
   10.25 +#include "nsc/sim/sim_interface.h"
   10.26 +
   10.27 +namespace ns3 {
   10.28 +
   10.29 +class NscStackStringAccessor : public AttributeAccessor
   10.30 +{
   10.31 +  public:
   10.32 +  NscStackStringAccessor (std::string name) : m_name (name) {}
   10.33 +
   10.34 +  virtual bool Set (ObjectBase * object, const AttributeValue &val) const;
   10.35 +  virtual bool Get (const ObjectBase * object, AttributeValue &val) const;
   10.36 +  virtual bool HasGetter (void) const;
   10.37 +  virtual bool HasSetter (void) const;
   10.38 +  private:
   10.39 +  std::string m_name;
   10.40 +};
   10.41 +
   10.42 +bool NscStackStringAccessor::HasGetter(void) const
   10.43 +{
   10.44 +  return true;
   10.45 +}
   10.46 +
   10.47 +bool NscStackStringAccessor::HasSetter(void) const
   10.48 +{
   10.49 +  return true;
   10.50 +}
   10.51 +
   10.52 +
   10.53 +bool NscStackStringAccessor::Set (ObjectBase * object, const AttributeValue & val) const
   10.54 +{
   10.55 +  const StringValue *value = dynamic_cast<const StringValue *> (&val);
   10.56 +  if (value == 0)
   10.57 +    {
   10.58 +      return false;
   10.59 +    }
   10.60 +  Ns3NscStack *obj = dynamic_cast<Ns3NscStack *> (object);
   10.61 +  if (obj == 0)
   10.62 +    {
   10.63 +      return false;
   10.64 +    }
   10.65 +  obj->Set (m_name, value->Get ());
   10.66 +  return true;
   10.67 +}
   10.68 +
   10.69 +bool NscStackStringAccessor::Get (const ObjectBase * object, AttributeValue &val) const
   10.70 +{
   10.71 +  StringValue *value = dynamic_cast<StringValue *> (&val);
   10.72 +  if (value == 0)
   10.73 +    {
   10.74 +      return false;
   10.75 +    }
   10.76 +  const Ns3NscStack *obj = dynamic_cast<const Ns3NscStack *> (object);
   10.77 +  if (obj == 0)
   10.78 +    {
   10.79 +      return false;
   10.80 +    }
   10.81 +  value->Set (obj->Get (m_name));
   10.82 +  return true;
   10.83 +}
   10.84 +
   10.85 +
   10.86 +TypeId
   10.87 +Ns3NscStack::GetInstanceTypeId (void) const
   10.88 +{
   10.89 +  if (m_stack == 0)
   10.90 +    {
   10.91 +      // if we have no stack, we are a normal NscStack without any attributes.
   10.92 +      return GetTypeId ();
   10.93 +    }
   10.94 +  std::string name = "ns3::Ns3NscStack<";
   10.95 +  name += m_stack->get_name ();
   10.96 +  name += ">";
   10.97 +  TypeId tid;
   10.98 +  if (TypeId::LookupByNameFailSafe (name, &tid))
   10.99 +    {
  10.100 +      // if the relevant TypeId has already been registered, no need to do it again.
  10.101 +      return tid;
  10.102 +    }
  10.103 +  else
  10.104 +    {
  10.105 +      // Now, we register a new TypeId for this stack which will look
  10.106 +      // like a subclass of the Ns3NscStack. The class Ns3NscStack is effectively
  10.107 +      // mutating into a subclass of itself from the point of view of the TypeId
  10.108 +      // system _here_
  10.109 +      tid = TypeId (name.c_str ());
  10.110 +      tid.SetParent<Ns3NscStack> ();
  10.111 +      char buf[256];
  10.112 +      for (int i=0; m_stack->sysctl_getnum(i, buf, sizeof(buf)) > 0 ;i++)
  10.113 +        {
  10.114 +          char value[256];
  10.115 +          if (m_stack->sysctl_get (buf, value, sizeof(value)) > 0)
  10.116 +            {
  10.117 +              tid.AddAttribute (buf, "Help text",
  10.118 +                                StringValue (value),
  10.119 +                                Create<NscStackStringAccessor> (buf),
  10.120 +                                MakeStringChecker ());
  10.121 +            }
  10.122 +        }
  10.123 +      return tid;
  10.124 +    }
  10.125 +}
  10.126 +
  10.127 +std::string
  10.128 +Ns3NscStack::Get (std::string name) const
  10.129 +{
  10.130 +  char buf[512];
  10.131 +  if (m_stack->sysctl_get (name.c_str (), buf, sizeof(buf)) <= 0)
  10.132 +    { // name.c_str () is not a valid sysctl name, or internal NSC error (eg. error converting value)
  10.133 +      return NULL;
  10.134 +    }
  10.135 +  return std::string(buf);
  10.136 +}
  10.137 +
  10.138 +void
  10.139 +Ns3NscStack::Set (std::string name, std::string value)
  10.140 +{
  10.141 +  int ret = m_stack->sysctl_set (name.c_str (), value.c_str ());
  10.142 +  if (ret < 0)
  10.143 +    {
  10.144 +      NS_FATAL_ERROR ("setting " << name << " to " << value << "failed (retval " << ret << ")");
  10.145 +    }
  10.146 +}
  10.147 +
  10.148 +TypeId
  10.149 +Ns3NscStack::Ns3NscStack::GetTypeId (void)
  10.150 +{
  10.151 +  static TypeId tid = TypeId ("ns3::Ns3NscStack")
  10.152 +  .SetParent<Object> ()
  10.153 +  ;
  10.154 +  return tid;
  10.155 +}
  10.156 +
  10.157 +} // namespace ns3
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/src/internet-stack/nsc-sysctl.h	Tue Sep 02 10:45:06 2008 -0700
    11.3 @@ -0,0 +1,44 @@
    11.4 +/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
    11.5 +/*
    11.6 + * This program is free software; you can redistribute it and/or modify
    11.7 + * it under the terms of the GNU General Public License version 2 as
    11.8 + * published by the Free Software Foundation;
    11.9 + *
   11.10 + * This program is distributed in the hope that it will be useful,
   11.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   11.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   11.13 + * GNU General Public License for more details.
   11.14 + *
   11.15 + * You should have received a copy of the GNU General Public License
   11.16 + * along with this program; if not, write to the Free Software
   11.17 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   11.18 + *
   11.19 + * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
   11.20 + */
   11.21 +
   11.22 +#include <string>
   11.23 +
   11.24 +#include "ns3/attribute.h"
   11.25 +#include "ns3/object.h"
   11.26 +
   11.27 +struct INetStack;
   11.28 +
   11.29 +namespace ns3 {
   11.30 +
   11.31 +// This object represents the underlying nsc stack,
   11.32 +// which is aggregated to a Node object, and which provides access to the
   11.33 +// sysctls of the nsc stack through attributes.
   11.34 +class Ns3NscStack : public Object
   11.35 +{
   11.36 +public:
   11.37 +  static TypeId GetTypeId (void);
   11.38 +  virtual TypeId GetInstanceTypeId (void) const;
   11.39 +  void SetStack (INetStack *stack) {m_stack = stack;}
   11.40 +
   11.41 +private:
   11.42 +  friend class NscStackStringAccessor;
   11.43 +  void Set (std::string name, std::string value);
   11.44 +  std::string Get (std::string name) const;
   11.45 +  INetStack *m_stack;
   11.46 +};
   11.47 +} // namespace ns3
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/src/internet-stack/nsc-tcp-l4-protocol.cc	Tue Sep 02 10:45:06 2008 -0700
    12.3 @@ -0,0 +1,368 @@
    12.4 +/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
    12.5 +/*
    12.6 + * This program is free software; you can redistribute it and/or modify
    12.7 + * it under the terms of the GNU General Public License version 2 as
    12.8 + * published by the Free Software Foundation;
    12.9 + *
   12.10 + * This program is distributed in the hope that it will be useful,
   12.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   12.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12.13 + * GNU General Public License for more details.
   12.14 + *
   12.15 + * You should have received a copy of the GNU General Public License
   12.16 + * along with this program; if not, write to the Free Software
   12.17 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   12.18 + *
   12.19 + * based on earlier integration work by Tom Henderson and Sam Jansen.
   12.20 + * 2008 Florian Westphal <fw@strlen.de>
   12.21 + */
   12.22 +
   12.23 +#include "ns3/assert.h"
   12.24 +#include "ns3/log.h"
   12.25 +#include "ns3/nstime.h"
   12.26 +
   12.27 +#include "ns3/packet.h"
   12.28 +#include "ns3/node.h"
   12.29 +
   12.30 +#include "tcp-header.h"
   12.31 +#include "ipv4-end-point-demux.h"
   12.32 +#include "ipv4-end-point.h"
   12.33 +#include "ipv4-l3-protocol.h"
   12.34 +#include "nsc-tcp-l4-protocol.h"
   12.35 +#include "nsc-tcp-socket-impl.h"
   12.36 +#include "nsc-sysctl.h"
   12.37 +
   12.38 +#include "tcp-typedefs.h"
   12.39 +
   12.40 +#include <vector>
   12.41 +#include <sstream>
   12.42 +#include <dlfcn.h>
   12.43 +#include <iomanip>
   12.44 +
   12.45 +#include <netinet/ip.h>
   12.46 +#include <netinet/tcp.h>
   12.47 +
   12.48 +NS_LOG_COMPONENT_DEFINE ("NscTcpL4Protocol");
   12.49 +
   12.50 +namespace ns3 {
   12.51 +
   12.52 +NS_OBJECT_ENSURE_REGISTERED (NscTcpL4Protocol);
   12.53 +
   12.54 +/* see http://www.iana.org/assignments/protocol-numbers */
   12.55 +const uint8_t NscTcpL4Protocol::PROT_NUMBER = 6;
   12.56 +
   12.57 +ObjectFactory
   12.58 +NscTcpL4Protocol::GetDefaultRttEstimatorFactory (void)
   12.59 +{
   12.60 +  ObjectFactory factory;
   12.61 +  factory.SetTypeId (RttMeanDeviation::GetTypeId ());
   12.62 +  return factory;
   12.63 +}
   12.64 +
   12.65 +TypeId 
   12.66 +NscTcpL4Protocol::GetTypeId (void)
   12.67 +{
   12.68 +  static TypeId tid = TypeId ("ns3::NscTcpL4Protocol")
   12.69 +    .SetParent<Ipv4L4Protocol> ()
   12.70 +
   12.71 +    .AddAttribute ("RttEstimatorFactory",
   12.72 +                   "How RttEstimator objects are created.",
   12.73 +                   ObjectFactoryValue (GetDefaultRttEstimatorFactory ()),
   12.74 +                   MakeObjectFactoryAccessor (&NscTcpL4Protocol::m_rttFactory),
   12.75 +                   MakeObjectFactoryChecker ())
   12.76 +    ;
   12.77 +  return tid;
   12.78 +}
   12.79 +
   12.80 +int external_rand()
   12.81 +{
   12.82 +    return 1; // TODO
   12.83 +}
   12.84 +
   12.85 +NscTcpL4Protocol::NscTcpL4Protocol ()
   12.86 +  : m_endPoints (new Ipv4EndPointDemux ()),
   12.87 +    m_nscStack (0),
   12.88 +    m_nscInterfacesSetUp(false),
   12.89 +    m_softTimer (Timer::CANCEL_ON_DESTROY)
   12.90 +{
   12.91 +  m_dlopenHandle = NULL;
   12.92 +  NS_LOG_FUNCTION_NOARGS ();
   12.93 +  NS_LOG_LOGIC("Made a NscTcpL4Protocol "<<this);
   12.94 +}
   12.95 +
   12.96 +NscTcpL4Protocol::~NscTcpL4Protocol ()
   12.97 +{
   12.98 +  NS_LOG_FUNCTION_NOARGS ();
   12.99 +  dlclose(m_dlopenHandle);
  12.100 +}
  12.101 +
  12.102 +void
  12.103 +NscTcpL4Protocol::SetNscLibrary(const std::string &soname)
  12.104 +{
  12.105 +  NS_ASSERT(!m_dlopenHandle);
  12.106 +  m_dlopenHandle = dlopen(soname.c_str (), RTLD_NOW);
  12.107 +  if (m_dlopenHandle == NULL)
  12.108 +    NS_FATAL_ERROR (dlerror());
  12.109 +}
  12.110 +
  12.111 +void 
  12.112 +NscTcpL4Protocol::SetNode (Ptr<Node> node)
  12.113 +{
  12.114 +  m_node = node;
  12.115 +
  12.116 +  if (m_nscStack)
  12.117 +    { // stack has already been loaded...
  12.118 +      return;
  12.119 +    }
  12.120 +
  12.121 +  NS_ASSERT(m_dlopenHandle);
  12.122 +
  12.123 +  FCreateStack create = (FCreateStack)dlsym(m_dlopenHandle, "nsc_create_stack");
  12.124 +  NS_ASSERT(create);
  12.125 +  m_nscStack = create(this, this, external_rand);
  12.126 +  int hzval = m_nscStack->get_hz();
  12.127 +
  12.128 +  NS_ASSERT(hzval > 0);
  12.129 +
  12.130 +  m_softTimer.SetFunction (&NscTcpL4Protocol::SoftInterrupt, this);
  12.131 +  m_softTimer.SetDelay (MilliSeconds (1000/hzval));
  12.132 +  m_nscStack->init(hzval);
  12.133 +  // This enables stack and NSC debug messages
  12.134 +  // m_nscStack->set_diagnostic(1000);
  12.135 +
  12.136 +  Ptr<Ns3NscStack> nscStack = Create<Ns3NscStack> ();
  12.137 +  nscStack->SetStack (m_nscStack);
  12.138 +  node->AggregateObject (nscStack);
  12.139 +
  12.140 +  m_softTimer.Schedule ();
  12.141 +}
  12.142 +
  12.143 +int 
  12.144 +NscTcpL4Protocol::GetProtocolNumber (void) const
  12.145 +{
  12.146 +  return PROT_NUMBER;
  12.147 +}
  12.148 +int 
  12.149 +NscTcpL4Protocol::GetVersion (void) const
  12.150 +{
  12.151 +  return 2;
  12.152 +}
  12.153 +
  12.154 +void
  12.155 +NscTcpL4Protocol::DoDispose (void)
  12.156 +{
  12.157 +  NS_LOG_FUNCTION_NOARGS ();
  12.158 +  if (m_endPoints != 0)
  12.159 +    {
  12.160 +      delete m_endPoints;
  12.161 +      m_endPoints = 0;
  12.162 +    }
  12.163 +  m_node = 0;
  12.164 +  Ipv4L4Protocol::DoDispose ();
  12.165 +}
  12.166 +
  12.167 +Ptr<Socket>
  12.168 +NscTcpL4Protocol::CreateSocket (void)
  12.169 +{
  12.170 +  NS_LOG_FUNCTION_NOARGS ();
  12.171 +  if (!m_nscInterfacesSetUp)
  12.172 +  {
  12.173 +    Ptr<Ipv4> ip = m_node->GetObject<Ipv4> ();
  12.174 +
  12.175 +    const uint32_t nInterfaces = ip->GetNInterfaces ();
  12.176 +    // start from 1, ignore the loopback interface (HACK)
  12.177 +
  12.178 +    NS_ASSERT_MSG (nInterfaces <= 2, "nsc does not support multiple interfaces per node");
  12.179 +
  12.180 +    for (uint32_t i = 1; i < nInterfaces; i++)
  12.181 +    {
  12.182 +      Ipv4Address addr = ip->GetAddress(i);
  12.183 +      Ipv4Mask mask = ip->GetNetworkMask(i);
  12.184 +      uint16_t mtu = ip->GetMtu (i);
  12.185 +
  12.186 +      std::ostringstream addrOss, maskOss;
  12.187 +
  12.188 +      addr.Print(addrOss);
  12.189 +      mask.Print(maskOss);
  12.190 +
  12.191 +      NS_LOG_LOGIC ("if_attach " << addrOss.str().c_str() << " " << maskOss.str().c_str() << " " << mtu);
  12.192 +
  12.193 +      std::string addrStr = addrOss.str();
  12.194 +      std::string maskStr = maskOss.str();
  12.195 +      const char* addrCStr = addrStr.c_str();
  12.196 +      const char* maskCStr = maskStr.c_str();
  12.197 +      m_nscStack->if_attach(addrCStr, maskCStr, mtu);
  12.198 +
  12.199 +      if (i == 1)
  12.200 +      {
  12.201 +        // We need to come up with a default gateway here. Can't guarantee this to be
  12.202 +        // correct really...
  12.203 +
  12.204 +        uint8_t addrBytes[4];
  12.205 +        addr.Serialize(addrBytes);
  12.206 +
  12.207 +        // XXX: this is all a bit of a horrible hack
  12.208 +        //
  12.209 +        // Just increment the last octet, this gives a decent chance of this being
  12.210 +        // 'enough'.
  12.211 +        //
  12.212 +        // All we need is another address on the same network as the interface. This
  12.213 +        // will force the stack to output the packet out of the network interface.
  12.214 +        addrBytes[3]++;
  12.215 +        addr.Deserialize(addrBytes);
  12.216 +        addrOss.str("");
  12.217 +        addr.Print(addrOss);
  12.218 +        m_nscStack->add_default_gateway(addrOss.str().c_str());
  12.219 +      }
  12.220 +    }
  12.221 +    m_nscInterfacesSetUp = true;
  12.222 +  }
  12.223 +
  12.224 +  Ptr<RttEstimator> rtt = m_rttFactory.Create<RttEstimator> ();
  12.225 +  Ptr<NscTcpSocketImpl> socket = CreateObject<NscTcpSocketImpl> ();
  12.226 +  socket->SetNode (m_node);
  12.227 +  socket->SetTcp (this);
  12.228 +  socket->SetRtt (rtt);
  12.229 +  return socket;
  12.230 +}
  12.231 +
  12.232 +Ipv4EndPoint *
  12.233 +NscTcpL4Protocol::Allocate (void)
  12.234 +{
  12.235 +  NS_LOG_FUNCTION_NOARGS ();
  12.236 +  return m_endPoints->Allocate ();
  12.237 +}
  12.238 +
  12.239 +Ipv4EndPoint *
  12.240 +NscTcpL4Protocol::Allocate (Ipv4Address address)
  12.241 +{
  12.242 +  NS_LOG_FUNCTION (this << address);
  12.243 +  return m_endPoints->Allocate (address);
  12.244 +}
  12.245 +
  12.246 +Ipv4EndPoint *
  12.247 +NscTcpL4Protocol::Allocate (uint16_t port)
  12.248 +{
  12.249 +  NS_LOG_FUNCTION (this << port);
  12.250 +  return m_endPoints->Allocate (port);
  12.251 +}
  12.252 +
  12.253 +Ipv4EndPoint *
  12.254 +NscTcpL4Protocol::Allocate (Ipv4Address address, uint16_t port)
  12.255 +{
  12.256 +  NS_LOG_FUNCTION (this << address << port);
  12.257 +  return m_endPoints->Allocate (address, port);
  12.258 +}
  12.259 +
  12.260 +Ipv4EndPoint *
  12.261 +NscTcpL4Protocol::Allocate (Ipv4Address localAddress, uint16_t localPort,
  12.262 +                         Ipv4Address peerAddress, uint16_t peerPort)
  12.263 +{
  12.264 +  NS_LOG_FUNCTION (this << localAddress << localPort << peerAddress << peerPort);
  12.265 +  return m_endPoints->Allocate (localAddress, localPort,
  12.266 +                                peerAddress, peerPort);
  12.267 +}
  12.268 +
  12.269 +void 
  12.270 +NscTcpL4Protocol::DeAllocate (Ipv4EndPoint *endPoint)
  12.271 +{
  12.272 +  NS_LOG_FUNCTION (this << endPoint);
  12.273 +  // NSC m_endPoints->DeAllocate (endPoint);
  12.274 +}
  12.275 +
  12.276 +void
  12.277 +NscTcpL4Protocol::Receive (Ptr<Packet> packet,
  12.278 +             Ipv4Address const &source,
  12.279 +             Ipv4Address const &destination,
  12.280 +             Ptr<Ipv4Interface> incomingInterface)
  12.281 +{
  12.282 +  NS_LOG_FUNCTION (this << packet << source << destination << incomingInterface);
  12.283 +  Ipv4Header ipHeader;
  12.284 +  uint32_t packetSize = packet->GetSize();
  12.285 +
  12.286 +  // The way things work at the moment, the IP header has been removed
  12.287 +  // by the ns-3 IPv4 processing code. However, the NSC stack expects
  12.288 +  // a complete IP packet, so we add the IP header back.
  12.289 +  // Since the original header is already gone, we create a new one
  12.290 +  // based on the information we have.
  12.291 +  ipHeader.SetSource (source);
  12.292 +  ipHeader.SetDestination (destination);
  12.293 +  ipHeader.SetProtocol (PROT_NUMBER);
  12.294 +  ipHeader.SetPayloadSize (packetSize);
  12.295 +  ipHeader.SetTtl (1);
  12.296 +  // all NSC stacks check the IP checksum
  12.297 +  ipHeader.EnableChecksum ();
  12.298 +
  12.299 +  packet->AddHeader(ipHeader);
  12.300 +  packetSize = packet->GetSize();
  12.301 +
  12.302 +  const uint8_t *data = const_cast<uint8_t *>(packet->PeekData());
  12.303 +
  12.304 +  // deliver complete packet to the NSC network stack
  12.305 +  m_nscStack->if_receive_packet(0, data, packetSize);
  12.306 +  wakeup ();
  12.307 +}
  12.308 +
  12.309 +void NscTcpL4Protocol::SoftInterrupt (void)
  12.310 +{
  12.311 +  NS_LOG_FUNCTION_NOARGS ();
  12.312 +  m_nscStack->timer_interrupt ();
  12.313 +  m_nscStack->increment_ticks ();
  12.314 +  m_softTimer.Schedule ();
  12.315 +}
  12.316 +
  12.317 +void NscTcpL4Protocol::send_callback(const void* data, int datalen)
  12.318 +{
  12.319 +  Ptr<Packet> p;
  12.320 +
  12.321 +  NS_ASSERT(datalen > (int)sizeof(struct iphdr));
  12.322 +
  12.323 +  const uint8_t *rawdata = reinterpret_cast<const uint8_t *>(data);
  12.324 +  rawdata += sizeof(struct iphdr);
  12.325 +
  12.326 +  const struct iphdr *ipHdr = reinterpret_cast<const struct iphdr *>(data);
  12.327 +
  12.328 +  // create packet, without IP header. The TCP header is not touched.
  12.329 +  // Not using the IP header makes integration easier, but it destroys
  12.330 +  // eg. ECN.
  12.331 +  p = Create<Packet> (rawdata, datalen - sizeof(struct iphdr));
  12.332 +
  12.333 +  Ipv4Address saddr(ntohl(ipHdr->saddr));
  12.334 +  Ipv4Address daddr(ntohl(ipHdr->daddr));
  12.335 +
  12.336 +  Ptr<Ipv4L3Protocol> ipv4 = m_node->GetObject<Ipv4L3Protocol> ();
  12.337 +  if (ipv4 != 0)
  12.338 +    {
  12.339 +      ipv4->Send (p, saddr, daddr, PROT_NUMBER);
  12.340 +    }
  12.341 +  m_nscStack->if_send_finish(0);
  12.342 +}
  12.343 +
  12.344 +void NscTcpL4Protocol::wakeup()
  12.345 +{
  12.346 +  // TODO
  12.347 +  // this should schedule a timer to read from all tcp sockets now... this is
  12.348 +  // an indication that data might be waiting on the socket
  12.349 +
  12.350 +  Ipv4EndPointDemux::EndPoints endPoints = m_endPoints->GetAllEndPoints ();
  12.351 +  for (Ipv4EndPointDemux::EndPointsI endPoint = endPoints.begin ();
  12.352 +       endPoint != endPoints.end (); endPoint++) {
  12.353 +          // NSC HACK: (ab)use TcpSocket::ForwardUp for signalling
  12.354 +          (*endPoint)->ForwardUp (NULL, Ipv4Address(), 0);
  12.355 +  }
  12.356 +}
  12.357 +
  12.358 +void NscTcpL4Protocol::gettime(unsigned int* sec, unsigned int* usec)
  12.359 +{
  12.360 +  // Only used by the Linux network stack, e.g. during ISN generation
  12.361 +  // and in the kernel rng initialization routine. Also used in Linux
  12.362 +  // printk output.
  12.363 +  Time t = Simulator::Now ();
  12.364 +  int64_t us = t.GetMicroSeconds ();
  12.365 +  *sec = us / (1000*1000);
  12.366 +  *usec = us - *sec * (1000*1000);
  12.367 +}
  12.368 +
  12.369 +
  12.370 +}; // namespace ns3
  12.371 +
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/src/internet-stack/nsc-tcp-l4-protocol.h	Tue Sep 02 10:45:06 2008 -0700
    13.3 @@ -0,0 +1,121 @@
    13.4 +/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
    13.5 +/*
    13.6 + * This program is free software; you can redistribute it and/or modify
    13.7 + * it under the terms of the GNU General Public License version 2 as
    13.8 + * published by the Free Software Foundation;
    13.9 + *
   13.10 + * This program is distributed in the hope that it will be useful,
   13.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   13.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   13.13 + * GNU General Public License for more details.
   13.14 + *
   13.15 + * You should have received a copy of the GNU General Public License
   13.16 + * along with this program; if not, write to the Free Software
   13.17 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   13.18 + */
   13.19 +
   13.20 +#ifndef NSC_TCP_L4_PROTOCOL_H
   13.21 +#define NSC_TCP_L4_PROTOCOL_H
   13.22 +
   13.23 +#include <stdint.h>
   13.24 +
   13.25 +#include "ns3/packet.h"
   13.26 +#include "ns3/ipv4-address.h"
   13.27 +#include "ns3/ptr.h"
   13.28 +#include "ns3/object-factory.h"
   13.29 +#include "ipv4-end-point-demux.h"
   13.30 +#include "ipv4-l4-protocol.h"
   13.31 +#include "ipv4-interface.h"
   13.32 +
   13.33 +#include "tcp-header.h"
   13.34 +
   13.35 +#include "ns3/timer.h"
   13.36 +#include "nsc/sim/sim_interface.h"
   13.37 +
   13.38 +namespace ns3 {
   13.39 +
   13.40 +class Node;
   13.41 +class Socket;
   13.42 +class TcpHeader;
   13.43 +/**
   13.44 + * \brief Nsc wrapper glue.
   13.45 + */
   13.46 +class NscTcpL4Protocol : public Ipv4L4Protocol, ISendCallback, IInterruptCallback {
   13.47 +public:
   13.48 +  static const uint8_t PROT_NUMBER;
   13.49 +  static TypeId GetTypeId (void);
   13.50 +  /**
   13.51 +   * \brief Constructor
   13.52 +   */
   13.53 +  NscTcpL4Protocol ();
   13.54 +  virtual ~NscTcpL4Protocol ();
   13.55 +
   13.56 +  void SetNode (Ptr<Node> node);
   13.57 +  void SetNscLibrary(const std::string &lib);
   13.58 +
   13.59 +  virtual int GetProtocolNumber (void) const;
   13.60 +  virtual int GetVersion (void) const;
   13.61 +
   13.62 +  /**
   13.63 +   * \return A smart Socket pointer to a NscTcpSocketImpl, allocated by this instance
   13.64 +   * of the TCP protocol
   13.65 +   */
   13.66 +  Ptr<Socket> CreateSocket (void);
   13.67 +
   13.68 +  Ipv4EndPoint *Allocate (void);
   13.69 +  Ipv4EndPoint *Allocate (Ipv4Address address);
   13.70 +  Ipv4EndPoint *Allocate (uint16_t port);
   13.71 +  Ipv4EndPoint *Allocate (Ipv4Address address, uint16_t port);
   13.72 +  Ipv4EndPoint *Allocate (Ipv4Address localAddress, uint16_t localPort,
   13.73 +                          Ipv4Address peerAddress, uint16_t peerPort);
   13.74 +
   13.75 +  void DeAllocate (Ipv4EndPoint *endPoint);
   13.76 +
   13.77 +  /**
   13.78 +   * \brief Recieve a packet up the protocol stack
   13.79 +   * \param p The Packet to dump the contents into
   13.80 +   * \param source The source's Ipv4Address
   13.81 +   * \param destination The destinations Ipv4Address
   13.82 +   * \param incomingInterface The Ipv4Interface it was received on
   13.83 +   */
   13.84 +  virtual void Receive (Ptr<Packet> p,
   13.85 +                       Ipv4Address const &source,
   13.86 +                       Ipv4Address const &destination,
   13.87 +                       Ptr<Ipv4Interface> incomingInterface);
   13.88 +
   13.89 +  // NSC callbacks.
   13.90 +  // NSC invokes these hooks to interact with the simulator.
   13.91 +  // In any case, these methods are only to be called by NSC.
   13.92 +  //
   13.93 +  // send_callback is invoked by NSCs 'ethernet driver' to re-inject
   13.94 +  // a packet (i.e. an octet soup consisting of an IP Header, TCP Header
   13.95 +  // and user payload, if any), into ns-3.
   13.96 +  virtual void send_callback(const void *data, int datalen);
   13.97 +  // This is called by the NSC stack whenever something of interest
   13.98 +  // has happened, e.g. when data arrives on a socket, a listen socket
   13.99 +  // has a new connection pending, etc.
  13.100 +  virtual void wakeup();
  13.101 +  // This is called by the Linux stack RNG initialization.
  13.102 +  // Its also used by the cradle code to add a timestamp to
  13.103 +  // printk/printf/debug output.
  13.104 +  virtual void gettime(unsigned int *, unsigned int *);
  13.105 +
  13.106 +protected:
  13.107 +  virtual void DoDispose (void);
  13.108 +private:
  13.109 +  Ptr<Node> m_node;
  13.110 +  Ipv4EndPointDemux *m_endPoints;
  13.111 +  ObjectFactory m_rttFactory;
  13.112 +private:
  13.113 +  void SoftInterrupt (void);
  13.114 +  static ObjectFactory GetDefaultRttEstimatorFactory (void);
  13.115 +  friend class NscTcpSocketImpl;
  13.116 +  INetStack* m_nscStack;
  13.117 +  void *m_dlopenHandle;
  13.118 +  bool m_nscInterfacesSetUp;
  13.119 +  Timer m_softTimer;
  13.120 +};
  13.121 +
  13.122 +}; // namespace ns3
  13.123 +
  13.124 +#endif /* NSC_TCP_L4_PROTOCOL_H */
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/src/internet-stack/nsc-tcp-socket-factory-impl.cc	Tue Sep 02 10:45:06 2008 -0700
    14.3 @@ -0,0 +1,50 @@
    14.4 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
    14.5 +/*
    14.6 + * This program is free software; you can redistribute it and/or modify
    14.7 + * it under the terms of the GNU General Public License version 2 as
    14.8 + * published by the Free Software Foundation;
    14.9 + *
   14.10 + * This program is distributed in the hope that it will be useful,
   14.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   14.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14.13 + * GNU General Public License for more details.
   14.14 + *
   14.15 + * You should have received a copy of the GNU General Public License
   14.16 + * along with this program; if not, write to the Free Software
   14.17 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   14.18 + */
   14.19 +#include "nsc-tcp-socket-factory-impl.h"
   14.20 +#include "nsc-tcp-l4-protocol.h"
   14.21 +#include "ns3/socket.h"
   14.22 +#include "ns3/assert.h"
   14.23 +
   14.24 +namespace ns3 {
   14.25 +
   14.26 +NscTcpSocketFactoryImpl::NscTcpSocketFactoryImpl ()
   14.27 +  : m_tcp (0)
   14.28 +{}
   14.29 +NscTcpSocketFactoryImpl::~NscTcpSocketFactoryImpl ()
   14.30 +{
   14.31 +  NS_ASSERT (m_tcp == 0);
   14.32 +}
   14.33 +
   14.34 +void 
   14.35 +NscTcpSocketFactoryImpl::SetTcp (Ptr<NscTcpL4Protocol> tcp)
   14.36 +{
   14.37 +  m_tcp = tcp;
   14.38 +}
   14.39 +
   14.40 +Ptr<Socket>
   14.41 +NscTcpSocketFactoryImpl::CreateSocket (void)
   14.42 +{
   14.43 +  return m_tcp->CreateSocket ();
   14.44 +}
   14.45 +
   14.46 +void 
   14.47 +NscTcpSocketFactoryImpl::DoDispose (void)
   14.48 +{
   14.49 +  m_tcp = 0;
   14.50 +  TcpSocketFactory::DoDispose ();
   14.51 +}
   14.52 +
   14.53 +} // namespace ns3
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/src/internet-stack/nsc-tcp-socket-factory-impl.h	Tue Sep 02 10:45:06 2008 -0700
    15.3 @@ -0,0 +1,44 @@
    15.4 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
    15.5 +/*
    15.6 + * This program is free software; you can redistribute it and/or modify
    15.7 + * it under the terms of the GNU General Public License version 2 as
    15.8 + * published by the Free Software Foundation;
    15.9 + *
   15.10 + * This program is distributed in the hope that it will be useful,
   15.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   15.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   15.13 + * GNU General Public License for more details.
   15.14 + *
   15.15 + * You should have received a copy of the GNU General Public License
   15.16 + * along with this program; if not, write to the Free Software
   15.17 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   15.18 + */
   15.19 +#ifndef NSC_TCP_SOCKET_FACTORY_IMPL_H
   15.20 +#define NSC_TCP_SOCKET_FACTORY_IMPL_H
   15.21 +
   15.22 +#include "ns3/tcp-socket-factory.h"
   15.23 +#include "ns3/ptr.h"
   15.24 +
   15.25 +namespace ns3 {
   15.26 +
   15.27 +class NscTcpL4Protocol;
   15.28 +
   15.29 +class NscTcpSocketFactoryImpl : public TcpSocketFactory
   15.30 +{
   15.31 +public:
   15.32 +  NscTcpSocketFactoryImpl ();
   15.33 +  virtual ~NscTcpSocketFactoryImpl ();
   15.34 +
   15.35 +  void SetTcp (Ptr<NscTcpL4Protocol> tcp);
   15.36 +
   15.37 +  virtual Ptr<Socket> CreateSocket (void);
   15.38 +
   15.39 +protected:
   15.40 +  virtual void DoDispose (void);
   15.41 +private:
   15.42 +  Ptr<NscTcpL4Protocol> m_tcp;
   15.43 +};
   15.44 +
   15.45 +} // namespace ns3
   15.46 +
   15.47 +#endif /* NSC_TCP_SOCKET_FACTORY_IMPL_H */
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/src/internet-stack/nsc-tcp-socket-impl.cc	Tue Sep 02 10:45:06 2008 -0700
    16.3 @@ -0,0 +1,842 @@
    16.4 +/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
    16.5 +/*
    16.6 + * This program is free software; you can redistribute it and/or modify
    16.7 + * it under the terms of the GNU General Public License version 2 as
    16.8 + * published by the Free Software Foundation;
    16.9 + *
   16.10 + * This program is distributed in the hope that it will be useful,
   16.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   16.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   16.13 + * GNU General Public License for more details.
   16.14 + *
   16.15 + * You should have received a copy of the GNU General Public License
   16.16 + * along with this program; if not, write to the Free Software
   16.17 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   16.18 + *
   16.19 + * based on tcp-socket-impl.cc, Author: Raj Bhattacharjea <raj.b@gatech.edu>
   16.20 + * Author: Florian Westphal <fw@strlen.de>
   16.21 + */
   16.22 +
   16.23 +#include "ns3/node.h"
   16.24 +#include "ns3/inet-socket-address.h"
   16.25 +#include "ns3/log.h"
   16.26 +#include "ns3/ipv4.h"
   16.27 +#include "ipv4-end-point.h"
   16.28 +#include "ipv4-l4-demux.h"
   16.29 +#include "nsc-tcp-l4-protocol.h"
   16.30 +#include "nsc-tcp-socket-impl.h"
   16.31 +#include "ns3/simulation-singleton.h"
   16.32 +#include "tcp-typedefs.h"
   16.33 +#include "ns3/simulator.h"
   16.34 +#include "ns3/packet.h"
   16.35 +#include "ns3/uinteger.h"
   16.36 +#include "ns3/trace-source-accessor.h"
   16.37 +
   16.38 +#include <algorithm>
   16.39 +
   16.40 +#include <sys/socket.h>
   16.41 +#include <netinet/in.h>
   16.42 +#include <arpa/inet.h>
   16.43 +#include <netinet/ip.h>
   16.44 +#include <netinet/tcp.h>
   16.45 +
   16.46 +#include "nsc/sim/sim_errno.h"
   16.47 +
   16.48 +NS_LOG_COMPONENT_DEFINE ("NscTcpSocketImpl");
   16.49 +
   16.50 +using namespace std;
   16.51 +
   16.52 +namespace ns3 {
   16.53 +
   16.54 +NS_OBJECT_ENSURE_REGISTERED (NscTcpSocketImpl);
   16.55 +
   16.56 +TypeId
   16.57 +NscTcpSocketImpl::GetTypeId ()
   16.58 +{
   16.59 +  static TypeId tid = TypeId("ns3::NscTcpSocketImpl")
   16.60 +    .SetParent<TcpSocket> ()
   16.61 +    .AddTraceSource ("CongestionWindow",
   16.62 +                     "The TCP connection's congestion window",
   16.63 +                     MakeTraceSourceAccessor (&NscTcpSocketImpl::m_cWnd))
   16.64 +    ;
   16.65 +  return tid;
   16.66 +}
   16.67 +
   16.68 +  NscTcpSocketImpl::NscTcpSocketImpl ()
   16.69 +  : m_endPoint (0),
   16.70 +    m_node (0),
   16.71 +    m_tcp (0),
   16.72 +    m_peerAddress ("0.0.0.0", 0),
   16.73 +    m_errno (ERROR_NOTERROR),
   16.74 +    m_shutdownSend (false),
   16.75 +    m_shutdownRecv (false),
   16.76 +    m_connected (false),
   16.77 +    m_state (CLOSED),
   16.78 +    m_closeOnEmpty (false),
   16.79 +    m_txBufferSize (0),
   16.80 +    m_rtt (0),
   16.81 +    m_lastMeasuredRtt (Seconds(0.0))
   16.82 +{
   16.83 +  NS_LOG_FUNCTION (this);
   16.84 +}
   16.85 +
   16.86 +NscTcpSocketImpl::NscTcpSocketImpl(const NscTcpSocketImpl& sock)
   16.87 +  : TcpSocket(sock), //copy the base class callbacks
   16.88 +    m_delAckMaxCount (sock.m_delAckMaxCount),
   16.89 +    m_delAckTimeout (sock.m_delAckTimeout),
   16.90 +    m_endPoint (0),
   16.91 +    m_node (sock.m_node),
   16.92 +    m_tcp (sock.m_tcp),
   16.93 +    m_remoteAddress (sock.m_remoteAddress),
   16.94 +    m_remotePort (sock.m_remotePort),
   16.95 +    m_localAddress (sock.m_localAddress),
   16.96 +    m_localPort (sock.m_localPort),
   16.97 +    m_peerAddress (sock.m_peerAddress),
   16.98 +    m_errno (sock.m_errno),
   16.99 +    m_shutdownSend (sock.m_shutdownSend),
  16.100 +    m_shutdownRecv (sock.m_shutdownRecv),
  16.101 +    m_connected (sock.m_connected),
  16.102 +    m_state (sock.m_state),
  16.103 +    m_closeOnEmpty (sock.m_closeOnEmpty),
  16.104 +    m_segmentSize (sock.m_segmentSize),
  16.105 +    m_rxWindowSize (sock.m_rxWindowSize),
  16.106 +    m_advertisedWindowSize (sock.m_advertisedWindowSize),
  16.107 +    m_cWnd (sock.m_cWnd),
  16.108 +    m_ssThresh (sock.m_ssThresh),
  16.109 +    m_initialCWnd (sock.m_initialCWnd),
  16.110 +    m_rtt (0),
  16.111 +    m_lastMeasuredRtt (Seconds(0.0)),
  16.112 +    m_cnTimeout (sock.m_cnTimeout),
  16.113 +    m_cnCount (sock.m_cnCount),
  16.114 +    m_rxAvailable (0),
  16.115 +    m_nscTcpSocket (0),
  16.116 +    m_sndBufSize (sock.m_sndBufSize)
  16.117 +{
  16.118 +  NS_LOG_FUNCTION_NOARGS ();
  16.119 +  NS_LOG_LOGIC("Invoked the copy constructor");
  16.120 +  //copy the pending data if necessary
  16.121 +  if(!sock.m_txBuffer.empty () )
  16.122 +    {
  16.123 +      m_txBuffer = sock.m_txBuffer;
  16.124 +    }
  16.125 +  //copy the rtt if necessary
  16.126 +  if (sock.m_rtt)
  16.127 +    {
  16.128 +      m_rtt = sock.m_rtt->Copy();
  16.129 +    }
  16.130 +  //can't "copy" the endpoint just yes, must do this when we know the peer info
  16.131 +  //too; this is in SYN_ACK_TX
  16.132 +}
  16.133 +
  16.134 +NscTcpSocketImpl::~NscTcpSocketImpl ()
  16.135 +{
  16.136 +  NS_LOG_FUNCTION(this);
  16.137 +  m_node = 0;
  16.138 +  if (m_endPoint != 0)
  16.139 +    {
  16.140 +      NS_ASSERT (m_tcp != 0);
  16.141 +      /**
  16.142 +       * Note that this piece of code is a bit tricky:
  16.143 +       * when DeAllocate is called, it will call into
  16.144 +       * Ipv4EndPointDemux::Deallocate which triggers
  16.145 +       * a delete of the associated endPoint which triggers
  16.146 +       * in turn a call to the method ::Destroy below
  16.147 +       * will will zero the m_endPoint field.
  16.148 +       */
  16.149 +      NS_ASSERT (m_endPoint != 0);
  16.150 +      m_tcp->DeAllocate (m_endPoint);
  16.151 +      NS_ASSERT (m_endPoint == 0);
  16.152 +    }
  16.153 +  m_tcp = 0;
  16.154 +}
  16.155 +
  16.156 +void
  16.157 +NscTcpSocketImpl::SetNode (Ptr<Node> node)
  16.158 +{
  16.159 +  m_node = node;
  16.160 +  // Initialize some variables 
  16.161 +  m_cWnd = m_initialCWnd * m_segmentSize;
  16.162 +  m_rxWindowSize = m_advertisedWindowSize;
  16.163 +}
  16.164 +
  16.165 +void 
  16.166 +NscTcpSocketImpl::SetTcp (Ptr<NscTcpL4Protocol> tcp)
  16.167 +{
  16.168 +  m_nscTcpSocket = tcp->m_nscStack->new_tcp_socket();
  16.169 +  m_tcp = tcp;
  16.170 +}
  16.171 +void 
  16.172 +NscTcpSocketImpl::SetRtt (Ptr<RttEstimator> rtt)
  16.173 +{
  16.174 +  m_rtt = rtt;
  16.175 +}
  16.176 +
  16.177 +
  16.178 +enum Socket::SocketErrno
  16.179 +NscTcpSocketImpl::GetErrno (void) const
  16.180 +{
  16.181 +  NS_LOG_FUNCTION_NOARGS ();
  16.182 +  return m_errno;
  16.183 +}
  16.184 +
  16.185 +Ptr<Node>
  16.186 +NscTcpSocketImpl::GetNode (void) const
  16.187 +{
  16.188 +  NS_LOG_FUNCTION_NOARGS ();
  16.189 +  return m_node;
  16.190 +}
  16.191 +
  16.192 +void 
  16.193 +NscTcpSocketImpl::Destroy (void)
  16.194 +{
  16.195 +  NS_LOG_FUNCTION_NOARGS ();
  16.196 +  m_node = 0;
  16.197 +  m_endPoint = 0;
  16.198 +  m_tcp = 0;
  16.199 +}
  16.200 +int
  16.201 +NscTcpSocketImpl::FinishBind (void)
  16.202 +{
  16.203 +  NS_LOG_FUNCTION_NOARGS ();
  16.204 +  if (m_endPoint == 0)
  16.205 +    {
  16.206 +      return -1;
  16.207 +    }
  16.208 +  m_endPoint->SetRxCallback (MakeCallback (&NscTcpSocketImpl::ForwardUp, Ptr<NscTcpSocketImpl>(this)));
  16.209 +  m_endPoint->SetDestroyCallback (MakeCallback (&NscTcpSocketImpl::Destroy, Ptr<NscTcpSocketImpl>(this)));
  16.210 +  m_localAddress = m_endPoint->GetLocalAddress ();
  16.211 +  m_localPort = m_endPoint->GetLocalPort ();
  16.212 +  return 0;
  16.213 +}
  16.214 +
  16.215 +int
  16.216 +NscTcpSocketImpl::Bind (void)
  16.217 +{
  16.218 +  NS_LOG_FUNCTION_NOARGS ();
  16.219 +  m_endPoint = m_tcp->Allocate ();
  16.220 +  return FinishBind ();
  16.221 +}
  16.222 +int 
  16.223 +NscTcpSocketImpl::Bind (const Address &address)
  16.224 +{
  16.225 +  NS_LOG_FUNCTION (this<<address);
  16.226 +  if (!InetSocketAddress::IsMatchingType (address))
  16.227 +    {
  16.228 +      return ERROR_INVAL;
  16.229 +    }
  16.230 +  InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
  16.231 +  Ipv4Address ipv4 = transport.GetIpv4 ();
  16.232 +  uint16_t port = transport.GetPort ();
  16.233 +  if (ipv4 == Ipv4Address::GetAny () && port == 0)
  16.234 +    {
  16.235 +      m_endPoint = m_tcp->Allocate ();
  16.236 +      NS_LOG_LOGIC ("TcpSocketImpl "<<this<<" got an endpoint: "<<m_endPoint);
  16.237 +    }
  16.238 +  else if (ipv4 == Ipv4Address::GetAny () && port != 0)
  16.239 +    {
  16.240 +      m_endPoint = m_tcp->Allocate (port);
  16.241 +      NS_LOG_LOGIC ("TcpSocketImpl "<<this<<" got an endpoint: "<<m_endPoint);
  16.242 +    }
  16.243 +  else if (ipv4 != Ipv4Address::GetAny () && port == 0)
  16.244 +    {
  16.245 +      m_endPoint = m_tcp->Allocate (ipv4);
  16.246 +      NS_LOG_LOGIC ("TcpSocketImpl "<<this<<" got an endpoint: "<<m_endPoint);
  16.247 +    }
  16.248 +  else if (ipv4 != Ipv4Address::GetAny () && port != 0)
  16.249 +    {
  16.250 +      m_endPoint = m_tcp->Allocate (ipv4, port);
  16.251 +      NS_LOG_LOGIC ("TcpSocketImpl "<<this<<" got an endpoint: "<<m_endPoint);
  16.252 +    }
  16.253 +
  16.254 +  m_localPort = port;
  16.255 +  return FinishBind ();
  16.256 +}
  16.257 +
  16.258 +int 
  16.259 +NscTcpSocketImpl::ShutdownSend (void)
  16.260 +{
  16.261 +  NS_LOG_FUNCTION_NOARGS ();
  16.262 +  m_shutdownSend = true;
  16.263 +  return 0;
  16.264 +}
  16.265 +int 
  16.266 +NscTcpSocketImpl::ShutdownRecv (void)
  16.267 +{
  16.268 +  NS_LOG_FUNCTION_NOARGS ();
  16.269 +  m_shutdownRecv = false;
  16.270 +  return 0;
  16.271 +}
  16.272 +
  16.273 +int
  16.274 +NscTcpSocketImpl::Close (void)
  16.275 +{
  16.276 +  NS_LOG_FUNCTION (this << m_state);
  16.277 +
  16.278 +  if (m_state == CLOSED)
  16.279 +    {
  16.280 +      return -1;
  16.281 +    }
  16.282 +  if (!m_txBuffer.empty ())
  16.283 +    { // App close with pending data must wait until all data transmitted
  16.284 +      m_closeOnEmpty = true;
  16.285 +      NS_LOG_LOGIC("Socket " << this << 
  16.286 +                   " deferring close, state " << m_state);
  16.287 +      return 0;
  16.288 +    }
  16.289 +
  16.290 +  m_nscTcpSocket->disconnect();
  16.291 +  m_state = CLOSED;
  16.292 +  ShutdownSend ();
  16.293 +  return 0;
  16.294 +}
  16.295 +
  16.296 +int
  16.297 +NscTcpSocketImpl::Connect (const Address & address)
  16.298 +{
  16.299 +  NS_LOG_FUNCTION (this << address);
  16.300 +  if (m_endPoint == 0)
  16.301 +    {
  16.302 +      if (Bind () == -1)
  16.303 +        {
  16.304 +          NS_ASSERT (m_endPoint == 0);
  16.305 +          return -1;
  16.306 +        }
  16.307 +      NS_ASSERT (m_endPoint != 0);
  16.308 +    }
  16.309 +  InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
  16.310 +  m_remoteAddress = transport.GetIpv4 ();
  16.311 +  m_remotePort = transport.GetPort ();
  16.312 +
  16.313 +  struct in_addr remoteAddr;
  16.314 +  uint32_t addr32;
  16.315 +
  16.316 +  m_remoteAddress.Serialize((uint8_t*)&addr32);
  16.317 +  remoteAddr.s_addr = addr32;
  16.318 +
  16.319 +  m_nscTcpSocket->connect(inet_ntoa(remoteAddr), m_remotePort);
  16.320 +  m_state = SYN_SENT;
  16.321 +  return 0;
  16.322 +}
  16.323 +
  16.324 +int
  16.325 +NscTcpSocketImpl::Send (const Ptr<Packet> p, uint32_t flags)
  16.326 +{
  16.327 +  NS_LOG_FUNCTION (this << p);
  16.328 +
  16.329 +  NS_ASSERT (p->GetSize () > 0);
  16.330 +  if (m_state == ESTABLISHED || m_state == SYN_SENT || m_state == CLOSE_WAIT)
  16.331 +  {
  16.332 +    if (p->GetSize () > GetTxAvailable ())
  16.333 +    {
  16.334 +      m_errno = ERROR_MSGSIZE;
  16.335 +      return -1;
  16.336 +    }
  16.337 +
  16.338 +    bool txEmpty = m_txBuffer.empty();
  16.339 +    if (m_state == ESTABLISHED)
  16.340 +      {
  16.341 +        if (txEmpty)
  16.342 +          {
  16.343 +            m_txBuffer.push(p);
  16.344 +            m_txBufferSize += p->GetSize ();
  16.345 +          }
  16.346 +        if (!SendPendingData())
  16.347 +          {
  16.348 +             if (m_errno == ERROR_AGAIN)
  16.349 +               {
  16.350 +                 return txEmpty ? p->GetSize () : -1;
  16.351 +               }
  16.352 +             if (txEmpty)
  16.353 +               {
  16.354 +                  m_txBuffer.pop ();
  16.355 +                  m_txBufferSize = 0;
  16.356 +               }
  16.357 +             return -1;
  16.358 +          }
  16.359 +      }
  16.360 +      else
  16.361 +      {  // SYN_SET -- Queue Data
  16.362 +         m_txBuffer.push(p);
  16.363 +         m_txBufferSize += p->GetSize ();
  16.364 +      }
  16.365 +    return p->GetSize ();
  16.366 +  }
  16.367 +  else
  16.368 +  {
  16.369 +    m_errno = ERROR_NOTCONN;
  16.370 +    return -1;
  16.371 +  }
  16.372 +}
  16.373 +
  16.374 +int
  16.375 +NscTcpSocketImpl::SendTo (Ptr<Packet> p, uint32_t flags, const Address &address)
  16.376 +{
  16.377 +  NS_LOG_FUNCTION (this << address << p);
  16.378 +  if (!m_connected)
  16.379 +    {
  16.380 +      m_errno = ERROR_NOTCONN;
  16.381 +      return -1;
  16.382 +    }
  16.383 +  else
  16.384 +    {
  16.385 +      return Send (p, flags); //drop the address according to BSD manpages
  16.386 +    }
  16.387 +}
  16.388 +
  16.389 +uint32_t
  16.390 +NscTcpSocketImpl::GetTxAvailable (void) const
  16.391 +{
  16.392 +  NS_LOG_FUNCTION_NOARGS ();
  16.393 +  if (m_txBufferSize != 0)
  16.394 +    {
  16.395 +      NS_ASSERT (m_txBufferSize <= m_sndBufSize);
  16.396 +      return m_sndBufSize - m_txBufferSize;
  16.397 +    }
  16.398 +  else
  16.399 +    {
  16.400 +      return m_sndBufSize;
  16.401 +    }
  16.402 +}
  16.403 +
  16.404 +int
  16.405 +NscTcpSocketImpl::Listen (uint32_t q)
  16.406 +{
  16.407 +  NS_LOG_FUNCTION (this << q);
  16.408 +  m_nscTcpSocket->listen(m_localPort);
  16.409 +  m_state = LISTEN;
  16.410 +  return 0;
  16.411 +}
  16.412 +
  16.413 +
  16.414 +void
  16.415 +NscTcpSocketImpl::NSCWakeup ()
  16.416 +{
  16.417 +  switch (m_state) {
  16.418 +  case SYN_SENT:
  16.419 +      if (!m_nscTcpSocket->is_connected())
  16.420 +          break;
  16.421 +      m_state = ESTABLISHED;
  16.422 +      Simulator::ScheduleNow(&NscTcpSocketImpl::ConnectionSucceeded, this);
  16.423 +      // fall through to schedule read/write events
  16.424 +  case ESTABLISHED:
  16.425 +      if (!m_txBuffer.empty ())
  16.426 +          Simulator::ScheduleNow(&NscTcpSocketImpl::SendPendingData, this);
  16.427 +      Simulator::ScheduleNow(&NscTcpSocketImpl::ReadPendingData, this);
  16.428 +      break;
  16.429 +  case LISTEN:
  16.430 +      Simulator::ScheduleNow(&NscTcpSocketImpl::Accept, this);
  16.431 +      break;
  16.432 +  case CLOSED: break;
  16.433 +  default:
  16.434 +      NS_LOG_DEBUG (this << " invalid state: " << m_state);
  16.435 +  }
  16.436 +}
  16.437 +
  16.438 +Ptr<Packet>
  16.439 +NscTcpSocketImpl::Recv (uint32_t maxSize, uint32_t flags)
  16.440 +{
  16.441 +  NS_LOG_FUNCTION_NOARGS ();
  16.442 +  if (m_deliveryQueue.empty() )
  16.443 +    {
  16.444 +      return 0;
  16.445 +    }
  16.446 +  Ptr<Packet> p = m_deliveryQueue.front ();
  16.447 +  if (p->GetSize () <= maxSize)
  16.448 +    {
  16.449 +      m_deliveryQueue.pop ();
  16.450 +      m_rxAvailable -= p->GetSize ();
  16.451 +    }
  16.452 +  else
  16.453 +    {
  16.454 +      p = 0;
  16.455 +    }
  16.456 +  return p;
  16.457 +}
  16.458 +
  16.459 +Ptr<Packet>
  16.460 +NscTcpSocketImpl::RecvFrom (uint32_t maxSize, uint32_t flags,
  16.461 +  Address &fromAddress)
  16.462 +{
  16.463 +  NS_LOG_FUNCTION (this << maxSize << flags);
  16.464 +  Ptr<Packet> packet = Recv (maxSize, flags);
  16.465 +  if (packet != 0)
  16.466 +    {
  16.467 +      SocketAddressTag tag;
  16.468 +      bool found;
  16.469 +      found = packet->FindFirstMatchingTag (tag);
  16.470 +      NS_ASSERT (found);
  16.471 +      fromAddress = tag.GetAddress ();
  16.472 +    }
  16.473 +  return packet;
  16.474 +}
  16.475 +
  16.476 +uint32_t
  16.477 +NscTcpSocketImpl::GetRxAvailable (void) const
  16.478 +{
  16.479 +  NS_LOG_FUNCTION_NOARGS ();
  16.480 +  // We separately maintain this state to avoid walking the queue 
  16.481 +  // every time this might be called
  16.482 +  return m_rxAvailable;
  16.483 +}
  16.484 +
  16.485 +void
  16.486 +NscTcpSocketImpl::ForwardUp (Ptr<Packet> packet, Ipv4Address ipv4, uint16_t port)
  16.487 +{
  16.488 +  NSCWakeup();
  16.489 +}
  16.490 +
  16.491 +void NscTcpSocketImpl::CompleteFork(void)
  16.492 +{
  16.493 +  // The address pairs (m_localAddress, m_localPort, m_remoteAddress, m_remotePort)
  16.494 +  // are bogus, but this isn't important at the moment, because
  16.495 +  // address <-> Socket handling is done by NSC internally.
  16.496 +  // We only need to add the new ns-3 socket to the list of sockets, so
  16.497 +  // we use plain Allocate() instead of Allocate(m_localAddress, ... )
  16.498 +  uint8_t buf[4];
  16.499 +  int port;
  16.500 +  size_t buflen = sizeof(buf);
  16.501 +
  16.502 +  if (0 == m_nscTcpSocket->getpeername((void *) buf, &buflen, &port)) {
  16.503 +    m_remotePort = ntohs(port);
  16.504 +    m_remoteAddress = m_remoteAddress.Deserialize(buf);
  16.505 +    m_peerAddress = InetSocketAddress(m_remoteAddress, m_remotePort);
  16.506 +  }
  16.507 +
  16.508 +  m_endPoint = m_tcp->Allocate ();
  16.509 +
  16.510 +  //the cloned socket with be in listen state, so manually change state
  16.511 +  NS_ASSERT(m_state == LISTEN);
  16.512 +  m_state = ESTABLISHED;
  16.513 +
  16.514 +  buflen = sizeof(buf);
  16.515 +  if (0 == m_nscTcpSocket->getsockname((void *) &buf, &buflen, &port))
  16.516 +    m_localAddress = m_localAddress.Deserialize(buf);
  16.517 +
  16.518 +  NS_LOG_LOGIC ("NscTcpSocketImpl " << this << " accepted connection from " 
  16.519 +                 << m_remoteAddress << ":" << m_remotePort
  16.520 +                 << " to " << m_localAddress << ":" << m_localPort);
  16.521 +  //equivalent to FinishBind
  16.522 +  m_endPoint->SetRxCallback (MakeCallback (&NscTcpSocketImpl::ForwardUp, Ptr<NscTcpSocketImpl>(this)));
  16.523 +  m_endPoint->SetDestroyCallback (MakeCallback (&NscTcpSocketImpl::Destroy, Ptr<NscTcpSocketImpl>(this)));
  16.524 +
  16.525 +  NotifyNewConnectionCreated (this, m_peerAddress);
  16.526 +}
  16.527 +
  16.528 +void NscTcpSocketImpl::ConnectionSucceeded()
  16.529 +{ // We would preferred to have scheduled an event directly to
  16.530 +  // NotifyConnectionSucceeded, but (sigh) these are protected
  16.531 +  // and we can get the address of it :(
  16.532 +
  16.533 +  uint8_t buf[4];
  16.534 +  int port;
  16.535 +  size_t buflen = sizeof(buf);
  16.536 +  if (0 == m_nscTcpSocket->getsockname((void *) &buf, &buflen, &port)) {
  16.537 +    m_localAddress = m_localAddress.Deserialize(buf);
  16.538 +    m_localPort = ntohs(port);
  16.539 +  }
  16.540 +
  16.541 +  NS_LOG_LOGIC ("NscTcpSocketImpl " << this << " connected to "
  16.542 +                 << m_remoteAddress << ":" << m_remotePort
  16.543 +                 << " from " << m_localAddress << ":" << m_localPort);
  16.544 +  NotifyConnectionSucceeded();
  16.545 +}
  16.546 +
  16.547 +
  16.548 +bool NscTcpSocketImpl::Accept (void)
  16.549 +{
  16.550 +  if (m_state == CLOSED)
  16.551 +    {  // Happens if application closes listening socket after Accept() was scheduled.
  16.552 +      return false;
  16.553 +    }
  16.554 +  NS_ASSERT (m_state == LISTEN);
  16.555 +
  16.556 +  if (!m_nscTcpSocket->is_listening())
  16.557 +    {
  16.558 +      return false;
  16.559 +    }
  16.560 +  INetStreamSocket *newsock;
  16.561 +  int res = m_nscTcpSocket->accept(&newsock);
  16.562 +  if (res != 0)
  16.563 +    {
  16.564 +      return false;
  16.565 +    }
  16.566 +// We could obtain a fromAddress using getpeername, but we've already
  16.567 +// finished the tcp handshake here, i.e. this is a new connection
  16.568 +// and not a connection request.
  16.569 +// if (!NotifyConnectionRequest(fromAddress))
  16.570 +//   return true;
  16.571 +
  16.572 +  // Clone the socket
  16.573 +  Ptr<NscTcpSocketImpl> newSock = Copy ();
  16.574 +  newSock->m_nscTcpSocket = newsock;
  16.575 +  NS_LOG_LOGIC ("Cloned a NscTcpSocketImpl " << newSock);
  16.576 +
  16.577 +  Simulator::ScheduleNow (&NscTcpSocketImpl::CompleteFork, newSock);
  16.578 +  return true;
  16.579 +}
  16.580 +
  16.581 +bool NscTcpSocketImpl::ReadPendingData (void)
  16.582 +{
  16.583 +  if (m_state != ESTABLISHED)
  16.584 +    {
  16.585 +      return false;
  16.586 +    }
  16.587 +  int len, err;
  16.588 +  uint8_t buffer[8192];
  16.589 +  len = sizeof(buffer);
  16.590 +  m_errno = ERROR_NOTERROR;
  16.591 +  err = m_nscTcpSocket->read_data(buffer, &len);
  16.592 +  if (err == 0 && len == 0)
  16.593 +    {
  16.594 +      NS_LOG_LOGIC ("ReadPendingData got EOF from socket");
  16.595 +      m_state = CLOSED;
  16.596 +      return false;
  16.597 +    }
  16.598 +  m_errno = GetNativeNs3Errno(err);
  16.599 +  switch (m_errno)
  16.600 +    {
  16.601 +      case ERROR_NOTERROR: break; // some data was sent
  16.602 +      case ERROR_AGAIN: return false;
  16.603 +      default:
  16.604 +        NS_LOG_WARN ("Error (" << err << ") " <<
  16.605 +                     "during read_data, ns-3 errno set to" << m_errno);
  16.606 +        m_state = CLOSED;
  16.607 +        return false;
  16.608 +    }
  16.609 +
  16.610 +  Ptr<Packet> p =  Create<Packet> (buffer, len);
  16.611 +
  16.612 +  SocketAddressTag tag;
  16.613 +
  16.614 +  tag.SetAddress (m_peerAddress);
  16.615 +  p->AddTag (tag);
  16.616 +  m_deliveryQueue.push (p);
  16.617 +  m_rxAvailable += p->GetSize ();
  16.618 +
  16.619 +  NotifyDataRecv ();
  16.620 +  return true;
  16.621 +}
  16.622 +
  16.623 +bool NscTcpSocketImpl::SendPendingData (void)
  16.624 +{
  16.625 +  NS_LOG_FUNCTION (this);
  16.626 +  NS_LOG_LOGIC ("ENTERING SendPendingData");
  16.627 +
  16.628 +  if (m_txBuffer.empty ())
  16.629 +    {
  16.630 +      return false;
  16.631 +    }
  16.632 +
  16.633 +  int ret;
  16.634 +  size_t size, written = 0;
  16.635 +
  16.636 +  do {
  16.637 +    Ptr<Packet> &p = m_txBuffer.front ();
  16.638 +    size = p->GetSize ();
  16.639 +    NS_ASSERT (size > 0);
  16.640 +
  16.641 +    m_errno = ERROR_NOTERROR;
  16.642 +    ret = m_nscTcpSocket->send_data((const char *)p->PeekData (), size);
  16.643 +    if (ret <= 0)
  16.644 +      {
  16.645 +        m_errno = GetNativeNs3Errno(ret);
  16.646 +        if (m_errno != ERROR_AGAIN)
  16.647 +          {
  16.648 +            NS_LOG_WARN ("Error (" << ret << ") " <<
  16.649 +                         "during send_data, ns-3 errno set to" << m_errno);
  16.650 +          }
  16.651 +        break;
  16.652 +      }
  16.653 +    written += ret;
  16.654 +
  16.655 +    NS_ASSERT (m_txBufferSize >= (size_t)ret);
  16.656 +    m_txBufferSize -= ret;
  16.657 +
  16.658 +    if ((size_t)ret < size)
  16.659 +      {
  16.660 +        p->RemoveAtStart(ret);
  16.661 +        break;
  16.662 +      }
  16.663 +
  16.664 +    m_txBuffer.pop ();
  16.665 +
  16.666 +    if (m_txBuffer.empty ())
  16.667 +      {
  16.668 +        if (m_closeOnEmpty)
  16.669 +          {
  16.670 +            m_nscTcpSocket->disconnect();
  16.671 +            m_state = CLOSED;
  16.672 +          }
  16.673 +        break;
  16.674 +      }
  16.675 +  } while ((size_t) ret == size);
  16.676 +
  16.677 +  if (written > 0)
  16.678 +    {
  16.679 +      Simulator::ScheduleNow(&NscTcpSocketImpl::NotifyDataSent, this, ret);
  16.680 +      return true;
  16.681 +    }
  16.682 +  return false;
  16.683 +}
  16.684 +
  16.685 +Ptr<NscTcpSocketImpl> NscTcpSocketImpl::Copy ()
  16.686 +{
  16.687 +  return CopyObject<NscTcpSocketImpl> (this);
  16.688 +}
  16.689 +
  16.690 +void
  16.691 +NscTcpSocketImpl::SetSndBufSize (uint32_t size)
  16.692 +{
  16.693 +  m_sndBufSize = size;
  16.694 +}
  16.695 +
  16.696 +uint32_t
  16.697 +NscTcpSocketImpl::GetSndBufSize (void) const
  16.698 +{
  16.699 +  return m_sndBufSize;
  16.700 +}
  16.701 +
  16.702 +void
  16.703 +NscTcpSocketImpl::SetRcvBufSize (uint32_t size)
  16.704 +{
  16.705 +  m_rcvBufSize = size;
  16.706 +}
  16.707 +
  16.708 +uint32_t
  16.709 +NscTcpSocketImpl::GetRcvBufSize (void) const
  16.710 +{
  16.711 +  return m_rcvBufSize;
  16.712 +}
  16.713 +
  16.714 +void
  16.715 +NscTcpSocketImpl::SetSegSize (uint32_t size)
  16.716 +{
  16.717 +  m_segmentSize = size;
  16.718 +}
  16.719 +
  16.720 +uint32_t
  16.721 +NscTcpSocketImpl::GetSegSize (void) const
  16.722 +{
  16.723 +  return m_segmentSize;
  16.724 +}
  16.725 +
  16.726 +void
  16.727 +NscTcpSocketImpl::SetAdvWin (uint32_t window)
  16.728 +{
  16.729 +  m_advertisedWindowSize = window;
  16.730 +}
  16.731 +
  16.732 +uint32_t
  16.733 +NscTcpSocketImpl::GetAdvWin (void) const
  16.734 +{
  16.735 +  return m_advertisedWindowSize;
  16.736 +}
  16.737 +
  16.738 +void
  16.739 +NscTcpSocketImpl::SetSSThresh (uint32_t threshold)
  16.740 +{
  16.741 +  m_ssThresh = threshold;
  16.742 +}
  16.743 +
  16.744 +uint32_t
  16.745 +NscTcpSocketImpl::GetSSThresh (void) const
  16.746 +{
  16.747 +  return m_ssThresh;
  16.748 +}
  16.749 +
  16.750 +void
  16.751 +NscTcpSocketImpl::SetInitialCwnd (uint32_t cwnd)
  16.752 +{
  16.753 +  m_initialCWnd = cwnd;
  16.754 +}
  16.755 +
  16.756 +uint32_t
  16.757 +NscTcpSocketImpl::GetInitialCwnd (void) const
  16.758 +{
  16.759 +  return m_initialCWnd;
  16.760 +}
  16.761 +
  16.762 +void 
  16.763 +NscTcpSocketImpl::SetConnTimeout (Time timeout)
  16.764 +{
  16.765 +  m_cnTimeout = timeout;
  16.766 +}
  16.767 +
  16.768 +Time
  16.769 +NscTcpSocketImpl::GetConnTimeout (void) const
  16.770 +{
  16.771 +  return m_cnTimeout;
  16.772 +}
  16.773 +
  16.774 +void 
  16.775 +NscTcpSocketImpl::SetConnCount (uint32_t count)
  16.776 +{
  16.777 +  m_cnCount = count;
  16.778 +}
  16.779 +
  16.780 +uint32_t 
  16.781 +NscTcpSocketImpl::GetConnCount (void) const
  16.782 +{
  16.783 +  return m_cnCount;
  16.784 +}
  16.785 +
  16.786 +void 
  16.787 +NscTcpSocketImpl::SetDelAckTimeout (Time timeout)
  16.788 +{
  16.789 +  m_delAckTimeout = timeout;
  16.790 +}
  16.791 +
  16.792 +Time
  16.793 +NscTcpSocketImpl::GetDelAckTimeout (void) const
  16.794 +{
  16.795 +  return m_delAckTimeout;
  16.796 +}
  16.797 +
  16.798 +void
  16.799 +NscTcpSocketImpl::SetDelAckMaxCount (uint32_t count)
  16.800 +{
  16.801 +  m_delAckMaxCount = count;
  16.802 +}
  16.803 +
  16.804 +uint32_t
  16.805 +NscTcpSocketImpl::GetDelAckMaxCount (void) const
  16.806 +{
  16.807 +  return m_delAckMaxCount;
  16.808 +}
  16.809 +
  16.810 +enum Socket::SocketErrno
  16.811 +NscTcpSocketImpl::GetNativeNs3Errno(int error) const
  16.812 +{
  16.813 +  enum nsc_errno err;
  16.814 +
  16.815 +  if (error >= 0)
  16.816 +    {
  16.817 +       return ERROR_NOTERROR;
  16.818 +    }
  16.819 +  err = (enum nsc_errno) error;
  16.820 +  switch (err)
  16.821 +    {
  16.822 +      case NSC_EADDRINUSE: // fallthrough
  16.823 +      case NSC_EADDRNOTAVAIL: return ERROR_AFNOSUPPORT;
  16.824 +      case NSC_EINPROGRESS: // Altough nsc sockets are nonblocking, we pretend they're not.
  16.825 +      case NSC_EAGAIN: return ERROR_AGAIN;
  16.826 +      case NSC_EISCONN: // fallthrough
  16.827 +      case NSC_EALREADY: return ERROR_ISCONN;
  16.828 +      case NSC_ECONNREFUSED: return ERROR_NOROUTETOHOST; // XXX, better mapping?
  16.829 +      case NSC_ECONNRESET: // for no, all of these fall through
  16.830 +      case NSC_EHOSTDOWN:
  16.831 +      case NSC_ENETUNREACH:
  16.832 +      case NSC_EHOSTUNREACH: return ERROR_NOROUTETOHOST;
  16.833 +      case NSC_EMSGSIZE: return ERROR_MSGSIZE;
  16.834 +      case NSC_ENOTCONN: return ERROR_NOTCONN;
  16.835 +      case NSC_ESHUTDOWN: return ERROR_SHUTDOWN;
  16.836 +      case NSC_ETIMEDOUT: return ERROR_NOTCONN; // XXX - this mapping isn't correct
  16.837 +      case NSC_ENOTDIR: // used by eg. sysctl(2). Shouldn't happen normally,
  16.838 +                        // but is triggered by e.g. show_config().
  16.839 +      case NSC_EUNKNOWN: return ERROR_INVAL; // Catches stacks that 'return -1' without real mapping
  16.840 +    }
  16.841 +  NS_ASSERT_MSG(0, "Unknown NSC error");
  16.842 +  return ERROR_INVAL;
  16.843 +}
  16.844 +
  16.845 +}//namespace ns3
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/src/internet-stack/nsc-tcp-socket-impl.h	Tue Sep 02 10:45:06 2008 -0700
    17.3 @@ -0,0 +1,171 @@
    17.4 +/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
    17.5 +/*
    17.6 + * This program is free software; you can redistribute it and/or modify
    17.7 + * it under the terms of the GNU General Public License version 2 as
    17.8 + * published by the Free Software Foundation;
    17.9 + *
   17.10 + * This program is distributed in the hope that it will be useful,
   17.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   17.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   17.13 + * GNU General Public License for more details.
   17.14 + *
   17.15 + * You should have received a copy of the GNU General Public License
   17.16 + * along with this program; if not, write to the Free Software
   17.17 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   17.18 + */
   17.19 +#ifndef NSC_TCP_SOCKET_IMPL_H
   17.20 +#define NSC_TCP_SOCKET_IMPL_H
   17.21 +
   17.22 +#include <stdint.h>
   17.23 +#include <queue>
   17.24 +#include <vector>
   17.25 +
   17.26 +#include "ns3/callback.h"
   17.27 +#include "ns3/traced-value.h"
   17.28 +#include "ns3/tcp-socket.h"
   17.29 +#include "ns3/ptr.h"
   17.30 +#include "ns3/ipv4-address.h"
   17.31 +#include "ns3/inet-socket-address.h"
   17.32 +#include "ns3/event-id.h"
   17.33 +#include "tcp-typedefs.h"
   17.34 +#include "pending-data.h"
   17.35 +#include "sequence-number.h"
   17.36 +#include "rtt-estimator.h"
   17.37 +
   17.38 +#include "nsc/sim/sim_interface.h"
   17.39 +
   17.40 +namespace ns3 {
   17.41 +
   17.42 +class Ipv4EndPoint;
   17.43 +class Node;
   17.44 +class Packet;
   17.45 +class NscTcpL4Protocol;
   17.46 +class TcpHeader;
   17.47 +
   17.48 +class NscTcpSocketImpl : public TcpSocket
   17.49 +{
   17.50 +public:
   17.51 +  static TypeId GetTypeId (void);
   17.52 +  /**
   17.53 +   * Create an unbound tcp socket.
   17.54 +   */
   17.55 +  NscTcpSocketImpl ();
   17.56 +  NscTcpSocketImpl (const NscTcpSocketImpl& sock);
   17.57 +  virtual ~NscTcpSocketImpl ();
   17.58 +
   17.59 +  void SetNode (Ptr<Node> node);
   17.60 +  void SetTcp (Ptr<NscTcpL4Protocol> tcp);
   17.61 +  void SetRtt (Ptr<RttEstimator> rtt);
   17.62 +
   17.63 +  virtual enum SocketErrno GetErrno (void) const;
   17.64 +  virtual Ptr<Node> GetNode (void) const;
   17.65 +  virtual int Bind (void);
   17.66 +  virtual int Bind (const Address &address);
   17.67 +  virtual int Close (void);
   17.68 +  virtual int ShutdownSend (void);
   17.69 +  virtual int ShutdownRecv (void);
   17.70 +  virtual int Connect(const Address &address);
   17.71 +  virtual int Listen(uint32_t queueLimit);
   17.72 +  virtual uint32_t GetTxAvailable (void) const;
   17.73 +  virtual int Send (Ptr<Packet> p, uint32_t flags);
   17.74 +  virtual int SendTo(Ptr<Packet> p, uint32_t flags, const Address &toAddress);
   17.75 +  virtual uint32_t GetRxAvailable (void) const;
   17.76 +  virtual Ptr<Packet> Recv (uint32_t maxSize, uint32_t flags);
   17.77 +  virtual Ptr<Packet> RecvFrom (uint32_t maxSize, uint32_t flags,
   17.78 +    Address &fromAddress);
   17.79 +
   17.80 +private:
   17.81 +  void NSCWakeup(void);
   17.82 +  friend class Tcp;
   17.83 +  // invoked by Tcp class
   17.84 +  int FinishBind (void);
   17.85 +  void ForwardUp (Ptr<Packet> p, Ipv4Address ipv4, uint16_t port);
   17.86 +  void Destroy (void);
   17.87 +  //methods for state
   17.88 +  bool SendPendingData(void);
   17.89 +  bool ReadPendingData(void);
   17.90 +  bool Accept(void);
   17.91 +  void CompleteFork(void);
   17.92 +  void ConnectionSucceeded();
   17.93 +
   17.94 +  // Manage data tx/rx
   17.95 +  // XXX This should be virtual and overridden
   17.96 +  Ptr<NscTcpSocketImpl> Copy ();
   17.97 +
   17.98 +  // attribute related
   17.99 +  virtual void SetSndBufSize (uint32_t size);
  17.100 +  virtual uint32_t GetSndBufSize (void) const;
  17.101 +  virtual void SetRcvBufSize (uint32_t size);
  17.102 +  virtual uint32_t GetRcvBufSize (void) const;
  17.103 +  virtual void SetSegSize (uint32_t size);
  17.104 +  virtual uint32_t GetSegSize (void) const;
  17.105 +  virtual void SetAdvWin (uint32_t window);
  17.106 +  virtual uint32_t GetAdvWin (void) const;
  17.107 +  virtual void SetSSThresh (uint32_t threshold);
  17.108 +  virtual uint32_t GetSSThresh (void) const;
  17.109 +  virtual void SetInitialCwnd (uint32_t cwnd);
  17.110 +  virtual uint32_t GetInitialCwnd (void) const;
  17.111 +  virtual void SetConnTimeout (Time timeout);
  17.112 +  virtual Time GetConnTimeout (void) const;
  17.113 +  virtual void SetConnCount (uint32_t count);
  17.114 +  virtual uint32_t GetConnCount (void) const;
  17.115 +  virtual void SetDelAckTimeout (Time timeout);
  17.116 +  virtual Time GetDelAckTimeout (void) const;
  17.117 +  virtual void SetDelAckMaxCount (uint32_t count);
  17.118 +  virtual uint32_t GetDelAckMaxCount (void) const;
  17.119 +
  17.120 +  enum Socket::SocketErrno GetNativeNs3Errno(int err) const;
  17.121 +  uint32_t m_delAckMaxCount;
  17.122 +  Time m_delAckTimeout;
  17.123 +
  17.124 +  Ipv4EndPoint *m_endPoint;
  17.125 +  Ptr<Node> m_node;
  17.126 +  Ptr<NscTcpL4Protocol> m_tcp;
  17.127 +  Ipv4Address m_remoteAddress;
  17.128 +  uint16_t m_remotePort;
  17.129 +  //these two are so that the socket/endpoint cloning works
  17.130 +  Ipv4Address m_localAddress;
  17.131 +  uint16_t m_localPort;
  17.132 +  InetSocketAddress m_peerAddress;
  17.133 +  enum SocketErrno m_errno;
  17.134 +  bool m_shutdownSend;
  17.135 +  bool m_shutdownRecv;
  17.136 +  bool m_connected;
  17.137 +  
  17.138 +  //manage the state infomation
  17.139 +  States_t m_state;
  17.140 +  bool m_closeOnEmpty;
  17.141 +
  17.142 +  //needed to queue data when in SYN_SENT state
  17.143 +  std::queue<Ptr<Packet> > m_txBuffer;
  17.144 +  uint32_t m_txBufferSize;
  17.145 +
  17.146 +  // Window management
  17.147 +  uint32_t                       m_segmentSize;          //SegmentSize
  17.148 +  uint32_t                       m_rxWindowSize;
  17.149 +  uint32_t                       m_advertisedWindowSize; //Window to advertise
  17.150 +  TracedValue<uint32_t>          m_cWnd;                 //Congestion window
  17.151 +  uint32_t                       m_ssThresh;             //Slow Start Threshold
  17.152 +  uint32_t                       m_initialCWnd;          //Initial cWnd value
  17.153 +
  17.154 +  // Round trip time estimation
  17.155 +  Ptr<RttEstimator> m_rtt;
  17.156 +  Time m_lastMeasuredRtt;
  17.157 +
  17.158 +  // Timer-related members
  17.159 +  Time              m_cnTimeout; 
  17.160 +  uint32_t          m_cnCount;
  17.161 +
  17.162 +  // Temporary queue for delivering data to application
  17.163 +  std::queue<Ptr<Packet> > m_deliveryQueue;
  17.164 +  uint32_t m_rxAvailable;
  17.165 +  INetStreamSocket* m_nscTcpSocket;
  17.166 +
  17.167 +  // Attributes
  17.168 +  uint32_t m_sndBufSize;   // buffer limit for the outgoing queue
  17.169 +  uint32_t m_rcvBufSize;   // maximum receive socket buffer size
  17.170 +};
  17.171 +
  17.172 +}//namespace ns3
  17.173 +
  17.174 +#endif /* NSC_TCP_SOCKET_IMPL_H */
    18.1 --- a/src/internet-stack/wscript	Tue Sep 02 10:44:28 2008 -0700
    18.2 +++ b/src/internet-stack/wscript	Tue Sep 02 10:45:06 2008 -0700
    18.3 @@ -1,4 +1,61 @@
    18.4  ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
    18.5 +import Params
    18.6 +import os
    18.7 +
    18.8 +# Mercurial repository of the network simulation cradle
    18.9 +NETWORK_SIMULATION_CRADLE_REPO = "https://secure.wand.net.nz/mercurial/nsc"
   18.10 +def nsc_fetch():
   18.11 +    def nsc_clone():
   18.12 +        print "Retrieving nsc from " + NETWORK_SIMULATION_CRADLE_REPO
   18.13 +        if os.system("hg version > /dev/null 2>&1") != 0:
   18.14 +            Params.fatal("Mercurial not installed, http fallback not yet implemented")
   18.15 +        if os.system("hg -q clone " + NETWORK_SIMULATION_CRADLE_REPO) != 0:
   18.16 +            Params.fatal("hg -q clone %s failed" % NETWORK_SIMULATION_CRADLE_REPO)
   18.17 +
   18.18 +    def nsc_update():
   18.19 +        if os.system("hg version > /dev/null 2>&1") != 0:
   18.20 +            Params.warning("Mercurial not installed, not updating nsc source")
   18.21 +
   18.22 +        print "Pulling nsc updates from " + NETWORK_SIMULATION_CRADLE_REPO
   18.23 +        if os.system("cd nsc && hg -q pull %s && hg -q update" % NETWORK_SIMULATION_CRADLE_REPO) != 0:
   18.24 +            Params.warning("Updating nsc using mercurial failed")
   18.25 +
   18.26 +    if not os.path.exists("nsc"):
   18.27 +        nsc_clone()
   18.28 +    else:
   18.29 +        nsc_update()
   18.30 +
   18.31 +def configure(conf):
   18.32 +    # checks for flex and bison, which is needed to build NSCs globaliser
   18.33 +    def check_nsc_buildutils():
   18.34 +        import flex
   18.35 +        import bison
   18.36 +        conf.check_tool('flex bison')
   18.37 +        e = conf.create_library_configurator()
   18.38 +        e.mandatory = True
   18.39 +        e.name = 'fl'
   18.40 +        e.run()
   18.41 +
   18.42 +    if not Params.g_options.nsc:
   18.43 +	return
   18.44 +
   18.45 +    check_nsc_buildutils()
   18.46 +
   18.47 +    arch = os.uname()[4]
   18.48 +    ok = False
   18.49 +    if arch == 'x86_64' or arch == 'i686' or arch == 'i586' or arch == 'i486' or arch == 'i386':
   18.50 +        conf.env['NSC_ENABLED'] = 'yes'
   18.51 +        conf.define('NETWORK_SIMULATION_CRADLE', 1)
   18.52 +        conf.write_config_header('ns3/core-config.h')
   18.53 +        e = conf.create_library_configurator()
   18.54 +        e.mandatory = True
   18.55 +        e.name = 'dl'
   18.56 +        e.define = 'HAVE_DL'
   18.57 +        e.uselib = 'DL'
   18.58 +        e.run()
   18.59 +        ok = True
   18.60 +    conf.check_message('NSC supported architecture', arch, ok)
   18.61 +    nsc_fetch()
   18.62  
   18.63  
   18.64  def build(bld):
   18.65 @@ -43,3 +100,9 @@
   18.66          'ipv4-l3-protocol.h',
   18.67          'ipv4-static-routing.h',
   18.68          ]
   18.69 +
   18.70 +    if bld.env()['NSC_ENABLED']:
   18.71 +        obj.source.append ('nsc-tcp-socket-impl.cc')
   18.72 +        obj.source.append ('nsc-tcp-l4-protocol.cc')
   18.73 +        obj.source.append ('nsc-tcp-socket-factory-impl.cc')
   18.74 +        obj.source.append ('nsc-sysctl.cc')
    19.1 --- a/src/wscript	Tue Sep 02 10:44:28 2008 -0700
    19.2 +++ b/src/wscript	Tue Sep 02 10:45:06 2008 -0700
    19.3 @@ -50,6 +50,7 @@
    19.4      conf.sub_config('core')
    19.5      conf.sub_config('simulator')
    19.6      conf.sub_config('contrib')
    19.7 +    conf.sub_config('internet-stack')
    19.8  
    19.9      blddir = os.path.abspath(os.path.join(conf.m_blddir, conf.env.variant()))
   19.10      conf.env.append_value('NS3_MODULE_PATH', blddir)
    20.1 --- a/wscript	Tue Sep 02 10:44:28 2008 -0700
    20.2 +++ b/wscript	Tue Sep 02 10:45:06 2008 -0700
    20.3 @@ -55,6 +55,8 @@
    20.4  #
    20.5  TRACEBALL_SUFFIX = ".tar.bz2"
    20.6  
    20.7 +# directory that contains network simulation cradle source
    20.8 +NSC_DIR = "nsc"
    20.9  
   20.10  def dist_hook():
   20.11      import tarfile
   20.12 @@ -165,6 +167,10 @@
   20.13                     help=('For regression testing, only run/generate the indicated regression tests, '
   20.14                           'specified as a comma separated list of test names'),
   20.15                     dest='regression_tests', type="string")
   20.16 +    opt.add_option('--nsc',
   20.17 +                   help=('Enable Network Simulation Cradle to allow the use real-world network stacks'),
   20.18 +                   action="store_true", default=False,
   20.19 +                   dest='nsc')
   20.20  
   20.21      # options provided in a script in a subdirectory named "src"
   20.22      opt.sub_options('src')
   20.23 @@ -193,6 +199,7 @@
   20.24      
   20.25  
   20.26  def configure(conf):
   20.27 +    conf.env['NS3_BUILDDIR'] = conf.m_blddir
   20.28      conf.check_tool('compiler_cxx')
   20.29  
   20.30      # create the second environment, set the variant and set its name
   20.31 @@ -304,6 +311,28 @@
   20.32      return stat >> 8
   20.33  
   20.34  
   20.35 +def nsc_build(bld):
   20.36 +    # XXX: Detect gcc major version(s) available to build supported stacks
   20.37 +    kernels = [['linux-2.6.18', 'linux2.6.18'],
   20.38 +               ['linux-2.6.26', 'linux2.6.26']]
   20.39 +    for dir,name in kernels:
   20.40 +        soname = 'lib' + name + '.so'
   20.41 +        tmp = NSC_DIR + '/' + dir +'/' + soname
   20.42 +        if not os.path.exists(tmp):
   20.43 +            if os.system('cd ' + NSC_DIR + ' && python scons.py ' + dir) != 0:
   20.44 +                Params.fatal("Building NSC stack failed")
   20.45 +        builddir = os.path.abspath(os.path.join(bld.env()['NS3_BUILDDIR'], bld.env ().variant()))
   20.46 +        if not os.path.exists(builddir + '/nsc'):
   20.47 +            try:
   20.48 +                os.symlink('../../' + NSC_DIR, builddir + '/nsc')
   20.49 +            except:
   20.50 +                Params.fatal("Error linkink " + builddir + '/nsc')
   20.51 +        if not os.path.exists(builddir + '/' + soname):
   20.52 +            try:
   20.53 +                os.symlink('../../' + NSC_DIR + '/' + dir + '/' + soname, builddir +  '/' + soname)
   20.54 +            except:
   20.55 +                Params.fatal("Error linking " + builddir + '/' + soname)
   20.56 +
   20.57  def build(bld):
   20.58      if Params.g_options.no_task_lines:
   20.59          import Runner
   20.60 @@ -393,6 +422,9 @@
   20.61  
   20.62      bld.add_subdirs('bindings/python')
   20.63  
   20.64 +    if env['NSC_ENABLED'] == 'yes':
   20.65 +        nsc_build(bld)
   20.66 +
   20.67  def get_command_template():
   20.68      if Params.g_options.valgrind:
   20.69          if Params.g_options.command_template: