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: