traffic-control: QueueDiscs do not assume that the receiving object is a NetDevice
This commit is contained in:
@@ -369,9 +369,7 @@ TrafficControlHelper::Install (Ptr<NetDevice> d)
|
||||
// Create queue discs (from leaves to root)
|
||||
for (auto i = m_queueDiscFactory.size (); i-- > 0; )
|
||||
{
|
||||
Ptr<QueueDisc> q = m_queueDiscFactory[i].CreateQueueDisc (m_queueDiscs);
|
||||
q->SetNetDevice (d);
|
||||
m_queueDiscs[i] = q;
|
||||
m_queueDiscs[i] = m_queueDiscFactory[i].CreateQueueDisc (m_queueDiscs);
|
||||
}
|
||||
|
||||
// Set the root queue disc (if any has been created) on the device
|
||||
|
||||
@@ -318,6 +318,27 @@ FqCoDelQueueDisc::CheckConfig (void)
|
||||
return false;
|
||||
}
|
||||
|
||||
// we are at initialization time. If the user has not set a quantum value,
|
||||
// set the quantum to the MTU of the device (if any)
|
||||
if (!m_quantum)
|
||||
{
|
||||
Ptr<NetDeviceQueueInterface> ndqi = GetNetDeviceQueueInterface ();
|
||||
Ptr<NetDevice> dev;
|
||||
// if the NetDeviceQueueInterface object is aggregated to a
|
||||
// NetDevice, get the MTU of such NetDevice
|
||||
if (ndqi && (dev = ndqi->GetObject<NetDevice> ()))
|
||||
{
|
||||
m_quantum = dev->GetMtu ();
|
||||
NS_LOG_DEBUG ("Setting the quantum to the MTU of the device: " << m_quantum);
|
||||
}
|
||||
|
||||
if (!m_quantum)
|
||||
{
|
||||
NS_LOG_ERROR ("The quantum parameter cannot be null");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -326,16 +347,6 @@ FqCoDelQueueDisc::InitializeParams (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
// we are at initialization time. If the user has not set a quantum value,
|
||||
// set the quantum to the MTU of the device
|
||||
if (!m_quantum)
|
||||
{
|
||||
Ptr<NetDevice> device = GetNetDevice ();
|
||||
NS_ASSERT_MSG (device, "Device not set for the queue disc");
|
||||
m_quantum = device->GetMtu ();
|
||||
NS_LOG_DEBUG ("Setting the quantum to the MTU of the device: " << m_quantum);
|
||||
}
|
||||
|
||||
m_flowFactory.SetTypeId ("ns3::FqCoDelFlow");
|
||||
|
||||
m_queueDiscFactory.SetTypeId ("ns3::CoDelQueueDisc");
|
||||
|
||||
@@ -384,9 +384,13 @@ QueueDisc::DoDispose (void)
|
||||
m_queues.clear ();
|
||||
m_filters.clear ();
|
||||
m_classes.clear ();
|
||||
m_device = 0;
|
||||
m_devQueueIface = 0;
|
||||
m_send = nullptr;
|
||||
m_requeued = 0;
|
||||
m_internalQueueDbeFunctor = nullptr;
|
||||
m_internalQueueDadFunctor = nullptr;
|
||||
m_childQueueDiscDbeFunctor = nullptr;
|
||||
m_childQueueDiscDadFunctor = nullptr;
|
||||
Object::DoDispose ();
|
||||
}
|
||||
|
||||
@@ -394,12 +398,6 @@ void
|
||||
QueueDisc::DoInitialize (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
// When adding a new interface, the traffic control aggregates
|
||||
// a NetDeviceQueueInterface object to the netdevice
|
||||
if (m_device)
|
||||
{
|
||||
m_devQueueIface = m_device->GetObject<NetDeviceQueueInterface> ();
|
||||
}
|
||||
|
||||
// Check the configuration and initialize the parameters of this queue disc
|
||||
bool ok = CheckConfig ();
|
||||
@@ -536,17 +534,31 @@ QueueDisc::GetCurrentSize (void)
|
||||
}
|
||||
|
||||
void
|
||||
QueueDisc::SetNetDevice (Ptr<NetDevice> device)
|
||||
QueueDisc::SetNetDeviceQueueInterface (Ptr<NetDeviceQueueInterface> ndqi)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << device);
|
||||
m_device = device;
|
||||
NS_LOG_FUNCTION (this << ndqi);
|
||||
m_devQueueIface = ndqi;
|
||||
}
|
||||
|
||||
Ptr<NetDevice>
|
||||
QueueDisc::GetNetDevice (void) const
|
||||
Ptr<NetDeviceQueueInterface>
|
||||
QueueDisc::GetNetDeviceQueueInterface (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return m_device;
|
||||
return m_devQueueIface;
|
||||
}
|
||||
|
||||
void
|
||||
QueueDisc::SetSendCallback (SendCallback func)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_send = func;
|
||||
}
|
||||
|
||||
QueueDisc::SendCallback
|
||||
QueueDisc::GetSendCallback (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return m_send;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1073,7 +1085,8 @@ QueueDisc::Transmit (Ptr<QueueDiscItem> item)
|
||||
SocketPriorityTag priorityTag;
|
||||
item->GetPacket ()->RemovePacketTag (priorityTag);
|
||||
}
|
||||
m_device->Send (item->GetPacket (), item->GetAddress (), item->GetProtocol ());
|
||||
NS_ASSERT_MSG (m_send, "Send callback not set");
|
||||
m_send (item);
|
||||
|
||||
// the behavior here slightly diverges from Linux. In Linux, it is advised that
|
||||
// the function called when a packet needs to be transmitted (ndo_start_xmit)
|
||||
|
||||
@@ -339,16 +339,39 @@ public:
|
||||
const Stats& GetStats (void);
|
||||
|
||||
/**
|
||||
* \brief Set the NetDevice on which this queue discipline is installed.
|
||||
* \param device the NetDevice on which this queue discipline is installed.
|
||||
* \param ndqi the NetDeviceQueueInterface aggregated to the receiving object.
|
||||
*
|
||||
* Set the pointer to the NetDeviceQueueInterface object aggregated to the
|
||||
* object receiving the packets dequeued from this queue disc.
|
||||
*/
|
||||
void SetNetDevice (Ptr<NetDevice> device);
|
||||
void SetNetDeviceQueueInterface (Ptr<NetDeviceQueueInterface> ndqi);
|
||||
|
||||
/**
|
||||
* \brief Get the NetDevice on which this queue discipline is installed
|
||||
* \return the NetDevice on which this queue discipline is installed.
|
||||
* \return the NetDeviceQueueInterface aggregated to the receiving object.
|
||||
*
|
||||
* Get the pointer to the NetDeviceQueueInterface object aggregated to the
|
||||
* object receiving the packets dequeued from this queue disc.
|
||||
*/
|
||||
Ptr<NetDevice> GetNetDevice (void) const;
|
||||
Ptr<NetDeviceQueueInterface> GetNetDeviceQueueInterface (void) const;
|
||||
|
||||
/// Callback invoked to send a packet to the receiving object when Run is called
|
||||
typedef std::function<void (Ptr<QueueDiscItem>)> SendCallback;
|
||||
|
||||
/**
|
||||
* \param func the callback to send a packet to the receiving object.
|
||||
*
|
||||
* Set the callback used by the Transmit method (called eventually by the Run
|
||||
* method) to send a packet to the receiving object.
|
||||
*/
|
||||
void SetSendCallback (SendCallback func);
|
||||
|
||||
/**
|
||||
* \return the callback to send a packet to the receiving object.
|
||||
*
|
||||
* Get the callback used by the Transmit method (called eventually by the Run
|
||||
* method) to send a packet to the receiving object.
|
||||
*/
|
||||
SendCallback GetSendCallback (void) const;
|
||||
|
||||
/**
|
||||
* \brief Set the maximum number of dequeue operations following a packet enqueue
|
||||
@@ -671,8 +694,8 @@ private:
|
||||
|
||||
Stats m_stats; //!< The collected statistics
|
||||
uint32_t m_quota; //!< Maximum number of packets dequeued in a qdisc run
|
||||
Ptr<NetDevice> m_device; //!< The NetDevice on which this queue discipline is installed
|
||||
Ptr<NetDeviceQueueInterface> m_devQueueIface; //!< NetDevice queue interface
|
||||
SendCallback m_send; //!< Callback used to send a packet to the receiving object
|
||||
bool m_running; //!< The queue disc is performing multiple dequeue operations
|
||||
Ptr<QueueDiscItem> m_requeued; //!< The last packet that failed to be transmitted
|
||||
bool m_peeked; //!< A packet was dequeued because Peek was called
|
||||
|
||||
@@ -62,7 +62,7 @@ TypeId TbfQueueDisc::GetTypeId (void)
|
||||
MakeUintegerChecker<uint32_t> ())
|
||||
.AddAttribute ("Mtu",
|
||||
"Size of the second bucket in bytes. If null, it is initialized"
|
||||
" to the MTU of the attached NetDevice (if any)",
|
||||
" to the MTU of the receiving NetDevice (if any)",
|
||||
UintegerValue (0),
|
||||
MakeUintegerAccessor (&TbfQueueDisc::SetMtu),
|
||||
MakeUintegerChecker<uint32_t> ())
|
||||
@@ -310,9 +310,16 @@ TbfQueueDisc::CheckConfig (void)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_mtu == 0 && GetNetDevice ())
|
||||
if (m_mtu == 0)
|
||||
{
|
||||
m_mtu = GetNetDevice ()->GetMtu ();
|
||||
Ptr<NetDeviceQueueInterface> ndqi = GetNetDeviceQueueInterface ();
|
||||
Ptr<NetDevice> dev;
|
||||
// if the NetDeviceQueueInterface object is aggregated to a
|
||||
// NetDevice, get the MTU of such NetDevice
|
||||
if (ndqi && (dev = ndqi->GetObject<NetDevice> ()))
|
||||
{
|
||||
m_mtu = dev->GetMtu ();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_mtu == 0 && m_peakRate > DataRate ("0bps"))
|
||||
|
||||
@@ -178,6 +178,15 @@ TrafficControlLayer::ScanDevices (void)
|
||||
{
|
||||
ndi->second.m_queueDiscsToWake.push_back (ndi->second.m_rootQueueDisc);
|
||||
}
|
||||
|
||||
// set the NetDeviceQueueInterface object and the SendCallback on the queue discs
|
||||
// into which packets are enqueued and dequeued by calling Run
|
||||
for (auto& q : ndi->second.m_queueDiscsToWake)
|
||||
{
|
||||
q->SetNetDeviceQueueInterface (ndqi);
|
||||
q->SetSendCallback ([dev] (Ptr<QueueDiscItem> item)
|
||||
{ dev->Send (item->GetPacket (), item->GetAddress (), item->GetProtocol ()); });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -237,6 +246,11 @@ TrafficControlLayer::DeleteRootQueueDiscOnDevice (Ptr<NetDevice> device)
|
||||
|
||||
// remove the root queue disc
|
||||
ndi->second.m_rootQueueDisc = 0;
|
||||
for (auto& q : ndi->second.m_queueDiscsToWake)
|
||||
{
|
||||
q->SetNetDeviceQueueInterface (nullptr);
|
||||
q->SetSendCallback (nullptr);
|
||||
}
|
||||
ndi->second.m_queueDiscsToWake.clear ();
|
||||
|
||||
Ptr<NetDeviceQueueInterface> ndqi = ndi->second.m_ndqi;
|
||||
|
||||
@@ -287,7 +287,6 @@ TbfQueueDiscTestCase::RunTbfTest (QueueSizeUnit mode)
|
||||
|
||||
Ptr<TrafficControlLayer> tcA = CreateObject<TrafficControlLayer> ();
|
||||
nodesA.Get (0)->AggregateObject (tcA);
|
||||
queue->SetNetDevice (txDevA);
|
||||
tcA->SetRootQueueDiscOnDevice (txDevA, queue);
|
||||
tcA->Initialize ();
|
||||
|
||||
@@ -361,7 +360,6 @@ TbfQueueDiscTestCase::RunTbfTest (QueueSizeUnit mode)
|
||||
|
||||
Ptr<TrafficControlLayer> tcB = CreateObject<TrafficControlLayer> ();
|
||||
nodesB.Get (0)->AggregateObject (tcB);
|
||||
queue->SetNetDevice (txDevB);
|
||||
tcB->SetRootQueueDiscOnDevice (txDevB, queue);
|
||||
tcB->Initialize ();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user