Skip to content

SNDCPv1 Trunked Packet Data - #134

Merged
gatekeep merged 4 commits into
DVMProject:r05a06_devfrom
dandrzejewski:sndcp-trunked-packet-data
Nov 11, 2026
Merged

gatekeep merged 4 commits into
DVMProject:r05a06_devfrom
dandrzejewski:sndcp-trunked-packet-data

Conversation

@dandrzejewski

Copy link
Copy Markdown

Summary

Makes trunked SNDCP packet data work end to end with a Motorola APX: the radio activates a context, passes IP datagrams both ways on a data channel, and can be reached from the network while it is idle on the control channel.

This code was 100% written using AI. I personally reviewed it for correctness and tested as thoroughly as I'm able. I am not a dvmproject expert (or, for that matter, a c/c++ expert). I'm obviously happy to accept feedback and make requested changes.

Fixes to the existing SNDCP support:

  • FNE: send the link-layer ACK for the context activation request. Without it the radio retries and gives up.
  • Common: Assembler::disassemble shifted the coded block stream by the data header offset. The offset counts octets of reassembled user data, so every PDU with a non-zero offset failed to decode.
  • Host: OSP_SNDCP_CH_ANN set autonomous access while announcing the control channel, which receives no SN-Data. The flag is now clear.
  • Host: OSP_SNDCP_CH_GNT now echoes the Data Service Options of the request. The radio ignores a grant whose options differ.
  • Host: the SNDCP reconnect request was read as an ISP_SNDCP_CH_REQ; the factory builds an ISP_SNDCP_REC_REQ for it.
  • FNE: standby timer in the context accept raised from 1 minute to 4 hours. At 1 minute the radio dropped its context about 70 seconds after the last data. I don't fully understand why, to be frank.

Added to complete the data path:

  • FNE: SN-Data uplink (strip the 2-octet SNDCP header on the user data SAP) and SN-Data downlink framing for a radio with a context.
  • FNE and host: SNDCP data paging. New OSP_SNDCP_DATA_PAGE_REQ ($15) and ISP_SNDCP_DATA_PAGE_RES ($13). The host relays each SNDCP grant to the FNE; the FNE pages a radio that has left the data channel through the control channel that last granted it one, and holds the PDU until the grant is reported.
  • FNE: retransmission of a confirmed downlink the radio does not acknowledge, up to twice, with the same N(S).

Component(s)

Which part(s) of the project does this affect?

  • dvmhost
  • dvmfne
  • dvmbridge
  • dvmpatch
  • dvmcmd
  • sysview
  • tged
  • peered
  • Other (explain below)

Other: the common library (src/common/p25): two new TSBK classes, TSBKFactory, P25Defines.h, Assembler.cpp, OSP_SNDCP_CH_ANN.cpp.

Type of change

  • Bug fix
  • Refactor / cleanup
  • Performance improvement
  • Documentation update
  • Build / tooling change

Also adds function (data paging, downlink retransmission)... this template has no box for that.

Related issues

None that I'm able to find.

Build & test notes

Fairly limited testing, but it has been running the CTRS FNE, and I've tested it on my personal hotspot with my personal APX on R36.

  • OS / distro: Linux, Ubuntu 26.04 (FNE) and Debian Trixie (Host)
  • Compiler version: gcc/g++ version 15.2.0
  • Build flags: defaults

What I saw: context activation, registration with an IP application server, traffic in both directions, and delivery to an idle radio through data paging.

Builds on the current (as of the time of this writing) r05a06_dev. CTRS FNE is running this patch but on an older rev of r05a06_dev, before breaking changes to the network protocol were made.

Logs / output (if applicable)

Control channel host, earlier form of the change, radio idle on the control channel when a datagram arrives for it. The FNE pages, the radio answers "proceed", the host grants a data channel:

(NET) P25, TSDU (Trunking System Data Unit), TSBKO, OSP_SNDCP_DATA_PAGE_REQ (SNDCP Data Page Request), dstId = <rid>
(NET) P25, TSDU (Trunking System Data Unit), TSBKO, OSP_SNDCP_DATA_PAGE_REQ (SNDCP Data Page Request), dstId = <rid>
(RF) P25, TSDU (Trunking System Data Unit), TSBKO, ISP_SNDCP_DATA_PAGE_RES (SNDCP Data Page Response), dataServiceOptions = $01, answer = $20, dataAccessControl = $0001, srcId = <rid>
(RF) P25, TSDU (Trunking System Data Unit), TSBKO, OSP_SNDCP_CH_GNT (SNDCP Data Channel Grant), chNo = <ch>, srcId = <rid>

The second page is 2.6 seconds after the first; the radio answers about 3 seconds after a page. The page retry interval in this branch is 4 seconds for that reason.

I can provide additional logs if needed.

Checklist

  • Change is scoped and focused
  • Existing functionality verified**
  • No unrelated refactors included
  • Documentation updated if needed
  • No secrets or credentials included

**I did not do a complete regression test of all components, but all the basic functions seem to work.

…et and clear autonomous access in the SNDCP channel announcement;

- add ISP_SNDCP_DATA_PAGE_RES ($13) and OSP_SNDCP_DATA_PAGE_REQ ($15)
- Assembler::disassemble no longer shifts the coded block stream by the
  data header offset; the offset counts octets of reassembled user data
- OSP_SNDCP_CH_ANN no longer sets autonomous access; the announced
  channel is the control channel, which receives no SN-Data
…d relay SNDCP grants to the FNE;

- the SNDCP data channel grant echoes the Data Service Options of the
  request; an SU ignores a grant whose options differ
- transmit an SNDCP data page request received from the FNE and answer
  a "proceed" page response with a data channel grant
- pass the first copy of each SNDCP grant to the network, so the FNE
  knows the SU has been directed to a data channel
- read the SNDCP reconnect request as an ISP_SNDCP_REC_REQ, the class
  the factory builds for it
…ta uplink and downlink, data paging and downlink retransmission;

- send the link-layer ACK for the SNDCP context activation request
- strip the SNDCP header from SN-Data received on the user data SAP and
  handle the IPv4 datagram as packet data
- frame downlink datagrams as SN-Data for an SU with an SNDCP context
- raise the standby timer in the context accept from 1 minute to 4 hours
- page an SU that has left the data channel through the control channel
  that last granted it one, and hold the PDU until the grant is reported
- retransmit a confirmed downlink the SU does not acknowledge, up to
  twice, with the same N(S)
@gatekeep

Copy link
Copy Markdown
Member

This looks entirely reasonable. I don't see anything from code review that stands out as problematic.

Correct the outstanding merge conflicts and this can be merged.

…cket-data

Conflicts resolved by keeping both sides:
- src/common/p25/lc/tsbk/TSBKFactory.cpp
- src/common/p25/lc/tsbk/TSBKFactory.h
@gatekeep
gatekeep merged commit 50cf3b5 into DVMProject:r05a06_dev Nov 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants