@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> node) const
{
if (node->GetObject<Ipv4> () != 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<Object> ());
Ptr<PacketSocketFactory> factory = CreateObject<PacketSocketFactory> ();
node->AggregateObject (factory);
// Set routing
Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
Ptr<Ipv4RoutingProtocol> 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<NetDevice> device, Ptr<const Packet> 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<Ipv4L3Protocol> ()} to obtain a pointer, as follows:
@verbatim
Ptr<Ipv4L3Protocol> ipv4 = m_node->GetObject<Ipv4L3Protocol> ();
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<const Packet> 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<Udp> udpSocketFactory = GetNode ()->GetObject<Udp> ();
Ptr<Socket> 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<void, Ptr<Socket>,
Ptr<Packet>, 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