nsc: move nsc glue code from nsc-tcp-l4-protocol to node/nsc-glue.cc. default tip
authorFlorian Westphal <fw@strlen.de>
Wed Jul 15 18:46:14 2009 +0200 (2009-07-15)
changeset 4685ae536d9e0d6d
parent 4684 44b325571ab4
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.
src/internet-stack/nsc-sysctl.cc
src/internet-stack/nsc-sysctl.h
src/internet-stack/nsc-tcp-l4-protocol.cc
src/internet-stack/nsc-tcp-l4-protocol.h
src/internet-stack/nsc-tcp-socket-impl.cc
src/internet-stack/nsc-tcp-socket-impl.h
src/internet-stack/sim_interface.h
src/internet-stack/wscript
src/node/node.cc
src/node/node.h
src/node/nsc-glue.cc
src/node/nsc-glue.h
src/node/nsc-sysctl.cc
src/node/nsc-sysctl.h
src/node/sim_interface.h
src/node/wscript
     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'