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