@node Internet Stack @chapter Internet Stack @section Internet stack aggregation A bare @code{class Node} is not very useful as-is; other objects must be aggregated to it to provide useful node functionality. The ns-3 source code directory @code{src/internet-stack} provides implementation of TCP/IPv4- and IPv6-related components. These include IPv4, ARP, UDP, TCP, IPv6, Neighbor Discovery, and other related protocols. Internet Nodes are not subclasses of class Node; they are simply Nodes that have had a bunch of IPv4-related objects aggregated to them. They can be put together by hand, or via a helper function @code{InternetStackHelper::Install ()} which does the following to all nodes passed in as arguments: @smallformat @example void InternetStackHelper::Install (Ptr node) const { if (node->GetObject () != 0) { NS_FATAL_ERROR ("InternetStackHelper::Install(): Aggregating " "an InternetStack to a node with an existing Ipv4 object"); return; } CreateAndAggregateObjectFromTypeId (node, "ns3::ArpL3Protocol"); CreateAndAggregateObjectFromTypeId (node, "ns3::Ipv4L3Protocol"); CreateAndAggregateObjectFromTypeId (node, "ns3::Icmpv4L4Protocol"); CreateAndAggregateObjectFromTypeId (node, "ns3::UdpL4Protocol"); node->AggregateObject (m_tcpFactory.Create ()); Ptr factory = CreateObject (); node->AggregateObject (factory); // Set routing Ptr ipv4 = node->GetObject (); Ptr ipv4Routing = m_routing->Create (node); ipv4->SetRoutingProtocol (ipv4Routing); } @end example @end smallformat Where multiple implementations exist in ns-3 (TCP, IP routing), these objects are added by a factory object (TCP) or by a routing helper (m_routing). Note that the routing protocol is configured and set outside this function. By default, the following protocols are added to Ipv4: @verbatim InternetStackHelper::InternetStackHelper () { SetTcp ("ns3::TcpL4Protocol"); static Ipv4StaticRoutingHelper staticRouting; static Ipv4GlobalRoutingHelper globalRouting; static Ipv4ListRoutingHelper listRouting; listRouting.Add (staticRouting, 0); listRouting.Add (globalRouting, -10); SetRoutingHelper (listRouting); } @end verbatim By default, IPv4 and IPv6 are enabled. @subsection Internet Node structure An IPv4-capable Node (an ns-3 Node augmented by aggregation to have one or more IP stacks) has the following internal structure. @subsubsection Layer-3 protocols At the lowest layer, sitting above the NetDevices, are the "layer 3" protocols, including IPv4, IPv6 (in the future), and ARP. The @code{class Ipv4L3Protocol} is an implementation class whose public interface is typically @code{class Ipv4} (found in src/node directory), but the Ipv4L3Protocol public API is also used internally in the src/internet-stack directory at present. In class Ipv4L3Protocol, one method described below is @code{Receive ()}: @smallformat @example /** * Lower layer calls this method after calling L3Demux::Lookup * The ARP subclass needs to know from which NetDevice this * packet is coming to: * - implement a per-NetDevice ARP cache * - send back arp replies on the right device */ void Receive( Ptr device, Ptr p, uint16_t protocol, const Address &from, const Address &to, NetDevice::PacketType packetType); @end example @end smallformat First, note that the @code{Receive ()} function has a matching signature to the ReceiveCallback in the @code{class Node}. This function pointer is inserted into the Node's protocol handler when @code{AddInterface ()} is called. The actual registration is done with a statement such as: follows: @verbatim RegisterProtocolHandler ( MakeCallback (&Ipv4Protocol::Receive, ipv4), Ipv4L3Protocol::PROT_NUMBER, 0); @end verbatim The Ipv4L3Protocol object is aggregated to the Node; there is only one such Ipv4L3Protocol object. Higher-layer protocols that have a packet to send down to the Ipv4L3Protocol object can call @code{GetObject ()} to obtain a pointer, as follows: @verbatim Ptr ipv4 = m_node->GetObject (); if (ipv4 != 0) { ipv4->Send (packet, saddr, daddr, PROT_NUMBER); } @end verbatim This class nicely demonstrates two techniques we exploit in ns-3 to bind objects together: callbacks, and object aggregation. Once IPv4 routing has determined that a packet is for the local node, it forwards it up the stack. This is done with the following function: @smallformat @example void Ipv4L3Protocol::LocalDeliver (Ptr packet, Ipv4Header const&ip, uint32_t iif) @end example @end smallformat The first step is to find the right Ipv4L4Protocol object , based on IP protocol number. For instance, TCP is registered in the demux as protocol number 6. Finally, the @code{Receive()} function on the Ipv4L4Protocol (such as @code{TcpL4Protocol::Receive} is called. We have not yet introduced the class Ipv4Interface. Basically, each NetDevice is paired with an IPv4 representation of such device. In Linux, this @code{class Ipv4Interface} roughly corresponds to the @code{struct in_device}; the main purpose is to provide address-family specific information (addresses) about an interface. The IPv6 implementation follows a similar architecture. @subsubsection Layer-4 protocols and sockets We next describe how the transport protocols, sockets, and applications tie together. In summary, each transport protocol implementation is a socket factory. An application that needs a new socket For instance, to create a UDP socket, an application would use a code snippet such as the following: @verbatim Ptr udpSocketFactory = GetNode ()->GetObject (); Ptr m_socket = socketFactory->CreateSocket (); m_socket->Bind (m_local_address); ... @end verbatim The above will query the node to get a pointer to its UDP socket factory, will create one such socket, and will use the socket with an API similar to the C-based sockets API, such as @code{Connect ()} and @code{Send ()}. See the chapter on ns-3 sockets for more information. We have described so far a socket factory (e.g. @code{class Udp}) and a socket, which may be specialized (e.g., @code{class UdpSocket}). There are a few more key objects that relate to the specialized task of demultiplexing a packet to one or more receiving sockets. The key object in this task is @code{class Ipv4EndPointDemux}. This demultiplexer stores objects of @code{class Ipv4EndPoint}. This class holds the addressing/port tuple (local port, local address, destination port, destination address) associated with the socket, and a receive callback. This receive callback has a receive function registered by the socket. The @code{Lookup ()} function to Ipv4EndPointDemux returns a list of Ipv4EndPoint objects (there may be a list since more than one socket may match the packet). The layer-4 protocol copies the packet to each Ipv4EndPoint and calls its @code{ForwardUp ()} method, which then calls the @code{Receive ()} function registered by the socket. An issue that arises when working with the sockets API on real systems is the need to manage the reading from a socket, using some type of I/O (e.g., blocking, non-blocking, asynchronous, ...). ns-3 implements an asynchronous model for socket I/O; the application sets a callback to be notified of received data ready to be read, and the callback is invoked by the transport protocol when data is available. This callback is specified as follows: @verbatim void Socket::SetRecvCallback (Callback, Ptr, const Address&> receivedData); @end verbatim The data being received is conveyed in the Packet data buffer. An example usage is in @code{class PacketSink}: @verbatim m_socket->SetRecvCallback (MakeCallback(&PacketSink::HandleRead, this)); @end verbatim To summarize, internally, the UDP implementation is organized as follows: @itemize @bullet @item a @code{UdpImpl} class that implements the UDP socket factory functionality @item a @code{UdpL4Protocol} class that implements the protocol logic that is socket-independent @item a @code{UdpSocketImpl} class that implements socket-specific aspects of UDP @item a class called @code{Ipv4EndPoint} that stores the addressing tuple (local port, local address, destination port, destination address) associated with the socket, and a receive callback for the socket. @end itemize @subsection Ipv4-capable node interfaces Many of the implementation details, or internal objects themselves, of Ipv4-capable Node objects are not exposed at the simulator public API. This allows for different implementations; for instance, replacing the native ns-3 models with ported TCP/IP stack code. The C++ public APIs of all of these objects is found in the @code{src/node} directory, including principally: @itemize @bullet @item @code{socket.h} @item @code{tcp.h} @item @code{udp.h} @item @code{ipv4.h} @end itemize These are typically base class objects that implement the default values used in the implementation, implement access methods to get/set state variables, host attributes, and implement publicly-available methods exposed to clients such as @code{CreateSocket}. @subsection Example path of a packet These two figures show an example stack trace of how packets flow through the Internet Node objects. @float Figure,fig:internet-node-send @caption{Send path of a packet.} @image{figures/internet-node-send,5in} @end float @float Figure,fig:internet-node-recv @caption{Receive path of a packet.} @image{figures/internet-node-recv,5in} @end float