traffic-control: (closes !209) Add option for set associative hash (with contributions from Stefano Avallone)

This commit is contained in:
Avakash Bhat
2020-06-01 18:09:09 +05:30
committed by Tom Henderson
parent cd906e1c12
commit deb08d9d21
2 changed files with 72 additions and 3 deletions

View File

@@ -153,6 +153,16 @@ TypeId FqCoDelQueueDisc::GetTypeId (void)
TimeValue (Time::Max ()),
MakeTimeAccessor (&FqCoDelQueueDisc::m_ceThreshold),
MakeTimeChecker ())
.AddAttribute ("EnableSetAssociativeHash",
"Enable/Disable Set Associative Hash",
BooleanValue (false),
MakeBooleanAccessor (&FqCoDelQueueDisc::m_enableSetAssociativeHash),
MakeBooleanChecker ())
.AddAttribute ("SetWays",
"The size of a set of queues (used by set associative hash)",
UintegerValue (8),
MakeUintegerAccessor (&FqCoDelQueueDisc::m_setWays),
MakeUintegerChecker<uint32_t> ())
;
return tid;
}
@@ -182,16 +192,45 @@ FqCoDelQueueDisc::GetQuantum (void) const
return m_quantum;
}
uint32_t
FqCoDelQueueDisc::SetAssociativeHash (uint32_t flowHash)
{
NS_LOG_FUNCTION (this << flowHash);
uint32_t h = (flowHash % m_flows);
uint32_t innerHash = h % m_setWays;
uint32_t outerHash = h - innerHash;
for (uint32_t i = outerHash; i < outerHash + m_setWays; i++)
{
auto it = m_flowsIndices.find (i);
if (it == m_flowsIndices.end ()
|| (m_tags.find (i) != m_tags.end () && m_tags[i] == flowHash)
|| StaticCast<FqCoDelFlow> (GetQueueDiscClass (it->second))->GetStatus () == FqCoDelFlow::INACTIVE)
{
// this queue has not been created yet or is associated with this flow
// or is inactive, hence we can use it
m_tags[i] = flowHash;
return i;
}
}
// all the queues of the set are used. Use the first queue of the set
m_tags[outerHash] = flowHash;
return outerHash;
}
bool
FqCoDelQueueDisc::DoEnqueue (Ptr<QueueDiscItem> item)
{
NS_LOG_FUNCTION (this << item);
uint32_t h = 0;
uint32_t flowHash, h;
if (GetNPacketFilters () == 0)
{
h = item->Hash (m_perturbation) % m_flows;
flowHash = item->Hash (m_perturbation);
}
else
{
@@ -199,7 +238,7 @@ FqCoDelQueueDisc::DoEnqueue (Ptr<QueueDiscItem> item)
if (ret != PacketFilter::PF_NO_MATCH)
{
h = ret % m_flows;
flowHash = static_cast<uint32_t> (ret);
}
else
{
@@ -209,6 +248,15 @@ FqCoDelQueueDisc::DoEnqueue (Ptr<QueueDiscItem> item)
}
}
if (m_enableSetAssociativeHash)
{
h = SetAssociativeHash (flowHash);
}
else
{
h = flowHash % m_flows;
}
Ptr<FqCoDelFlow> flow;
if (m_flowsIndices.find (h) == m_flowsIndices.end ())
{
@@ -374,6 +422,13 @@ FqCoDelQueueDisc::CheckConfig (void)
}
}
if (m_enableSetAssociativeHash && (m_flows % m_setWays != 0))
{
NS_LOG_ERROR ("The number of queues must be an integer multiple of the size "
"of the set of queues used by set associative hash");
return false;
}
return true;
}
@@ -427,3 +482,4 @@ FqCoDelQueueDisc::FqCoDelDrop (void)
}
} // namespace ns3

View File

@@ -154,18 +154,30 @@ private:
uint32_t FqCoDelDrop (void);
bool m_useEcn; //!< True if ECN is used (packets are marked instead of being dropped)
/**
* Compute the index of the queue for the flow having the given flowHash,
* according to the set associative hash approach.
*
* \param flowHash the hash of the flow 5-tuple
* \return the index of the queue for the given flow
*/
uint32_t SetAssociativeHash (uint32_t flowHash);
std::string m_interval; //!< CoDel interval attribute
std::string m_target; //!< CoDel target attribute
uint32_t m_quantum; //!< Deficit assigned to flows at each round
uint32_t m_flows; //!< Number of flow queues
uint32_t m_setWays; //!< size of a set of queues (used by set associative hash)
uint32_t m_dropBatchSize; //!< Max number of packets dropped from the fat flow
uint32_t m_perturbation; //!< hash perturbation value
Time m_ceThreshold; //!< Threshold above which to CE mark
bool m_enableSetAssociativeHash; //!< whether to enable set associative hash
std::list<Ptr<FqCoDelFlow> > m_newFlows; //!< The list of new flows
std::list<Ptr<FqCoDelFlow> > m_oldFlows; //!< The list of old flows
std::map<uint32_t, uint32_t> m_flowsIndices; //!< Map with the index of class for each flow
std::map<uint32_t, uint32_t> m_tags; //!< Tags used by set associative hash
ObjectFactory m_flowFactory; //!< Factory to create a new flow
ObjectFactory m_queueDiscFactory; //!< Factory to create a new queue
@@ -174,3 +186,4 @@ private:
} // namespace ns3
#endif /* FQ_CODEL_QUEUE_DISC */