From 0273d706b04349b767c0afd596ab8fefc8b50f28 Mon Sep 17 00:00:00 2001 From: Natale Patriciello Date: Wed, 24 Oct 2018 10:38:03 +0200 Subject: [PATCH] lte: EpsBearer uses a lookup table Moving the existing switch/cases statement to a lookup in a lookup-table, created with an unordered_map at compile time. The default values for the lookup table are taken from Rel. 11, as they were in previous ns-3 releases. --- src/lte/model/eps-bearer.cc | 129 ++++++++++-------------------------- src/lte/model/eps-bearer.h | 111 ++++++++++++++++++++++++++++--- 2 files changed, 137 insertions(+), 103 deletions(-) diff --git a/src/lte/model/eps-bearer.cc b/src/lte/model/eps-bearer.cc index aa3c47e81..7782f52d7 100644 --- a/src/lte/model/eps-bearer.cc +++ b/src/lte/model/eps-bearer.cc @@ -45,131 +45,74 @@ AllocationRetentionPriority::AllocationRetentionPriority () EpsBearer::EpsBearer () : qci (NGBR_VIDEO_TCP_DEFAULT) { + m_requirements = GetRequirementsRel11 (); } EpsBearer::EpsBearer (Qci x) : qci (x) { + m_requirements = GetRequirementsRel11 (); } EpsBearer::EpsBearer (Qci x, struct GbrQosInformation y) : qci (x), gbrQosInfo (y) { + m_requirements = GetRequirementsRel11 (); } bool EpsBearer::IsGbr () const { - // 3GPP 23.203 Section 6.1.7.2 - switch (qci) - { - case GBR_CONV_VOICE: - case GBR_CONV_VIDEO: - case GBR_GAMING: - case GBR_NON_CONV_VIDEO: - return true; - case NGBR_IMS: - case NGBR_VIDEO_TCP_OPERATOR: - case NGBR_VOICE_VIDEO_GAMING: - case NGBR_VIDEO_TCP_PREMIUM: - case NGBR_VIDEO_TCP_DEFAULT: - return false; - default: - NS_FATAL_ERROR ("unknown QCI value " << qci); - return false; - } + return IsGbr (m_requirements, qci); } uint8_t EpsBearer::GetPriority () const { - // 3GPP 23.203 Section 6.1.7.2 - switch (qci) - { - case GBR_CONV_VOICE: - return 2; - case GBR_CONV_VIDEO: - return 4; - case GBR_GAMING: - return 3; - case GBR_NON_CONV_VIDEO: - return 5; - case NGBR_IMS: - return 1; - case NGBR_VIDEO_TCP_OPERATOR: - return 6; - case NGBR_VOICE_VIDEO_GAMING: - return 7; - case NGBR_VIDEO_TCP_PREMIUM: - return 8; - case NGBR_VIDEO_TCP_DEFAULT: - return 9; - default: - NS_FATAL_ERROR ("unknown QCI value " << qci); - return 0; - } + return GetPriority (m_requirements, qci); } uint16_t EpsBearer::GetPacketDelayBudgetMs () const { - // 3GPP 23.203 Section 6.1.7.2 - switch (qci) - { - case GBR_CONV_VOICE: - return 100; - case GBR_CONV_VIDEO: - return 150; - case GBR_GAMING: - return 50; - case GBR_NON_CONV_VIDEO: - return 300; - case NGBR_IMS: - return 100; - case NGBR_VIDEO_TCP_OPERATOR: - return 300; - case NGBR_VOICE_VIDEO_GAMING: - return 100; - case NGBR_VIDEO_TCP_PREMIUM: - return 300; - case NGBR_VIDEO_TCP_DEFAULT: - return 300; - default: - NS_FATAL_ERROR ("unknown QCI value " << qci); - return 0; - } + return GetPacketDelayBudgetMs (m_requirements, qci); } double EpsBearer::GetPacketErrorLossRate () const { - // 3GPP 23.203 Section 6.1.7.2 - switch (qci) - { - case GBR_CONV_VOICE: - return 1.0e-2; - case GBR_CONV_VIDEO: - return 1.0e-3; - case GBR_GAMING: - return 1.0e-3; - case GBR_NON_CONV_VIDEO: - return 1.0e-6; - case NGBR_IMS: - return 1.0e-6; - case NGBR_VIDEO_TCP_OPERATOR: - return 1.0e-6; - case NGBR_VOICE_VIDEO_GAMING: - return 1.0e-3; - case NGBR_VIDEO_TCP_PREMIUM: - return 1.0e-6; - case NGBR_VIDEO_TCP_DEFAULT: - return 1.0e-6; - default: - NS_FATAL_ERROR ("unknown QCI value " << qci); - return 0; - } + return GetPacketErrorLossRate (m_requirements, qci); } +EpsBearer::BearerRequirementsMap +EpsBearer::GetRequirementsRel11 () +{ + /* Needed to support GCC 4.9. Otherwise, use list constructors, for example: + * EpsBearer::BearerRequirementsMap + * EpsBearer::GetRequirementsRel15 () + * { + * return + * { + * { GBR_CONV_VOICE , { true, 20, 100, 1.0e-2, 0, 2000} }, + * ... + * }; + * } + */ + static EpsBearer::BearerRequirementsMap ret; + if (ret.size () == 0) + { + ret.insert (std::make_pair (GBR_CONV_VOICE, std::make_tuple (true, 2, 100, 1.0e-2, 0, 0))); + ret.insert (std::make_pair (GBR_CONV_VIDEO, std::make_tuple (true, 4, 150, 1.0e-3, 0, 0))); + ret.insert (std::make_pair (GBR_GAMING, std::make_tuple (true, 3, 50, 1.0e-3, 0, 0))); + ret.insert (std::make_pair (GBR_NON_CONV_VIDEO, std::make_tuple (true, 5, 300, 1.0e-6, 0, 0))); + ret.insert (std::make_pair (NGBR_IMS, std::make_tuple (false, 1, 100, 1.0e-6, 0, 0))); + ret.insert (std::make_pair (NGBR_VIDEO_TCP_OPERATOR, std::make_tuple (false, 6, 300, 1.0e-6, 0, 0))); + ret.insert (std::make_pair (NGBR_VOICE_VIDEO_GAMING, std::make_tuple (false, 7, 100, 1.0e-3, 0, 0))); + ret.insert (std::make_pair (NGBR_VIDEO_TCP_PREMIUM, std::make_tuple (false, 8, 300, 1.0e-6, 0, 0))); + ret.insert (std::make_pair (NGBR_VIDEO_TCP_DEFAULT, std::make_tuple (false, 9, 300, 1.0e-6, 0, 0))); + } + return ret; +} } // namespace ns3 diff --git a/src/lte/model/eps-bearer.h b/src/lte/model/eps-bearer.h index c0bb27d58..72521e8fa 100644 --- a/src/lte/model/eps-bearer.h +++ b/src/lte/model/eps-bearer.h @@ -23,6 +23,7 @@ #define EPS_BEARER #include +#include namespace ns3 { @@ -73,18 +74,19 @@ struct EpsBearer /** * QoS Class Indicator. See 3GPP 23.203 Section 6.1.7.2 for standard values. + * Updated to Release 15. */ - enum Qci + enum Qci : uint8_t { - GBR_CONV_VOICE = 1, - GBR_CONV_VIDEO = 2, - GBR_GAMING = 3, - GBR_NON_CONV_VIDEO = 4, - NGBR_IMS = 5, - NGBR_VIDEO_TCP_OPERATOR = 6, - NGBR_VOICE_VIDEO_GAMING = 7, - NGBR_VIDEO_TCP_PREMIUM = 8, - NGBR_VIDEO_TCP_DEFAULT = 9, + GBR_CONV_VOICE = 1, ///< GBR Conversational Voice + GBR_CONV_VIDEO = 2, ///< GBR Conversational Video (Live streaming) + GBR_GAMING = 3, ///< GBR Real Time Gaming + GBR_NON_CONV_VIDEO = 4, ///< GBR Non-Conversational Video (Buffered Streaming) + NGBR_IMS = 5, ///< Non-GBR IMS Signalling + NGBR_VIDEO_TCP_OPERATOR = 6, ///< Non-GBR TCP-based Video (Buffered Streaming, e.g., www, e-mail...) + NGBR_VOICE_VIDEO_GAMING = 7, ///< Non-GBR Voice, Video, Interactive Streaming + NGBR_VIDEO_TCP_PREMIUM = 8, ///< Non-GBR TCP-based Video (Buffered Streaming, e.g., www, e-mail...) + NGBR_VIDEO_TCP_DEFAULT = 9, ///< Non-GBR TCP-based Video (Buffered Streaming, e.g., www, e-mail...) } qci; ///< Qos class indicator GbrQosInformation gbrQosInfo; ///< GBR QOS information @@ -139,6 +141,95 @@ struct EpsBearer */ double GetPacketErrorLossRate () const; +private: + /** + * \brief Hashing QCI + * + * Qci are just uint8_t, so that's how we calculate the hash. Unfortunately, + * we have to provide this struct because gcc 4.9 would not compile otherwise. + */ + struct QciHash + { + /** + * \brief Hash the QCI like a normal uint8_t + * \param s Qci to hash + * \return Hash of Qci + */ + std::size_t + operator () (Qci const& s) const noexcept + { + return std::hash {} (s); + } + }; + + /** + * \brief Map between QCI and requirements + * + * The tuple is formed by: isGbr, priority, packet delay budget, packet error rate, + * default maximum data burst, default averaging window (0 when does not apply) + */ + typedef std::unordered_map, QciHash > BearerRequirementsMap; + + /** + * \brief Is the selected QCI GBR? + * \param map Map between QCI and requirements + * \param qci QCI to look for + * \return GBR flag for the selected CQI + */ + static uint32_t + IsGbr (const BearerRequirementsMap &map, Qci qci) {return std::get<0> (map.at (qci));} + + /** + * \brief Get priority for the selected QCI + * \param map Map between QCI and requirements + * \param qci QCI to look for + * \return priority for the selected QCI + */ + static uint8_t + GetPriority (const BearerRequirementsMap &map, Qci qci) {return std::get<1> (map.at (qci));} + /** + * \brief Get packet delay in ms for the selected QCI + * \param map Map between QCI and requirements + * \param qci QCI to look for + * \return packet delay in ms for the selected QCI + */ + static uint16_t + GetPacketDelayBudgetMs (const BearerRequirementsMap &map, Qci qci) {return std::get<2> (map.at (qci));} + /** + * \brief Get packet error rate for the selected QCI + * \param map Map between QCI and requirements + * \param qci QCI to look for + * \return packet error rate for the selected QCI + */ + static double + GetPacketErrorLossRate (const BearerRequirementsMap &map, Qci qci) {return std::get<3> (map.at (qci));} + /** + * \brief Get maximum data burst for the selected QCI + * \param map Map between QCI and requirements + * \param qci QCI to look for + * \return maximum data burst for the selected QCI + */ + static uint32_t + GetMaxDataBurst (const BearerRequirementsMap &map, Qci qci) {return std::get<4> (map.at (qci));} + /** + * \brief Get default averaging window for the selected QCI + * \param map Map between QCI and requirements + * \param qci QCI to look for + * \return default averaging window for the selected QCI + */ + static uint32_t + GetAvgWindow (const BearerRequirementsMap &map, Qci qci) {return std::get<5> (map.at (qci));} + + /** + * \brief Retrieve requirements for Rel. 11 + * \return the BearerRequirementsMap for Release 11 + */ + static BearerRequirementsMap GetRequirementsRel11 (); + + /** + * \brief Requirements per bearer + */ + BearerRequirementsMap m_requirements; }; } // namespace ns3