nsc: move nsc glue code from nsc-tcp-l4-protocol to node/nsc-glue.cc.
known problems:
- sim_interface.h is duplicated
- nsc-glue.cc adds hooks in node.cc, "hijacks" incoming packets
- nsc-glue exports NSCs INetStack (instead of wrapping it completely)
- nsc-tcp-l4-protocol and nsc-tcp-socket-impl make calls into nsc-glue
- nsc-tcp-socket-impl should really be "nsc-socket-core" (or something
like that)
needs fixing on nsc side:
- no support for multiple interfaces yet (also not yet supported
on nsc side)
- nsc initialisation still tied to IP (Adding an Interface and assigning the
IP address is a single step; it should be separate)
maybe there is more.
There is a NSC_NEXT define in nsc-glue.h, its main purpose is to flag
the places where the NSC API needs to be adapted to support multiple
interfaces in nsc.
1.1 --- a/src/internet-stack/nsc-sysctl.cc Wed Jul 15 14:59:44 2009 +0200
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,154 +0,0 @@
1.4 -/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
1.5 -/*
1.6 - * This program is free software; you can redistribute it and/or modify
1.7 - * it under the terms of the GNU General Public License version 2 as
1.8 - * published by the Free Software Foundation;
1.9 - *
1.10 - * This program is distributed in the hope that it will be useful,
1.11 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.12 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.13 - * GNU General Public License for more details.
1.14 - *
1.15 - * You should have received a copy of the GNU General Public License
1.16 - * along with this program; if not, write to the Free Software
1.17 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1.18 - *
1.19 - * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
1.20 - */
1.21 -
1.22 -#include "ns3/string.h"
1.23 -#include "nsc-sysctl.h"
1.24 -
1.25 -#include "sim_interface.h"
1.26 -
1.27 -namespace ns3 {
1.28 -
1.29 -class NscStackStringAccessor : public AttributeAccessor
1.30 -{
1.31 - public:
1.32 - NscStackStringAccessor (std::string name) : m_name (name) {}
1.33 -
1.34 - virtual bool Set (ObjectBase * object, const AttributeValue &val) const;
1.35 - virtual bool Get (const ObjectBase * object, AttributeValue &val) const;
1.36 - virtual bool HasGetter (void) const;
1.37 - virtual bool HasSetter (void) const;
1.38 - private:
1.39 - std::string m_name;
1.40 -};
1.41 -
1.42 -bool NscStackStringAccessor::HasGetter(void) const
1.43 -{
1.44 - return true;
1.45 -}
1.46 -
1.47 -bool NscStackStringAccessor::HasSetter(void) const
1.48 -{
1.49 - return true;
1.50 -}
1.51 -
1.52 -
1.53 -bool NscStackStringAccessor::Set (ObjectBase * object, const AttributeValue & val) const
1.54 -{
1.55 - const StringValue *value = dynamic_cast<const StringValue *> (&val);
1.56 - if (value == 0)
1.57 - {
1.58 - return false;
1.59 - }
1.60 - Ns3NscStack *obj = dynamic_cast<Ns3NscStack *> (object);
1.61 - if (obj == 0)
1.62 - {
1.63 - return false;
1.64 - }
1.65 - obj->Set (m_name, value->Get ());
1.66 - return true;
1.67 -}
1.68 -
1.69 -bool NscStackStringAccessor::Get (const ObjectBase * object, AttributeValue &val) const
1.70 -{
1.71 - StringValue *value = dynamic_cast<StringValue *> (&val);
1.72 - if (value == 0)
1.73 - {
1.74 - return false;
1.75 - }
1.76 - const Ns3NscStack *obj = dynamic_cast<const Ns3NscStack *> (object);
1.77 - if (obj == 0)
1.78 - {
1.79 - return false;
1.80 - }
1.81 - value->Set (obj->Get (m_name));
1.82 - return true;
1.83 -}
1.84 -
1.85 -
1.86 -TypeId
1.87 -Ns3NscStack::GetInstanceTypeId (void) const
1.88 -{
1.89 - if (m_stack == 0)
1.90 - {
1.91 - // if we have no stack, we are a normal NscStack without any attributes.
1.92 - return GetTypeId ();
1.93 - }
1.94 - std::string name = "ns3::Ns3NscStack<";
1.95 - name += m_stack->get_name ();
1.96 - name += ">";
1.97 - TypeId tid;
1.98 - if (TypeId::LookupByNameFailSafe (name, &tid))
1.99 - {
1.100 - // if the relevant TypeId has already been registered, no need to do it again.
1.101 - return tid;
1.102 - }
1.103 - else
1.104 - {
1.105 - // Now, we register a new TypeId for this stack which will look
1.106 - // like a subclass of the Ns3NscStack. The class Ns3NscStack is effectively
1.107 - // mutating into a subclass of itself from the point of view of the TypeId
1.108 - // system _here_
1.109 - tid = TypeId (name.c_str ());
1.110 - tid.SetParent<Ns3NscStack> ();
1.111 - char buf[256];
1.112 - for (int i=0; m_stack->sysctl_getnum(i, buf, sizeof(buf)) > 0 ;i++)
1.113 - {
1.114 - char value[256];
1.115 - if (m_stack->sysctl_get (buf, value, sizeof(value)) > 0)
1.116 - {
1.117 - tid.AddAttribute (buf, "Help text",
1.118 - StringValue (value),
1.119 - Create<NscStackStringAccessor> (buf),
1.120 - MakeStringChecker ());
1.121 - }
1.122 - }
1.123 - return tid;
1.124 - }
1.125 -}
1.126 -
1.127 -std::string
1.128 -Ns3NscStack::Get (std::string name) const
1.129 -{
1.130 - char buf[512];
1.131 - if (m_stack->sysctl_get (name.c_str (), buf, sizeof(buf)) <= 0)
1.132 - { // name.c_str () is not a valid sysctl name, or internal NSC error (eg. error converting value)
1.133 - return NULL;
1.134 - }
1.135 - return std::string(buf);
1.136 -}
1.137 -
1.138 -void
1.139 -Ns3NscStack::Set (std::string name, std::string value)
1.140 -{
1.141 - int ret = m_stack->sysctl_set (name.c_str (), value.c_str ());
1.142 - if (ret < 0)
1.143 - {
1.144 - NS_FATAL_ERROR ("setting " << name << " to " << value << "failed (retval " << ret << ")");
1.145 - }
1.146 -}
1.147 -
1.148 -TypeId
1.149 -Ns3NscStack::Ns3NscStack::GetTypeId (void)
1.150 -{
1.151 - static TypeId tid = TypeId ("ns3::Ns3NscStack")
1.152 - .SetParent<Object> ()
1.153 - ;
1.154 - return tid;
1.155 -}
1.156 -
1.157 -} // namespace ns3
2.1 --- a/src/internet-stack/nsc-sysctl.h Wed Jul 15 14:59:44 2009 +0200
2.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2.3 @@ -1,44 +0,0 @@
2.4 -/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2.5 -/*
2.6 - * This program is free software; you can redistribute it and/or modify
2.7 - * it under the terms of the GNU General Public License version 2 as
2.8 - * published by the Free Software Foundation;
2.9 - *
2.10 - * This program is distributed in the hope that it will be useful,
2.11 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
2.12 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2.13 - * GNU General Public License for more details.
2.14 - *
2.15 - * You should have received a copy of the GNU General Public License
2.16 - * along with this program; if not, write to the Free Software
2.17 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2.18 - *
2.19 - * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
2.20 - */
2.21 -
2.22 -#include <string>
2.23 -
2.24 -#include "ns3/attribute.h"
2.25 -#include "ns3/object.h"
2.26 -
2.27 -struct INetStack;
2.28 -
2.29 -namespace ns3 {
2.30 -
2.31 -// This object represents the underlying nsc stack,
2.32 -// which is aggregated to a Node object, and which provides access to the
2.33 -// sysctls of the nsc stack through attributes.
2.34 -class Ns3NscStack : public Object
2.35 -{
2.36 -public:
2.37 - static TypeId GetTypeId (void);
2.38 - virtual TypeId GetInstanceTypeId (void) const;
2.39 - void SetStack (INetStack *stack) {m_stack = stack;}
2.40 -
2.41 -private:
2.42 - friend class NscStackStringAccessor;
2.43 - void Set (std::string name, std::string value);
2.44 - std::string Get (std::string name) const;
2.45 - INetStack *m_stack;
2.46 -};
2.47 -} // namespace ns3
3.1 --- a/src/internet-stack/nsc-tcp-l4-protocol.cc Wed Jul 15 14:59:44 2009 +0200
3.2 +++ b/src/internet-stack/nsc-tcp-l4-protocol.cc Wed Jul 15 18:46:14 2009 +0200
3.3 @@ -19,7 +19,6 @@
3.4
3.5 #include "ns3/assert.h"
3.6 #include "ns3/log.h"
3.7 -#include "ns3/nstime.h"
3.8
3.9 #include "ns3/packet.h"
3.10 #include "ns3/node.h"
3.11 @@ -32,7 +31,7 @@
3.12 #include "ipv4-end-point.h"
3.13 #include "ipv4-l3-protocol.h"
3.14 #include "nsc-tcp-l4-protocol.h"
3.15 -#include "nsc-sysctl.h"
3.16 +
3.17 #include "nsc-tcp-socket-factory-impl.h"
3.18
3.19 #include "tcp-typedefs.h"
3.20 @@ -87,36 +86,18 @@
3.21 return tid;
3.22 }
3.23
3.24 -int external_rand()
3.25 +NscTcpL4Protocol::NscTcpL4Protocol ()
3.26 + : m_endPoints (new Ipv4EndPointDemux ())
3.27 {
3.28 - return 1; // TODO
3.29 -}
3.30 -
3.31 -NscTcpL4Protocol::NscTcpL4Protocol ()
3.32 - : m_endPoints (new Ipv4EndPointDemux ()),
3.33 - m_nscStack (0),
3.34 - m_softTimer (Timer::CANCEL_ON_DESTROY)
3.35 -{
3.36 - m_dlopenHandle = NULL;
3.37 NS_LOG_LOGIC("Made a NscTcpL4Protocol "<<this);
3.38 }
3.39
3.40 -NscTcpL4Protocol::~NscTcpL4Protocol ()
3.41 -{
3.42 - NS_LOG_FUNCTION (this);
3.43 - dlclose(m_dlopenHandle);
3.44 -}
3.45 -
3.46 void
3.47 NscTcpL4Protocol::SetNscLibrary(const std::string &soname)
3.48 {
3.49 if (soname!="")
3.50 {
3.51 m_nscLibrary = soname;
3.52 - NS_ASSERT(!m_dlopenHandle);
3.53 - m_dlopenHandle = dlopen(soname.c_str (), RTLD_NOW);
3.54 - if (m_dlopenHandle == NULL)
3.55 - NS_FATAL_ERROR (dlerror());
3.56 }
3.57 }
3.58
3.59 @@ -125,40 +106,14 @@
3.60 {
3.61 return m_nscLibrary;
3.62 }
3.63 -void
3.64 +
3.65 +
3.66 +void
3.67 NscTcpL4Protocol::SetNode (Ptr<Node> node)
3.68 {
3.69 m_node = node;
3.70 -
3.71 - if (m_nscStack)
3.72 - { // stack has already been loaded...
3.73 - return;
3.74 - }
3.75 -
3.76 - NS_ASSERT(m_dlopenHandle);
3.77 -
3.78 - FCreateStack create = (FCreateStack)dlsym(m_dlopenHandle, "nsc_create_stack");
3.79 - NS_ASSERT(create);
3.80 - m_nscStack = create(this, this, external_rand);
3.81 - int hzval = m_nscStack->get_hz();
3.82 -
3.83 - NS_ASSERT(hzval > 0);
3.84 -
3.85 - m_softTimer.SetFunction (&NscTcpL4Protocol::SoftInterrupt, this);
3.86 - m_softTimer.SetDelay (MilliSeconds (1000/hzval));
3.87 - m_nscStack->init(hzval);
3.88 - // This enables stack and NSC debug messages
3.89 - // m_nscStack->set_diagnostic(1000);
3.90 -
3.91 - Ptr<Ns3NscStack> nscStack = Create<Ns3NscStack> ();
3.92 - nscStack->SetStack (m_nscStack);
3.93 - node->AggregateObject (nscStack);
3.94 -
3.95 - m_softTimer.Schedule ();
3.96 -
3.97 - // its likely no ns-3 interface exits at this point, so
3.98 - // we dealy adding the nsc interface until the start of the simulation.
3.99 - Simulator::ScheduleNow (&NscTcpL4Protocol::AddInterface, this);
3.100 + m_node->SetNscLibrary (m_nscLibrary);
3.101 + m_node->RegisterNscWakeupCallback (MakeCallback (&NscTcpL4Protocol::Wakeup , this));
3.102 }
3.103
3.104 void
3.105 @@ -270,82 +225,10 @@
3.106 NscTcpL4Protocol::DeAllocate (Ipv4EndPoint *endPoint)
3.107 {
3.108 NS_LOG_FUNCTION (this << endPoint);
3.109 - // NSC m_endPoints->DeAllocate (endPoint);
3.110 + m_endPoints->DeAllocate (endPoint);
3.111 }
3.112
3.113 -Ipv4L4Protocol::RxStatus
3.114 -NscTcpL4Protocol::Receive (Ptr<Packet> packet,
3.115 - Ipv4Address const &source,
3.116 - Ipv4Address const &destination,
3.117 - Ptr<Ipv4Interface> incomingInterface)
3.118 -{
3.119 - NS_LOG_FUNCTION (this << packet << source << destination << incomingInterface);
3.120 - Ipv4Header ipHeader;
3.121 - uint32_t packetSize = packet->GetSize();
3.122 -
3.123 - // The way things work at the moment, the IP header has been removed
3.124 - // by the ns-3 IPv4 processing code. However, the NSC stack expects
3.125 - // a complete IP packet, so we add the IP header back.
3.126 - // Since the original header is already gone, we create a new one
3.127 - // based on the information we have.
3.128 - ipHeader.SetSource (source);
3.129 - ipHeader.SetDestination (destination);
3.130 - ipHeader.SetProtocol (PROT_NUMBER);
3.131 - ipHeader.SetPayloadSize (packetSize);
3.132 - ipHeader.SetTtl (1);
3.133 - // all NSC stacks check the IP checksum
3.134 - ipHeader.EnableChecksum ();
3.135 -
3.136 - packet->AddHeader(ipHeader);
3.137 - packetSize = packet->GetSize();
3.138 -
3.139 - const uint8_t *data = const_cast<uint8_t *>(packet->PeekData());
3.140 -
3.141 - // deliver complete packet to the NSC network stack
3.142 - m_nscStack->if_receive_packet(0, data, packetSize);
3.143 - wakeup ();
3.144 - return Ipv4L4Protocol::RX_OK;
3.145 -}
3.146 -
3.147 -void NscTcpL4Protocol::SoftInterrupt (void)
3.148 -{
3.149 - m_nscStack->timer_interrupt ();
3.150 - m_nscStack->increment_ticks ();
3.151 - m_softTimer.Schedule ();
3.152 -}
3.153 -
3.154 -void NscTcpL4Protocol::send_callback(const void* data, int datalen)
3.155 -{
3.156 - Ptr<Packet> p;
3.157 - uint32_t ipv4Saddr, ipv4Daddr;
3.158 -
3.159 - NS_ASSERT(datalen > 20);
3.160 -
3.161 -
3.162 - // create packet, without IP header. The TCP header is not touched.
3.163 - // Not using the IP header makes integration easier, but it destroys
3.164 - // eg. ECN.
3.165 - const uint8_t *rawdata = reinterpret_cast<const uint8_t *>(data);
3.166 - rawdata += 20; // skip IP header. IP options aren't supported at this time.
3.167 - datalen -= 20;
3.168 - p = Create<Packet> (rawdata, datalen);
3.169 -
3.170 - // we need the real source/destination ipv4 addresses for Send ().
3.171 - const uint32_t *ipheader = reinterpret_cast<const uint32_t *>(data);
3.172 - ipv4Saddr = *(ipheader+3);
3.173 - ipv4Daddr = *(ipheader+4);
3.174 -
3.175 - Ipv4Address saddr(ntohl(ipv4Saddr));
3.176 - Ipv4Address daddr(ntohl(ipv4Daddr));
3.177 -
3.178 - Ptr<Ipv4L3Protocol> ipv4 = m_node->GetObject<Ipv4L3Protocol> ();
3.179 - NS_ASSERT_MSG (ipv4, "nsc callback invoked, but node has no ipv4 object");
3.180 -
3.181 - ipv4->Send (p, saddr, daddr, PROT_NUMBER, 0);
3.182 - m_nscStack->if_send_finish(0);
3.183 -}
3.184 -
3.185 -void NscTcpL4Protocol::wakeup()
3.186 +void NscTcpL4Protocol::Wakeup()
3.187 {
3.188 // TODO
3.189 // this should schedule a timer to read from all tcp sockets now... this is
3.190 @@ -359,70 +242,13 @@
3.191 }
3.192 }
3.193
3.194 -void NscTcpL4Protocol::gettime(unsigned int* sec, unsigned int* usec)
3.195 -{
3.196 - // Only used by the Linux network stack, e.g. during ISN generation
3.197 - // and in the kernel rng initialization routine. Also used in Linux
3.198 - // printk output.
3.199 - Time t = Simulator::Now ();
3.200 - int64_t us = t.GetMicroSeconds ();
3.201 - *sec = us / (1000*1000);
3.202 - *usec = us - *sec * (1000*1000);
3.203 -}
3.204 -
3.205 -
3.206 -void NscTcpL4Protocol::AddInterface(void)
3.207 -{
3.208 - Ptr<Ipv4> ip = m_node->GetObject<Ipv4> ();
3.209 - const uint32_t nInterfaces = ip->GetNInterfaces ();
3.210 -
3.211 - NS_ASSERT_MSG (nInterfaces <= 2, "nsc does not support multiple interfaces per node");
3.212 -
3.213 - // start from 1, ignore the loopback interface (HACK)
3.214 - // we really don't need the loop, but its here to illustrate
3.215 - // how things _should_ be (once nsc can deal with multiple interfaces...)
3.216 - for (uint32_t i = 1; i < nInterfaces; i++)
3.217 - {
3.218 - Ipv4InterfaceAddress ifAddr = ip->GetAddress (i, 0);
3.219 - Ipv4Address addr = ifAddr.GetLocal ();
3.220 - Ipv4Mask mask = ifAddr.GetMask ();
3.221 - uint16_t mtu = ip->GetMtu (i);
3.222 -
3.223 - std::ostringstream addrOss, maskOss;
3.224 -
3.225 - addr.Print(addrOss);
3.226 - mask.Print(maskOss);
3.227 -
3.228 - NS_LOG_LOGIC ("if_attach " << addrOss.str().c_str() << " " << maskOss.str().c_str() << " " << mtu);
3.229 -
3.230 - std::string addrStr = addrOss.str();
3.231 - std::string maskStr = maskOss.str();
3.232 - const char* addrCStr = addrStr.c_str();
3.233 - const char* maskCStr = maskStr.c_str();
3.234 - m_nscStack->if_attach(addrCStr, maskCStr, mtu);
3.235 -
3.236 - if (i == 1)
3.237 - {
3.238 - // We need to come up with a default gateway here. Can't guarantee this to be
3.239 - // correct really...
3.240 -
3.241 - uint8_t addrBytes[4];
3.242 - addr.Serialize(addrBytes);
3.243 -
3.244 - // XXX: this is all a bit of a horrible hack
3.245 - //
3.246 - // Just increment the last octet, this gives a decent chance of this being
3.247 - // 'enough'.
3.248 - //
3.249 - // All we need is another address on the same network as the interface. This
3.250 - // will force the stack to output the packet out of the network interface.
3.251 - addrBytes[3]++;
3.252 - addr.Deserialize(addrBytes);
3.253 - addrOss.str("");
3.254 - addr.Print(addrOss);
3.255 - m_nscStack->add_default_gateway(addrOss.str().c_str());
3.256 - }
3.257 - }
3.258 +Ipv4L4Protocol::RxStatus
3.259 +NscTcpL4Protocol::Receive (Ptr<Packet> p,
3.260 + Ipv4Address const &source,
3.261 + Ipv4Address const &destination,
3.262 + Ptr<Ipv4Interface> incomingInterface)
3.263 +{ // STUB, RX happens in node/node.cc if NSC is in use.
3.264 + return Ipv4L4Protocol::RX_OK;
3.265 }
3.266
3.267 }; // namespace ns3
4.1 --- a/src/internet-stack/nsc-tcp-l4-protocol.h Wed Jul 15 14:59:44 2009 +0200
4.2 +++ b/src/internet-stack/nsc-tcp-l4-protocol.h Wed Jul 15 18:46:14 2009 +0200
4.3 @@ -29,10 +29,8 @@
4.4
4.5 #include "tcp-header.h"
4.6
4.7 -#include "ns3/timer.h"
4.8 +#include "nsc-tcp-socket-impl.h"
4.9 #include "sim_interface.h"
4.10 -#include "nsc-tcp-socket-impl.h"
4.11 -
4.12 namespace ns3 {
4.13
4.14 class Node;
4.15 @@ -40,10 +38,10 @@
4.16 class TcpHeader;
4.17 /**
4.18 * \ingroup nsctcp
4.19 - *
4.20 + *
4.21 * \brief Nsc wrapper glue, to interface with the Ipv4 protocol underneath.
4.22 */
4.23 -class NscTcpL4Protocol : public Ipv4L4Protocol, ISendCallback, IInterruptCallback {
4.24 +class NscTcpL4Protocol : public Ipv4L4Protocol {
4.25 public:
4.26 static const uint8_t PROT_NUMBER;
4.27 static TypeId GetTypeId (void);
4.28 @@ -51,11 +49,13 @@
4.29 * \brief Constructor
4.30 */
4.31 NscTcpL4Protocol ();
4.32 - virtual ~NscTcpL4Protocol ();
4.33
4.34 void SetNode (Ptr<Node> node);
4.35 +
4.36 + // legacy, moved to node/node.cc
4.37 void SetNscLibrary (const std::string &lib);
4.38 std::string GetNscLibrary (void) const;
4.39 +
4.40 virtual int GetProtocolNumber (void) const;
4.41 virtual int GetVersion (void) const;
4.42
4.43 @@ -81,27 +81,12 @@
4.44 * \param destination The destinations Ipv4Address
4.45 * \param incomingInterface The Ipv4Interface it was received on
4.46 */
4.47 +
4.48 + // Stub function, not used in nsc
4.49 virtual Ipv4L4Protocol::RxStatus Receive (Ptr<Packet> p,
4.50 - Ipv4Address const &source,
4.51 - Ipv4Address const &destination,
4.52 - Ptr<Ipv4Interface> incomingInterface);
4.53 -
4.54 - // NSC callbacks.
4.55 - // NSC invokes these hooks to interact with the simulator.
4.56 - // In any case, these methods are only to be called by NSC.
4.57 - //
4.58 - // send_callback is invoked by NSCs 'ethernet driver' to re-inject
4.59 - // a packet (i.e. an octet soup consisting of an IP Header, TCP Header
4.60 - // and user payload, if any), into ns-3.
4.61 - virtual void send_callback(const void *data, int datalen);
4.62 - // This is called by the NSC stack whenever something of interest
4.63 - // has happened, e.g. when data arrives on a socket, a listen socket
4.64 - // has a new connection pending, etc.
4.65 - virtual void wakeup();
4.66 - // This is called by the Linux stack RNG initialization.
4.67 - // Its also used by the cradle code to add a timestamp to
4.68 - // printk/printf/debug output.
4.69 - virtual void gettime(unsigned int *, unsigned int *);
4.70 + Ipv4Address const &source,
4.71 + Ipv4Address const &destination,
4.72 + Ptr<Ipv4Interface> incomingInterface);
4.73
4.74 protected:
4.75 virtual void DoDispose (void);
4.76 @@ -111,14 +96,11 @@
4.77 Ipv4EndPointDemux *m_endPoints;
4.78 ObjectFactory m_rttFactory;
4.79 private:
4.80 - void AddInterface (void);
4.81 - void SoftInterrupt (void);
4.82 static ObjectFactory GetDefaultRttEstimatorFactory (void);
4.83 friend class NscTcpSocketImpl;
4.84 INetStack* m_nscStack;
4.85 - void *m_dlopenHandle;
4.86 + void Wakeup (void);
4.87 std::string m_nscLibrary;
4.88 - Timer m_softTimer;
4.89 std::vector<Ptr<NscTcpSocketImpl> > m_sockets;
4.90 };
4.91
5.1 --- a/src/internet-stack/nsc-tcp-socket-impl.cc Wed Jul 15 14:59:44 2009 +0200
5.2 +++ b/src/internet-stack/nsc-tcp-socket-impl.cc Wed Jul 15 18:46:14 2009 +0200
5.3 @@ -162,10 +162,10 @@
5.4 void
5.5 NscTcpSocketImpl::SetTcp (Ptr<NscTcpL4Protocol> tcp)
5.6 {
5.7 - m_nscTcpSocket = tcp->m_nscStack->new_tcp_socket();
5.8 m_tcp = tcp;
5.9 + m_nscTcpSocket = m_node->GetNscInetStack()->new_tcp_socket();
5.10 }
5.11 -void
5.12 +void
5.13 NscTcpSocketImpl::SetRtt (Ptr<RttEstimator> rtt)
5.14 {
5.15 m_rtt = rtt;
6.1 --- a/src/internet-stack/nsc-tcp-socket-impl.h Wed Jul 15 14:59:44 2009 +0200
6.2 +++ b/src/internet-stack/nsc-tcp-socket-impl.h Wed Jul 15 18:46:14 2009 +0200
6.3 @@ -32,6 +32,7 @@
6.4 #include "sequence-number.h"
6.5 #include "rtt-estimator.h"
6.6
6.7 +class INetStreamSocket;
6.8 namespace ns3 {
6.9
6.10 class Ipv4EndPoint;
7.1 --- a/src/internet-stack/sim_interface.h Wed Jul 15 14:59:44 2009 +0200
7.2 +++ b/src/internet-stack/sim_interface.h Wed Jul 15 18:46:14 2009 +0200
7.3 @@ -28,9 +28,19 @@
7.4
7.5 virtual void init(int hz) = 0;
7.6
7.7 - virtual void if_receive_packet(int if_id, const void *data, int datalen) = 0;
7.8 -
7.9 - virtual void if_send_packet(const void *data, int datalen) = 0;
7.10 + virtual void if_receive_packet(int if_id, const void *data, unsigned int datalen) = 0;
7.11 +
7.12 + /*
7.13 + * called by NSCs network driver. It invokes ISendCallback->send_callback() to pass
7.14 + * the packet to the simulator.
7.15 + */
7.16 + virtual void if_send_packet(const void *data, unsigned int datalen) = 0;
7.17 + //virtual void if_send_packet(int if_id, const void *data, unsigned int datalen) = 0;
7.18 +
7.19 + /*
7.20 + * called by network simulator after packet tx was sucessful.
7.21 + * on Linux, this wakes up the netdev xmit queue.
7.22 + */
7.23 virtual void if_send_finish(int if_id) = 0;
7.24
7.25 virtual void if_attach(const char *addr, const char *mask, int mtu) = 0;
7.26 @@ -179,7 +189,8 @@
7.27 {
7.28 virtual ~ISendCallback() {}
7.29
7.30 - virtual void send_callback(const void *data, int datalen) = 0;
7.31 +// virtual void send_callback(int id, const void *data, unsigned int datalen) = 0;
7.32 + virtual void send_callback(const void *data, unsigned int datalen) = 0;
7.33 };
7.34
7.35 struct IInterruptCallback
8.1 --- a/src/internet-stack/wscript Wed Jul 15 14:59:44 2009 +0200
8.2 +++ b/src/internet-stack/wscript Wed Jul 15 18:46:14 2009 +0200
8.3 @@ -68,7 +68,6 @@
8.4 os.path.abspath(os.path.join(conf.env['WITH_NSC'], nsc_module)))
8.5
8.6
8.7 -
8.8 def build(bld):
8.9 obj = bld.create_ns3_module('internet-stack', ['node'])
8.10 obj.source = [
8.11 @@ -108,11 +107,12 @@
8.12 'tcp-header.h',
8.13 'sequence-number.h',
8.14 'icmpv4.h',
8.15 + 'ipv4-interface.h',
8.16 + 'ipv4-l3-protocol.h',
8.17 ]
8.18
8.19 if bld.env['NSC_ENABLED']:
8.20 obj.source.append ('nsc-tcp-socket-impl.cc')
8.21 obj.source.append ('nsc-tcp-l4-protocol.cc')
8.22 obj.source.append ('nsc-tcp-socket-factory-impl.cc')
8.23 - obj.source.append ('nsc-sysctl.cc')
8.24 obj.uselib = 'DL'
9.1 --- a/src/node/node.cc Wed Jul 15 14:59:44 2009 +0200
9.2 +++ b/src/node/node.cc Wed Jul 15 18:46:14 2009 +0200
9.3 @@ -31,6 +31,8 @@
9.4 #include "ns3/global-value.h"
9.5 #include "ns3/boolean.h"
9.6
9.7 +#include "nsc-glue.h"
9.8 +
9.9 NS_LOG_COMPONENT_DEFINE ("Node");
9.10
9.11 namespace ns3{
9.12 @@ -67,7 +69,8 @@
9.13
9.14 Node::Node()
9.15 : m_id(0),
9.16 - m_sid(0)
9.17 + m_sid(0),
9.18 + m_useNsc(false)
9.19 {
9.20 Construct ();
9.21 }
9.22 @@ -251,6 +254,11 @@
9.23 << ") Packet UID " << packet->GetUid ());
9.24 bool found = false;
9.25
9.26 + if (m_useNsc && m_nscGlue->IsNscProtocol (protocol)) {
9.27 + m_nscGlue->PassPacketToNsc (packet, 0); // 0: NSC interface ID. XXX: Map &device <-> nscindex
9.28 + return true;
9.29 + }
9.30 +
9.31 for (ProtocolHandlerList::iterator i = m_handlers.begin ();
9.32 i != m_handlers.end (); i++)
9.33 {
9.34 @@ -271,4 +279,36 @@
9.35 return found;
9.36 }
9.37
9.38 +#ifdef NETWORK_SIMULATION_CRADLE
9.39 +void
9.40 +Node::SetNscLibrary(const std::string &soname)
9.41 +{
9.42 + m_nscGlue = CreateObject <NscGlue> ();
9.43 + m_nscGlue->SetNode (this);
9.44 + m_nscGlue->SetNscLibrary (soname);
9.45 +
9.46 + m_useNsc = true;
9.47 +}
9.48 +
9.49 +std::string
9.50 +Node::GetNscLibrary(void) const
9.51 +{
9.52 + return m_nscGlue->GetNscLibrary ();
9.53 +}
9.54 +
9.55 +
9.56 +
9.57 +INetStack *
9.58 +Node::GetNscInetStack(void)
9.59 +{
9.60 + NS_ASSERT_MSG(m_useNsc, "GetNscInetStack called, but nsc disabled on this node");
9.61 + return m_nscGlue->m_nscStack;
9.62 +}
9.63 +
9.64 +void Node::RegisterNscWakeupCallback(Callback<void> cb)
9.65 +{
9.66 + NS_ASSERT (m_nscGlue);
9.67 + m_nscGlue->RegisterWakeupCallback (cb);
9.68 +}
9.69 +#endif
9.70 }//namespace ns3
10.1 --- a/src/node/node.h Wed Jul 15 14:59:44 2009 +0200
10.2 +++ b/src/node/node.h Wed Jul 15 18:46:14 2009 +0200
10.3 @@ -28,12 +28,14 @@
10.4 #include "ns3/ptr.h"
10.5 #include "ns3/net-device.h"
10.6
10.7 +struct INetStack;
10.8 +
10.9 namespace ns3 {
10.10
10.11 class Application;
10.12 class Packet;
10.13 class Address;
10.14 -
10.15 +class NscGlue;
10.16
10.17 /**
10.18 * \ingroup node
10.19 @@ -172,13 +174,16 @@
10.20 */
10.21 void UnregisterProtocolHandler (ProtocolHandler handler);
10.22
10.23 + void SetNscLibrary (const std::string &soname);
10.24 + std::string GetNscLibrary (void) const;
10.25 + INetStack* GetNscInetStack(void);
10.26 + void RegisterNscWakeupCallback (Callback<void>);
10.27
10.28 /**
10.29 * \returns true if checksums are enabled, false otherwise.
10.30 */
10.31 static bool ChecksumEnabled (void);
10.32
10.33 -
10.34 protected:
10.35 /**
10.36 * The dispose method. Subclasses must override this method
10.37 @@ -216,6 +221,8 @@
10.38 std::vector<Ptr<Application> > m_applications;
10.39 ProtocolHandlerList m_handlers;
10.40
10.41 + Ptr <NscGlue> m_nscGlue;
10.42 + bool m_useNsc;
10.43 };
10.44
10.45 } //namespace ns3
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
11.2 +++ b/src/node/nsc-glue.cc Wed Jul 15 18:46:14 2009 +0200
11.3 @@ -0,0 +1,236 @@
11.4 +#include <dlfcn.h>
11.5 +
11.6 +#include "ns3/boolean.h"
11.7 +#include "ns3/log.h"
11.8 +#include "ns3/ipv4-l3-protocol.h"
11.9 +
11.10 +#include "ns3/ipv4-interface.h"
11.11 +#include "ns3/object.h"
11.12 +#include "ns3/packet.h"
11.13 +#include "ns3/ptr.h"
11.14 +#include "ns3/nstime.h"
11.15 +
11.16 +#include "nsc-glue.h"
11.17 +#include "node.h"
11.18 +
11.19 +#include <netinet/ip.h>
11.20 +#include <arpa/inet.h>
11.21 +
11.22 +namespace ns3 {
11.23 +
11.24 +NS_OBJECT_ENSURE_REGISTERED (NscGlue);
11.25 +
11.26 +TypeId
11.27 +NscGlue::GetTypeId (void)
11.28 +{
11.29 + static TypeId tid = TypeId ("ns3::NscGlue")
11.30 + .SetParent <Object> ()
11.31 + ;
11.32 + return tid;
11.33 +}
11.34 +
11.35 +NscGlue::NscGlue(void)
11.36 + : m_wakeupCallbacks(0),
11.37 + m_dlopenHandle(0)
11.38 +{
11.39 +}
11.40 +
11.41 +void
11.42 +NscGlue::SetNode(Ptr<Node> n)
11.43 +{
11.44 + m_node = n;
11.45 +}
11.46 +
11.47 +void
11.48 +NscGlue::PassPacketToNsc (Ptr<const Packet> packet, int idx)
11.49 +{
11.50 + uint32_t packetSize = packet->GetSize();
11.51 + const uint8_t *data = const_cast<uint8_t *>(packet->PeekData());
11.52 +
11.53 + // deliver complete packet to the NSC network stack
11.54 + m_nscStack->if_receive_packet(idx, data, packetSize);
11.55 + wakeup ();
11.56 +}
11.57 +
11.58 +bool
11.59 +NscGlue::IsNscProtocol (uint16_t proto)
11.60 +{
11.61 + return proto == 0x0800; // NSC can only handle ipv4 at the moment.
11.62 +}
11.63 +
11.64 +static int external_rand(void)
11.65 +{
11.66 + return 1; // XXX: check which NSC stacks actually use this
11.67 +}
11.68 +
11.69 +void
11.70 +NscGlue::SetNscLibrary(const std::string &soname)
11.71 +{
11.72 + NS_ASSERT(!m_dlopenHandle);
11.73 + m_dlopenHandle = dlopen(soname.c_str (), RTLD_NOW);
11.74 + if (m_dlopenHandle == NULL)
11.75 + NS_FATAL_ERROR (dlerror());
11.76 +
11.77 + FCreateStack create = (FCreateStack)dlsym(m_dlopenHandle, "nsc_create_stack");
11.78 +
11.79 + m_nscStack = create(this, this, external_rand);
11.80 + int hzval = m_nscStack->get_hz();
11.81 +
11.82 + NS_ASSERT(hzval > 0);
11.83 +
11.84 + m_softTimer.SetFunction (&NscGlue::SoftRtcInterrupt, this);
11.85 + m_softTimer.SetDelay (MilliSeconds (1000/hzval));
11.86 + // This enables stack and NSC debug messages
11.87 + m_nscStack->set_diagnostic(10);
11.88 + m_nscStack->init(hzval);
11.89 +
11.90 + Ptr<Ns3NscStack> nscStack = Create<Ns3NscStack> ();
11.91 + nscStack->SetStack (m_nscStack);
11.92 + m_node->AggregateObject (nscStack);
11.93 +
11.94 + m_softTimer.Schedule ();
11.95 + // its likely no ns-3 interface exits at this point, so
11.96 + // we delay adding the nsc interface until the start of the simulation.
11.97 + Simulator::ScheduleNow(&NscGlue::AddIface, this);
11.98 +
11.99 + m_nscLibrary = soname;
11.100 +}
11.101 +
11.102 +std::string
11.103 +NscGlue::GetNscLibrary () const
11.104 +{
11.105 + return m_nscLibrary;
11.106 +}
11.107 +
11.108 +
11.109 +void NscGlue::wakeup()
11.110 +{
11.111 + // TODO
11.112 + // this should schedule a timer to read from all tcp sockets now... this is
11.113 + // an indication that data might be waiting on the socket
11.114 + for (std::list<Callback<void> >::iterator i = m_wakeupCallbacks.begin ();
11.115 + i != m_wakeupCallbacks.end (); i++)
11.116 + {
11.117 + Callback<void> cb = *i;
11.118 + cb ();
11.119 + }
11.120 +}
11.121 +
11.122 +void NscGlue::SoftRtcInterrupt (void)
11.123 +{
11.124 + m_nscStack->timer_interrupt ();
11.125 + m_nscStack->increment_ticks ();
11.126 + m_softTimer.Schedule ();
11.127 +}
11.128 +
11.129 +void NscGlue::gettime(unsigned int* sec, unsigned int* usec)
11.130 +{
11.131 + // Only used by the Linux network stack, e.g. during ISN generation
11.132 + // and in the kernel rng initialization routine. Also used in Linux
11.133 + // printk output.
11.134 + Time t = Simulator::Now ();
11.135 + int64_t us = t.GetMicroSeconds ();
11.136 + *sec = us / (1000*1000);
11.137 + *usec = us - *sec * (1000*1000);
11.138 +}
11.139 +
11.140 +#ifdef NSC_NEXT
11.141 +void NscGlue::send_callback(int idx, const void* data, unsigned int datalen)
11.142 +#else
11.143 +void NscGlue::send_callback(/* int idx,*/ const void* data, unsigned int datalen)
11.144 +#endif
11.145 +{
11.146 +#ifndef NSC_NEXT
11.147 + int idx = 0;
11.148 +#endif
11.149 + Ptr<Packet> p;
11.150 + uint32_t ipv4Daddr;
11.151 +
11.152 + NS_ASSERT(datalen > 20);
11.153 +
11.154 + // FIXME: XXX: This won't really work when NSC is able to use
11.155 + // L3 protocols other than AF_INET. We really really really
11.156 + // should be able to do all routing decisions inside nsc and just
11.157 + // pass packets to whatever network interface without looking at its contents.
11.158 + const uint8_t *rawdata = reinterpret_cast<const uint8_t *>(data);
11.159 +
11.160 + p = Create<Packet> (rawdata, datalen);
11.161 +
11.162 + // we need the destination ipv4 address for Send ().
11.163 + const uint32_t *ipheader = reinterpret_cast<const uint32_t *>(data);
11.164 +
11.165 + ipv4Daddr = *(ipheader+4);
11.166 +
11.167 + Ipv4Address daddr(ntohl(ipv4Daddr));
11.168 +
11.169 + Ptr<Ipv4L3Protocol> ipv4 = m_node->GetObject<Ipv4L3Protocol> ();
11.170 + NS_ASSERT_MSG (ipv4, "nsc callback invoked, but node has no ipv4 object");
11.171 + // FIXME: do _all_ routing via NSC and provide a ns3-nsc mapping that
11.172 + // tells us which ns-3 interface the nsc interface "idx" is corresponding to.
11.173 +//NS_LOG_LOGIC ("ns3: xmit via device number " << idx);
11.174 + Ptr<Ipv4Interface> outInterface = ipv4->GetInterface ( idx + 1);
11.175 +
11.176 + NS_ASSERT (outInterface);
11.177 + outInterface->Send (p, daddr);
11.178 + m_nscStack->if_send_finish(0);
11.179 +}
11.180 +
11.181 +
11.182 +void NscGlue::RegisterWakeupCallback(Callback<void> cb)
11.183 +{
11.184 + m_wakeupCallbacks.push_back (cb);
11.185 +}
11.186 +
11.187 +void NscGlue::AddIface(void)
11.188 +{
11.189 + Ptr<Ipv4> ip = m_node->GetObject<Ipv4> ();
11.190 +
11.191 + const uint32_t nInterfaces = ip->GetNInterfaces ();
11.192 + // start from 1, ignore the loopback interface (HACK)
11.193 +
11.194 + for (uint32_t i = 1; i < nInterfaces; i++)
11.195 + {
11.196 + Ipv4InterfaceAddress ifAddr = ip->GetAddress (i, 0);
11.197 + Ipv4Address addr = ifAddr.GetLocal ();
11.198 + Ipv4Mask mask = ifAddr.GetMask ();
11.199 +
11.200 + uint16_t mtu = ip->GetMtu (i);
11.201 +
11.202 + std::ostringstream addrOss, maskOss;
11.203 +
11.204 + addr.Print(addrOss);
11.205 + mask.Print(maskOss);
11.206 +
11.207 +// NS_LOG_LOGIC ("if_attach " << addrOss.str().c_str() << " " << maskOss.str().c_str() << " " << mtu);
11.208 +
11.209 + std::string addrStr = addrOss.str();
11.210 + std::string maskStr = maskOss.str();
11.211 + const char* addrCStr = addrStr.c_str();
11.212 + const char* maskCStr = maskStr.c_str();
11.213 + NS_ASSERT_MSG (m_nscStack, "m_nscStackError");
11.214 + m_nscStack->if_attach(addrCStr, maskCStr, mtu);
11.215 +
11.216 + if (i == 1)
11.217 + {
11.218 + // We need to come up with a default gateway here. Can't guarantee this to be
11.219 + // correct really...
11.220 +
11.221 + uint8_t addrBytes[4];
11.222 + addr.Serialize(addrBytes);
11.223 +
11.224 + // XXX: this is all a bit of a horrible hack
11.225 + //
11.226 + // Just increment the last octet, this gives a decent chance of this being
11.227 + // 'enough'.
11.228 + //
11.229 + // All we need is another address on the same network as the interface. This
11.230 + // will force the stack to output the packet out of the network interface.
11.231 + addrBytes[3]++;
11.232 + addr.Deserialize(addrBytes);
11.233 + addrOss.str("");
11.234 + addr.Print(addrOss);
11.235 + m_nscStack->add_default_gateway(addrOss.str().c_str());
11.236 + }
11.237 + }
11.238 +}
11.239 +} // namespace ns3
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
12.2 +++ b/src/node/nsc-glue.h Wed Jul 15 18:46:14 2009 +0200
12.3 @@ -0,0 +1,116 @@
12.4 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
12.5 +/*
12.6 + * Copyright (c) 2008 Florian Westphal
12.7 + *
12.8 + * This program is free software; you can redistribute it and/or modify
12.9 + * it under the terms of the GNU General Public License version 2 as
12.10 + * published by the Free Software Foundation;
12.11 + *
12.12 + * This program is distributed in the hope that it will be useful,
12.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
12.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12.15 + * GNU General Public License for more details.
12.16 + *
12.17 + * You should have received a copy of the GNU General Public License
12.18 + * along with this program; if not, write to the Free Software
12.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
12.20 + *
12.21 + * Author: Florian Westphal <fw@strlen.de>
12.22 + */
12.23 +#ifndef NODE_NSC_H
12.24 +#define NODE_NSC_H
12.25 +
12.26 +#include <string>
12.27 +#include <list>
12.28 +
12.29 +#include "ns3/callback.h"
12.30 +#include "ns3/ptr.h"
12.31 +#include "ns3/object.h"
12.32 +#include "ns3/net-device.h"
12.33 +#include "ns3/timer.h"
12.34 +
12.35 +#include "nsc-sysctl.h"
12.36 +
12.37 +#include "sim_interface.h"
12.38 +
12.39 +/*
12.40 + * silly hack to switch betwwen NSC API revisions faster during development.
12.41 + * should be removed before erging with upstream ns3-dev.
12.42 + */
12.43 +#if NSC_VERSION == 0x00500
12.44 +#undef NSC_NEXT
12.45 +#else
12.46 +#define NSC_NEXT 1
12.47 +#endif
12.48 +
12.49 +
12.50 +namespace ns3 {
12.51 +
12.52 +// IInterruptCallback and ISendCallback are NSC interfaces.
12.53 +class NscGlue : public Object, IInterruptCallback, ISendCallback
12.54 +{
12.55 +public:
12.56 + static TypeId GetTypeId (void);
12.57 +
12.58 + NscGlue (void);
12.59 +
12.60 + void SetNode(Ptr<Node> n);
12.61 + void SetNscLibrary(const std::string &soname);
12.62 + std::string GetNscLibrary () const;
12.63 +
12.64 + // returns true if l3 protocol number can be handled by NSC.
12.65 + // currently only returns true for IPv4.
12.66 + bool IsNscProtocol (uint16_t proto);
12.67 +
12.68 + // passes packet on to NSC. NSC will see the packet arriving on
12.69 + // interface ifindex.
12.70 + void PassPacketToNsc (Ptr<const Packet> packet, int ifindex);
12.71 +
12.72 + // used to register the L4 wakeup call:
12.73 + // maybe it should directly be used to register individual
12.74 + // sockets?
12.75 + void RegisterWakeupCallback (Callback<void> cb);
12.76 +
12.77 + // HACK, make this private.
12.78 + // Socket implementations should not use m_nscStack-> methods
12.79 + // directly.
12.80 + INetStack* m_nscStack;
12.81 +private:
12.82 + // IInterruptCallback methods: wakeup and gettime.
12.83 + // wakeup is called by the NSC stack whenever something of interest
12.84 + // has happened, e.g. when data arrives on a socket, a listen socket
12.85 + // has a new connection pending, etc.
12.86 + virtual void wakeup();
12.87 +
12.88 + // This is called by the Linux stack RNG initialization.
12.89 + // Its also used by the cradle code to add a timestamp to
12.90 + // printk/printf/debug output.
12.91 + virtual void gettime(unsigned int *, unsigned int *);
12.92 +
12.93 + // send_callback is invoked by NSCs 'ethernet driver' to re-inject
12.94 + // a packet (i.e. an octet soup consisting of an IP Header, TCP Header
12.95 + // and user payload, if any), into ns-3.
12.96 +#ifdef NSC_NEXT
12.97 + void send_callback(int idx, const void* data, unsigned int datalen);
12.98 +#else
12.99 + void send_callback(const void* data, unsigned int datalen);
12.100 +#endif
12.101 + // internal helper. adds ipv4 addresses.
12.102 + // XXX: rethink. This really doesn't belong here.
12.103 + // NSC should also split up interface creation and address assignment.
12.104 + void AddIface(void);
12.105 +
12.106 + std::list<Callback<void> > m_wakeupCallbacks;
12.107 +
12.108 + void *m_dlopenHandle;
12.109 + Timer m_softTimer;
12.110 + // called by m_softTimer
12.111 + void SoftRtcInterrupt (void);
12.112 +
12.113 + std::string m_nscLibrary;
12.114 + Ptr<Node> m_node; // sigh...
12.115 +};
12.116 +
12.117 +} //namespace ns3
12.118 +
12.119 +#endif /* NODE_NSC_H */
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
13.2 +++ b/src/node/nsc-sysctl.cc Wed Jul 15 18:46:14 2009 +0200
13.3 @@ -0,0 +1,154 @@
13.4 +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
13.5 +/*
13.6 + * This program is free software; you can redistribute it and/or modify
13.7 + * it under the terms of the GNU General Public License version 2 as
13.8 + * published by the Free Software Foundation;
13.9 + *
13.10 + * This program is distributed in the hope that it will be useful,
13.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
13.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13.13 + * GNU General Public License for more details.
13.14 + *
13.15 + * You should have received a copy of the GNU General Public License
13.16 + * along with this program; if not, write to the Free Software
13.17 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
13.18 + *
13.19 + * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
13.20 + */
13.21 +
13.22 +#include "ns3/string.h"
13.23 +#include "nsc-sysctl.h"
13.24 +
13.25 +#include "sim_interface.h"
13.26 +
13.27 +namespace ns3 {
13.28 +
13.29 +class NscStackStringAccessor : public AttributeAccessor
13.30 +{
13.31 + public:
13.32 + NscStackStringAccessor (std::string name) : m_name (name) {}
13.33 +
13.34 + virtual bool Set (ObjectBase * object, const AttributeValue &val) const;
13.35 + virtual bool Get (const ObjectBase * object, AttributeValue &val) const;
13.36 + virtual bool HasGetter (void) const;
13.37 + virtual bool HasSetter (void) const;
13.38 + private:
13.39 + std::string m_name;
13.40 +};
13.41 +
13.42 +bool NscStackStringAccessor::HasGetter(void) const
13.43 +{
13.44 + return true;
13.45 +}
13.46 +
13.47 +bool NscStackStringAccessor::HasSetter(void) const
13.48 +{
13.49 + return true;
13.50 +}
13.51 +
13.52 +
13.53 +bool NscStackStringAccessor::Set (ObjectBase * object, const AttributeValue & val) const
13.54 +{
13.55 + const StringValue *value = dynamic_cast<const StringValue *> (&val);
13.56 + if (value == 0)
13.57 + {
13.58 + return false;
13.59 + }
13.60 + Ns3NscStack *obj = dynamic_cast<Ns3NscStack *> (object);
13.61 + if (obj == 0)
13.62 + {
13.63 + return false;
13.64 + }
13.65 + obj->Set (m_name, value->Get ());
13.66 + return true;
13.67 +}
13.68 +
13.69 +bool NscStackStringAccessor::Get (const ObjectBase * object, AttributeValue &val) const
13.70 +{
13.71 + StringValue *value = dynamic_cast<StringValue *> (&val);
13.72 + if (value == 0)
13.73 + {
13.74 + return false;
13.75 + }
13.76 + const Ns3NscStack *obj = dynamic_cast<const Ns3NscStack *> (object);
13.77 + if (obj == 0)
13.78 + {
13.79 + return false;
13.80 + }
13.81 + value->Set (obj->Get (m_name));
13.82 + return true;
13.83 +}
13.84 +
13.85 +
13.86 +TypeId
13.87 +Ns3NscStack::GetInstanceTypeId (void) const
13.88 +{
13.89 + if (m_stack == 0)
13.90 + {
13.91 + // if we have no stack, we are a normal NscStack without any attributes.
13.92 + return GetTypeId ();
13.93 + }
13.94 + std::string name = "ns3::Ns3NscStack<";
13.95 + name += m_stack->get_name ();
13.96 + name += ">";
13.97 + TypeId tid;
13.98 + if (TypeId::LookupByNameFailSafe (name, &tid))
13.99 + {
13.100 + // if the relevant TypeId has already been registered, no need to do it again.
13.101 + return tid;
13.102 + }
13.103 + else
13.104 + {
13.105 + // Now, we register a new TypeId for this stack which will look
13.106 + // like a subclass of the Ns3NscStack. The class Ns3NscStack is effectively
13.107 + // mutating into a subclass of itself from the point of view of the TypeId
13.108 + // system _here_
13.109 + tid = TypeId (name.c_str ());
13.110 + tid.SetParent<Ns3NscStack> ();
13.111 + char buf[256];
13.112 + for (int i=0; m_stack->sysctl_getnum(i, buf, sizeof(buf)) > 0 ;i++)
13.113 + {
13.114 + char value[256];
13.115 + if (m_stack->sysctl_get (buf, value, sizeof(value)) > 0)
13.116 + {
13.117 + tid.AddAttribute (buf, "Help text",
13.118 + StringValue (value),
13.119 + Create<NscStackStringAccessor> (buf),
13.120 + MakeStringChecker ());
13.121 + }
13.122 + }
13.123 + return tid;
13.124 + }
13.125 +}
13.126 +
13.127 +std::string
13.128 +Ns3NscStack::Get (std::string name) const
13.129 +{
13.130 + char buf[512];
13.131 + if (m_stack->sysctl_get (name.c_str (), buf, sizeof(buf)) <= 0)
13.132 + { // name.c_str () is not a valid sysctl name, or internal NSC error (eg. error converting value)
13.133 + return NULL;
13.134 + }
13.135 + return std::string(buf);
13.136 +}
13.137 +
13.138 +void
13.139 +Ns3NscStack::Set (std::string name, std::string value)
13.140 +{
13.141 + int ret = m_stack->sysctl_set (name.c_str (), value.c_str ());
13.142 + if (ret < 0)
13.143 + {
13.144 + NS_FATAL_ERROR ("setting " << name << " to " << value << "failed (retval " << ret << ")");
13.145 + }
13.146 +}
13.147 +
13.148 +TypeId
13.149 +Ns3NscStack::Ns3NscStack::GetTypeId (void)
13.150 +{
13.151 + static TypeId tid = TypeId ("ns3::Ns3NscStack")
13.152 + .SetParent<Object> ()
13.153 + ;
13.154 + return tid;
13.155 +}
13.156 +
13.157 +} // namespace ns3
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
14.2 +++ b/src/node/nsc-sysctl.h Wed Jul 15 18:46:14 2009 +0200
14.3 @@ -0,0 +1,44 @@
14.4 +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
14.5 +/*
14.6 + * This program is free software; you can redistribute it and/or modify
14.7 + * it under the terms of the GNU General Public License version 2 as
14.8 + * published by the Free Software Foundation;
14.9 + *
14.10 + * This program is distributed in the hope that it will be useful,
14.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
14.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14.13 + * GNU General Public License for more details.
14.14 + *
14.15 + * You should have received a copy of the GNU General Public License
14.16 + * along with this program; if not, write to the Free Software
14.17 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
14.18 + *
14.19 + * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
14.20 + */
14.21 +
14.22 +#include <string>
14.23 +
14.24 +#include "ns3/attribute.h"
14.25 +#include "ns3/object.h"
14.26 +
14.27 +struct INetStack;
14.28 +
14.29 +namespace ns3 {
14.30 +
14.31 +// This object represents the underlying nsc stack,
14.32 +// which is aggregated to a Node object, and which provides access to the
14.33 +// sysctls of the nsc stack through attributes.
14.34 +class Ns3NscStack : public Object
14.35 +{
14.36 +public:
14.37 + static TypeId GetTypeId (void);
14.38 + virtual TypeId GetInstanceTypeId (void) const;
14.39 + void SetStack (INetStack *stack) {m_stack = stack;}
14.40 +
14.41 +private:
14.42 + friend class NscStackStringAccessor;
14.43 + void Set (std::string name, std::string value);
14.44 + std::string Get (std::string name) const;
14.45 + INetStack *m_stack;
14.46 +};
14.47 +} // namespace ns3
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
15.2 +++ b/src/node/sim_interface.h Wed Jul 15 18:46:14 2009 +0200
15.3 @@ -0,0 +1,211 @@
15.4 +#ifndef __SIM_INTERFACE_H__
15.5 +#define __SIM_INTERFACE_H__
15.6 +/*
15.7 + Network Simulation Cradle
15.8 + Copyright (C) 2003-2005 Sam Jansen
15.9 +
15.10 + This program is free software; you can redistribute it and/or modify it
15.11 + under the terms of the GNU General Public License as published by the Free
15.12 + Software Foundation; either version 2 of the License, or (at your option)
15.13 + any later version.
15.14 +
15.15 + This program is distributed in the hope that it will be useful, but WITHOUT
15.16 + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15.17 + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15.18 + more details.
15.19 +
15.20 + You should have received a copy of the GNU General Public License along
15.21 + with this program; if not, write to the Free Software Foundation, Inc., 59
15.22 + Temple Place, Suite 330, Boston, MA 02111-1307 USA
15.23 +
15.24 +*/
15.25 +
15.26 +#define NSC_VERSION 0x000500
15.27 +
15.28 +struct INetStack
15.29 +{
15.30 + virtual ~INetStack() {}
15.31 +
15.32 + virtual void init(int hz) = 0;
15.33 +
15.34 + virtual void if_receive_packet(int if_id, const void *data, unsigned int datalen) = 0;
15.35 +
15.36 + /*
15.37 + * called by NSCs network driver. It invokes ISendCallback->send_callback() to pass
15.38 + * the packet to the simulator.
15.39 + */
15.40 + virtual void if_send_packet(const void *data, unsigned int datalen) = 0;
15.41 + //virtual void if_send_packet(int if_id, const void *data, unsigned int datalen) = 0;
15.42 +
15.43 + /*
15.44 + * called by network simulator after packet tx was sucessful.
15.45 + * on Linux, this wakes up the netdev xmit queue.
15.46 + */
15.47 + virtual void if_send_finish(int if_id) = 0;
15.48 +
15.49 + virtual void if_attach(const char *addr, const char *mask, int mtu) = 0;
15.50 + virtual void add_default_gateway(const char *addr) = 0;
15.51 +
15.52 + /** Purely for debugging/diagnostic purposes. This returns the internal id
15.53 + * of the stack instance.
15.54 + */
15.55 + virtual int get_id() = 0;
15.56 +
15.57 + /** Should return a short one-word name of the stack. Eg. Linux 2.4.x ->
15.58 + * linux24, FreeBSD 5.x -> freebsd5. This can be used to identify output
15.59 + * from a stack, for example a packet trace file. */
15.60 + virtual const char *get_name() = 0;
15.61 +
15.62 + /** This is used so the simulator can call the stack timer_interrupt function
15.63 + * the correct amount of times per second. For example, lwip has a hz of 10,
15.64 + * which it returns here to say that it's timer_interrupt should be called
15.65 + * 10 times a second. FreeBSD uses 100, as does Linux 2.4, while Linux 2.6
15.66 + * uses 1000. (This is often configurable in the kernel in question, also.)
15.67 + */
15.68 + virtual int get_hz() = 0;
15.69 +
15.70 + virtual void timer_interrupt() = 0;
15.71 + virtual void increment_ticks() = 0;
15.72 +
15.73 + virtual void buffer_size(int size) = 0;
15.74 +
15.75 + virtual struct INetDatagramSocket *new_udp_socket() { return NULL; }
15.76 + virtual struct INetStreamSocket *new_tcp_socket() { return NULL; }
15.77 + virtual struct INetStreamSocket *new_sctp_socket() { return NULL; }
15.78 +
15.79 + // The following I've made optional to implement for now. Eases
15.80 + // integration of new features.
15.81 + virtual int sysctl(const char *sysctl_name, void *oldval, size_t *oldlenp,
15.82 + void *newval, size_t newlen)
15.83 + {
15.84 + return -1;
15.85 + }
15.86 +
15.87 + // alternate, simpler interface. the stack cradle code is expected
15.88 + // to convert the string-value to something that the stack can handle.
15.89 + // The idea here is that this is a front-end to the sysctl(2) call,
15.90 + // much like the sysctl(8) program.
15.91 + virtual int sysctl_set(const char *name, const char *value)
15.92 + {
15.93 + return -1;
15.94 + }
15.95 +
15.96 + // same as above, cradle code is expected to convert the sysctl value
15.97 + // into a string.
15.98 + // returns length of the string in value, i.e. retval > len: 'output truncated'.
15.99 + virtual int sysctl_get(const char *name, char *value, size_t len)
15.100 + {
15.101 + return -1;
15.102 + }
15.103 +
15.104 + // this tells the cradle code to put the name of sysctl number 'idx'
15.105 + // into name[].
15.106 + // The idea is that this can be used to get a list of all available sysctls:
15.107 + // char buf[256]
15.108 + // for (i=0; sysctl_getnum(i, buf, sizeof(buf)) > 0 ;i++)
15.109 + // puts(buf);
15.110 + // returns -1 if idx is out of range and the length of the sysctl name otherwise.
15.111 + virtual int sysctl_getnum(size_t idx, char *name, size_t len)
15.112 + {
15.113 + return -1;
15.114 + }
15.115 +
15.116 + virtual void show_config()
15.117 + {
15.118 + ;
15.119 + }
15.120 +
15.121 + /* Optional functions used to get and set variables for this stack */
15.122 + virtual bool get_var(const char *var, char *result, int result_len)
15.123 + {
15.124 + return false;
15.125 + }
15.126 +
15.127 + virtual bool set_var(const char *var, const char *val)
15.128 + {
15.129 + return false;
15.130 + }
15.131 +
15.132 + /** The level of debugging or diagnostic information to print out. This
15.133 + * normally means kernel messages printed out during initialisation but
15.134 + * may also include extra debugging messages that are part of NSC. */
15.135 + virtual void set_diagnostic(int level) {}
15.136 +
15.137 + /** Simple interface to support sending any textual command to a stack
15.138 + *
15.139 + * @returns 0 on success
15.140 + */
15.141 + virtual int cmd(const char *)
15.142 + {
15.143 + return 1;
15.144 + }
15.145 +};
15.146 +
15.147 +struct INetStreamSocket
15.148 +{
15.149 + virtual ~INetStreamSocket() {}
15.150 +
15.151 + virtual void connect(const char *, int) = 0;
15.152 + virtual void disconnect() = 0;
15.153 + virtual void listen(int) = 0;
15.154 + virtual int accept(INetStreamSocket **) = 0;
15.155 + virtual int send_data(const void *data, int datalen) = 0;
15.156 + virtual int read_data(void *buf, int *buflen) = 0;
15.157 + /* We need to pass the option name in as a string here. The reason for
15.158 + * this is that different operating systems you compile on will have
15.159 + * different numbers defined for the constants SO_SNDBUF and so on. */
15.160 + virtual int setsockopt(char *optname, void *val, size_t valsize) = 0;
15.161 + virtual void print_state(FILE *) = 0;
15.162 + virtual bool is_connected() = 0;
15.163 + virtual bool is_listening() = 0;
15.164 +
15.165 + virtual int getpeername(struct sockaddr *sa, size_t *salen) {
15.166 + return -1;
15.167 + }
15.168 + virtual int getsockname(struct sockaddr *sa, size_t *salen) {
15.169 + return -1;
15.170 + }
15.171 + /* Optional functions used to get and set variables for this TCP
15.172 + * connection. */
15.173 + virtual bool get_var(const char *var, char *result, int result_len)
15.174 + {
15.175 + return false;
15.176 + }
15.177 +
15.178 + virtual bool set_var(const char *var, const char *val)
15.179 + {
15.180 + return false;
15.181 + }
15.182 +};
15.183 +
15.184 +struct INetDatagramSocket
15.185 +{
15.186 + virtual ~INetDatagramSocket() {}
15.187 +
15.188 + virtual void set_destination(const char *, int) = 0;
15.189 + virtual void send_data(const void *data, int datalen) = 0;
15.190 +};
15.191 +struct ISendCallback
15.192 +{
15.193 + virtual ~ISendCallback() {}
15.194 +
15.195 +// virtual void send_callback(int id, const void *data, unsigned int datalen) = 0;
15.196 + virtual void send_callback(const void *data, unsigned int datalen) = 0;
15.197 +};
15.198 +
15.199 +struct IInterruptCallback
15.200 +{
15.201 + virtual ~IInterruptCallback() {}
15.202 +
15.203 + virtual void wakeup() = 0;
15.204 + virtual void gettime(unsigned int *, unsigned int *) = 0;
15.205 +};
15.206 +
15.207 +typedef int (*FRandom)();
15.208 +typedef INetStack *(*FCreateStack)(ISendCallback *, IInterruptCallback *,
15.209 + FRandom);
15.210 +
15.211 +#define CREATE_STACK_FUNC(a,b,c) extern "C" INetStack *nsc_create_stack(\
15.212 + ISendCallback *a, IInterruptCallback *b, FRandom c)
15.213 +
15.214 +#endif
16.1 --- a/src/node/wscript Wed Jul 15 14:59:44 2009 +0200
16.2 +++ b/src/node/wscript Wed Jul 15 18:46:14 2009 +0200
16.3 @@ -82,3 +82,8 @@
16.4 'ipv6-header.h',
16.5 'ipv4-raw-socket-factory.h',
16.6 ]
16.7 +
16.8 + if bld.env['WITH_NSC']:
16.9 + node.source.append ('nsc-glue.cc')
16.10 + node.source.append ('nsc-sysctl.cc')
16.11 + node.uselib = 'DL'