From deb08d9d21792471be98be870aff3bf5b149b35d Mon Sep 17 00:00:00 2001 From: Avakash Bhat Date: Mon, 1 Jun 2020 18:09:09 +0530 Subject: [PATCH] traffic-control: (closes !209) Add option for set associative hash (with contributions from Stefano Avallone) --- .../model/fq-codel-queue-disc.cc | 62 ++++++++++++++++++- .../model/fq-codel-queue-disc.h | 13 ++++ 2 files changed, 72 insertions(+), 3 deletions(-) diff --git a/src/traffic-control/model/fq-codel-queue-disc.cc b/src/traffic-control/model/fq-codel-queue-disc.cc index 44479cfd1..4d8053136 100644 --- a/src/traffic-control/model/fq-codel-queue-disc.cc +++ b/src/traffic-control/model/fq-codel-queue-disc.cc @@ -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 ()) ; 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 (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 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 item) if (ret != PacketFilter::PF_NO_MATCH) { - h = ret % m_flows; + flowHash = static_cast (ret); } else { @@ -209,6 +248,15 @@ FqCoDelQueueDisc::DoEnqueue (Ptr item) } } + if (m_enableSetAssociativeHash) + { + h = SetAssociativeHash (flowHash); + } + else + { + h = flowHash % m_flows; + } + Ptr 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 + diff --git a/src/traffic-control/model/fq-codel-queue-disc.h b/src/traffic-control/model/fq-codel-queue-disc.h index ce26e79c4..c2820ac89 100644 --- a/src/traffic-control/model/fq-codel-queue-disc.h +++ b/src/traffic-control/model/fq-codel-queue-disc.h @@ -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 > m_newFlows; //!< The list of new flows std::list > m_oldFlows; //!< The list of old flows std::map m_flowsIndices; //!< Map with the index of class for each flow + std::map 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 */ +