Network Simulation Cradle Integration
Network Simulation Cradle Integration
Network Simulation Crade (nsc) is a project to allow real-world network stacks to be used in simulated networks. A porting effort to bring nsc to version 3 of the network simulator was started by Tom Henderson. This Project continues this work and also will update at least the Linux network stack to current git (2.6.26).
ns3-nsc is able to run the tcp-large-transfer example that is included in ns-3
NSC provides its API in the form of a number of classes which are defined in sim/sim_interface.h in the nsc directory.
INetStack contains the 'low level' operations for the operating system network stack, e.g. in and output functions from and to the network stack (think of this as the 'network driver interface'. There are also functions to create new TCP or UDP sockets.
This is called by NSC when a packet should be sent out to the network. This simulator should use this callback to re-inject the packet into the simulator so the actual data can be delivered/routed to its destination, where it will eventually be handed into Receive() (and eventually back to the receivers NSC instance via INetStack->if_receive() ).
This is the structure defining a particular connection endpoint (file descriptor). It contains methods to operate on this endpoint, e.g. connect, disconnect, accept, listen, send_data/read_data, ...
This contains the wakeup callback, which is called by NSC whenever something of interest happens. Think of wakeup() as a replacement of the operating systems wakeup function: Whenever the operating system would wake up a process that has been waiting for an operation to complete (for example the TCP handshake during connect()), NSC invokes the wakeup() callback to allow the simulator to check for state changes in its connection endpoints.
NSC Todo and Wish list
More consistent API. Example: send_data() and read_data() return values. send_data() behaves generally like send(2) and write(2), i.e. it returns the number of bytes written or a (negative) error value. read_data(), on the other hand, returns 0 on success (storing the number of bytes read at the location specified by the int *buflen argument) and something else on error. Its important to note that the error codes returned by NSC are quite useless, because they depend on the stack that is in use -- there is no way to decide if a nonzero value is a "soft error" (like EAGAIN) or a "hard" error (like ECONNRESET). For this to be consistent _AND_ usable, nsc would have to return e.g. an "enum nsc_errno" that defines NSC_EAGAIN, NSC_ECONNRESET and so forth and takes care of the stack-errorcode <-> nsc-errorcode mapping.
Such a mapping will probably added after the sysctl wrapper is completed (see below).
Another possible area to look into is getting protocols like SCTP and DCCP to work with nsc. The sctp code in the 2.6.26-rc6 port works, but needs proper integration within ns-3-nsc.
- Integrate nsc into ns-3 without circumventing ns-3s tcp/ip infrastructure
Done as of June 1st, although there is room for improvement (e.g. removing redundant code, cleanups, etc).
- allow nsc to use layer2 code directly without having to piggyback data inside ns3-tcp
Done, with a twist. Nsc uses layer 3 directly. For this to work, nsc-tcp-l4 does no longer include the nsc ipv4 header in the packet. Instead, the ns-3 ip header is used. In the long run, it would be better to use the complete tcp/ip packet, e.g. for ECN.
- extend ns-3 API so users can create "Linux-Nodes", "FreeBSD-Nodes", etc.
Partially done. One can call e.g. 'internet.SetNscTcp("Linux");' before internet.Install(). This also allows to assign different nsc stack to some nodes.
- Think about the ns-3-nsc API. It is desirable to allow a simulation to use nsc-setsockopts and tune the nsc stack via available sysctl tunables (e.g. for disabling SACK support on Linux at run time).
Mathieu Lacage suggested to use ns-3s Attribute facility for this. The current plan is to:
- Add an nsc API that allows a user to iterate through all the sysctls provided by the current stack
done as of early July.
- then, using this NSC API, dynamically build a tree of attribute objects in ns-3 that reflect the sysctl hierarchy.
At the moment, a simple sysctl interface (that resembles the sysctl(8) utility, i.e. sysctl(const char *name, const char *value) is being added to nsc. After that, a query mechanism will be added to retrieve available sysctls and their current setting.
- rework ns-3-nsc, especially nsc-tcp-l4-protocol.cc.
The stack initialization/handling as well as the NSC-TCP related code is handles in nsc-tcp-l4-protocol.cc, this is wrong, and the two functionalities should be separated. As SCTP will be supported again in the Linux stack, this is being worked on as of 8th July because its a prerequisite of the SCTP ns-3-nsc integration work.
This is here to document some parts of the actual ns-3/nsc plumbing.
The two main parts are:
- nsc-tcp-l4-protocol, a subclass of Ipv4L4Protocol (and two nsc classes: ISendCallback and IInterruptCallback)
- nsc-tcp-socket-impl, a subclass of TcpSocket
There is also a factory to create new NSC sockets (nsc-tcp-socket-factory-impl.cc).
This is the main class. Upon Initialization, it loads an nsc network stack to use (via dlopen()). Each instance of this class may use a different stack. The stack (=shared library) to use is set using the SetNscLibrary() method (at this time its called indirectly via the internet stack helper). The nsc stack is then set up accordingly (timers etc). The NscTcpL4Protocol::Receive() function hands the packet it receives (must be a complete tcp/ip packet) to the nsc stack for further processing. TO be able to send packets, this class implements the nsc send_callback method. This method is called by nsc whenever the nsc stack wishes to send a packet out to the network. Its arguments are a raw buffer, containing a complete Tcp/ip packet, and a length value. This method therefore has to convert the raw data to a Ptr<Packet> usable by ns-3. In order to avoid various ipv4 header issues, the nsc ip header is not included. Instead, the tcp header and the actual payload are put into the Ptr<Packet>, after this the Packet is passed down to layer 3 for sending the packet out (no further special treatment is needed in the send code path).
This class calls nsc-tcp-socket-impl both from the nsc wakeup() callback and from the Receive path (to ensure that possibly queued data is scheduled for sending).
This implements the nsc socket interface. Each instance has its own nscTcpSocket. Data that is Send() will be handed to the nsc stack via m_nscTcpSocket->send_data(). (and not to nsc-tcp-l4, this is the major difference compared to ns-3). The class also queues up data that is Send() before the underlying descriptor has entered an ESTABLISHED state. This class is called from the nsc-tcp-l4 class, when the nsc-tcp-l4 wakeup() callback is invoked by nsc. nsc-tcp-socket-impl then checks the current connection state (SYN_SENT, ESTABLISHED, LISTEN...) and schedules appropriate callbacks as needed, e.g. a LISTEN socket will schedule Accept to see if a new connection must be accepted, an ESTABLISHED socket schedules any pending data for writing, schedule a read callback, etc.
ns-3-nsc integration diagram
Note that nsc-tcp-socket-impl does not interact with nsc-tcp directly: instead, data is redirected to nsc. nsc-tcp calls the nsc-tcp-sockets of a node when its wakeup callback is invoked by nsc.
The ns-3-nsc integration repository contains the current status. This port uses the latest nsc release (0.3.0). The nsc glue code has been moved off to its own files in src/internet-node:
- src/internet-node/nsc-tcp-socket-impl.cc contains ns-3s tcp-socket code, with nsc modifications.
- src/internet-node/nsc-tcp-l4-protocol.cc contains the ns3 tcp-l4 code, with nsc modifications.
- src/internet-node/nsc-tcp-socket-factory-impl.cc is like tcp-socket-factory-impl.cc , except that
it uses the NscTcpL4Protocol class.
AddInternetStack() has been extended to allow setting a TcpStack to use, this allows a simulation to switch to a particular stack supported by NSC.
NSC is now hosted at WAND NSC repository. A private branch with more experimental changes is located here. There is also a branch that privides a port of Linux 2.6.26-rc6, the plan is to merge this into the 'official' repository after Linux 2.6.26 is released and the port has been updated.