From 7b27eadbd77c26a2675e220cdfe1db4fe3574938 Mon Sep 17 00:00:00 2001 From: Bryan Biedenkapp Date: Fri, 20 Sep 2024 15:01:34 -0400 Subject: [PATCH] correct issue where DMR would round-robin assign slots for TGs, instead ensure available channel resources for the request slot exist and grant or queue accordingly; add some experimental support to generate a CSBK grant from network traffic if the destination ID hasn't already been granted; --- src/host/dmr/Control.cpp | 10 ++++ src/host/dmr/lookups/DMRAffiliationLookup.cpp | 57 ++++++++++++++++--- src/host/dmr/lookups/DMRAffiliationLookup.h | 6 ++ src/host/dmr/packet/ControlSignaling.cpp | 17 ++++-- src/host/dmr/packet/ControlSignaling.h | 1 + 5 files changed, 78 insertions(+), 13 deletions(-) diff --git a/src/host/dmr/Control.cpp b/src/host/dmr/Control.cpp index 05030690..ba30ac4d 100644 --- a/src/host/dmr/Control.cpp +++ b/src/host/dmr/Control.cpp @@ -712,6 +712,16 @@ void Control::processNetwork() data.setN(n); } + // are we TSCC enabled? + if (m_enableTSCC) { + Slot* tscc = getTSCCSlot(); + if (tscc != nullptr) { + if (!tscc->m_affiliations->isGranted(dstId)) { + tscc->m_control->writeRF_CSBK_Grant(srcId, dstId, 4U, (flco == FLCO::GROUP) ? true : false, true); + } + } + } + // forward onto the specific slot for final processing and delivery switch (slotNo) { case 1U: diff --git a/src/host/dmr/lookups/DMRAffiliationLookup.cpp b/src/host/dmr/lookups/DMRAffiliationLookup.cpp index 4c717e9b..9791fa61 100644 --- a/src/host/dmr/lookups/DMRAffiliationLookup.cpp +++ b/src/host/dmr/lookups/DMRAffiliationLookup.cpp @@ -36,14 +36,8 @@ DMRAffiliationLookup::~DMRAffiliationLookup() = default; bool DMRAffiliationLookup::grantCh(uint32_t dstId, uint32_t srcId, uint32_t grantTimeout, bool grp, bool netGranted) { - uint32_t chNo = m_chLookup->getFirstRFChannel(); - uint8_t slot = getAvailableSlotForChannel(chNo); - - if (slot == 0U) { - return false; - } - - return grantChSlot(dstId, srcId, slot, grantTimeout, grp, netGranted); + ::LogDebug(LOG_HOST, "%s, DMRAffiliationLookup::grantCh() use grantChSlot() BUGBUG"); + return false; } /* Helper to grant a channel and slot. */ @@ -58,7 +52,11 @@ bool DMRAffiliationLookup::grantChSlot(uint32_t dstId, uint32_t srcId, uint8_t s return false; } - uint32_t chNo = m_chLookup->getFirstRFChannel(); + uint32_t chNo = getAvailableChannelForSlot(slot); + if (chNo == 0U) { + return false; + } + if (chNo == m_tsccChNo && slot == m_tsccSlot) { return false; } @@ -212,6 +210,47 @@ void DMRAffiliationLookup::setSlotForChannelTSCC(uint32_t chNo, uint8_t slot) m_tsccSlot = slot; } +/* Helper to determine the an available channel for a slot. */ + +uint32_t DMRAffiliationLookup::getAvailableChannelForSlot(uint8_t slot) const +{ + if (slot == 0U) { + return 0U; + } + + uint32_t chNo = 0U; + for (auto entry : m_chLookup->rfChDataTable()) { + if (entry.second.chNo() == m_tsccChNo && slot == m_tsccSlot) { + continue; + } else { + // lookup dynamic channel slot grant table entry + bool chAvailSlot = false; + for (auto gntEntry : m_grantChSlotTable) { + uint32_t foundChNo = std::get<0>(gntEntry.second); + if (foundChNo == entry.second.chNo()) { + uint8_t foundSlot = std::get<1>(gntEntry.second); + if (slot == foundSlot) + continue; + else { + chAvailSlot = true; + break; + } + } + } + + // if we have no granted channels -- return true + if (m_grantChSlotTable.size() == 0U) + chAvailSlot = true; + + chNo = entry.second.chNo(); + if (chAvailSlot) + break; + } + } + + return chNo; +} + /* Helper to determine the first available slot for given the channel number. */ uint8_t DMRAffiliationLookup::getAvailableSlotForChannel(uint32_t chNo) const diff --git a/src/host/dmr/lookups/DMRAffiliationLookup.h b/src/host/dmr/lookups/DMRAffiliationLookup.h index e182db86..90c85125 100644 --- a/src/host/dmr/lookups/DMRAffiliationLookup.h +++ b/src/host/dmr/lookups/DMRAffiliationLookup.h @@ -100,6 +100,12 @@ namespace dmr */ void setSlotForChannelTSCC(uint32_t chNo, uint8_t slot); + /** + * @brief Helper to determine the an available channel for a slot. + * @param chNo Channel Number. + */ + uint32_t getAvailableChannelForSlot(uint8_t slot) const; + /** * @brief Helper to determine the first available slot for given the channel number. * @param chNo Channel Number. diff --git a/src/host/dmr/packet/ControlSignaling.cpp b/src/host/dmr/packet/ControlSignaling.cpp index fa778713..dd3b1347 100644 --- a/src/host/dmr/packet/ControlSignaling.cpp +++ b/src/host/dmr/packet/ControlSignaling.cpp @@ -854,7 +854,11 @@ bool ControlSignaling::writeRF_CSBK_Grant(uint32_t srcId, uint32_t dstId, uint8_ } if (!m_tscc->m_affiliations->isGranted(dstId)) { - if (!m_tscc->m_affiliations->rfCh()->isRFChAvailable()) { + ::lookups::TalkgroupRuleGroupVoice groupVoice = m_tscc->m_tidLookup->find(dstId); + slot = groupVoice.source().tgSlot(); + + uint32_t availChNo = m_tscc->m_affiliations->getAvailableChannelForSlot(slot); + if (!m_tscc->m_affiliations->rfCh()->isRFChAvailable() || availChNo == 0U) { if (grp) { if (!net) { LogWarning(LOG_RF, "DMR Slot %u, CSBK, RAND (Random Access, GRP_VOICE_CALL (Group Voice Call) queued, no channels available, dstId = %u", m_tscc->m_slotNo, dstId); @@ -879,9 +883,10 @@ bool ControlSignaling::writeRF_CSBK_Grant(uint32_t srcId, uint32_t dstId, uint8_ } } else { - if (m_tscc->m_affiliations->grantCh(dstId, srcId, GRANT_TIMER_TIMEOUT, grp, net)) { + if (m_tscc->m_affiliations->grantChSlot(dstId, srcId, slot, GRANT_TIMER_TIMEOUT, grp, net)) { chNo = m_tscc->m_affiliations->getGrantedCh(dstId); slot = m_tscc->m_affiliations->getGrantedSlot(dstId); + LogDebug(LOG_RF, "DMR Slot %u, CSBK, RAND (Random Access, VOICE_CALL (Voice Call), chNo = %u, slot = %u, tsccChNo = %u", m_tscc->m_slotNo, chNo, slot, m_tscc->m_channelNo); //m_tscc->m_siteData.setChCnt(m_tscc->m_affiliations->getRFChCnt() + m_tscc->m_affiliations->getGrantedRFChCnt()); } } @@ -1136,7 +1141,11 @@ bool ControlSignaling::writeRF_CSBK_Data_Grant(uint32_t srcId, uint32_t dstId, u } if (!m_tscc->m_affiliations->isGranted(dstId)) { - if (!m_tscc->m_affiliations->rfCh()->isRFChAvailable()) { + ::lookups::TalkgroupRuleGroupVoice groupVoice = m_tscc->m_tidLookup->find(dstId); + slot = groupVoice.source().tgSlot(); + + uint32_t availChNo = m_tscc->m_affiliations->getAvailableChannelForSlot(slot); + if (!m_tscc->m_affiliations->rfCh()->isRFChAvailable() || availChNo == 0U) { if (grp) { if (!net) { LogWarning(LOG_RF, "DMR Slot %u, CSBK, RAND (Random Access, GRP_DATA_CALL (Group Data Call) queued, no channels available, dstId = %u", m_tscc->m_slotNo, dstId); @@ -1161,7 +1170,7 @@ bool ControlSignaling::writeRF_CSBK_Data_Grant(uint32_t srcId, uint32_t dstId, u } } else { - if (m_tscc->m_affiliations->grantCh(dstId, srcId, GRANT_TIMER_TIMEOUT, grp, net)) { + if (m_tscc->m_affiliations->grantChSlot(dstId, srcId, slot, GRANT_TIMER_TIMEOUT, grp, net)) { chNo = m_tscc->m_affiliations->getGrantedCh(dstId); slot = m_tscc->m_affiliations->getGrantedSlot(dstId); diff --git a/src/host/dmr/packet/ControlSignaling.h b/src/host/dmr/packet/ControlSignaling.h index cb8151f6..64a6806d 100644 --- a/src/host/dmr/packet/ControlSignaling.h +++ b/src/host/dmr/packet/ControlSignaling.h @@ -85,6 +85,7 @@ namespace dmr /** @} */ private: + friend class dmr::Control; friend class dmr::Slot; Slot* m_slot;