traffic-control: Add the traffic control layer
This commit is contained in:
@@ -55,6 +55,7 @@
|
||||
* - spectrum
|
||||
* - stats
|
||||
* - tap-bridge
|
||||
* - traffic-control
|
||||
* - test
|
||||
* - topology-read
|
||||
* - uan
|
||||
|
||||
@@ -17,6 +17,7 @@ SOURCES = \
|
||||
source/internet-models.rst \
|
||||
source/network.rst \
|
||||
source/emulation-overview.rst \
|
||||
source/traffic-control.rst \
|
||||
$(SRC)/antenna/doc/source/antenna.rst \
|
||||
$(SRC)/antenna/doc/source/antenna-design.rst \
|
||||
$(SRC)/antenna/doc/source/antenna-user.rst \
|
||||
@@ -75,6 +76,7 @@ SOURCES = \
|
||||
$(SRC)/wimax/doc/wimax.rst \
|
||||
$(SRC)/uan/doc/uan.rst \
|
||||
$(SRC)/topology-read/doc/topology.rst \
|
||||
$(SRC)/traffic-control/doc/traffic-control-layer.rst \
|
||||
$(SRC)/spectrum/doc/spectrum.rst \
|
||||
$(SRC)/stats/doc/adaptor.rst \
|
||||
$(SRC)/stats/doc/aggregator.rst \
|
||||
|
||||
@@ -47,6 +47,7 @@ This document is written in `reStructuredText <http://docutils.sourceforge.net/r
|
||||
spectrum
|
||||
sixlowpan
|
||||
topology
|
||||
traffic-control
|
||||
uan
|
||||
wave
|
||||
wifi
|
||||
|
||||
6
doc/models/source/traffic-control.rst
Normal file
6
doc/models/source/traffic-control.rst
Normal file
@@ -0,0 +1,6 @@
|
||||
Traffic Control Layer
|
||||
---------------------------------------------------------------------
|
||||
|
||||
.. toctree::
|
||||
|
||||
traffic-control-layer
|
||||
127
src/traffic-control/doc/traffic-control-layer.rst
Normal file
127
src/traffic-control/doc/traffic-control-layer.rst
Normal file
@@ -0,0 +1,127 @@
|
||||
Traffic Control Layer
|
||||
---------------------
|
||||
|
||||
.. heading hierarchy:
|
||||
------------- Chapter
|
||||
************* Section (#.#)
|
||||
============= Subsection (#.#.#)
|
||||
############# Paragraph (no number)
|
||||
|
||||
The Traffic Control layer aims at introducing an equivalent of the Linux Traffic
|
||||
Control infrastructure into ns-3. The Traffic Control layer sits in between
|
||||
the NetDevices (L2) and any network protocol (e.g. IP). It is in charge of processing
|
||||
packets and performing actions on them: scheduling, dropping, marking, policing, etc.
|
||||
|
||||
|
||||
Introducing the Traffic Control Layer
|
||||
*************************************
|
||||
|
||||
The Traffic Control layer intercepts both outgoing packets flowing downwards from
|
||||
the network layer to the network device and incoming packets flowing in the opposite
|
||||
direction. Currently, only outgoing packets are processed by the Traffic Control layer.
|
||||
In particular, outgoing packets are enqueued in a queuing discipline, which can perform
|
||||
multiple actions on them.
|
||||
|
||||
In the following, more details are given about how the Traffic Control layer intercepts
|
||||
outgoing and incoming packets and, more in general, about how the packets traverse the
|
||||
network stack.
|
||||
|
||||
Transmitting packets
|
||||
====================
|
||||
|
||||
The IPv{4,6} interfaces uses the aggregated object TrafficControlLayer to send
|
||||
down packets, instead of calling NetDevice::Send() directly. After the analysis
|
||||
and the process of the packet, when the backpressure mechanism allows it,
|
||||
TrafficControlLayer will call the Send() method on the right NetDevice.
|
||||
|
||||
Receiving packets
|
||||
=================
|
||||
|
||||
The callback chain that (in the past) involved IPv{4,6}L3Protocol and NetDevices,
|
||||
through ReceiveCallback, is extended to involve TrafficControlLayer. When an
|
||||
IPv{4,6}Interface is added in the IPv{4,6}L3Protocol, the callback chain is
|
||||
configured to have the following packet exchange:
|
||||
|
||||
NetDevice --> Node --> TrafficControlLayer --> IPv{4,6}L3Protocol
|
||||
|
||||
Brief description of old node/device/protocol interactions
|
||||
**************************************************************
|
||||
|
||||
The main question that we would like to answer in the following paragraphs is:
|
||||
how a ns-3 node can send/receive packets?
|
||||
|
||||
If we analyze any example out there, the ability of the node to receive/transmit
|
||||
packets derives from the interaction of two helper:
|
||||
|
||||
* L2 Helper (something derived from NetDevice)
|
||||
* L3 Helper (usually from Internet module)
|
||||
|
||||
L2 Helper main operations
|
||||
=========================
|
||||
|
||||
Any good L2 Helper will do the following operations:
|
||||
|
||||
* Create n netdevices (n>1)
|
||||
* Attach a channel between these devices
|
||||
* Call Node::AddDevice ()
|
||||
|
||||
Obviously the last point is the most important.
|
||||
|
||||
Node::AddDevice (network/model/node.cc:128) assigns an interface index to the
|
||||
device, calls NetDevice::SetNode, sets the receive callback of the device to
|
||||
Node::NonPromiscReceiveFromDevice. Then, it schedules NetDevice::Initialize() method at
|
||||
Seconds(0.0), then notify the registered DeviceAdditionListener handlers (not used BY ANYONE).
|
||||
|
||||
Node::NonPromiscReceiveFromDevice calls Node::ReceiveFromDevice.
|
||||
|
||||
Node::ReceiveFromDevice iterates through ProtocolHandlers, which are callbacks
|
||||
which accept as signature:
|
||||
|
||||
ProtocolHandler (Ptr<NetDevice>, Ptr<const Packet>, protocol, from_addr, to_addr, packetType).
|
||||
|
||||
If device, protocol number and promiscuous flag corresponds, the handler is
|
||||
invoked.
|
||||
|
||||
Who is responsible to set ProtocolHandler ? We will analyze that in the next
|
||||
section.
|
||||
|
||||
L3 Helper
|
||||
=========
|
||||
|
||||
We have only internet which provides network protocol (IP). That module splits
|
||||
the operations between two helpers: InternetStackHelper and Ipv{4,6}AddressHelper.
|
||||
|
||||
InternetStackHelper::Install (internet/helper/internet-stack-helper.cc:423)
|
||||
creates and aggregates protocols {ArpL3,Ipv4L3,Icmpv4}Protocol. It creates the
|
||||
routing protocol, and if Ipv6 is enabled it adds {Ipv6L3,Icmpv6L4}Protocol. In
|
||||
any case, it instantiates and aggregates an UdpL4Protocol object, along with a
|
||||
PacketSocketFactory.
|
||||
Ultimately, it creates the required objects and aggregates them to the node.
|
||||
|
||||
Let's assume an Ipv4 environment (things are the same for Ipv6).
|
||||
|
||||
Ipv4AddressHelper::Assign (src/internet/helper/ipv4-address-helper.cc:131)
|
||||
registers the handlers. The process is a bit long. The method is called with
|
||||
a list of NetDevice. For each of them, the node and Ipv4L3Protocol pointers are
|
||||
retrieved; if an Ipv4Interface is already registered for the device, on that the
|
||||
address is set. Otherwise, the method Ipv4L3Protocol::AddInterface is called,
|
||||
before adding the address.
|
||||
|
||||
IP interfaces
|
||||
=============
|
||||
|
||||
In Ipv4L3Protocol::AddInterface (src/internet/model/ipv4-l3-protocol.cc:300)
|
||||
two protocol handlers are installed: one that react to ipv4 protocol number,
|
||||
and one that react to arp protocol number (Ipv4L3Protocol::Receive and
|
||||
ArpL3Protocol::Receive, respectively). The interface is then created,
|
||||
initialized, and returned.
|
||||
|
||||
Ipv4L3Protocol::Receive (src/internet/model/ipv4-l3-protocol.cc:472) iterates
|
||||
through the interface. Once it finds the Ipv4Interface which has the same device
|
||||
as the one passed as argument, invokes the rxTrace callback. If the interface is
|
||||
down, the packet is dropped. Then, it removes the header and trim any residual
|
||||
frame padding. If checksum is not OK, it drops the packet. Otherwise, forward
|
||||
the packet to the raw sockets (not used). Then, it ask the routing protocol what
|
||||
is the destiny of that packet. The choices are: Ipv4L3Protocol::{IpForward,
|
||||
IpMulticastForward,LocalDeliver,RouteInputError}.
|
||||
|
||||
7
src/traffic-control/examples/wscript
Normal file
7
src/traffic-control/examples/wscript
Normal file
@@ -0,0 +1,7 @@
|
||||
# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
|
||||
|
||||
def build(bld):
|
||||
pass
|
||||
# obj = bld.create_ns3_program('traffic-control-example', ['traffic-control'])
|
||||
# obj.source = 'traffic-control-example.cc'
|
||||
|
||||
116
src/traffic-control/model/traffic-control-layer.cc
Normal file
116
src/traffic-control/model/traffic-control-layer.cc
Normal file
@@ -0,0 +1,116 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2015 Natale Patriciello <natale.patriciello@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "traffic-control-layer.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/packet.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("TrafficControlLayer");
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (TrafficControlLayer);
|
||||
|
||||
TypeId
|
||||
TrafficControlLayer::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::TrafficControlLayer")
|
||||
.SetParent<Object> ()
|
||||
.SetGroupName ("TrafficControl")
|
||||
.AddConstructor<TrafficControlLayer> ()
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
TypeId
|
||||
TrafficControlLayer::GetInstanceTypeId (void) const
|
||||
{
|
||||
return GetTypeId ();
|
||||
}
|
||||
|
||||
TrafficControlLayer::TrafficControlLayer ()
|
||||
: Object ()
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS ();
|
||||
}
|
||||
|
||||
void
|
||||
TrafficControlLayer::RegisterProtocolHandler (Node::ProtocolHandler handler,
|
||||
uint16_t protocolType, Ptr<NetDevice> device)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << protocolType << device);
|
||||
|
||||
struct ProtocolHandlerEntry entry;
|
||||
entry.handler = handler;
|
||||
entry.protocol = protocolType;
|
||||
entry.device = device;
|
||||
entry.promiscuous = false;
|
||||
|
||||
m_handlers.push_back (entry);
|
||||
|
||||
NS_LOG_DEBUG ("Handler for NetDevice: " << device << " registered for protocol " <<
|
||||
protocolType << ".");
|
||||
}
|
||||
|
||||
void
|
||||
TrafficControlLayer::Receive (Ptr<NetDevice> device, Ptr<const Packet> p,
|
||||
uint16_t protocol, const Address &from, const Address &to,
|
||||
NetDevice::PacketType packetType)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << device << p << protocol << from << to << packetType);
|
||||
|
||||
bool found = false;
|
||||
|
||||
for (ProtocolHandlerList::iterator i = m_handlers.begin ();
|
||||
i != m_handlers.end (); i++)
|
||||
{
|
||||
if (i->device == 0
|
||||
|| (i->device != 0 && i->device == device))
|
||||
{
|
||||
if (i->protocol == 0
|
||||
|| i->protocol == protocol)
|
||||
{
|
||||
NS_LOG_DEBUG ("Found handler for packet " << p << ", protocol " <<
|
||||
protocol << " and NetDevice " << device <<
|
||||
". Send packet up");
|
||||
i->handler (device, p, protocol, from, to, packetType);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! found)
|
||||
{
|
||||
NS_FATAL_ERROR ("Handler for protocol " << p << " and device " << device <<
|
||||
" not found. It isn't forwarded up; it dies here.");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TrafficControlLayer::Send (Ptr<NetDevice> device, Ptr<Packet> packet,
|
||||
const Address &dest, uint16_t protocolNumber)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << device << packet << dest << protocolNumber);
|
||||
|
||||
NS_LOG_DEBUG ("Send packet to device " << device << " protocol number " <<
|
||||
protocolNumber);
|
||||
|
||||
device->Send (packet, dest, protocolNumber);
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
164
src/traffic-control/model/traffic-control-layer.h
Normal file
164
src/traffic-control/model/traffic-control-layer.h
Normal file
@@ -0,0 +1,164 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2015 Natale Patriciello <natale.patriciello@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef TRAFFICCONTROLLAYER_H
|
||||
#define TRAFFICCONTROLLAYER_H
|
||||
|
||||
#include "ns3/object.h"
|
||||
#include "ns3/address.h"
|
||||
#include "ns3/net-device.h"
|
||||
#include "ns3/node.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
class Packet;
|
||||
|
||||
/**
|
||||
* \brief Traffic control layer definition
|
||||
*
|
||||
* This layer stays between NetDevices (L2) and any network protocol (e.g. IP).
|
||||
* When enabled, it is responsible to analyze packets and to perform actions on
|
||||
* them: the most common is scheduling.
|
||||
*
|
||||
* Basically, we manage both IN and OUT directions (sometimes called RX and TX,
|
||||
* respectively). The OUT direction is easy to follow, since it involves
|
||||
* direct calls: upper layer (e.g. IP) calls the Send method on an instance of
|
||||
* this class, which then call the Send method of some NetDevice.
|
||||
*
|
||||
* The IN direction uses a little trick to reduce dependencies between modules.
|
||||
* In simple words, we use Callbacks to connect upper layer (which should register
|
||||
* their Receive callback through RegisterProtocolHandler) and NetDevices.
|
||||
*
|
||||
* An example of the IN connection between this layer and IP layer is the following:
|
||||
*\verbatim
|
||||
Ptr<TrafficControlLayer> tc = m_node->GetObject<TrafficControlLayer> ();
|
||||
|
||||
NS_ASSERT (tc != 0);
|
||||
|
||||
m_node->RegisterProtocolHandler (MakeCallback (&TrafficControlLayer::Receive, tc),
|
||||
Ipv4L3Protocol::PROT_NUMBER, device);
|
||||
m_node->RegisterProtocolHandler (MakeCallback (&TrafficControlLayer::Receive, tc),
|
||||
ArpL3Protocol::PROT_NUMBER, device);
|
||||
|
||||
tc->RegisterProtocolHandler (MakeCallback (&Ipv4L3Protocol::Receive, this),
|
||||
Ipv4L3Protocol::PROT_NUMBER, device);
|
||||
tc->RegisterProtocolHandler (MakeCallback (&ArpL3Protocol::Receive, PeekPointer (GetObject<ArpL3Protocol> ())),
|
||||
ArpL3Protocol::PROT_NUMBER, device);
|
||||
\endverbatim
|
||||
* On the node, for IPv4 and ARP packet, is registered the
|
||||
* TrafficControlLayer::Receive callback. At the same time, on the TrafficControlLayer
|
||||
* object, is registered the callbacks associated to the upper layers (IPv4 or ARP).
|
||||
*
|
||||
* When the node receives an IPv4 or ARP packet, it calls the Receive method
|
||||
* on TrafficControlLayer, that calls the right upper-layer callback once it
|
||||
* finishes the operations on the packet received.
|
||||
*
|
||||
* Discrimination through callbacks (in other words: what is the right upper-layer
|
||||
* callback for this packet?) is done through checks over the device and the
|
||||
* protocol number.
|
||||
*/
|
||||
class TrafficControlLayer : public Object
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* \brief Get the type ID.
|
||||
* \return the object TypeId
|
||||
*/
|
||||
static TypeId GetTypeId (void);
|
||||
|
||||
/**
|
||||
* \brief Get the type ID for the instance
|
||||
* \return the instance TypeId
|
||||
*/
|
||||
virtual TypeId GetInstanceTypeId (void) const;
|
||||
|
||||
/**
|
||||
* \brief Constructor
|
||||
*/
|
||||
TrafficControlLayer ();
|
||||
|
||||
/**
|
||||
* \brief Register an IN handler
|
||||
*
|
||||
* The handler will be invoked when a packet is received to pass it to
|
||||
* upper layers.
|
||||
*
|
||||
* \param handler the handler to register
|
||||
* \param protocolType the type of protocol this handler is
|
||||
* interested in. This protocol type is a so-called
|
||||
* EtherType, as registered here:
|
||||
* http://standards.ieee.org/regauth/ethertype/eth.txt
|
||||
* the value zero is interpreted as matching all
|
||||
* protocols.
|
||||
* \param device the device attached to this handler. If the
|
||||
* value is zero, the handler is attached to all
|
||||
* devices.
|
||||
*/
|
||||
void RegisterProtocolHandler (Node::ProtocolHandler handler,
|
||||
uint16_t protocolType,
|
||||
Ptr<NetDevice> device);
|
||||
|
||||
/**
|
||||
* \brief Called by NetDevices, incoming packet
|
||||
*
|
||||
* After analyses and scheduling, this method will call the right handler
|
||||
* to pass the packet up in the stack.
|
||||
*
|
||||
* \param device network device
|
||||
* \param p the packet
|
||||
* \param protocol next header value
|
||||
* \param from address of the correspondant
|
||||
* \param to address of the destination
|
||||
* \param packetType type of the packet
|
||||
*/
|
||||
virtual void Receive (Ptr<NetDevice> device, Ptr<const Packet> p,
|
||||
uint16_t protocol, const Address &from,
|
||||
const Address &to, NetDevice::PacketType packetType);
|
||||
/**
|
||||
* \brief Called from upper layer to queue a packet for the transmission.
|
||||
*
|
||||
* \param packet packet sent from above
|
||||
* \param dest mac address of the destination (already resolved)
|
||||
* \param protocolNumber identifies the type of payload contained in
|
||||
* this packet. Used to call the right L3Protocol when the packet
|
||||
* is received.
|
||||
*
|
||||
*/
|
||||
virtual void Send (Ptr<NetDevice> device, Ptr<Packet> packet,
|
||||
const Address& dest, uint16_t protocolNumber);
|
||||
|
||||
private:
|
||||
/**
|
||||
* \brief Protocol handler entry.
|
||||
* This structure is used to demultiplex all the protocols.
|
||||
*/
|
||||
struct ProtocolHandlerEntry {
|
||||
Node::ProtocolHandler handler; //!< the protocol handler
|
||||
Ptr<NetDevice> device; //!< the NetDevice
|
||||
uint16_t protocol; //!< the protocol number
|
||||
bool promiscuous; //!< true if it is a promiscuous handler
|
||||
};
|
||||
|
||||
/// Typedef for protocol handlers container
|
||||
typedef std::vector<struct ProtocolHandlerEntry> ProtocolHandlerList;
|
||||
|
||||
ProtocolHandlerList m_handlers; //!< List of upper-layer handlers
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif // TRAFFICCONTROLLAYER_H
|
||||
29
src/traffic-control/wscript
Normal file
29
src/traffic-control/wscript
Normal file
@@ -0,0 +1,29 @@
|
||||
# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
|
||||
|
||||
# def options(opt):
|
||||
# pass
|
||||
|
||||
# def configure(conf):
|
||||
# conf.check_nonfatal(header_name='stdint.h', define_name='HAVE_STDINT_H')
|
||||
|
||||
def build(bld):
|
||||
module = bld.create_ns3_module('traffic-control', ['core'])
|
||||
module.source = [
|
||||
'model/traffic-control-layer.cc'
|
||||
]
|
||||
|
||||
module_test = bld.create_ns3_module_test_library('traffic-control')
|
||||
module_test.source = [
|
||||
]
|
||||
|
||||
headers = bld(features='ns3header')
|
||||
headers.module = 'traffic-control'
|
||||
headers.source = [
|
||||
'model/traffic-control-layer.h'
|
||||
]
|
||||
|
||||
if bld.env.ENABLE_EXAMPLES:
|
||||
bld.recurse('examples')
|
||||
|
||||
# bld.ns3_python_bindings()
|
||||
|
||||
Reference in New Issue
Block a user