From bed079f68e401b0f58772cf73b82599922b4d0af Mon Sep 17 00:00:00 2001 From: Bryan Biedenkapp Date: Tue, 11 Jul 2023 21:49:04 -0400 Subject: [PATCH] implement a fixed internal TG hangtimer for network traffic, this will put a hold on the last received TG for 2 seconds; refactor how P25 handles simultaneous calls from the network and how RF preemption of in-progress network calls when RF wants to transmit on a different TG works; --- src/dmr/Slot.cpp | 25 +++++++ src/dmr/Slot.h | 1 + src/dmr/packet/Voice.cpp | 23 +++++-- src/network/Network.cpp | 6 ++ src/nxdn/Control.cpp | 14 ++++ src/nxdn/Control.h | 1 + src/nxdn/packet/Voice.cpp | 34 ++++++++-- src/p25/Control.cpp | 14 ++++ src/p25/Control.h | 1 + src/p25/packet/Voice.cpp | 134 +++++++++++++++++++++++--------------- 10 files changed, 192 insertions(+), 61 deletions(-) diff --git a/src/dmr/Slot.cpp b/src/dmr/Slot.cpp index 66a72a31..51ca5368 100644 --- a/src/dmr/Slot.cpp +++ b/src/dmr/Slot.cpp @@ -140,6 +140,7 @@ Slot::Slot(uint32_t slotNo, uint32_t timeout, uint32_t tgHang, uint32_t queueSiz m_rfTimeoutTimer(1000U, timeout), m_rfTGHang(1000U, tgHang), m_netTimeoutTimer(1000U, timeout), + m_netTGHang(1000U, 2U), m_packetTimer(1000U, 0U, 50U), m_ccPacketInterval(1000U, 0U, DMR_SLOT_TIME), m_interval(), @@ -363,6 +364,17 @@ void Slot::processNetwork(const data::Data& dmrData) } } + // don't process network frames if the destination ID's don't match and the network TG hang timer is running + if (m_netLastDstId != 0U && dmrData.getDstId() != 0U && m_netState != RS_NET_IDLE) { + if (m_netLastDstId != dmrData.getDstId() && (m_netTGHang.isRunning() && !m_netTGHang.hasExpired())) { + return; + } + + if (m_netLastDstId == dmrData.getDstId() && (m_netTGHang.isRunning() && !m_netTGHang.hasExpired())) { + m_netTGHang.start(); + } + } + m_networkWatchdog.start(); uint8_t dataType = dmrData.getDataType(); @@ -514,6 +526,19 @@ void Slot::clock() } } + if (m_netTGHang.isRunning()) { + m_netTGHang.clock(ms); + + if (m_netTGHang.hasExpired()) { + m_netTGHang.stop(); + if (m_verbose) { + LogMessage(LOG_NET, "Slot %u, talkgroup hang has expired, lastDstId = %u", m_slotNo, m_netLastDstId); + } + m_netLastDstId = 0U; + m_netLastSrcId = 0U; + } + } + if (m_netState == RS_NET_AUDIO || m_netState == RS_NET_DATA) { m_networkWatchdog.clock(ms); diff --git a/src/dmr/Slot.h b/src/dmr/Slot.h index 0e8aa127..4d980f1e 100644 --- a/src/dmr/Slot.h +++ b/src/dmr/Slot.h @@ -173,6 +173,7 @@ namespace dmr Timer m_rfTimeoutTimer; Timer m_rfTGHang; Timer m_netTimeoutTimer; + Timer m_netTGHang; Timer m_packetTimer; Timer m_ccPacketInterval; diff --git a/src/dmr/packet/Voice.cpp b/src/dmr/packet/Voice.cpp index 02066031..5b375dfb 100644 --- a/src/dmr/packet/Voice.cpp +++ b/src/dmr/packet/Voice.cpp @@ -70,12 +70,20 @@ using namespace dmr::packet; return false; \ } -#define CHECK_TG_HANG(_DST_ID) \ +// Don't process network frames if the destination ID's don't match and the network TG hang +// timer is running, and don't process network frames if the RF modem isn't in a listening state +#define CHECK_NET_TRAFFIC_COLLISION(_DST_ID) \ if (m_slot->m_rfLastDstId != 0U) { \ if (m_slot->m_rfLastDstId != _DST_ID && (m_slot->m_rfTGHang.isRunning() && !m_slot->m_rfTGHang.hasExpired())) { \ return; \ } \ - } + } \ + \ + if (m_slot->m_netLastDstId != 0U) { \ + if (m_slot->m_netLastDstId != _DST_ID && (m_slot->m_netTGHang.isRunning() && !m_slot->m_netTGHang.hasExpired())) { \ + return; \ + } \ + } \ // --------------------------------------------------------------------------- // Public Class Members @@ -291,6 +299,7 @@ bool Voice::process(uint8_t* data, uint32_t len) m_slot->m_rfFrames++; m_slot->m_rfTGHang.start(); + m_slot->m_netTGHang.stop(); m_slot->m_rfLastDstId = m_slot->m_rfLC->getDstId(); m_slot->m_rfLastSrcId = m_slot->m_rfLC->getSrcId(); @@ -359,6 +368,7 @@ bool Voice::process(uint8_t* data, uint32_t len) m_slot->m_rfFrames++; m_slot->m_rfTGHang.start(); + m_slot->m_netTGHang.stop(); m_slot->m_rfLastDstId = m_slot->m_rfLC->getDstId(); m_slot->m_rfLastSrcId = m_slot->m_rfLC->getSrcId(); @@ -615,6 +625,7 @@ bool Voice::process(uint8_t* data, uint32_t len) m_slot->m_rfState = RS_RF_AUDIO; m_slot->m_rfTGHang.start(); + m_slot->m_netTGHang.stop(); m_slot->m_rfLastDstId = dstId; m_slot->m_rfLastSrcId = srcId; @@ -658,7 +669,7 @@ void Voice::processNetwork(const data::Data& dmrData) uint8_t flco = lc->getFLCO(); CHECK_NET_AUTHORITATIVE(dstId); - CHECK_TG_HANG(dstId); + CHECK_NET_TRAFFIC_COLLISION(dstId); if (dstId != dmrData.getDstId() || srcId != dmrData.getSrcId() || flco != dmrData.getFLCO()) LogWarning(LOG_NET, "DMR Slot %u, DT_VOICE_LC_HEADER, header doesn't match the DMR RF header: %u->%s%u %u->%s%u", m_slot->m_slotNo, @@ -725,6 +736,7 @@ void Voice::processNetwork(const data::Data& dmrData) m_slot->m_netState = RS_NET_AUDIO; m_slot->m_netLastDstId = dstId; m_slot->m_netLastSrcId = srcId; + m_slot->m_netTGHang.start(); m_slot->setShortLC(m_slot->m_slotNo, dstId, flco, true); @@ -743,7 +755,7 @@ void Voice::processNetwork(const data::Data& dmrData) uint32_t dstId = lc->getDstId(); CHECK_NET_AUTHORITATIVE(dstId); - CHECK_TG_HANG(dstId); + CHECK_NET_TRAFFIC_COLLISION(dstId); m_slot->m_netLC = std::move(lc); @@ -793,6 +805,7 @@ void Voice::processNetwork(const data::Data& dmrData) m_slot->m_netState = RS_NET_AUDIO; m_slot->m_netLastDstId = dstId; m_slot->m_netLastSrcId = srcId; + m_slot->m_netTGHang.start(); m_slot->setShortLC(m_slot->m_slotNo, dstId, m_slot->m_netLC->getFLCO(), true); @@ -898,6 +911,7 @@ void Voice::processNetwork(const data::Data& dmrData) m_slot->m_netState = RS_NET_AUDIO; m_slot->m_netLastDstId = dstId; m_slot->m_netLastSrcId = srcId; + m_slot->m_netTGHang.start(); m_slot->setShortLC(m_slot->m_slotNo, dstId, m_slot->m_netLC->getFLCO(), true); @@ -965,6 +979,7 @@ void Voice::processNetwork(const data::Data& dmrData) } } m_slot->m_netBits += 141U; + m_slot->m_netTGHang.start(); // Get the LCSS from the EMB data::EMB emb; diff --git a/src/network/Network.cpp b/src/network/Network.cpp index e147d871..0e292a28 100644 --- a/src/network/Network.cpp +++ b/src/network/Network.cpp @@ -306,9 +306,11 @@ void Network::clock(uint32_t ms) LogWarning(LOG_NET, "DMR Stream %u out-of-sequence; %u != %u", streamId, m_pktSeq, m_pktLastSeq + 1); } } +/* else { m_rxDMRStreamId[slotNo] = streamId; } +*/ } m_pktLastSeq = m_pktSeq; @@ -333,9 +335,11 @@ void Network::clock(uint32_t ms) LogWarning(LOG_NET, "P25 Stream %u out-of-sequence; %u != %u", streamId, m_pktSeq, m_pktLastSeq + 1); } } +/* else { m_rxP25StreamId = streamId; } +*/ } m_pktLastSeq = m_pktSeq; @@ -360,9 +364,11 @@ void Network::clock(uint32_t ms) LogWarning(LOG_NET, "NXDN Stream %u out-of-sequence; %u != %u", streamId, m_pktSeq, m_pktLastSeq + 1); } } +/* else { m_rxNXDNStreamId = streamId; } +*/ } m_pktLastSeq = m_pktSeq; diff --git a/src/nxdn/Control.cpp b/src/nxdn/Control.cpp index 6f1fabe0..79899801 100644 --- a/src/nxdn/Control.cpp +++ b/src/nxdn/Control.cpp @@ -132,6 +132,7 @@ Control::Control(bool authoritative, uint32_t ran, uint32_t callHang, uint32_t q m_rfTimeout(1000U, timeout), m_rfTGHang(1000U, tgHang), m_netTimeout(1000U, timeout), + m_netTGHang(1000U, 2U), m_networkWatchdog(1000U, 0U, 1500U), m_ccPacketInterval(1000U, 0U, 80U), m_frameLossCnt(0U), @@ -603,6 +604,19 @@ void Control::clock(uint32_t ms) } } + if (m_netTGHang.isRunning()) { + m_netTGHang.clock(ms); + + if (m_netTGHang.hasExpired()) { + m_netTGHang.stop(); + if (m_verbose) { + LogMessage(LOG_NET, "talkgroup hang has expired, lastDstId = %u", m_netLastDstId); + } + m_netLastDstId = 0U; + m_netLastSrcId = 0U; + } + } + if (m_netState == RS_NET_AUDIO) { m_networkWatchdog.clock(ms); diff --git a/src/nxdn/Control.h b/src/nxdn/Control.h index d1536b04..33f4196d 100644 --- a/src/nxdn/Control.h +++ b/src/nxdn/Control.h @@ -191,6 +191,7 @@ namespace nxdn Timer m_rfTimeout; Timer m_rfTGHang; Timer m_netTimeout; + Timer m_netTGHang; Timer m_networkWatchdog; Timer m_ccPacketInterval; diff --git a/src/nxdn/packet/Voice.cpp b/src/nxdn/packet/Voice.cpp index 5d976211..4e8ff77b 100644 --- a/src/nxdn/packet/Voice.cpp +++ b/src/nxdn/packet/Voice.cpp @@ -75,6 +75,8 @@ using namespace nxdn::packet; LogWarning(LOG_RF, "Traffic collision detect, preempting existing network traffic to new RF traffic, rfDstId = %u, netDstId = %u", dstId, \ m_nxdn->m_netLastDstId); \ resetNet(); \ + if (m_network != nullptr) \ + m_network->resetNXDN(); \ } \ } @@ -82,27 +84,41 @@ using namespace nxdn::packet; // timer is running, and don't process network frames if the RF modem isn't in a listening state #define CHECK_NET_TRAFFIC_COLLISION(_LAYER3, _SRC_ID, _DST_ID) \ if (m_nxdn->m_rfLastDstId != 0U) { \ - if (m_nxdn->m_rfLastDstId != dstId && (m_nxdn->m_rfTGHang.isRunning() && !m_nxdn->m_rfTGHang.hasExpired())) { \ + if (m_nxdn->m_rfLastDstId != _DST_ID && (m_nxdn->m_rfTGHang.isRunning() && !m_nxdn->m_rfTGHang.hasExpired())) { \ resetNet(); \ return false; \ } \ \ - if (m_nxdn->m_rfLastDstId == dstId && (m_nxdn->m_rfTGHang.isRunning() && !m_nxdn->m_rfTGHang.hasExpired())) { \ + if (m_nxdn->m_rfLastDstId == _DST_ID && (m_nxdn->m_rfTGHang.isRunning() && !m_nxdn->m_rfTGHang.hasExpired())) { \ m_nxdn->m_rfTGHang.start(); \ } \ } \ \ + if (m_nxdn->m_netLastDstId != 0U) { \ + if (m_nxdn->m_netLastDstId != _DST_ID && (m_nxdn->m_netTGHang.isRunning() && !m_nxdn->m_netTGHang.hasExpired())) { \ + return false; \ + } \ + \ + if (m_nxdn->m_netLastDstId == _DST_ID && (m_nxdn->m_netTGHang.isRunning() && !m_nxdn->m_netTGHang.hasExpired())) { \ + m_nxdn->m_netTGHang.start(); \ + } \ + } \ + \ if (m_nxdn->m_rfState != RS_RF_LISTENING) { \ - if (_LAYER3.getSrcId() == srcId && _LAYER3.getDstId() == dstId) { \ + if (_LAYER3.getSrcId() == _SRC_ID && _LAYER3.getDstId() == _DST_ID) { \ LogWarning(LOG_RF, "Traffic collision detect, preempting new network traffic to existing RF traffic (Are we in a voting condition?), rfSrcId = %u, rfDstId = %u, netSrcId = %u, netDstId = %u", _LAYER3.getSrcId(), _LAYER3.getDstId(), \ - srcId, dstId); \ + _SRC_ID, _DST_ID); \ resetNet(); \ + if (m_network != nullptr) \ + m_network->resetNXDN(); \ return false; \ } \ else { \ LogWarning(LOG_RF, "Traffic collision detect, preempting new network traffic to existing RF traffic, rfDstId = %u, netDstId = %u", _LAYER3.getDstId(), \ - dstId); \ + _DST_ID); \ resetNet(); \ + if (m_network != nullptr) \ + m_network->resetNXDN(); \ return false; \ } \ } @@ -253,6 +269,8 @@ bool Voice::process(uint8_t fct, uint8_t option, uint8_t* data, uint32_t len) return false; } + m_nxdn->m_rfTGHang.start(); + m_nxdn->m_netTGHang.stop(); m_nxdn->m_rfLastDstId = lc.getDstId(); m_nxdn->m_rfLastSrcId = lc.getSrcId(); m_nxdn->m_rfLC = lc; @@ -414,6 +432,8 @@ bool Voice::process(uint8_t fct, uint8_t option, uint8_t* data, uint32_t len) // validate destination ID VALID_DSTID(srcId, dstId, group); + m_nxdn->m_rfTGHang.start(); + m_nxdn->m_netTGHang.stop(); m_nxdn->m_rfLastDstId = m_nxdn->m_rfLC.getDstId(); m_nxdn->m_rfLastSrcId = m_nxdn->m_rfLC.getSrcId(); m_rfFrames = 0U; @@ -685,6 +705,8 @@ bool Voice::processNetwork(uint8_t fct, uint8_t option, lc::RTCH& netLC, uint8_t m_nxdn->m_netState = RS_NET_IDLE; m_nxdn->m_netMask = 0x00U; m_nxdn->m_netLC.reset(); + m_nxdn->m_netLastDstId = 0U; + m_nxdn->m_netLastSrcId = 0U; return false; } } else if (type == RTCH_MESSAGE_TYPE_VCALL) { @@ -699,6 +721,7 @@ bool Voice::processNetwork(uint8_t fct, uint8_t option, lc::RTCH& netLC, uint8_t return false; } + m_nxdn->m_netTGHang.start(); m_nxdn->m_netLastDstId = lc.getDstId(); m_nxdn->m_netLastSrcId = lc.getSrcId(); m_nxdn->m_netLC = lc; @@ -839,6 +862,7 @@ bool Voice::processNetwork(uint8_t fct, uint8_t option, lc::RTCH& netLC, uint8_t // validate destination ID VALID_DSTID(srcId, dstId, group); + m_nxdn->m_netTGHang.start(); m_nxdn->m_netLastDstId = m_nxdn->m_netLC.getDstId(); m_nxdn->m_netLastSrcId = m_nxdn->m_netLC.getSrcId(); m_rfFrames = 0U; diff --git a/src/p25/Control.cpp b/src/p25/Control.cpp index 750782f7..ccf89ffc 100644 --- a/src/p25/Control.cpp +++ b/src/p25/Control.cpp @@ -129,6 +129,7 @@ Control::Control(bool authoritative, uint32_t nac, uint32_t callHang, uint32_t q m_rfTGHang(1000U, tgHang), m_rfLossWatchdog(1000U, 0U, 1500U), m_netTimeout(1000U, timeout), + m_netTGHang(1000U, 2U), m_networkWatchdog(1000U, 0U, 1500U), m_ccPacketInterval(1000U, 0U, 10U), m_hangCount(3U * 8U), @@ -763,6 +764,19 @@ void Control::clock(uint32_t ms) } } + if (m_netTGHang.isRunning()) { + m_netTGHang.clock(ms); + + if (m_netTGHang.hasExpired()) { + m_netTGHang.stop(); + if (m_verbose) { + LogMessage(LOG_NET, "talkgroup hang has expired, lastDstId = %u", m_netLastDstId); + } + m_netLastDstId = 0U; + m_netLastSrcId = 0U; + } + } + if (m_netState == RS_NET_AUDIO || m_netState == RS_NET_DATA) { m_networkWatchdog.clock(ms); diff --git a/src/p25/Control.h b/src/p25/Control.h index b86a1466..319230b2 100644 --- a/src/p25/Control.h +++ b/src/p25/Control.h @@ -204,6 +204,7 @@ namespace p25 Timer m_rfTGHang; Timer m_rfLossWatchdog; Timer m_netTimeout; + Timer m_netTGHang; Timer m_networkWatchdog; Timer m_ccPacketInterval; diff --git a/src/p25/packet/Voice.cpp b/src/p25/packet/Voice.cpp index 2fb1dd8e..d0fab4ec 100644 --- a/src/p25/packet/Voice.cpp +++ b/src/p25/packet/Voice.cpp @@ -180,7 +180,13 @@ bool Voice::process(uint8_t* data, uint32_t len) if (m_p25->m_netState != RS_NET_IDLE) { LogWarning(LOG_RF, "Traffic collision detect, preempting existing network traffic to new RF traffic, rfDstId = %u, netDstId = %u", lc.getDstId(), m_p25->m_netLastDstId); + if (!m_p25->m_dedicatedControl) { + m_p25->m_affiliations.releaseGrant(m_p25->m_netLastDstId, false); + } + resetNet(); + if (m_network != nullptr) + m_network->resetP25(); if (m_p25->m_duplex) { m_p25->writeRF_TDU(true); @@ -192,6 +198,7 @@ bool Voice::process(uint8_t* data, uint32_t len) } m_p25->m_rfTGHang.start(); + m_p25->m_netTGHang.stop(); m_p25->m_rfLastDstId = lc.getDstId(); m_p25->m_rfLastSrcId = lc.getSrcId(); @@ -265,7 +272,19 @@ bool Voice::process(uint8_t* data, uint32_t len) else { LogWarning(LOG_RF, "Traffic collision detect, preempting existing network traffic to new RF traffic, rfDstId = %u, netDstId = %u", dstId, m_p25->m_netLastDstId); + if (!m_p25->m_dedicatedControl) { + m_p25->m_affiliations.releaseGrant(m_p25->m_netLastDstId, false); + } + resetNet(); + if (m_network != nullptr) + m_network->resetP25(); + + if (m_p25->m_duplex) { + m_p25->writeRF_TDU(true); + } + + m_p25->m_netTGHang.stop(); } } @@ -400,7 +419,7 @@ bool Voice::process(uint8_t* data, uint32_t len) else { m_p25->m_rfTGHang.stop(); } - + m_p25->m_netTGHang.stop(); m_p25->m_rfLastDstId = dstId; m_p25->m_rfLastSrcId = srcId; @@ -763,8 +782,55 @@ bool Voice::process(uint8_t* data, uint32_t len) /// bool Voice::processNetwork(uint8_t* data, uint32_t len, lc::LC& control, data::LowSpeedData& lsd, uint8_t& duid, uint8_t& frameType) { - uint32_t count = 0U; + uint32_t dstId = control.getDstId(); + uint32_t srcId = control.getSrcId(); + + // don't process network frames if the destination ID's don't match and the RF TG hang timer is running + if (m_p25->m_rfLastDstId != 0U && dstId != 0U) { + if (m_p25->m_rfLastDstId != dstId && (m_p25->m_rfTGHang.isRunning() && !m_p25->m_rfTGHang.hasExpired())) { + resetNet(); + if (m_network != nullptr) + m_network->resetP25(); + return false; + } + + if (m_p25->m_rfLastDstId == dstId && (m_p25->m_rfTGHang.isRunning() && !m_p25->m_rfTGHang.hasExpired())) { + m_p25->m_rfTGHang.start(); + } + } + + // don't process network frames if the destination ID's don't match and the network TG hang timer is running + if (m_p25->m_netLastDstId != 0U && dstId != 0U && (duid == P25_DUID_LDU1 || duid == P25_DUID_LDU2)) { + if (m_p25->m_netLastDstId != dstId && (m_p25->m_netTGHang.isRunning() && !m_p25->m_netTGHang.hasExpired())) { + return false; + } + + if (m_p25->m_netLastDstId == dstId && (m_p25->m_netTGHang.isRunning() && !m_p25->m_netTGHang.hasExpired())) { + m_p25->m_netTGHang.start(); + } + } + + // don't process network frames if the RF modem isn't in a listening state + if (m_p25->m_rfState != RS_RF_LISTENING) { + if (m_rfLC.getSrcId() == srcId && m_rfLC.getDstId() == dstId) { + LogWarning(LOG_RF, "Traffic collision detect, preempting new network traffic to existing RF traffic (Are we in a voting condition?), rfSrcId = %u, rfDstId = %u, netSrcId = %u, netDstId = %u", m_rfLC.getSrcId(), m_rfLC.getDstId(), + srcId, dstId); + resetNet(); + if (m_network != nullptr) + m_network->resetP25(); + return false; + } + else { + LogWarning(LOG_RF, "Traffic collision detect, preempting new network traffic to existing RF traffic, rfDstId = %u, netDstId = %u", m_rfLC.getDstId(), + dstId); + resetNet(); + if (m_network != nullptr) + m_network->resetP25(); + return false; + } + } + uint32_t count = 0U; switch (duid) { case P25_DUID_LDU1: if ((data[0U] == dfsi::P25_DFSI_LDU1_VOICE1) && (data[22U] == dfsi::P25_DFSI_LDU1_VOICE2) && @@ -839,6 +905,7 @@ bool Voice::processNetwork(uint8_t* data, uint32_t len, lc::LC& control, data::L checkNet_LDU2(); if (m_p25->m_netState != RS_NET_IDLE) { + m_p25->m_netTGHang.start(); writeNet_LDU1(); } } @@ -914,6 +981,7 @@ bool Voice::processNetwork(uint8_t* data, uint32_t len, lc::LC& control, data::L } if (m_p25->m_netState != RS_NET_IDLE) { + m_p25->m_netTGHang.start(); writeNet_LDU2(); } } @@ -1111,8 +1179,6 @@ void Voice::writeNet_TDU() m_p25->m_networkWatchdog.stop(); resetNet(); m_p25->m_netState = RS_NET_IDLE; - m_p25->m_netLastDstId = 0U; - m_p25->m_netLastSrcId = 0U; m_p25->m_tailOnIdle = true; } @@ -1151,40 +1217,27 @@ void Voice::writeNet_LDU1() uint32_t srcId = control.getSrcId(); bool group = control.getLCO() == LC_GROUP; - // don't process network frames if the destination ID's don't match and the network TG hang timer is running - if (m_p25->m_rfLastDstId != 0U && dstId != 0U) { - if (m_p25->m_rfLastDstId != dstId && (m_p25->m_rfTGHang.isRunning() && !m_p25->m_rfTGHang.hasExpired())) { - resetNet(); - return; - } - - if (m_p25->m_rfLastDstId == dstId && (m_p25->m_rfTGHang.isRunning() && !m_p25->m_rfTGHang.hasExpired())) { - m_p25->m_rfTGHang.start(); - } - } - - // ensure our srcId and dstId are sane from the last LDU1 + // ensure our dstId are sane from the last LDU1 if (m_netLastLDU1.getDstId() != 0U) { if (dstId != m_netLastLDU1.getDstId()) { - LogWarning(LOG_NET, P25_LDU1_STR ", dstId = %u doesn't match last LDU1 dstId = %u, fixing", - m_rfLC.getDstId(), m_rfLastLDU1.getDstId()); + if (m_verbose) { + LogMessage(LOG_NET, P25_LDU1_STR ", dstId = %u doesn't match last LDU1 dstId = %u, fixing", + dstId, m_netLastLDU1.getDstId()); + } dstId = m_netLastLDU1.getDstId(); } } - else { - LogWarning(LOG_NET, P25_LDU1_STR ", last LDU1 LC has bad data, dstId = 0"); - } + // ensure our srcId are sane from the last LDU1 if (m_netLastLDU1.getSrcId() != 0U) { if (srcId != m_netLastLDU1.getSrcId()) { - LogWarning(LOG_NET, P25_LDU1_STR ", srcId = %u doesn't match last LDU1 srcId = %u, fixing", - m_rfLC.getSrcId(), m_rfLastLDU1.getSrcId()); + if (m_verbose) { + LogMessage(LOG_NET, P25_LDU1_STR ", srcId = %u doesn't match last LDU1 srcId = %u, fixing", + srcId, m_netLastLDU1.getSrcId()); + } srcId = m_netLastLDU1.getSrcId(); } } - else { - LogWarning(LOG_NET, P25_LDU1_STR ", last LDU1 LC has bad data, srcId = 0"); - } // don't process network frames if this modem isn't authoritative if (!m_p25->m_authoritative && m_p25->m_permittedDstId != dstId) { @@ -1193,22 +1246,6 @@ void Voice::writeNet_LDU1() return; } - // don't process network frames if the RF modem isn't in a listening state - if (m_p25->m_rfState != RS_RF_LISTENING) { - if (m_rfLC.getSrcId() == srcId && m_rfLC.getDstId() == dstId) { - LogWarning(LOG_RF, "Traffic collision detect, preempting new network traffic to existing RF traffic (Are we in a voting condition?), rfSrcId = %u, rfDstId = %u, netSrcId = %u, netDstId = %u", m_rfLC.getSrcId(), m_rfLC.getDstId(), - srcId, dstId); - resetNet(); - return; - } - else { - LogWarning(LOG_RF, "Traffic collision detect, preempting new network traffic to existing RF traffic, rfDstId = %u, netDstId = %u", m_rfLC.getDstId(), - dstId); - resetNet(); - return; - } - } - if (m_debug) { LogMessage(LOG_NET, P25_LDU1_STR " service flags, emerg = %u, encrypt = %u, prio = %u, DFSI emerg = %u, DFSI encrypt = %u, DFSI prio = %u", control.getEmergency(), control.getEncrypted(), control.getPriority(), @@ -1294,7 +1331,7 @@ void Voice::writeNet_LDU1() (m_netLC.getPriority() & 0x07U); // Priority if (!m_p25->m_trunk->writeRF_TSDU_Grant(srcId, dstId, serviceOptions, group, true)) { - LogError(LOG_NET, P25_HDU_STR " call failure, not granted, this should not happen, dstId = %u", dstId); + LogError(LOG_NET, P25_HDU_STR " call failure, network call not granted, dstId = %u", dstId); if (m_network != nullptr) m_network->resetP25(); @@ -1327,6 +1364,7 @@ void Voice::writeNet_LDU1() m_p25->m_netState = RS_NET_AUDIO; m_p25->m_netLastDstId = dstId; m_p25->m_netLastSrcId = srcId; + m_p25->m_netTGHang.start(); m_p25->m_netTimeout.start(); m_netFrames = 0U; m_netLost = 0U; @@ -1465,14 +1503,6 @@ void Voice::writeNet_LDU2() return; } - // don't process network frames if the destination ID's don't match and the network TG hang timer is running - if (m_p25->m_rfLastDstId != 0U) { - if (m_p25->m_rfLastDstId != m_netLastLDU1.getDstId() && (m_p25->m_rfTGHang.isRunning() && !m_p25->m_rfTGHang.hasExpired())) { - resetNet(); - return; - } - } - uint8_t mi[P25_MI_LENGTH_BYTES]; control.getMI(mi);