[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The above 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 src/internet-stack
provides
implmentation of TCP/IPv4-related components. These include IPv4,
ARP, UDP, TCP, 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 AddInternetStack ()
which does the
following:
void AddInternetStack (Ptr<Node> node) { // Create layer-3 protocols Ptr<Ipv4L3Protocol> ipv4 = CreateObject<Ipv4L3Protocol> (); Ptr<ArpL3Protocol> arp = CreateObject<ArpL3Protocol> (); ipv4->SetNode (node); arp->SetNode (node); // Create an L4 demux Ptr<Ipv4L4Demux> ipv4L4Demux = CreateObject<Ipv4L4Demux> (); // Create transport protocols and insert them into the demux Ptr<UdpL4Protocol> udp = CreateObject<UdpL4Protocol> (); Ptr<TcpL4Protocol> tcp = CreateObject<TcpL4Protocol> (); ipv4L4Demux->SetNode (node); udp->SetNode (node); tcp->SetNode (node); ipv4L4Demux->Insert (udp); ipv4L4Demux->Insert (tcp); // Add factories for instantiating transport protocol sockets Ptr<UdpSocketFactoryImpl> udpFactory = CreateObject<UdpSocketFactoryImpl> (); Ptr<TcpSocketFactoryImpl> tcpFactory = CreateObject<TcpSocketFactoryImpl> (); Ptr<Ipv4Impl> ipv4Impl = CreateObject<Ipv4Impl> (); udpFactory->SetUdp (udp); tcpFactory->SetTcp (tcp); ipv4Impl->SetIpv4 (ipv4); // Aggregate all of these new objects to the node node->AggregateObject (ipv4); node->AggregateObject (arp); node->AggregateObject (ipv4Impl); node->AggregateObject (udpFactory); node->AggregateObject (tcpFactory); node->AggregateObject (ipv4L4Demux); }
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The Internet Node (an ns-3 Node augmented by aggregation to have one or more IP stacks) has the following internal structure.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
At the lowest layer, sitting above the NetDevices, are the "layer 3" protocols, including IPv4, IPv6, and ARP. These protocols provide the following key methods and data members:
class Ipv4L3Protocol : public Object { public: // Add an Ipv4 interface corresponding to the provided NetDevice uint32_t AddInterface (Ptr<NetDevice> device); // Receive function that can be bound to a callback, for receiving // packets up the stack void Receive( Ptr<NetDevice> device, Ptr<Packet> p, uint16_t protocol, const Address &from); // Higher-level layers call this method to send a packet // down the stack to the MAC and PHY layers // void Send (Ptr<Packet> packet, Ipv4Address source, Ipv4Address destination, uint8_t protocol); private: Ipv4InterfaceList m_interfaces; // Protocol handlers }
There are many more functions (such as Forward ()
) but we will
focus on the above four items from an architectural perspective.
First, note that the Receive ()
function has a matching signature
to the ReceiveCallback in the class Node
. This function pointer
is inserted into the the Node's protocol handler when
AddInterface ()
is called. The actual registration is done
with a statement such as:
follows:
RegisterProtocolHandler ( MakeCallback (&Ipv4Protocol::Receive, ipv4), Ipv4L3Protocol::PROT_NUMBER, 0);
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
GetObject<Ipv4L3Protocol> ()
to obtain a pointer, as follows:
Ptr<Ipv4L3Protocol> ipv4 = m_node->GetObject<Ipv4L3Protocol> (); if (ipv4 != 0) { ipv4->Send (packet, saddr, daddr, PROT_NUMBER); }
This class nicely demonstrates two techniques we exploit in ns-3 to bind objects together: callbacks, and object aggregation.
Once IPv4 has determined that a packet is for the local node, it forwards it up the stack. This is done with the following function:
void Ipv4L3Protocol::ForwardUp (Ptr<Packet> p, Ipv4Header const&ip, Ptr<Ipv4Interface> incomingInterface) { NS_LOG_FUNCTION (this << p << &ip); Ptr<Ipv4L4Demux> demux = m_node->GetObject<Ipv4L4Demux> (); Ptr<Ipv4L4Protocol> protocol = demux->GetProtocol (ip.GetProtocol ()); protocol->Receive (p, ip.GetSource (), ip.GetDestination (), incomingInterface); }
The first step is to find the aggregated Ipv4L4Demux object. Then, this
object is consulted to look up the right Ipv4L4Protocol, based on IP protocol
number. For instance, TCP is registered in the demux as protocol number 6.
Finally, the Receive()
function on the Ipv4L4Protocol (such as
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 class Ipv4Interface
roughly corresponds to
the struct in_device
; the main purpose is to provide
address-family specific information (addresses) about an interface.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
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:
Ptr<Udp> udpSocketFactory = GetNode ()->GetObject<Udp> (); Ptr<Socket> m_socket = socketFactory->CreateSocket (); m_socket->Bind (m_local_address); ...
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 Connect ()
and Send ()
. See the chapter on ns-3 sockets for more information.
We have described so far a socket factory (e.g. class Udp
) and
a socket, which may be specialized (e.g., 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 class Ipv4EndPointDemux
.
This demultiplexer stores objects of 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 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 ForwardUp ()
method, which then calls the 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:
void Socket::SetRecvCallback (Callback<void, Ptr<Socket>, Ptr<Packet>, const Address&> receivedData);
The data being received is conveyed in the Packet data buffer. An example
usage is in class PacketSink
:
m_socket->SetRecvCallback (MakeCallback(&PacketSink::HandleRead, this));
To summarize, internally, the UDP implementation is organized as follows:
UdpImpl
class that implements the Udp socket factory
functionality
UdpL4Protocol
class that implements the protocol logic
that is socket-independent
UdpSocketImpl
class that implements socket-specific aspects
of UDP
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.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Many of the implementation details, or internal objects themselves, of Internet 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
src/node
directory, including principally:
socket.h
tcp.h
udp.h
ipv4.h
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 CreateSocket
.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
These two figures show an example stack trace of how packets flow through the Internet Node objects.
Figure 7.2: Send path of a packet.
Figure 7.3: Receive path of a packet.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] |
This document was generated on September, 23 2008 using texi2html 1.76.