MAVLink Spec Alignment for 1.0

Copy Markdown View Source

Review date: 2026-05-08

Primary references:

1.0 Support Posture

XMAVLink's 1.0 compatibility target is MAVLink 2 first. MAVLink 1 remains supported for basic frame parsing, packing, and routing while that support stays cheap to maintain, but MAVLink 1-only work should not displace MAVLink 2 correctness. If a future gap requires significant MAVLink 1-specific investment, prefer an explicit support reduction over slowing MAVLink 2 work.

Supported runtime scope:

  • MAVLink 2 unsigned frames without incompatible flags.
  • MAVLink 2 signed-frame boundary parsing and signature trailer representation. Configured inbound signed frames are authenticated before unpacking and routed with replay protection, and unsigned outbound MAVLink 2 frames are signed on signing-enabled connections. Applications can configure timestamp load/save callbacks for local signing timestamp persistence. Inbound SETUP_SIGNING frames are delivered locally but not forwarded between MAVLink connections.
  • MAVLink 1 frames for existing users and legacy links.
  • Serial, udpin, udpout, and outbound TCP (tcpout) transports.
  • Generated dialect modules from trusted MAVLink XML build inputs.

Known non-goals for 1.0 unless separately implemented:

  • Automatic SETUP_SIGNING key provisioning.
  • TCP server (tcpin) transport.
  • Treating untrusted XML dialect files as safe input.
  • Full mavgen feature parity for XML validation, WIP filtering, and every generated helper surface.

Checklist

AreaStatusNotes
MAVLink 2 frame shapeSupportedParses and emits the v2 header, 24-bit message id, payload, checksum, and compatible flags. Unsupported incompatible flags are discarded.
MAVLink 2 signingSupported with provisioning caveatSigned-frame boundaries and the 13-byte signature trailer are parsed and represented. Configured inbound signed frames are verified before unpacking and routed with per-connection replay checks. Unsigned MAVLink 2 inbound frames are rejected by default while signing is enabled unless explicitly accepted. Unsigned outbound MAVLink 2 frames are signed on signing-enabled connections with per-connection timestamp increments. Optional timestamp load/save callbacks let applications persist local signing timestamps. Inbound SETUP_SIGNING frames are local-only; XMAVLink does not automate key provisioning. See MAVLINK2_SIGNING.md.
MAVLink 2 payload truncationSupportedOutbound payloads trim trailing zero bytes while preserving a non-empty all-zero payload's first byte; inbound v2 payloads are padded back to known dialect length before unpacking.
MAVLink 2 future extension bytesSupportedGenerated v2 unpack clauses now ignore trailing extension bytes that are unknown to the local dialect. This preserves extension-field forward compatibility.
MAVLink 2 extension CRC behaviorSupportedCRC_EXTRA generation excludes extension fields, matching the serialization guide.
MAVLink 2 extension field packing defaultsSupportedOmitted known extension fields are packed as zero-equivalent values for v2 messages while remaining omitted from v1 payloads.
MAVLink 1 frame shapeSupportedExisting parser/packer handles v1 framing, checksum, and 8-bit message ids. New MAVLink 1-only expansion is not a priority for 1.0.
CRC_EXTRA calculationSupportedField ordering is size-stable for base fields, arrays are ordered by element size, and extension fields are excluded.
Field orderingSupportedBase fields are stably sorted by native type size; extension fields remain in XML declaration order.
Unknown message handlingPartialUnknown known-shape frames are forwarded as broadcast when the message id is not present in the dialect. Unknown messages cannot expose target fields because the payload cannot be decoded.
Compatible flagsSupportedMAVLink 2 compatible flags are retained and otherwise ignored.
Incompatible flagsSupportedUnknown incompatible flags are discarded as required. Signing's known 13-byte trailer is consumed when present so stream boundaries stay aligned.
Routing unchanged packetsSupported with signing caveatForwarding generally uses the original raw frame bytes. Unsigned MAVLink 2 frames sent over signing-enabled connections are signed for that outbound link; already signed MAVLink 2 frames are forwarded unchanged.
Target inferenceSupportedGenerated metadata classifies broadcast, system, component, and system-component targets from target_system and target_component fields.
Route reset after rebootSupportedRouting tracks SYSTEM_TIME.time_boot_ms per source system/component and clears learned routes for that system when the same source reports a lower boot time.
XML includesSupported with limitsIncludes are recursive and deterministic. Missing includes, empty includes, include cycles, conflicting include paths, excessive include depth/count, and oversized XML files return explicit errors.
Enum mergingPartialMatching enum names are merged and sorted by value. Duplicate enum entries and duplicate resolved values are rejected.
Duplicate message idsSupported validationDuplicate message ids are rejected across the combined dialect, including included XML files.
XML bitmask="true"SupportedEnum-level bitmask declarations are parsed and used before heuristic bitmask detection.
XML identifiers and source generation safetyPartialXML is treated as trusted build input. The parser validates generated identifiers, rejects reserved enum/message/field names, and escapes generated docs/descriptions before source generation.
Generated Common dialectSupported within above scopelib/common.ex is regenerated from config/common.xml and should be treated as build output.

Changes Made In This Pass

  • Generated MAVLink 2 unpackers now accept extra trailing bytes after all locally known fields and ignore them as future extension fields.
  • Generated unpack specs now match the actual unpack/3 runtime API and include an unpack/3 fallback.
  • Generated modules now compile for XML dialects with no enums or units.
  • Enum-level bitmask="true" is parsed and reflected in generated field types, packing, and unpacking.
  • Generated MAVLink 2 packers use zero-equivalent defaults for omitted known extension fields.
  • MAVLink 2 signed frames now parse the 13-byte signature trailer into frame metadata.
  • Low-level MAVLink 2 frame signing can set the signed incompatibility flag, recalculate checksum bytes, and append a generated signature trailer for an already packed frame.
  • Low-level MAVLink 2 signing validation can verify signed frames and reject replayed or too-old timestamps.
  • Inbound router and connection signing policy can verify signed MAVLink 2 frames before unpacking, track replay state per connection, and reject unsigned MAVLink 2 frames by default while signing is enabled.
  • Outbound router signing can sign unsigned MAVLink 2 frames on signing-enabled connections while leaving MAVLink 1 frames unsigned.
  • Signing policy can load and save local signing timestamps through application callbacks, and rejects state-advancing frames when configured persistence fails.
  • Inbound SETUP_SIGNING frames are delivered locally but not forwarded between MAVLink connections by generic routing.
  • Learned routes are cleared for a remote system when the same system/component reports a lower SYSTEM_TIME.time_boot_ms, preventing stale targeted forwarding after reboot.
  • Unsupported signed MAVLink 2 frames consume the 13-byte signature trailer when present, preventing TCP/serial stream buffers from treating signature bytes as a new frame prefix.
  • MAVLink 2 packing now preserves a truly empty payload as length zero.
  • Core MAVLink integer types were tightened for the signed 32-bit minimum and unsigned 64-bit zero value.

Follow-Up Issues

  • #53: Continue aligning XML parser/generator validation with mavgen.

These follow-ups should be prioritized by MAVLink 2 impact first. None of the reviewed gaps require new MAVLink 1-only work before 1.0.