nsc: core files.
This adds the core network simulation cradle support
code.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/nsc-sysctl.cc Fri Aug 29 23:08:18 2008 +0200
@@ -0,0 +1,154 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include "ns3/string.h"
+#include "nsc-sysctl.h"
+
+#include "nsc/sim/sim_interface.h"
+
+namespace ns3 {
+
+class NscStackStringAccessor : public AttributeAccessor
+{
+ public:
+ NscStackStringAccessor (std::string name) : m_name (name) {}
+
+ virtual bool Set (ObjectBase * object, const AttributeValue &val) const;
+ virtual bool Get (const ObjectBase * object, AttributeValue &val) const;
+ virtual bool HasGetter (void) const;
+ virtual bool HasSetter (void) const;
+ private:
+ std::string m_name;
+};
+
+bool NscStackStringAccessor::HasGetter(void) const
+{
+ return true;
+}
+
+bool NscStackStringAccessor::HasSetter(void) const
+{
+ return true;
+}
+
+
+bool NscStackStringAccessor::Set (ObjectBase * object, const AttributeValue & val) const
+{
+ const StringValue *value = dynamic_cast<const StringValue *> (&val);
+ if (value == 0)
+ {
+ return false;
+ }
+ Ns3NscStack *obj = dynamic_cast<Ns3NscStack *> (object);
+ if (obj == 0)
+ {
+ return false;
+ }
+ obj->Set (m_name, value->Get ());
+ return true;
+}
+
+bool NscStackStringAccessor::Get (const ObjectBase * object, AttributeValue &val) const
+{
+ StringValue *value = dynamic_cast<StringValue *> (&val);
+ if (value == 0)
+ {
+ return false;
+ }
+ const Ns3NscStack *obj = dynamic_cast<const Ns3NscStack *> (object);
+ if (obj == 0)
+ {
+ return false;
+ }
+ value->Set (obj->Get (m_name));
+ return true;
+}
+
+
+TypeId
+Ns3NscStack::GetInstanceTypeId (void) const
+{
+ if (m_stack == 0)
+ {
+ // if we have no stack, we are a normal NscStack without any attributes.
+ return GetTypeId ();
+ }
+ std::string name = "ns3::Ns3NscStack<";
+ name += m_stack->get_name ();
+ name += ">";
+ TypeId tid;
+ if (TypeId::LookupByNameFailSafe (name, &tid))
+ {
+ // if the relevant TypeId has already been registered, no need to do it again.
+ return tid;
+ }
+ else
+ {
+ // Now, we register a new TypeId for this stack which will look
+ // like a subclass of the Ns3NscStack. The class Ns3NscStack is effectively
+ // mutating into a subclass of itself from the point of view of the TypeId
+ // system _here_
+ tid = TypeId (name.c_str ());
+ tid.SetParent<Ns3NscStack> ();
+ char buf[256];
+ for (int i=0; m_stack->sysctl_getnum(i, buf, sizeof(buf)) > 0 ;i++)
+ {
+ char value[256];
+ if (m_stack->sysctl_get (buf, value, sizeof(value)) > 0)
+ {
+ tid.AddAttribute (buf, "Help text",
+ StringValue (value),
+ Create<NscStackStringAccessor> (buf),
+ MakeStringChecker ());
+ }
+ }
+ return tid;
+ }
+}
+
+std::string
+Ns3NscStack::Get (std::string name) const
+{
+ char buf[512];
+ if (m_stack->sysctl_get (name.c_str (), buf, sizeof(buf)) <= 0)
+ { // name.c_str () is not a valid sysctl name, or internal NSC error (eg. error converting value)
+ return NULL;
+ }
+ return std::string(buf);
+}
+
+void
+Ns3NscStack::Set (std::string name, std::string value)
+{
+ int ret = m_stack->sysctl_set (name.c_str (), value.c_str ());
+ if (ret < 0)
+ {
+ NS_FATAL_ERROR ("setting " << name << " to " << value << "failed (retval " << ret << ")");
+ }
+}
+
+TypeId
+Ns3NscStack::Ns3NscStack::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::Ns3NscStack")
+ .SetParent<Object> ()
+ ;
+ return tid;
+}
+
+} // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/nsc-sysctl.h Fri Aug 29 23:08:18 2008 +0200
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include <string>
+
+#include "ns3/attribute.h"
+#include "ns3/object.h"
+
+struct INetStack;
+
+namespace ns3 {
+
+// This object represents the underlying nsc stack,
+// which is aggregated to a Node object, and which provides access to the
+// sysctls of the nsc stack through attributes.
+class Ns3NscStack : public Object
+{
+public:
+ static TypeId GetTypeId (void);
+ virtual TypeId GetInstanceTypeId (void) const;
+ void SetStack (INetStack *stack) {m_stack = stack;}
+
+private:
+ friend class NscStackStringAccessor;
+ void Set (std::string name, std::string value);
+ std::string Get (std::string name) const;
+ INetStack *m_stack;
+};
+} // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/nsc-tcp-l4-protocol.cc Fri Aug 29 23:08:18 2008 +0200
@@ -0,0 +1,368 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * based on earlier integration work by Tom Henderson and Sam Jansen.
+ * 2008 Florian Westphal <fw@strlen.de>
+ */
+
+#include "ns3/assert.h"
+#include "ns3/log.h"
+#include "ns3/nstime.h"
+
+#include "ns3/packet.h"
+#include "ns3/node.h"
+
+#include "tcp-header.h"
+#include "ipv4-end-point-demux.h"
+#include "ipv4-end-point.h"
+#include "ipv4-l3-protocol.h"
+#include "nsc-tcp-l4-protocol.h"
+#include "nsc-tcp-socket-impl.h"
+#include "nsc-sysctl.h"
+
+#include "tcp-typedefs.h"
+
+#include <vector>
+#include <sstream>
+#include <dlfcn.h>
+#include <iomanip>
+
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+
+NS_LOG_COMPONENT_DEFINE ("NscTcpL4Protocol");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (NscTcpL4Protocol);
+
+/* see http://www.iana.org/assignments/protocol-numbers */
+const uint8_t NscTcpL4Protocol::PROT_NUMBER = 6;
+
+ObjectFactory
+NscTcpL4Protocol::GetDefaultRttEstimatorFactory (void)
+{
+ ObjectFactory factory;
+ factory.SetTypeId (RttMeanDeviation::GetTypeId ());
+ return factory;
+}
+
+TypeId
+NscTcpL4Protocol::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::NscTcpL4Protocol")
+ .SetParent<Ipv4L4Protocol> ()
+
+ .AddAttribute ("RttEstimatorFactory",
+ "How RttEstimator objects are created.",
+ ObjectFactoryValue (GetDefaultRttEstimatorFactory ()),
+ MakeObjectFactoryAccessor (&NscTcpL4Protocol::m_rttFactory),
+ MakeObjectFactoryChecker ())
+ ;
+ return tid;
+}
+
+int external_rand()
+{
+ return 1; // TODO
+}
+
+NscTcpL4Protocol::NscTcpL4Protocol ()
+ : m_endPoints (new Ipv4EndPointDemux ()),
+ m_nscStack (0),
+ m_nscInterfacesSetUp(false),
+ m_softTimer (Timer::CANCEL_ON_DESTROY)
+{
+ m_dlopenHandle = NULL;
+ NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_LOGIC("Made a NscTcpL4Protocol "<<this);
+}
+
+NscTcpL4Protocol::~NscTcpL4Protocol ()
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ dlclose(m_dlopenHandle);
+}
+
+void
+NscTcpL4Protocol::SetNscLibrary(const std::string &soname)
+{
+ NS_ASSERT(!m_dlopenHandle);
+ m_dlopenHandle = dlopen(soname.c_str (), RTLD_NOW);
+ if (m_dlopenHandle == NULL)
+ NS_FATAL_ERROR (dlerror());
+}
+
+void
+NscTcpL4Protocol::SetNode (Ptr<Node> node)
+{
+ m_node = node;
+
+ if (m_nscStack)
+ { // stack has already been loaded...
+ return;
+ }
+
+ NS_ASSERT(m_dlopenHandle);
+
+ FCreateStack create = (FCreateStack)dlsym(m_dlopenHandle, "nsc_create_stack");
+ NS_ASSERT(create);
+ m_nscStack = create(this, this, external_rand);
+ int hzval = m_nscStack->get_hz();
+
+ NS_ASSERT(hzval > 0);
+
+ m_softTimer.SetFunction (&NscTcpL4Protocol::SoftInterrupt, this);
+ m_softTimer.SetDelay (MilliSeconds (1000/hzval));
+ m_nscStack->init(hzval);
+ // This enables stack and NSC debug messages
+ // m_nscStack->set_diagnostic(1000);
+
+ Ptr<Ns3NscStack> nscStack = Create<Ns3NscStack> ();
+ nscStack->SetStack (m_nscStack);
+ node->AggregateObject (nscStack);
+
+ m_softTimer.Schedule ();
+}
+
+int
+NscTcpL4Protocol::GetProtocolNumber (void) const
+{
+ return PROT_NUMBER;
+}
+int
+NscTcpL4Protocol::GetVersion (void) const
+{
+ return 2;
+}
+
+void
+NscTcpL4Protocol::DoDispose (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ if (m_endPoints != 0)
+ {
+ delete m_endPoints;
+ m_endPoints = 0;
+ }
+ m_node = 0;
+ Ipv4L4Protocol::DoDispose ();
+}
+
+Ptr<Socket>
+NscTcpL4Protocol::CreateSocket (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ if (!m_nscInterfacesSetUp)
+ {
+ Ptr<Ipv4> ip = m_node->GetObject<Ipv4> ();
+
+ const uint32_t nInterfaces = ip->GetNInterfaces ();
+ // start from 1, ignore the loopback interface (HACK)
+
+ NS_ASSERT_MSG (nInterfaces <= 2, "nsc does not support multiple interfaces per node");
+
+ for (uint32_t i = 1; i < nInterfaces; i++)
+ {
+ Ipv4Address addr = ip->GetAddress(i);
+ Ipv4Mask mask = ip->GetNetworkMask(i);
+ uint16_t mtu = ip->GetMtu (i);
+
+ std::ostringstream addrOss, maskOss;
+
+ addr.Print(addrOss);
+ mask.Print(maskOss);
+
+ NS_LOG_LOGIC ("if_attach " << addrOss.str().c_str() << " " << maskOss.str().c_str() << " " << mtu);
+
+ std::string addrStr = addrOss.str();
+ std::string maskStr = maskOss.str();
+ const char* addrCStr = addrStr.c_str();
+ const char* maskCStr = maskStr.c_str();
+ m_nscStack->if_attach(addrCStr, maskCStr, mtu);
+
+ if (i == 1)
+ {
+ // We need to come up with a default gateway here. Can't guarantee this to be
+ // correct really...
+
+ uint8_t addrBytes[4];
+ addr.Serialize(addrBytes);
+
+ // XXX: this is all a bit of a horrible hack
+ //
+ // Just increment the last octet, this gives a decent chance of this being
+ // 'enough'.
+ //
+ // All we need is another address on the same network as the interface. This
+ // will force the stack to output the packet out of the network interface.
+ addrBytes[3]++;
+ addr.Deserialize(addrBytes);
+ addrOss.str("");
+ addr.Print(addrOss);
+ m_nscStack->add_default_gateway(addrOss.str().c_str());
+ }
+ }
+ m_nscInterfacesSetUp = true;
+ }
+
+ Ptr<RttEstimator> rtt = m_rttFactory.Create<RttEstimator> ();
+ Ptr<NscTcpSocketImpl> socket = CreateObject<NscTcpSocketImpl> ();
+ socket->SetNode (m_node);
+ socket->SetTcp (this);
+ socket->SetRtt (rtt);
+ return socket;
+}
+
+Ipv4EndPoint *
+NscTcpL4Protocol::Allocate (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_endPoints->Allocate ();
+}
+
+Ipv4EndPoint *
+NscTcpL4Protocol::Allocate (Ipv4Address address)
+{
+ NS_LOG_FUNCTION (this << address);
+ return m_endPoints->Allocate (address);
+}
+
+Ipv4EndPoint *
+NscTcpL4Protocol::Allocate (uint16_t port)
+{
+ NS_LOG_FUNCTION (this << port);
+ return m_endPoints->Allocate (port);
+}
+
+Ipv4EndPoint *
+NscTcpL4Protocol::Allocate (Ipv4Address address, uint16_t port)
+{
+ NS_LOG_FUNCTION (this << address << port);
+ return m_endPoints->Allocate (address, port);
+}
+
+Ipv4EndPoint *
+NscTcpL4Protocol::Allocate (Ipv4Address localAddress, uint16_t localPort,
+ Ipv4Address peerAddress, uint16_t peerPort)
+{
+ NS_LOG_FUNCTION (this << localAddress << localPort << peerAddress << peerPort);
+ return m_endPoints->Allocate (localAddress, localPort,
+ peerAddress, peerPort);
+}
+
+void
+NscTcpL4Protocol::DeAllocate (Ipv4EndPoint *endPoint)
+{
+ NS_LOG_FUNCTION (this << endPoint);
+ // NSC m_endPoints->DeAllocate (endPoint);
+}
+
+void
+NscTcpL4Protocol::Receive (Ptr<Packet> packet,
+ Ipv4Address const &source,
+ Ipv4Address const &destination,
+ Ptr<Ipv4Interface> incomingInterface)
+{
+ NS_LOG_FUNCTION (this << packet << source << destination << incomingInterface);
+ Ipv4Header ipHeader;
+ uint32_t packetSize = packet->GetSize();
+
+ // The way things work at the moment, the IP header has been removed
+ // by the ns-3 IPv4 processing code. However, the NSC stack expects
+ // a complete IP packet, so we add the IP header back.
+ // Since the original header is already gone, we create a new one
+ // based on the information we have.
+ ipHeader.SetSource (source);
+ ipHeader.SetDestination (destination);
+ ipHeader.SetProtocol (PROT_NUMBER);
+ ipHeader.SetPayloadSize (packetSize);
+ ipHeader.SetTtl (1);
+ // all NSC stacks check the IP checksum
+ ipHeader.EnableChecksum ();
+
+ packet->AddHeader(ipHeader);
+ packetSize = packet->GetSize();
+
+ const uint8_t *data = const_cast<uint8_t *>(packet->PeekData());
+
+ // deliver complete packet to the NSC network stack
+ m_nscStack->if_receive_packet(0, data, packetSize);
+ wakeup ();
+}
+
+void NscTcpL4Protocol::SoftInterrupt (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_nscStack->timer_interrupt ();
+ m_nscStack->increment_ticks ();
+ m_softTimer.Schedule ();
+}
+
+void NscTcpL4Protocol::send_callback(const void* data, int datalen)
+{
+ Ptr<Packet> p;
+
+ NS_ASSERT(datalen > (int)sizeof(struct iphdr));
+
+ const uint8_t *rawdata = reinterpret_cast<const uint8_t *>(data);
+ rawdata += sizeof(struct iphdr);
+
+ const struct iphdr *ipHdr = reinterpret_cast<const struct iphdr *>(data);
+
+ // create packet, without IP header. The TCP header is not touched.
+ // Not using the IP header makes integration easier, but it destroys
+ // eg. ECN.
+ p = Create<Packet> (rawdata, datalen - sizeof(struct iphdr));
+
+ Ipv4Address saddr(ntohl(ipHdr->saddr));
+ Ipv4Address daddr(ntohl(ipHdr->daddr));
+
+ Ptr<Ipv4L3Protocol> ipv4 = m_node->GetObject<Ipv4L3Protocol> ();
+ if (ipv4 != 0)
+ {
+ ipv4->Send (p, saddr, daddr, PROT_NUMBER);
+ }
+ m_nscStack->if_send_finish(0);
+}
+
+void NscTcpL4Protocol::wakeup()
+{
+ // TODO
+ // this should schedule a timer to read from all tcp sockets now... this is
+ // an indication that data might be waiting on the socket
+
+ Ipv4EndPointDemux::EndPoints endPoints = m_endPoints->GetAllEndPoints ();
+ for (Ipv4EndPointDemux::EndPointsI endPoint = endPoints.begin ();
+ endPoint != endPoints.end (); endPoint++) {
+ // NSC HACK: (ab)use TcpSocket::ForwardUp for signalling
+ (*endPoint)->ForwardUp (NULL, Ipv4Address(), 0);
+ }
+}
+
+void NscTcpL4Protocol::gettime(unsigned int* sec, unsigned int* usec)
+{
+ // Only used by the Linux network stack, e.g. during ISN generation
+ // and in the kernel rng initialization routine. Also used in Linux
+ // printk output.
+ Time t = Simulator::Now ();
+ int64_t us = t.GetMicroSeconds ();
+ *sec = us / (1000*1000);
+ *usec = us - *sec * (1000*1000);
+}
+
+
+}; // namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/nsc-tcp-l4-protocol.h Fri Aug 29 23:08:18 2008 +0200
@@ -0,0 +1,121 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef NSC_TCP_L4_PROTOCOL_H
+#define NSC_TCP_L4_PROTOCOL_H
+
+#include <stdint.h>
+
+#include "ns3/packet.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/ptr.h"
+#include "ns3/object-factory.h"
+#include "ipv4-end-point-demux.h"
+#include "ipv4-l4-protocol.h"
+#include "ipv4-interface.h"
+
+#include "tcp-header.h"
+
+#include "ns3/timer.h"
+#include "nsc/sim/sim_interface.h"
+
+namespace ns3 {
+
+class Node;
+class Socket;
+class TcpHeader;
+/**
+ * \brief Nsc wrapper glue.
+ */
+class NscTcpL4Protocol : public Ipv4L4Protocol, ISendCallback, IInterruptCallback {
+public:
+ static const uint8_t PROT_NUMBER;
+ static TypeId GetTypeId (void);
+ /**
+ * \brief Constructor
+ */
+ NscTcpL4Protocol ();
+ virtual ~NscTcpL4Protocol ();
+
+ void SetNode (Ptr<Node> node);
+ void SetNscLibrary(const std::string &lib);
+
+ virtual int GetProtocolNumber (void) const;
+ virtual int GetVersion (void) const;
+
+ /**
+ * \return A smart Socket pointer to a NscTcpSocketImpl, allocated by this instance
+ * of the TCP protocol
+ */
+ Ptr<Socket> CreateSocket (void);
+
+ Ipv4EndPoint *Allocate (void);
+ Ipv4EndPoint *Allocate (Ipv4Address address);
+ Ipv4EndPoint *Allocate (uint16_t port);
+ Ipv4EndPoint *Allocate (Ipv4Address address, uint16_t port);
+ Ipv4EndPoint *Allocate (Ipv4Address localAddress, uint16_t localPort,
+ Ipv4Address peerAddress, uint16_t peerPort);
+
+ void DeAllocate (Ipv4EndPoint *endPoint);
+
+ /**
+ * \brief Recieve a packet up the protocol stack
+ * \param p The Packet to dump the contents into
+ * \param source The source's Ipv4Address
+ * \param destination The destinations Ipv4Address
+ * \param incomingInterface The Ipv4Interface it was received on
+ */
+ virtual void Receive (Ptr<Packet> p,
+ Ipv4Address const &source,
+ Ipv4Address const &destination,
+ Ptr<Ipv4Interface> incomingInterface);
+
+ // NSC callbacks.
+ // NSC invokes these hooks to interact with the simulator.
+ // In any case, these methods are only to be called by NSC.
+ //
+ // send_callback is invoked by NSCs 'ethernet driver' to re-inject
+ // a packet (i.e. an octet soup consisting of an IP Header, TCP Header
+ // and user payload, if any), into ns-3.
+ virtual void send_callback(const void *data, int datalen);
+ // This is called by the NSC stack whenever something of interest
+ // has happened, e.g. when data arrives on a socket, a listen socket
+ // has a new connection pending, etc.
+ virtual void wakeup();
+ // This is called by the Linux stack RNG initialization.
+ // Its also used by the cradle code to add a timestamp to
+ // printk/printf/debug output.
+ virtual void gettime(unsigned int *, unsigned int *);
+
+protected:
+ virtual void DoDispose (void);
+private:
+ Ptr<Node> m_node;
+ Ipv4EndPointDemux *m_endPoints;
+ ObjectFactory m_rttFactory;
+private:
+ void SoftInterrupt (void);
+ static ObjectFactory GetDefaultRttEstimatorFactory (void);
+ friend class NscTcpSocketImpl;
+ INetStack* m_nscStack;
+ void *m_dlopenHandle;
+ bool m_nscInterfacesSetUp;
+ Timer m_softTimer;
+};
+
+}; // namespace ns3
+
+#endif /* NSC_TCP_L4_PROTOCOL_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/nsc-tcp-socket-factory-impl.cc Fri Aug 29 23:08:18 2008 +0200
@@ -0,0 +1,50 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include "nsc-tcp-socket-factory-impl.h"
+#include "nsc-tcp-l4-protocol.h"
+#include "ns3/socket.h"
+#include "ns3/assert.h"
+
+namespace ns3 {
+
+NscTcpSocketFactoryImpl::NscTcpSocketFactoryImpl ()
+ : m_tcp (0)
+{}
+NscTcpSocketFactoryImpl::~NscTcpSocketFactoryImpl ()
+{
+ NS_ASSERT (m_tcp == 0);
+}
+
+void
+NscTcpSocketFactoryImpl::SetTcp (Ptr<NscTcpL4Protocol> tcp)
+{
+ m_tcp = tcp;
+}
+
+Ptr<Socket>
+NscTcpSocketFactoryImpl::CreateSocket (void)
+{
+ return m_tcp->CreateSocket ();
+}
+
+void
+NscTcpSocketFactoryImpl::DoDispose (void)
+{
+ m_tcp = 0;
+ TcpSocketFactory::DoDispose ();
+}
+
+} // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/nsc-tcp-socket-factory-impl.h Fri Aug 29 23:08:18 2008 +0200
@@ -0,0 +1,44 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef NSC_TCP_SOCKET_FACTORY_IMPL_H
+#define NSC_TCP_SOCKET_FACTORY_IMPL_H
+
+#include "ns3/tcp-socket-factory.h"
+#include "ns3/ptr.h"
+
+namespace ns3 {
+
+class NscTcpL4Protocol;
+
+class NscTcpSocketFactoryImpl : public TcpSocketFactory
+{
+public:
+ NscTcpSocketFactoryImpl ();
+ virtual ~NscTcpSocketFactoryImpl ();
+
+ void SetTcp (Ptr<NscTcpL4Protocol> tcp);
+
+ virtual Ptr<Socket> CreateSocket (void);
+
+protected:
+ virtual void DoDispose (void);
+private:
+ Ptr<NscTcpL4Protocol> m_tcp;
+};
+
+} // namespace ns3
+
+#endif /* NSC_TCP_SOCKET_FACTORY_IMPL_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/nsc-tcp-socket-impl.cc Fri Aug 29 23:08:18 2008 +0200
@@ -0,0 +1,842 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * based on tcp-socket-impl.cc, Author: Raj Bhattacharjea <raj.b@gatech.edu>
+ * Author: Florian Westphal <fw@strlen.de>
+ */
+
+#include "ns3/node.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/log.h"
+#include "ns3/ipv4.h"
+#include "ipv4-end-point.h"
+#include "ipv4-l4-demux.h"
+#include "nsc-tcp-l4-protocol.h"
+#include "nsc-tcp-socket-impl.h"
+#include "ns3/simulation-singleton.h"
+#include "tcp-typedefs.h"
+#include "ns3/simulator.h"
+#include "ns3/packet.h"
+#include "ns3/uinteger.h"
+#include "ns3/trace-source-accessor.h"
+
+#include <algorithm>
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+
+#include "nsc/sim/sim_errno.h"
+
+NS_LOG_COMPONENT_DEFINE ("NscTcpSocketImpl");
+
+using namespace std;
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (NscTcpSocketImpl);
+
+TypeId
+NscTcpSocketImpl::GetTypeId ()
+{
+ static TypeId tid = TypeId("ns3::NscTcpSocketImpl")
+ .SetParent<TcpSocket> ()
+ .AddTraceSource ("CongestionWindow",
+ "The TCP connection's congestion window",
+ MakeTraceSourceAccessor (&NscTcpSocketImpl::m_cWnd))
+ ;
+ return tid;
+}
+
+ NscTcpSocketImpl::NscTcpSocketImpl ()
+ : m_endPoint (0),
+ m_node (0),
+ m_tcp (0),
+ m_peerAddress ("0.0.0.0", 0),
+ m_errno (ERROR_NOTERROR),
+ m_shutdownSend (false),
+ m_shutdownRecv (false),
+ m_connected (false),
+ m_state (CLOSED),
+ m_closeOnEmpty (false),
+ m_txBufferSize (0),
+ m_rtt (0),
+ m_lastMeasuredRtt (Seconds(0.0))
+{
+ NS_LOG_FUNCTION (this);
+}
+
+NscTcpSocketImpl::NscTcpSocketImpl(const NscTcpSocketImpl& sock)
+ : TcpSocket(sock), //copy the base class callbacks
+ m_delAckMaxCount (sock.m_delAckMaxCount),
+ m_delAckTimeout (sock.m_delAckTimeout),
+ m_endPoint (0),
+ m_node (sock.m_node),
+ m_tcp (sock.m_tcp),
+ m_remoteAddress (sock.m_remoteAddress),
+ m_remotePort (sock.m_remotePort),
+ m_localAddress (sock.m_localAddress),
+ m_localPort (sock.m_localPort),
+ m_peerAddress (sock.m_peerAddress),
+ m_errno (sock.m_errno),
+ m_shutdownSend (sock.m_shutdownSend),
+ m_shutdownRecv (sock.m_shutdownRecv),
+ m_connected (sock.m_connected),
+ m_state (sock.m_state),
+ m_closeOnEmpty (sock.m_closeOnEmpty),
+ m_segmentSize (sock.m_segmentSize),
+ m_rxWindowSize (sock.m_rxWindowSize),
+ m_advertisedWindowSize (sock.m_advertisedWindowSize),
+ m_cWnd (sock.m_cWnd),
+ m_ssThresh (sock.m_ssThresh),
+ m_initialCWnd (sock.m_initialCWnd),
+ m_rtt (0),
+ m_lastMeasuredRtt (Seconds(0.0)),
+ m_cnTimeout (sock.m_cnTimeout),
+ m_cnCount (sock.m_cnCount),
+ m_rxAvailable (0),
+ m_nscTcpSocket (0),
+ m_sndBufSize (sock.m_sndBufSize)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_LOGIC("Invoked the copy constructor");
+ //copy the pending data if necessary
+ if(!sock.m_txBuffer.empty () )
+ {
+ m_txBuffer = sock.m_txBuffer;
+ }
+ //copy the rtt if necessary
+ if (sock.m_rtt)
+ {
+ m_rtt = sock.m_rtt->Copy();
+ }
+ //can't "copy" the endpoint just yes, must do this when we know the peer info
+ //too; this is in SYN_ACK_TX
+}
+
+NscTcpSocketImpl::~NscTcpSocketImpl ()
+{
+ NS_LOG_FUNCTION(this);
+ m_node = 0;
+ if (m_endPoint != 0)
+ {
+ NS_ASSERT (m_tcp != 0);
+ /**
+ * Note that this piece of code is a bit tricky:
+ * when DeAllocate is called, it will call into
+ * Ipv4EndPointDemux::Deallocate which triggers
+ * a delete of the associated endPoint which triggers
+ * in turn a call to the method ::Destroy below
+ * will will zero the m_endPoint field.
+ */
+ NS_ASSERT (m_endPoint != 0);
+ m_tcp->DeAllocate (m_endPoint);
+ NS_ASSERT (m_endPoint == 0);
+ }
+ m_tcp = 0;
+}
+
+void
+NscTcpSocketImpl::SetNode (Ptr<Node> node)
+{
+ m_node = node;
+ // Initialize some variables
+ m_cWnd = m_initialCWnd * m_segmentSize;
+ m_rxWindowSize = m_advertisedWindowSize;
+}
+
+void
+NscTcpSocketImpl::SetTcp (Ptr<NscTcpL4Protocol> tcp)
+{
+ m_nscTcpSocket = tcp->m_nscStack->new_tcp_socket();
+ m_tcp = tcp;
+}
+void
+NscTcpSocketImpl::SetRtt (Ptr<RttEstimator> rtt)
+{
+ m_rtt = rtt;
+}
+
+
+enum Socket::SocketErrno
+NscTcpSocketImpl::GetErrno (void) const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_errno;
+}
+
+Ptr<Node>
+NscTcpSocketImpl::GetNode (void) const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_node;
+}
+
+void
+NscTcpSocketImpl::Destroy (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_node = 0;
+ m_endPoint = 0;
+ m_tcp = 0;
+}
+int
+NscTcpSocketImpl::FinishBind (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ if (m_endPoint == 0)
+ {
+ return -1;
+ }
+ m_endPoint->SetRxCallback (MakeCallback (&NscTcpSocketImpl::ForwardUp, Ptr<NscTcpSocketImpl>(this)));
+ m_endPoint->SetDestroyCallback (MakeCallback (&NscTcpSocketImpl::Destroy, Ptr<NscTcpSocketImpl>(this)));
+ m_localAddress = m_endPoint->GetLocalAddress ();
+ m_localPort = m_endPoint->GetLocalPort ();
+ return 0;
+}
+
+int
+NscTcpSocketImpl::Bind (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_endPoint = m_tcp->Allocate ();
+ return FinishBind ();
+}
+int
+NscTcpSocketImpl::Bind (const Address &address)
+{
+ NS_LOG_FUNCTION (this<<address);
+ if (!InetSocketAddress::IsMatchingType (address))
+ {
+ return ERROR_INVAL;
+ }
+ InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
+ Ipv4Address ipv4 = transport.GetIpv4 ();
+ uint16_t port = transport.GetPort ();
+ if (ipv4 == Ipv4Address::GetAny () && port == 0)
+ {
+ m_endPoint = m_tcp->Allocate ();
+ NS_LOG_LOGIC ("TcpSocketImpl "<<this<<" got an endpoint: "<<m_endPoint);
+ }
+ else if (ipv4 == Ipv4Address::GetAny () && port != 0)
+ {
+ m_endPoint = m_tcp->Allocate (port);
+ NS_LOG_LOGIC ("TcpSocketImpl "<<this<<" got an endpoint: "<<m_endPoint);
+ }
+ else if (ipv4 != Ipv4Address::GetAny () && port == 0)
+ {
+ m_endPoint = m_tcp->Allocate (ipv4);
+ NS_LOG_LOGIC ("TcpSocketImpl "<<this<<" got an endpoint: "<<m_endPoint);
+ }
+ else if (ipv4 != Ipv4Address::GetAny () && port != 0)
+ {
+ m_endPoint = m_tcp->Allocate (ipv4, port);
+ NS_LOG_LOGIC ("TcpSocketImpl "<<this<<" got an endpoint: "<<m_endPoint);
+ }
+
+ m_localPort = port;
+ return FinishBind ();
+}
+
+int
+NscTcpSocketImpl::ShutdownSend (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_shutdownSend = true;
+ return 0;
+}
+int
+NscTcpSocketImpl::ShutdownRecv (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_shutdownRecv = false;
+ return 0;
+}
+
+int
+NscTcpSocketImpl::Close (void)
+{
+ NS_LOG_FUNCTION (this << m_state);
+
+ if (m_state == CLOSED)
+ {
+ return -1;
+ }
+ if (!m_txBuffer.empty ())
+ { // App close with pending data must wait until all data transmitted
+ m_closeOnEmpty = true;
+ NS_LOG_LOGIC("Socket " << this <<
+ " deferring close, state " << m_state);
+ return 0;
+ }
+
+ m_nscTcpSocket->disconnect();
+ m_state = CLOSED;
+ ShutdownSend ();
+ return 0;
+}
+
+int
+NscTcpSocketImpl::Connect (const Address & address)
+{
+ NS_LOG_FUNCTION (this << address);
+ if (m_endPoint == 0)
+ {
+ if (Bind () == -1)
+ {
+ NS_ASSERT (m_endPoint == 0);
+ return -1;
+ }
+ NS_ASSERT (m_endPoint != 0);
+ }
+ InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
+ m_remoteAddress = transport.GetIpv4 ();
+ m_remotePort = transport.GetPort ();
+
+ struct in_addr remoteAddr;
+ uint32_t addr32;
+
+ m_remoteAddress.Serialize((uint8_t*)&addr32);
+ remoteAddr.s_addr = addr32;
+
+ m_nscTcpSocket->connect(inet_ntoa(remoteAddr), m_remotePort);
+ m_state = SYN_SENT;
+ return 0;
+}
+
+int
+NscTcpSocketImpl::Send (const Ptr<Packet> p, uint32_t flags)
+{
+ NS_LOG_FUNCTION (this << p);
+
+ NS_ASSERT (p->GetSize () > 0);
+ if (m_state == ESTABLISHED || m_state == SYN_SENT || m_state == CLOSE_WAIT)
+ {
+ if (p->GetSize () > GetTxAvailable ())
+ {
+ m_errno = ERROR_MSGSIZE;
+ return -1;
+ }
+
+ bool txEmpty = m_txBuffer.empty();
+ if (m_state == ESTABLISHED)
+ {
+ if (txEmpty)
+ {
+ m_txBuffer.push(p);
+ m_txBufferSize += p->GetSize ();
+ }
+ if (!SendPendingData())
+ {
+ if (m_errno == ERROR_AGAIN)
+ {
+ return txEmpty ? p->GetSize () : -1;
+ }
+ if (txEmpty)
+ {
+ m_txBuffer.pop ();
+ m_txBufferSize = 0;
+ }
+ return -1;
+ }
+ }
+ else
+ { // SYN_SET -- Queue Data
+ m_txBuffer.push(p);
+ m_txBufferSize += p->GetSize ();
+ }
+ return p->GetSize ();
+ }
+ else
+ {
+ m_errno = ERROR_NOTCONN;
+ return -1;
+ }
+}
+
+int
+NscTcpSocketImpl::SendTo (Ptr<Packet> p, uint32_t flags, const Address &address)
+{
+ NS_LOG_FUNCTION (this << address << p);
+ if (!m_connected)
+ {
+ m_errno = ERROR_NOTCONN;
+ return -1;
+ }
+ else
+ {
+ return Send (p, flags); //drop the address according to BSD manpages
+ }
+}
+
+uint32_t
+NscTcpSocketImpl::GetTxAvailable (void) const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ if (m_txBufferSize != 0)
+ {
+ NS_ASSERT (m_txBufferSize <= m_sndBufSize);
+ return m_sndBufSize - m_txBufferSize;
+ }
+ else
+ {
+ return m_sndBufSize;
+ }
+}
+
+int
+NscTcpSocketImpl::Listen (uint32_t q)
+{
+ NS_LOG_FUNCTION (this << q);
+ m_nscTcpSocket->listen(m_localPort);
+ m_state = LISTEN;
+ return 0;
+}
+
+
+void
+NscTcpSocketImpl::NSCWakeup ()
+{
+ switch (m_state) {
+ case SYN_SENT:
+ if (!m_nscTcpSocket->is_connected())
+ break;
+ m_state = ESTABLISHED;
+ Simulator::ScheduleNow(&NscTcpSocketImpl::ConnectionSucceeded, this);
+ // fall through to schedule read/write events
+ case ESTABLISHED:
+ if (!m_txBuffer.empty ())
+ Simulator::ScheduleNow(&NscTcpSocketImpl::SendPendingData, this);
+ Simulator::ScheduleNow(&NscTcpSocketImpl::ReadPendingData, this);
+ break;
+ case LISTEN:
+ Simulator::ScheduleNow(&NscTcpSocketImpl::Accept, this);
+ break;
+ case CLOSED: break;
+ default:
+ NS_LOG_DEBUG (this << " invalid state: " << m_state);
+ }
+}
+
+Ptr<Packet>
+NscTcpSocketImpl::Recv (uint32_t maxSize, uint32_t flags)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ if (m_deliveryQueue.empty() )
+ {
+ return 0;
+ }
+ Ptr<Packet> p = m_deliveryQueue.front ();
+ if (p->GetSize () <= maxSize)
+ {
+ m_deliveryQueue.pop ();
+ m_rxAvailable -= p->GetSize ();
+ }
+ else
+ {
+ p = 0;
+ }
+ return p;
+}
+
+Ptr<Packet>
+NscTcpSocketImpl::RecvFrom (uint32_t maxSize, uint32_t flags,
+ Address &fromAddress)
+{
+ NS_LOG_FUNCTION (this << maxSize << flags);
+ Ptr<Packet> packet = Recv (maxSize, flags);
+ if (packet != 0)
+ {
+ SocketAddressTag tag;
+ bool found;
+ found = packet->FindFirstMatchingTag (tag);
+ NS_ASSERT (found);
+ fromAddress = tag.GetAddress ();
+ }
+ return packet;
+}
+
+uint32_t
+NscTcpSocketImpl::GetRxAvailable (void) const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ // We separately maintain this state to avoid walking the queue
+ // every time this might be called
+ return m_rxAvailable;
+}
+
+void
+NscTcpSocketImpl::ForwardUp (Ptr<Packet> packet, Ipv4Address ipv4, uint16_t port)
+{
+ NSCWakeup();
+}
+
+void NscTcpSocketImpl::CompleteFork(void)
+{
+ // The address pairs (m_localAddress, m_localPort, m_remoteAddress, m_remotePort)
+ // are bogus, but this isn't important at the moment, because
+ // address <-> Socket handling is done by NSC internally.
+ // We only need to add the new ns-3 socket to the list of sockets, so
+ // we use plain Allocate() instead of Allocate(m_localAddress, ... )
+ uint8_t buf[4];
+ int port;
+ size_t buflen = sizeof(buf);
+
+ if (0 == m_nscTcpSocket->getpeername((void *) buf, &buflen, &port)) {
+ m_remotePort = ntohs(port);
+ m_remoteAddress = m_remoteAddress.Deserialize(buf);
+ m_peerAddress = InetSocketAddress(m_remoteAddress, m_remotePort);
+ }
+
+ m_endPoint = m_tcp->Allocate ();
+
+ //the cloned socket with be in listen state, so manually change state
+ NS_ASSERT(m_state == LISTEN);
+ m_state = ESTABLISHED;
+
+ buflen = sizeof(buf);
+ if (0 == m_nscTcpSocket->getsockname((void *) &buf, &buflen, &port))
+ m_localAddress = m_localAddress.Deserialize(buf);
+
+ NS_LOG_LOGIC ("NscTcpSocketImpl " << this << " accepted connection from "
+ << m_remoteAddress << ":" << m_remotePort
+ << " to " << m_localAddress << ":" << m_localPort);
+ //equivalent to FinishBind
+ m_endPoint->SetRxCallback (MakeCallback (&NscTcpSocketImpl::ForwardUp, Ptr<NscTcpSocketImpl>(this)));
+ m_endPoint->SetDestroyCallback (MakeCallback (&NscTcpSocketImpl::Destroy, Ptr<NscTcpSocketImpl>(this)));
+
+ NotifyNewConnectionCreated (this, m_peerAddress);
+}
+
+void NscTcpSocketImpl::ConnectionSucceeded()
+{ // We would preferred to have scheduled an event directly to
+ // NotifyConnectionSucceeded, but (sigh) these are protected
+ // and we can get the address of it :(
+
+ uint8_t buf[4];
+ int port;
+ size_t buflen = sizeof(buf);
+ if (0 == m_nscTcpSocket->getsockname((void *) &buf, &buflen, &port)) {
+ m_localAddress = m_localAddress.Deserialize(buf);
+ m_localPort = ntohs(port);
+ }
+
+ NS_LOG_LOGIC ("NscTcpSocketImpl " << this << " connected to "
+ << m_remoteAddress << ":" << m_remotePort
+ << " from " << m_localAddress << ":" << m_localPort);
+ NotifyConnectionSucceeded();
+}
+
+
+bool NscTcpSocketImpl::Accept (void)
+{
+ if (m_state == CLOSED)
+ { // Happens if application closes listening socket after Accept() was scheduled.
+ return false;
+ }
+ NS_ASSERT (m_state == LISTEN);
+
+ if (!m_nscTcpSocket->is_listening())
+ {
+ return false;
+ }
+ INetStreamSocket *newsock;
+ int res = m_nscTcpSocket->accept(&newsock);
+ if (res != 0)
+ {
+ return false;
+ }
+// We could obtain a fromAddress using getpeername, but we've already
+// finished the tcp handshake here, i.e. this is a new connection
+// and not a connection request.
+// if (!NotifyConnectionRequest(fromAddress))
+// return true;
+
+ // Clone the socket
+ Ptr<NscTcpSocketImpl> newSock = Copy ();
+ newSock->m_nscTcpSocket = newsock;
+ NS_LOG_LOGIC ("Cloned a NscTcpSocketImpl " << newSock);
+
+ Simulator::ScheduleNow (&NscTcpSocketImpl::CompleteFork, newSock);
+ return true;
+}
+
+bool NscTcpSocketImpl::ReadPendingData (void)
+{
+ if (m_state != ESTABLISHED)
+ {
+ return false;
+ }
+ int len, err;
+ uint8_t buffer[8192];
+ len = sizeof(buffer);
+ m_errno = ERROR_NOTERROR;
+ err = m_nscTcpSocket->read_data(buffer, &len);
+ if (err == 0 && len == 0)
+ {
+ NS_LOG_LOGIC ("ReadPendingData got EOF from socket");
+ m_state = CLOSED;
+ return false;
+ }
+ m_errno = GetNativeNs3Errno(err);
+ switch (m_errno)
+ {
+ case ERROR_NOTERROR: break; // some data was sent
+ case ERROR_AGAIN: return false;
+ default:
+ NS_LOG_WARN ("Error (" << err << ") " <<
+ "during read_data, ns-3 errno set to" << m_errno);
+ m_state = CLOSED;
+ return false;
+ }
+
+ Ptr<Packet> p = Create<Packet> (buffer, len);
+
+ SocketAddressTag tag;
+
+ tag.SetAddress (m_peerAddress);
+ p->AddTag (tag);
+ m_deliveryQueue.push (p);
+ m_rxAvailable += p->GetSize ();
+
+ NotifyDataRecv ();
+ return true;
+}
+
+bool NscTcpSocketImpl::SendPendingData (void)
+{
+ NS_LOG_FUNCTION (this);
+ NS_LOG_LOGIC ("ENTERING SendPendingData");
+
+ if (m_txBuffer.empty ())
+ {
+ return false;
+ }
+
+ int ret;
+ size_t size, written = 0;
+
+ do {
+ Ptr<Packet> &p = m_txBuffer.front ();
+ size = p->GetSize ();
+ NS_ASSERT (size > 0);
+
+ m_errno = ERROR_NOTERROR;
+ ret = m_nscTcpSocket->send_data((const char *)p->PeekData (), size);
+ if (ret <= 0)
+ {
+ m_errno = GetNativeNs3Errno(ret);
+ if (m_errno != ERROR_AGAIN)
+ {
+ NS_LOG_WARN ("Error (" << ret << ") " <<
+ "during send_data, ns-3 errno set to" << m_errno);
+ }
+ break;
+ }
+ written += ret;
+
+ NS_ASSERT (m_txBufferSize >= (size_t)ret);
+ m_txBufferSize -= ret;
+
+ if ((size_t)ret < size)
+ {
+ p->RemoveAtStart(ret);
+ break;
+ }
+
+ m_txBuffer.pop ();
+
+ if (m_txBuffer.empty ())
+ {
+ if (m_closeOnEmpty)
+ {
+ m_nscTcpSocket->disconnect();
+ m_state = CLOSED;
+ }
+ break;
+ }
+ } while ((size_t) ret == size);
+
+ if (written > 0)
+ {
+ Simulator::ScheduleNow(&NscTcpSocketImpl::NotifyDataSent, this, ret);
+ return true;
+ }
+ return false;
+}
+
+Ptr<NscTcpSocketImpl> NscTcpSocketImpl::Copy ()
+{
+ return CopyObject<NscTcpSocketImpl> (this);
+}
+
+void
+NscTcpSocketImpl::SetSndBufSize (uint32_t size)
+{
+ m_sndBufSize = size;
+}
+
+uint32_t
+NscTcpSocketImpl::GetSndBufSize (void) const
+{
+ return m_sndBufSize;
+}
+
+void
+NscTcpSocketImpl::SetRcvBufSize (uint32_t size)
+{
+ m_rcvBufSize = size;
+}
+
+uint32_t
+NscTcpSocketImpl::GetRcvBufSize (void) const
+{
+ return m_rcvBufSize;
+}
+
+void
+NscTcpSocketImpl::SetSegSize (uint32_t size)
+{
+ m_segmentSize = size;
+}
+
+uint32_t
+NscTcpSocketImpl::GetSegSize (void) const
+{
+ return m_segmentSize;
+}
+
+void
+NscTcpSocketImpl::SetAdvWin (uint32_t window)
+{
+ m_advertisedWindowSize = window;
+}
+
+uint32_t
+NscTcpSocketImpl::GetAdvWin (void) const
+{
+ return m_advertisedWindowSize;
+}
+
+void
+NscTcpSocketImpl::SetSSThresh (uint32_t threshold)
+{
+ m_ssThresh = threshold;
+}
+
+uint32_t
+NscTcpSocketImpl::GetSSThresh (void) const
+{
+ return m_ssThresh;
+}
+
+void
+NscTcpSocketImpl::SetInitialCwnd (uint32_t cwnd)
+{
+ m_initialCWnd = cwnd;
+}
+
+uint32_t
+NscTcpSocketImpl::GetInitialCwnd (void) const
+{
+ return m_initialCWnd;
+}
+
+void
+NscTcpSocketImpl::SetConnTimeout (Time timeout)
+{
+ m_cnTimeout = timeout;
+}
+
+Time
+NscTcpSocketImpl::GetConnTimeout (void) const
+{
+ return m_cnTimeout;
+}
+
+void
+NscTcpSocketImpl::SetConnCount (uint32_t count)
+{
+ m_cnCount = count;
+}
+
+uint32_t
+NscTcpSocketImpl::GetConnCount (void) const
+{
+ return m_cnCount;
+}
+
+void
+NscTcpSocketImpl::SetDelAckTimeout (Time timeout)
+{
+ m_delAckTimeout = timeout;
+}
+
+Time
+NscTcpSocketImpl::GetDelAckTimeout (void) const
+{
+ return m_delAckTimeout;
+}
+
+void
+NscTcpSocketImpl::SetDelAckMaxCount (uint32_t count)
+{
+ m_delAckMaxCount = count;
+}
+
+uint32_t
+NscTcpSocketImpl::GetDelAckMaxCount (void) const
+{
+ return m_delAckMaxCount;
+}
+
+enum Socket::SocketErrno
+NscTcpSocketImpl::GetNativeNs3Errno(int error) const
+{
+ enum nsc_errno err;
+
+ if (error >= 0)
+ {
+ return ERROR_NOTERROR;
+ }
+ err = (enum nsc_errno) error;
+ switch (err)
+ {
+ case NSC_EADDRINUSE: // fallthrough
+ case NSC_EADDRNOTAVAIL: return ERROR_AFNOSUPPORT;
+ case NSC_EINPROGRESS: // Altough nsc sockets are nonblocking, we pretend they're not.
+ case NSC_EAGAIN: return ERROR_AGAIN;
+ case NSC_EISCONN: // fallthrough
+ case NSC_EALREADY: return ERROR_ISCONN;
+ case NSC_ECONNREFUSED: return ERROR_NOROUTETOHOST; // XXX, better mapping?
+ case NSC_ECONNRESET: // for no, all of these fall through
+ case NSC_EHOSTDOWN:
+ case NSC_ENETUNREACH:
+ case NSC_EHOSTUNREACH: return ERROR_NOROUTETOHOST;
+ case NSC_EMSGSIZE: return ERROR_MSGSIZE;
+ case NSC_ENOTCONN: return ERROR_NOTCONN;
+ case NSC_ESHUTDOWN: return ERROR_SHUTDOWN;
+ case NSC_ETIMEDOUT: return ERROR_NOTCONN; // XXX - this mapping isn't correct
+ case NSC_ENOTDIR: // used by eg. sysctl(2). Shouldn't happen normally,
+ // but is triggered by e.g. show_config().
+ case NSC_EUNKNOWN: return ERROR_INVAL; // Catches stacks that 'return -1' without real mapping
+ }
+ NS_ASSERT_MSG(0, "Unknown NSC error");
+ return ERROR_INVAL;
+}
+
+}//namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/nsc-tcp-socket-impl.h Fri Aug 29 23:08:18 2008 +0200
@@ -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 */