From c62d79e2bea581fe522dc0c5cfaa6d6de2217277 Mon Sep 17 00:00:00 2001 From: Bryan Biedenkapp Date: Tue, 25 Jul 2023 16:50:16 -0400 Subject: [PATCH] implement support for explicit source ID; --- configs/config.example.yml | 2 ++ src/network/BaseNetwork.cpp | 6 +++++ src/p25/Control.cpp | 9 +++++++ src/p25/Control.h | 1 + src/p25/packet/Voice.cpp | 51 +++++++++++++++++++++++++++++++++++-- src/p25/packet/Voice.h | 1 + 6 files changed, 68 insertions(+), 2 deletions(-) diff --git a/configs/config.example.yml b/configs/config.example.yml index 584fc290..9838dd08 100644 --- a/configs/config.example.yml +++ b/configs/config.example.yml @@ -209,6 +209,8 @@ protocols: noMessageAck: true # Flag indicating that unit-to-unit availiability checks should be performed for a private call. unitToUnitAvailCheck: true + # Flag indicating explicit source ID support is enabled. + allowExplicitSourceId: true # Flag indicating whether or not the host will respond to SNDCP data grant requests. sndcpGrant: false # BER/Error threshold for silencing voice packets. (0 or 1233 disables) diff --git a/src/network/BaseNetwork.cpp b/src/network/BaseNetwork.cpp index 3dd3c832..ce12176b 100644 --- a/src/network/BaseNetwork.cpp +++ b/src/network/BaseNetwork.cpp @@ -708,6 +708,12 @@ void BaseNetwork::createP25_MessageHdr(uint8_t* data, uint8_t duid, const p25::l data[15U] = control.getMFId(); // MFId + uint32_t netId = control.getSiteData().netId(); // Network ID + __SET_UINT16(netId, data, 16U); + uint16_t sysId = control.getSiteData().sysId(); // System ID + data[11U] = (sysId >> 8) & 0xFFU; + data[12U] = (sysId >> 0) & 0xFFU; + data[20U] = lsd.getLSD1(); // LSD 1 data[21U] = lsd.getLSD2(); // LSD 2 diff --git a/src/p25/Control.cpp b/src/p25/Control.cpp index 8aa96369..8ebb599a 100644 --- a/src/p25/Control.cpp +++ b/src/p25/Control.cpp @@ -369,6 +369,8 @@ void Control::setOptions(yaml::Node& conf, bool supervisor, const std::string cw m_notifyCC = false; } + m_allowExplicitSourceId = p25Protocol["allowExplicitSourceId"].as(true); + if (printOptions) { LogInfo(" Silence Threshold: %u (%.1f%%)", m_voice->m_silenceThreshold, float(m_voice->m_silenceThreshold) / 12.33F); @@ -405,6 +407,7 @@ void Control::setOptions(yaml::Node& conf, bool supervisor, const std::string cw LogInfo(" No Status ACK: %s", m_trunk->m_noStatusAck ? "yes" : "no"); LogInfo(" No Message ACK: %s", m_trunk->m_noMessageAck ? "yes" : "no"); LogInfo(" Unit-to-Unit Availability Check: %s", m_trunk->m_unitToUnitAvailCheck ? "yes" : "no"); + LogInfo(" Explicit Source ID Support: %s", m_allowExplicitSourceId ? "yes" : "no"); if (!m_trunk->m_redundantGrant) { LogInfo(" Redundant Grant Transmit: yes"); @@ -1124,6 +1127,9 @@ void Control::processNetwork() uint32_t srcId = __GET_UINT16(buffer, 5U); uint32_t dstId = __GET_UINT16(buffer, 8U); + uint32_t netId = __GET_UINT16(buffer, 16U); + uint32_t sysId = (buffer[11U] << 8) | (buffer[12U] << 0); + uint8_t lsd1 = buffer[20U]; uint8_t lsd2 = buffer[21U]; @@ -1172,6 +1178,9 @@ void Control::processNetwork() control.setDstId(dstId); control.setMFId(MFId); + control.setNetId(netId); + control.setSysId(sysId); + lsd.setLSD1(lsd1); lsd.setLSD2(lsd2); diff --git a/src/p25/Control.h b/src/p25/Control.h index 7ce4a724..8738f939 100644 --- a/src/p25/Control.h +++ b/src/p25/Control.h @@ -174,6 +174,7 @@ namespace p25 bool m_controlOnly; bool m_ackTSBKRequests; bool m_disableNetworkHDU; + bool m_allowExplicitSourceId; ::lookups::IdenTableLookup* m_idenTable; ::lookups::RadioIdLookup* m_ridLookup; diff --git a/src/p25/packet/Voice.cpp b/src/p25/packet/Voice.cpp index 715986c5..19696f92 100644 --- a/src/p25/packet/Voice.cpp +++ b/src/p25/packet/Voice.cpp @@ -55,6 +55,7 @@ using namespace p25::packet; // --------------------------------------------------------------------------- const uint32_t VOC_LDU1_COUNT = 3U; +const uint32_t ROAM_LDU1_COUNT = 1U; // --------------------------------------------------------------------------- // Public Class Members @@ -77,6 +78,7 @@ void Voice::resetRF() m_rfBits = 1U; m_rfUndecodableLC = 0U; m_vocLDU1Count = 0U; + m_roamLDU1Count = 0U; } /// @@ -93,6 +95,7 @@ void Voice::resetNet() m_netFrames = 0U; m_netLost = 0U; m_vocLDU1Count = 0U; + m_roamLDU1Count = 0U; } /// @@ -477,6 +480,7 @@ bool Voice::process(uint8_t* data, uint32_t len) m_rfBits = 1U; m_rfUndecodableLC = 0U; m_vocLDU1Count = 0U; + m_roamLDU1Count = 0U; m_p25->m_rfTimeout.start(); m_lastDUID = P25_DUID_HDU; @@ -889,6 +893,11 @@ bool Voice::processNetwork(uint8_t* data, uint32_t len, lc::LC& control, data::L m_dfsiLC.decodeLDU1(data + count, m_netLDU1 + 204U); count += dfsi::P25_DFSI_LDU1_VOICE9_FRAME_LENGTH_BYTES; + // these aren't set by the DFSI decoder, so we'll manually + // reset them + m_dfsiLC.control()->setNetId(control.getNetId()); + m_dfsiLC.control()->setSysId(control.getSysId()); + m_netLastLDU1 = control; m_netLastFrameType = frameType; @@ -1063,6 +1072,7 @@ Voice::Voice(Control* p25, network::BaseNetwork* network, bool debug, bool verbo m_lastRejectId(0U), m_silenceThreshold(DEFAULT_SILENCE_THRESHOLD), m_vocLDU1Count(0U), + m_roamLDU1Count(0U), m_verbose(verbose), m_debug(debug) { @@ -1374,6 +1384,7 @@ void Voice::writeNet_LDU1() m_netFrames = 0U; m_netLost = 0U; m_vocLDU1Count = 0U; + m_roamLDU1Count = 0U; if (!m_p25->m_disableNetworkHDU) { if (m_netLastFrameType != P25_FT_HDU_LATE_ENTRY) { @@ -1414,6 +1425,41 @@ void Voice::writeNet_LDU1() } } + uint32_t netId = control.getNetId(); + uint32_t sysId = control.getSysId(); + + // is the network peer a different WACN or system ID? + if (m_p25->m_control && m_p25->m_allowExplicitSourceId) { + if (netId == 0U) { + netId = lc::LC::getSiteData().netId(); + } + + if (sysId == 0U) { + sysId = lc::LC::getSiteData().sysId(); + } + + if (sysId != lc::LC::getSiteData().sysId()) { + // per TIA-102.AABD-D transmit EXPLICIT_SOURCE_ID every other frame (e.g. every other LDU1) + m_roamLDU1Count++; + if (m_roamLDU1Count > ROAM_LDU1_COUNT) { + m_roamLDU1Count = 0U; + m_netLC.setNetId(netId); + m_netLC.setSysId(sysId); + m_netLC.setLCO(LC_EXPLICIT_SOURCE_ID); + } + else { + // flag explicit block to follow in next LDU1 + if (m_netLC.getLCO() == LC_GROUP) { + m_netLC.setExplicitId(true); + } + } + } + } + else { + netId = lc::LC::getSiteData().netId(); + sysId = lc::LC::getSiteData().sysId(); + } + // single-channel trunking or voice on control support? if (m_p25->m_control && m_p25->m_voiceOnControl) { // per TIA-102.AABD-B transmit RFSS_STS_BCAST every 3 superframes (e.g. every 3 LDU1s) @@ -1463,8 +1509,9 @@ void Voice::writeNet_LDU1() m_p25->addFrame(buffer, P25_LDU_FRAME_LENGTH_BYTES + 2U, true); if (m_verbose) { - LogMessage(LOG_NET, P25_LDU1_STR " audio, srcId = %u, dstId = %u, group = %u, emerg = %u, encrypt = %u, prio = %u", - m_netLC.getSrcId(), m_netLC.getDstId(), m_netLC.getGroup(), m_netLC.getEmergency(), m_netLC.getEncrypted(), m_netLC.getPriority()); + LogMessage(LOG_NET, P25_LDU1_STR " audio, srcId = %u, dstId = %u, group = %u, emerg = %u, encrypt = %u, prio = %u, sysId = $%03X, netId = $%05X", + m_netLC.getSrcId(), m_netLC.getDstId(), m_netLC.getGroup(), m_netLC.getEmergency(), m_netLC.getEncrypted(), m_netLC.getPriority(), + sysId, netId); } ::memset(m_netLDU1, 0x00U, 9U * 25U); diff --git a/src/p25/packet/Voice.h b/src/p25/packet/Voice.h index bf80983b..afa899d7 100644 --- a/src/p25/packet/Voice.h +++ b/src/p25/packet/Voice.h @@ -112,6 +112,7 @@ namespace p25 uint32_t m_silenceThreshold; uint8_t m_vocLDU1Count; + uint8_t m_roamLDU1Count; bool m_verbose; bool m_debug;