traffic-control: QueueDiscs do not assume that the receiving object is a NetDevice

This commit is contained in:
Stefano Avallone
2018-09-18 15:50:15 +02:00
parent 1abd8331b8
commit d4f5759959
7 changed files with 103 additions and 39 deletions

View File

@@ -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

View File

@@ -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");

View File

@@ -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)

View File

@@ -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

View File

@@ -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"))

View File

@@ -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;

View File

@@ -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 ();