add support for processing CSBK on the FNE; add support to optionally log TSBK and CSBK network events to InfluxDB;

pull/51/head
Bryan Biedenkapp 2 years ago
parent f603949879
commit b19c1d5f6a

@ -88,6 +88,8 @@ master:
influxOrg: "dvm"
# Data Bucket Name on InfluxDB instance API.
influxBucket: "dvm"
# Flag indicating whether TSBK/CSBK/RCCH messages will be logged to InfluxDB.
influxLogRawData: false
#
# Talkgroup Rules Configuration

@ -72,7 +72,8 @@ CSBK::CSBK() :
m_logicalCh1(DMR_CHNULL),
m_logicalCh2(DMR_CHNULL),
m_slotNo(0U),
m_siteIdenEntry(::lookups::IdenTable())
m_siteIdenEntry(::lookups::IdenTable()),
m_raw(nullptr)
{
/* stub */
}
@ -80,7 +81,11 @@ CSBK::CSBK() :
/// <summary>
/// Finalizes a instance of the CSBK class.
/// </summary>
CSBK::~CSBK() = default;
CSBK::~CSBK()
{
if (m_raw != nullptr)
delete[] m_raw;
}
/// <summary>
/// Returns a string that represents the current CSBK.
@ -91,6 +96,16 @@ std::string CSBK::toString()
return std::string("CSBKO_UNKWN (Unknown CSBK)");
}
/// <summary>
/// Returns a copy of the raw decoded CSBK bytes.
/// </summary>
/// <remarks>This will only return data for a *decoded* CSBK, not a created or copied CSBK.</remarks>
/// <returns></returns>
uint8_t* CSBK::getDecodedRaw() const
{
return m_raw;
}
/// <summary>
/// Regenerate a DMR CSBK without decoding.
/// </summary>
@ -268,6 +283,9 @@ bool CSBK::decode(const uint8_t* data, uint8_t* payload)
Utils::dump(2U, "Decoded CSBK", csbk, DMR_CSBK_LENGTH_BYTES);
}
m_raw = new uint8_t[DMR_CSBK_LENGTH_BYTES];
::memcpy(m_raw, csbk, DMR_CSBK_LENGTH_BYTES);
m_CSBKO = csbk[0U] & 0x3FU; // CSBKO
m_lastBlock = (csbk[0U] & 0x80U) == 0x80U; // Last Block Marker
m_FID = csbk[1U]; // Feature ID

@ -46,6 +46,10 @@ namespace dmr
/// <summary>Returns a string that represents the current CSBK.</summary>
virtual std::string toString();
/// <summary>Returns a copy of the raw decoded CSBK bytes.</summary>
/// <remarks>This will only return data for a *decoded* CSBK, not a created or copied CSBK.</remarks>
uint8_t* getDecodedRaw() const;
/// <summary>Regenerate a DMR CSBK without decoding.</summary>
/// <remarks>This is because the DMR architecture allows fall-thru of unsupported CSBKs.</remarks>
static bool regenerate(uint8_t* data, uint8_t dataType);
@ -144,6 +148,9 @@ namespace dmr
void encode(uint8_t* data, const uint8_t* payload);
__PROTECTED_COPY(CSBK);
private:
uint8_t* m_raw;
};
} // namespace lc
} // namespace dmr

@ -95,7 +95,8 @@ TSBK::TSBK() :
m_group(true),
m_siteIdenEntry(lookups::IdenTable()),
m_rs(),
m_trellis()
m_trellis(),
m_raw(nullptr)
{
if (m_siteCallsign == nullptr) {
m_siteCallsign = new uint8_t[P25_MOT_CALLSIGN_LENGTH_BYTES];
@ -112,7 +113,8 @@ TSBK::TSBK() :
/// </summary>
TSBK::~TSBK()
{
/* stub */
if (m_raw != nullptr)
delete[] m_raw;
}
/// <summary>
@ -125,6 +127,16 @@ std::string TSBK::toString(bool isp)
return std::string("TSBK_IOSP_UNKWN (Unknown TSBK)");
}
/// <summary>
/// Returns a copy of the raw decoded TSBK bytes.
/// </summary>
/// <remarks>This will only return data for a *decoded* TSBK, not a created or copied TSBK.</remarks>
/// <returns></returns>
uint8_t* TSBK::getDecodedRaw() const
{
return m_raw;
}
/// <summary>
/// Sets the callsign.
/// </summary>
@ -270,6 +282,9 @@ bool TSBK::decode(const uint8_t* data, uint8_t* payload, bool rawTSBK)
Utils::dump(2U, "TSBK::decode(), TSBK Value", tsbk, P25_TSBK_LENGTH_BYTES);
}
m_raw = new uint8_t[P25_TSBK_LENGTH_BYTES];
::memcpy(m_raw, tsbk, P25_TSBK_LENGTH_BYTES);
m_lco = tsbk[0U] & 0x3F; // LCO
m_lastBlock = (tsbk[0U] & 0x80U) == 0x80U; // Last Block Marker
m_mfId = tsbk[1U]; // Mfg Id.

@ -68,6 +68,10 @@ namespace p25
/// <summary>Returns a string that represents the current TSBK.</summary>
virtual std::string toString(bool isp = false);
/// <summary>Returns a copy of the raw decoded TSBK bytes.</summary>
/// <remarks>This will only return data for a *decoded* TSBK, not a created or copied TSBK.</remarks>
uint8_t* getDecodedRaw() const;
/// <summary>Gets the flag indicating verbose log output.</summary>
static bool getVerbose() { return m_verbose; }
/// <summary>Sets the flag indicating verbose log output.</summary>
@ -159,6 +163,9 @@ namespace p25
void encode(uint8_t* data, const uint8_t* payload, bool rawTSBK = false, bool noTrellis = false);
__PROTECTED_COPY(TSBK);
private:
uint8_t* m_raw;
};
} // namespace lc
} // namespace p25

@ -101,6 +101,7 @@ FNENetwork::FNENetwork(HostFNE* host, const std::string& address, uint16_t port,
m_influxServerToken(),
m_influxOrg("dvm"),
m_influxBucket("dvm"),
m_influxLogRawData(false),
m_reportPeerPing(reportPeerPing),
m_verbose(verbose)
{
@ -151,6 +152,7 @@ void FNENetwork::setOptions(yaml::Node& conf, bool printOptions)
m_influxServerToken = conf["influxServerToken"].as<std::string>();
m_influxOrg = conf["influxOrg"].as<std::string>("dvm");
m_influxBucket = conf["influxBucket"].as<std::string>("dvm");
m_influxLogRawData = conf["influxLogRawData"].as<bool>(false);
if (m_enableInfluxDB) {
m_influxServer = influxdb::ServerInfo(m_influxServerAddress, m_influxServerPort, m_influxOrg, m_influxServerToken, m_influxBucket);
}
@ -168,6 +170,7 @@ void FNENetwork::setOptions(yaml::Node& conf, bool printOptions)
LogInfo(" InfluxDB Port: %u", m_influxServerPort);
LogInfo(" InfluxDB Organization: %s", m_influxOrg.c_str());
LogInfo(" InfluxDB Bucket: %s", m_influxBucket.c_str());
LogInfo(" InfluxDB Log Raw TSBK/CSBK/RCCH: %s", m_influxLogRawData ? "yes" : "no");
}
}
}

@ -300,6 +300,7 @@ namespace network
std::string m_influxServerToken;
std::string m_influxOrg;
std::string m_influxBucket;
bool m_influxLogRawData;
influxdb::ServerInfo m_influxServer;
bool m_reportPeerPing;

@ -231,6 +231,11 @@ bool TagDMRData::processFrame(const uint8_t* data, uint32_t len, uint32_t peerId
m_parrotFrames.push_back(std::make_tuple(copy, len, pktSeq, streamId));
}
// process CSBK from peer
if (!processCSBK(buffer, peerId, dmrData)) {
return false;
}
// repeat traffic to the connected peers
if (m_network->m_peers.size() > 0U) {
uint32_t i = 0U;
@ -504,6 +509,49 @@ bool TagDMRData::peerRewrite(uint32_t peerId, uint32_t& dstId, uint32_t& slotNo,
return rewrote;
}
/// <summary>
/// Helper to process CSBKs being passed from a peer.
/// </summary>
/// <param name="buffer"></param>
/// <param name="peerId">Peer ID</param>
/// <param name="data"></param>
bool TagDMRData::processCSBK(uint8_t* buffer, uint32_t peerId, dmr::data::Data& dmrData)
{
// are we receiving a CSBK?
if (dmrData.getDataType() == DT_CSBK) {
uint8_t data[DMR_FRAME_LENGTH_BYTES + 2U];
dmrData.getData(data + 2U);
std::unique_ptr<lc::CSBK> csbk = lc::csbk::CSBKFactory::createCSBK(data + 2U, DT_CSBK);
if (csbk != nullptr) {
// report csbk event to InfluxDB
if (m_network->m_enableInfluxDB && m_network->m_influxLogRawData) {
const uint8_t* raw = csbk->getDecodedRaw();
if (raw != nullptr) {
std::stringstream ss;
ss << std::hex <<
(int)raw[0] << (int)raw[1] << (int)raw[2] << (int)raw[4] <<
(int)raw[5] << (int)raw[6] << (int)raw[7] << (int)raw[8] <<
(int)raw[9] << (int)raw[10] << (int)raw[11];
influxdb::QueryBuilder()
.meas("csbk_event")
.tag("peerId", std::to_string(peerId))
.tag("lco", __INT_HEX_STR(csbk->getCSBKO()))
.tag("csbk", csbk->toString())
.field("raw", ss.str())
.timestamp(std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch()).count())
.request(m_network->m_influxServer);
}
}
} else {
LogWarning(LOG_NET, "PEER %u, passing CSBK that failed to decode? csbk == nullptr", peerId);
}
}
return true;
}
/// <summary>
/// Helper to determine if the peer is permitted for traffic.
/// </summary>

@ -77,6 +77,9 @@ namespace network
/// <summary>Helper to route rewrite destination ID and slot.</summary>
bool peerRewrite(uint32_t peerId, uint32_t& dstId, uint32_t& slotNo, bool outbound = true);
/// <summary>Helper to process CSBKs being passed from a peer.</summary>
bool processCSBK(uint8_t* buffer, uint32_t peerId, dmr::data::Data& dmrData);
/// <summary>Helper to determine if the peer is permitted for traffic.</summary>
bool isPeerPermitted(uint32_t peerId, dmr::data::Data& data, uint32_t streamId);
/// <summary>Helper to validate the DMR call stream.</summary>

@ -631,6 +631,27 @@ bool TagP25Data::processTSDU(uint8_t* buffer, uint32_t peerId, uint8_t duid)
std::unique_ptr<lc::TSBK> tsbk = lc::tsbk::TSBKFactory::createTSBK(data.get());
if (tsbk != nullptr) {
// report tsbk event to InfluxDB
if (m_network->m_enableInfluxDB && m_network->m_influxLogRawData) {
const uint8_t* raw = tsbk->getDecodedRaw();
if (raw != nullptr) {
std::stringstream ss;
ss << std::hex <<
(int)raw[0] << (int)raw[1] << (int)raw[2] << (int)raw[4] <<
(int)raw[5] << (int)raw[6] << (int)raw[7] << (int)raw[8] <<
(int)raw[9] << (int)raw[10] << (int)raw[11];
influxdb::QueryBuilder()
.meas("tsbk_event")
.tag("peerId", std::to_string(peerId))
.tag("lco", __INT_HEX_STR(tsbk->getLCO()))
.tag("tsbk", tsbk->toString())
.field("raw", ss.str())
.timestamp(std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch()).count())
.request(m_network->m_influxServer);
}
}
// handle standard P25 reference opcodes
switch (tsbk->getLCO()) {
case TSBK_OSP_ADJ_STS_BCAST:

Loading…
Cancel
Save

Powered by TurnKey Linux.