Also known as: PDU, packet data unit
A P25 Packet Data Unit (PDU) is the data-channel counterpart of the voice
LDU and the trunking TSBK: the frame
that carries user data — text messages, location reports, IP traffic — across a P25
system.1 It is identified by DUID 0xC and is structured
as a header block followed by a run of data blocks, each a 12-byte (96-bit) post-FEC
unit. GopherTrunk decodes the structured PDU from already-FEC-decoded block bytes and
reassembles the data blocks into a payload, which is typically an SNDCP message wrapping a
network packet.
Header and blocks
The PDU header names the format and the destination. GopherTrunk’s PDUHeader
(internal/radio/p25/phase1/pdu.go) decodes:
| Field | Meaning |
|---|---|
| Format | 0x03 response, 0x15 unconfirmed data, 0x16 confirmed data |
| Confirmed | flag: does the receiver acknowledge each block? |
| SAP | Service Access Point — which upper-layer service (e.g. packet data) |
| MFID | manufacturer ID |
| LLID | 24-bit logical link (destination) ID — the target radio |
| Block count | number of data blocks that follow |
A confirmed PDU (0x16) carries per-block serial numbers and CRCs so the sender can be
told which blocks arrived and retransmit the rest; an unconfirmed PDU (0x15) is
fire-and-forget. ReassemblePDU concatenates the data blocks in order into the payload. The
block bit layout here is GopherTrunk’s working model — TIA-102.BAAA’s PDU tables are not in
the repository — so it is confined to one file with symmetric encoders and defensive parsers.
SNDCP and IP transport
When the header’s SAP marks the payload as packet data, the reassembled bytes begin with an
SNDCP (Sub-Network Dependent Convergence Protocol) header. ParseSNDCP peels off a
1-octet header that packs a 4-bit PDU type and a 4-bit NSAPI (Network Service Access
Point Identifier), then exposes the encapsulated network-layer packet. That packet is most
often IPv4: ParseIPv4 decodes the standard 20-byte RFC 791 header to surface the source and
destination addresses and the protocol (ICMP/TCP/UDP) — the “who is talking to whom” of a
data call. Unlike the PDU and SNDCP layers, the IPv4 header is a fully-specified format, so
that layer is exact rather than a working model.
Relevance to SDR
GopherTrunk decodes the PDU from FEC-decoded blocks and walks the stack — PDU header →
reassembled payload → SNDCP → IPv4 — to characterise packet-data activity on a system. The
receiver-level framing that produces those blocks from the raw dibit stream (the FSW → NID →
trellis-coded-block chain for DUID 0xC) is a documented follow-up best built against real
packet-data captures; the structured decode above is what runs once the blocks exist. Because
much P25 data is short and bursty, and confirmed PDUs are acknowledged, a monitor can often
recover useful metadata (destination LLID, IP endpoints) even without reconstructing the full
application payload.
Sources
-
Project 25 — Wikipedia, on the P25 standard and its data services. PDU/SNDCP layouts follow TIA-102.BAAA / BAEA as a working model; the IPv4 header follows RFC 791. ↩