/src/internet/doc/internet-stack.rst
https://gitlab.com/msepahkar/location_in_wireless_ndn · ReStructuredText · 317 lines · 250 code · 67 blank · 0 comment · 0 complexity · 4a6935d0a7e46902c40f8a2a1696fc1a MD5 · raw file
- .. include:: replace.txt
- .. highlight:: cpp
- Internet Stack
- --------------
- Internet stack aggregation
- **************************
- A bare class :cpp:class:`Node` is not very useful as-is; other objects must be
- aggregated to it to provide useful node functionality.
- The |ns3| source code directory ``src/internet`` 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 IP-related objects aggregated to them. They can be put together
- by hand, or via a helper function :cpp:func:`InternetStackHelper::Install ()`
- which does the following to all nodes passed in as arguments::
- void
- InternetStackHelper::Install (Ptr<Node> node) const
- {
- if (m_ipv4Enabled)
- {
- /* IPv4 stack */
- 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");
- // Set routing
- Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
- Ptr<Ipv4RoutingProtocol> ipv4Routing = m_routing->Create (node);
- ipv4->SetRoutingProtocol (ipv4Routing);
- }
- if (m_ipv6Enabled)
- {
- /* IPv6 stack */
- if (node->GetObject<Ipv6> () != 0)
- {
- NS_FATAL_ERROR ("InternetStackHelper::Install (): Aggregating "
- "an InternetStack to a node with an existing Ipv6 object");
- return;
- }
- CreateAndAggregateObjectFromTypeId (node, "ns3::Ipv6L3Protocol");
- CreateAndAggregateObjectFromTypeId (node, "ns3::Icmpv6L4Protocol");
- // Set routing
- Ptr<Ipv6> ipv6 = node->GetObject<Ipv6> ();
- Ptr<Ipv6RoutingProtocol> ipv6Routing = m_routingv6->Create (node);
- ipv6->SetRoutingProtocol (ipv6Routing);
- /* register IPv6 extensions and options */
- ipv6->RegisterExtensions ();
- ipv6->RegisterOptions ();
- }
- if (m_ipv4Enabled || m_ipv6Enabled)
- {
- /* UDP and TCP stacks */
- CreateAndAggregateObjectFromTypeId (node, "ns3::UdpL4Protocol");
- node->AggregateObject (m_tcpFactory.Create<Object> ());
- Ptr<PacketSocketFactory> factory = CreateObject<PacketSocketFactory> ();
- node->AggregateObject (factory);
- }
- }
- Where multiple implementations exist in |ns3| (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::
- void InternetStackHelper::Initialize ()
- {
- SetTcp ("ns3::TcpL4Protocol");
- Ipv4StaticRoutingHelper staticRouting;
- Ipv4GlobalRoutingHelper globalRouting;
- Ipv4ListRoutingHelper listRouting;
- Ipv6ListRoutingHelper listRoutingv6;
- Ipv6StaticRoutingHelper staticRoutingv6;
- listRouting.Add (staticRouting, 0);
- listRouting.Add (globalRouting, -10);
- listRoutingv6.Add (staticRoutingv6, 0);
- SetRoutingHelper (listRouting);
- SetRoutingHelper (listRoutingv6);
- }
- By default, IPv4 and IPv6 are enabled.
- Internet Node structure
- +++++++++++++++++++++++
- An IP-capable Node (an |ns3| Node augmented by aggregation to have one or more
- IP stacks) has the following internal structure.
- Layer-3 protocols
- ~~~~~~~~~~~~~~~~~
- At the lowest layer, sitting above the NetDevices, are the "layer 3" protocols,
- including IPv4, IPv6, ARP and so on. The class
- :cpp:class:`Ipv4L3Protocol` is an implementation class whose public interface is
- typically class :cpp:class:`Ipv4`, but the
- Ipv4L3Protocol public API is also used internally at present.
- In class Ipv4L3Protocol, one method described below is ``Receive ()``::
- /**
- * 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);
- First, note that the ``Receive ()`` function has a matching signature to the
- ReceiveCallback in the class :cpp:class:`Node`. This function pointer is
- inserted into 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 |ns3| 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::
- void
- Ipv4L3Protocol::LocalDeliver (Ptr<const Packet> packet, Ipv4Header const&ip, uint32_t iif)
- 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 ``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
- :cpp:class:`Ipv4Interface` roughly corresponds to the ``struct in_device``; the
- main purpose is to provide address-family specific information (addresses) about
- an interface.
- All the classes have appropriate traces in order to track sent, received and lost packets.
- The users is encouraged to use them so to find out if (and where) a packet is dropped. A
- common mistake is to forget the effects of local queues when sending packets, e.g., the ARP
- queue. This can be particularly puzzling when sending jumbo packets or packet bursts using UDP.
- The ARP cache pending queue is limited (3 datagrams) and IP packets might be fragmented, easily
- overfilling the ARP cache queue size. In those cases it is useful to increase the ARP cache
- pending size to a proper value, e.g.::
- Config::SetDefault ("ns3::ArpCache::PendingQueueSize", UintegerValue (MAX_BURST_SIZE/L2MTU*3));
- The IPv6 implementation follows a similar architecture. Dual-stacked nodes (one with
- support for both IPv4 and IPv6) will allow an IPv6 socket to receive IPv4 connections
- as a standard dual-stacked system does. A socket bound and listening to an IPv6 endpoint
- can receive an IPv4 connection and will return the remote address as an IPv4-mapped address.
- Support for the IPV6_V6ONLY socket option does not currently exist.
- 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::
- 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 ()``. The address passed
- to the ``Bind ()``, ``Connect ()``, or ``Send ()`` functions may be a
- :cpp:class:`Ipv4Address`, :cpp:class:`Ipv6Address`, or :cpp:class:`Address`.
- If a :cpp:class:`Address` is passed in and contains anything other than
- a :cpp:class:`Ipv4Address` or :cpp:class:`Ipv6Address`, these functions will
- return an error. The ``Bind (void)`` and ``Bind6 (void)`` functions bind to
- "0.0.0.0" and "::" respectively.
- The socket can also be bound to a specific NetDevice though the
- ``BindToNetDevice (Ptr<NetDevice> netdevice)`` function.
- ``BindToNetDevice (Ptr<NetDevice> netdevice)`` will bind the socket
- to "0.0.0.0" and "::" (equivalent to calling ``Bind ()`` and ``Bind6 ()``,
- unless the socket has been already bound to a specific address.
- Summarizing, the correct sequence is::
- Ptr<Udp> udpSocketFactory = GetNode ()->GetObject<Udp> ();
- Ptr<Socket> m_socket = socketFactory->CreateSocket ();
- m_socket->BindToNetDevice (n_netDevice);
- ...
- or::
- Ptr<Udp> udpSocketFactory = GetNode ()->GetObject<Udp> ();
- Ptr<Socket> m_socket = socketFactory->CreateSocket ();
- m_socket->Bind (m_local_address);
- m_socket->BindToNetDevice (n_netDevice);
- ...
- The following raises an error::
- Ptr<Udp> udpSocketFactory = GetNode ()->GetObject<Udp> ();
- Ptr<Socket> m_socket = socketFactory->CreateSocket ();
- m_socket->BindToNetDevice (n_netDevice);
- m_socket->Bind (m_local_address);
- ...
- See the chapter on |ns3| 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 :cpp: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
- :cpp:class:`Ipv4EndPointDemux`. This demultiplexer stores objects of class
- :cpp: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, ...).
- |ns3| 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 :cpp:class:`PacketSink`::
- m_socket->SetRecvCallback (MakeCallback(&PacketSink::HandleRead, this));
- To summarize, internally, the UDP implementation is organized as follows:
- * a ``UdpImpl`` class that implements the UDP socket factory functionality
- * a ``UdpL4Protocol`` class that implements the protocol logic that is
- socket-independent
- * a ``UdpSocketImpl`` class that implements socket-specific aspects of UDP
- * a class called ``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.
- IP-capable node interfaces
- ++++++++++++++++++++++++++
- Many of the implementation details, or internal objects themselves, of
- IP-capable Node objects are not exposed at the simulator public API. This
- allows for different implementations; for instance, replacing the native |ns3|
- models with ported TCP/IP stack code.
-
- The C++ public APIs of all of these objects is found in the ``src/network``
- directory, including principally:
- * ``address.h``
- * ``socket.h``
- * ``node.h``
- * ``packet.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``.
- Example path of a packet
- ++++++++++++++++++++++++
- These two figures show an example stack trace of how packets flow through the
- Internet Node objects.
- .. _internet-node-send:
- .. figure:: figures/internet-node-send.*
-
- Send path of a packet.
- .. _internet-node-recv:
- .. figure:: figures/internet-node-recv.*
-
- Receive path of a packet.