network: Add the NetDeviceQueue and NetDeviceQueueInterface classes
This patch adds a NetDeviceQueue class to store information about a single transmission queue of a network device. This class is meant to store the state of a transmission queue (i.e., whether the queue is stopped or not) and some data used by techniques such as Byte Queue Limits. Also, multi-queue aware queue discs can aggregate a child queue disc to an object of this class. These features (excluding BQL) are added in subsequent commits. The NetDevice class maintains a vector of NetDeviceQueue pointers, one for each transmission queue. A NetDevice constructor is added which creates a single transmission queue by default for every device. The number of transmission queues can be modified (by child classes) by calling NetDevice::SetTxQueuesN. Two public methods, GetTxQueue and GetTxQueuesN, are also added to the NetDevice class to return the i-th NetDeviceQueue and the number of transmission queues, respectively.
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "ns3/object.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/abort.h"
|
||||
#include "ns3/uinteger.h"
|
||||
#include "net-device.h"
|
||||
#include "packet.h"
|
||||
@@ -64,6 +65,155 @@ std::ostream & operator << (std::ostream &os, const QueueItem &item)
|
||||
return os;
|
||||
}
|
||||
|
||||
NetDeviceQueue::NetDeviceQueue()
|
||||
: m_stopped (false)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
}
|
||||
|
||||
NetDeviceQueue::~NetDeviceQueue ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
}
|
||||
|
||||
bool
|
||||
NetDeviceQueue::IsStopped (void) const
|
||||
{
|
||||
return m_stopped;
|
||||
}
|
||||
|
||||
void
|
||||
NetDeviceQueue::Start (void)
|
||||
{
|
||||
m_stopped = false;
|
||||
}
|
||||
|
||||
void
|
||||
NetDeviceQueue::Stop (void)
|
||||
{
|
||||
m_stopped = true;
|
||||
}
|
||||
|
||||
void
|
||||
NetDeviceQueue::Wake (void)
|
||||
{
|
||||
Start ();
|
||||
|
||||
// Request the queue disc to dequeue a packet
|
||||
if (!m_wakeCallback.IsNull ())
|
||||
{
|
||||
m_wakeCallback ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NetDeviceQueue::SetWakeCallback (WakeCallback cb)
|
||||
{
|
||||
m_wakeCallback = cb;
|
||||
}
|
||||
|
||||
bool
|
||||
NetDeviceQueue::HasWakeCallbackSet (void) const
|
||||
{
|
||||
return (!m_wakeCallback.IsNull ());
|
||||
}
|
||||
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (NetDeviceQueueInterface);
|
||||
|
||||
TypeId NetDeviceQueueInterface::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::NetDeviceQueueInterface")
|
||||
.SetParent<Object> ()
|
||||
.SetGroupName("Network")
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
NetDeviceQueueInterface::NetDeviceQueueInterface ()
|
||||
: m_queueDiscInstalled (false)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
Ptr<NetDeviceQueue> devQueue = Create<NetDeviceQueue> ();
|
||||
m_txQueuesVector.push_back (devQueue);
|
||||
}
|
||||
|
||||
NetDeviceQueueInterface::~NetDeviceQueueInterface ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
}
|
||||
|
||||
Ptr<NetDeviceQueue>
|
||||
NetDeviceQueueInterface::GetTxQueue (uint8_t i) const
|
||||
{
|
||||
NS_ASSERT (i < m_txQueuesVector.size ());
|
||||
return m_txQueuesVector[i];
|
||||
}
|
||||
|
||||
uint8_t
|
||||
NetDeviceQueueInterface::GetTxQueuesN (void) const
|
||||
{
|
||||
return m_txQueuesVector.size ();
|
||||
}
|
||||
|
||||
void
|
||||
NetDeviceQueueInterface::DoDispose (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_txQueuesVector.clear ();
|
||||
Object::DoDispose ();
|
||||
}
|
||||
|
||||
void
|
||||
NetDeviceQueueInterface::SetTxQueuesN (uint8_t numTxQueues)
|
||||
{
|
||||
NS_ASSERT (numTxQueues > 0);
|
||||
|
||||
// check whether a queue disc has been installed on the device by
|
||||
// verifying whether a wake callback has been set on a transmission queue
|
||||
NS_ABORT_MSG_IF (GetTxQueue (0)->HasWakeCallbackSet (), "Cannot change the number of"
|
||||
" transmission queues after setting up the wake callback.");
|
||||
|
||||
uint8_t prevNumTxQueues = m_txQueuesVector.size ();
|
||||
m_txQueuesVector.resize (numTxQueues);
|
||||
|
||||
// Allocate new NetDeviceQueues if the number of queues increased
|
||||
for (uint8_t i = prevNumTxQueues; i < numTxQueues; i++)
|
||||
{
|
||||
Ptr<NetDeviceQueue> devQueue = Create<NetDeviceQueue> ();
|
||||
m_txQueuesVector[i] = devQueue;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NetDeviceQueueInterface::SetSelectQueueCallback (SelectQueueCallback cb)
|
||||
{
|
||||
m_selectQueueCallback = cb;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
NetDeviceQueueInterface::GetSelectedQueue (Ptr<QueueItem> item) const
|
||||
{
|
||||
if (!m_selectQueueCallback.IsNull ())
|
||||
{
|
||||
return m_selectQueueCallback (item);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool
|
||||
NetDeviceQueueInterface::IsQueueDiscInstalled (void) const
|
||||
{
|
||||
return m_queueDiscInstalled;
|
||||
}
|
||||
|
||||
void
|
||||
NetDeviceQueueInterface::SetQueueDiscInstalled (bool installed)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << installed);
|
||||
m_queueDiscInstalled = installed;
|
||||
}
|
||||
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (NetDevice);
|
||||
|
||||
|
||||
@@ -17,11 +17,13 @@
|
||||
*
|
||||
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
* Modified by Emmanuelle Laprise to remove dependence on LLC headers
|
||||
* Modified by Stefano Avallone to add NetDeviceQueue and NetDeviceQueueInterface
|
||||
*/
|
||||
#ifndef NET_DEVICE_H
|
||||
#define NET_DEVICE_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdint.h>
|
||||
#include "ns3/callback.h"
|
||||
#include "ns3/object.h"
|
||||
@@ -122,6 +124,184 @@ private:
|
||||
*/
|
||||
std::ostream& operator<< (std::ostream& os, const QueueItem &item);
|
||||
|
||||
/**
|
||||
* \ingroup netdevice
|
||||
*
|
||||
* \brief Network device transmission queue
|
||||
*
|
||||
* This class stores information about a single transmission queue
|
||||
* of a network device that is exposed to queue discs. Such information
|
||||
* includes the state of the transmission queue (whether it has been
|
||||
* stopped or not) and data used by techniques such as Byte Queue Limits.
|
||||
*
|
||||
* This class roughly models the struct netdev_queue of Linux.
|
||||
* \todo Implement BQL
|
||||
*/
|
||||
class NetDeviceQueue : public SimpleRefCount<NetDeviceQueue>
|
||||
{
|
||||
public:
|
||||
NetDeviceQueue ();
|
||||
virtual ~NetDeviceQueue();
|
||||
|
||||
/**
|
||||
* Called by the device to start this (hardware) transmission queue.
|
||||
* This is the analogous to the netif_tx_start_queue function of the Linux kernel.
|
||||
*/
|
||||
virtual void Start (void);
|
||||
|
||||
/**
|
||||
* Called by the device to stop this (hardware) transmission queue.
|
||||
* This is the analogous to the netif_tx_stop_queue function of the Linux kernel.
|
||||
*/
|
||||
virtual void Stop (void);
|
||||
|
||||
/**
|
||||
* Called by the device to wake the queue disc associated with this
|
||||
* (hardware) transmission queue. This is done by invoking the wake callback.
|
||||
* This is the analogous to the netif_tx_wake_queue function of the Linux kernel.
|
||||
*/
|
||||
virtual void Wake (void);
|
||||
|
||||
/**
|
||||
* \brief Get the status of the device transmission queue.
|
||||
* \return true if the (hardware) transmission queue is stopped.
|
||||
*
|
||||
* Called by queue discs to enquire about the status of a given transmission queue.
|
||||
* This is the analogous to the netif_tx_queue_stopped function of the Linux kernel.
|
||||
*/
|
||||
bool IsStopped (void) const;
|
||||
|
||||
/// Callback invoked by netdevices to wake upper layers
|
||||
typedef Callback< void > WakeCallback;
|
||||
|
||||
/**
|
||||
* \brief Set the wake callback
|
||||
* \param cb the callback to set
|
||||
*
|
||||
* Called by the traffic control layer to set the wake callback. The wake callback
|
||||
* is invoked by the device whenever it is needed to "wake" the upper layers (i.e.,
|
||||
* solicitate the queue disc associated with this transmission queue (in case of
|
||||
* multi-queue aware queue discs) or to the network device (otherwise) to send
|
||||
* packets down to the device).
|
||||
*/
|
||||
virtual void SetWakeCallback (WakeCallback cb);
|
||||
|
||||
/**
|
||||
* \brief Check whether a wake callback has been set on this device queue.
|
||||
* \return true if the wake callback has been set.
|
||||
*/
|
||||
virtual bool HasWakeCallbackSet (void) const;
|
||||
|
||||
private:
|
||||
bool m_stopped; //!< Status of the transmission queue
|
||||
WakeCallback m_wakeCallback; //!< Wake callback
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \ingroup netdevice
|
||||
*
|
||||
* \brief Network device transmission queue interface
|
||||
*
|
||||
* This interface is required by the traffic control layer to access the information
|
||||
* about the status of the transmission queues of a device. Thus, every NetDevice
|
||||
* (but loopback) needs to create this interface. NetDevices supporting flow control
|
||||
* can start and stop their device transmission queues and wake the upper layers through
|
||||
* this interface. By default, a NetDeviceQueueInterface object is created with a single
|
||||
* device transmission queue. Therefore, multi-queue devices need to call SetTxQueuesN
|
||||
* to create additional queues (before a root queue disc is installed, i.e., typically
|
||||
* before an IPv4/IPv6 address is assigned to the device), implement a GetSelectedQueue
|
||||
* method and pass a callback to such a method through the SetSelectedQueueCallback method.
|
||||
*/
|
||||
class NetDeviceQueueInterface : public Object
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* \brief Get the type ID.
|
||||
* \return the object TypeId
|
||||
*/
|
||||
static TypeId GetTypeId (void);
|
||||
|
||||
/**
|
||||
* \brief Constructor
|
||||
*
|
||||
* Creates one NetDeviceQueue by default
|
||||
*/
|
||||
NetDeviceQueueInterface ();
|
||||
virtual ~NetDeviceQueueInterface ();
|
||||
|
||||
/**
|
||||
* \brief Get the i-th transmission queue of the device.
|
||||
* \return the i-th transmission queue of the device.
|
||||
*
|
||||
* The index of the first transmission queue is zero.
|
||||
*/
|
||||
Ptr<NetDeviceQueue> GetTxQueue (uint8_t i) const;
|
||||
|
||||
/**
|
||||
* \brief Get the number of device transmission queues.
|
||||
* \return the number of device transmission queues.
|
||||
*/
|
||||
uint8_t GetTxQueuesN (void) const;
|
||||
|
||||
/**
|
||||
* \brief Set the number of device transmission queues.
|
||||
* \param numTxQueues number of device transmission queues.
|
||||
*
|
||||
* Called by a device to set the number of device transmission queues.
|
||||
* This method can be called by a NetDevice at initialization time only, because
|
||||
* it is not possible to change the number of device transmission queues after
|
||||
* the wake callbacks have been set on the device queues.
|
||||
*/
|
||||
void SetTxQueuesN (uint8_t numTxQueues);
|
||||
|
||||
/// Callback invoked to determine the tx queue selected for a given packet
|
||||
typedef Callback< uint8_t, Ptr<QueueItem> > SelectQueueCallback;
|
||||
|
||||
/**
|
||||
* \brief Set the select queue callback
|
||||
* \param cb the callback to set
|
||||
*
|
||||
* Called by a device to set the select queue callback, i.e., the method used
|
||||
* to select a device transmission queue for a given packet
|
||||
*/
|
||||
void SetSelectQueueCallback (SelectQueueCallback cb);
|
||||
|
||||
/**
|
||||
* \brief Get the id of the transmission queue selected for the given packet
|
||||
* \return the id of the transmission queue selected for the given packet
|
||||
*
|
||||
* Called by the traffic control when it needs to determine which device
|
||||
* transmission queue a given packet must be enqueued into. This function
|
||||
* calls the select queue callback, if set by the device. Return 0 otherwise.
|
||||
*/
|
||||
uint8_t GetSelectedQueue (Ptr<QueueItem> item) const;
|
||||
|
||||
/**
|
||||
* \brief Return true if a queue disc is installed on the device.
|
||||
* \return true if a queue disc is installed on the device.
|
||||
*/
|
||||
bool IsQueueDiscInstalled (void) const;
|
||||
|
||||
/**
|
||||
* \brief Set the member variable indicating whether a queue disc is installed or not
|
||||
* \param installed the value for the member variable indicating whether a queue disc is installed or not
|
||||
*/
|
||||
void SetQueueDiscInstalled (bool installed);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* \brief Dispose of the object
|
||||
*/
|
||||
virtual void DoDispose (void);
|
||||
|
||||
private:
|
||||
std::vector< Ptr<NetDeviceQueue> > m_txQueuesVector; //!< Device transmission queues
|
||||
SelectQueueCallback m_selectQueueCallback; //!< Select queue callback
|
||||
bool m_queueDiscInstalled; //!< Boolean value indicating whether a queue disc is installed or not
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \ingroup netdevice
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user