v0.22.0 — TSN (IEEE 802.1) QoS integration (dds::tsn)
Added
dds::tsn::Stream/StreamConfig(include/dds/tsn/tsn.hpp,src/tsn/tsn.cpp) — a C++ port of go-DDS'stsn/tsn.go, the fourth and last item ofROADMAP.md's "Tier 3 — xtypes, tsn, idl, cdr" (now fully complete).load_config()/parse_config()parse the identical JSONtsn_streamsshape via a small internal recursive-descent JSON reader scoped to exactly this config shape, matching this repo's established small-purpose-built-parser convention rather than a general-purpose dependency.include/dds/rtps/tsn.hppmirrors go-DDS'srtps/tsn.gosplit exactly:TSNParams/TSNStreamConfiglive insidedds::rtpsitself sodds::rtpsnever depends ondds::tsn.dds::tsn::StreamConfigAdapter/with_stream_config()is the adapter, assigned to a newParticipantOptions::tsn_configfield.include/dds/tsn/taprio.hpp+src/tsn/taprio.cpp—TAPRIOEntry/TAPRIOConfig(gate control list,cycle_duration()/validate()/tc_command()) plustaprio_from_streams(), all portable.src/tsn/taprio_linux.cpp(compiled only whenCMAKE_SYSTEM_NAMEis"Linux", mirroring Tier-1 phase 3'straffic_linux.cpp/traffic_other.cppsplit) programs and verifies the real Linuxtaprioqdisc via hand-builtRTM_NEWQDISC/RTM_GETQDISCnetlink messages overNETLINK_ROUTE— a byte-for-byte port of go-DDS'stsn/taprio_linux.goattribute layout, cross-checked field-by-field against a fresh go-DDS clone.src/tsn/taprio_other.cppreturns a documented "requires Linux" diagnostic everywhere else. Neitherapply()nor any TSN code is called automatically bydds::rtps::Participant, matching go-DDS's own participant.go.- Real
Participant/Writerwiring, not just types:ParticipantOptions::tsn_configset →new_publisherresolves each writer's topic against it (config match takes priority,QoS::transport_priority— a field that already existed — is the fallback PCP selector) and lazily creates/reuses one dedicatedUdpSocketper distinct PCP value, configured via the already-existing (Tier-1 phase 3)dds::rtps::traffic.hpphooks that had no caller anywhere in the codebase before this item.Writer::write()/send_heartbeat()route through that dedicated socket, computing aSO_TXTIMElaunch time for streams with a nonzerotx_offset. A TSN stream'smax_frag_payload()overridesfragment.hpp's default fragmentation threshold end-to-end. - 4 new cross-participant, real-loopback-UDP end-to-end tests plus 45 unit tests mirroring go-DDS's
tsn_test.go/taprio_test.gomatrices — 540/540 tests total.REQ-TSN-001throughREQ-TSN-007added, traced and tested.
Verified locally: Release C++17/C++20 builds clean, ctest 540/540, Debug ASan+UBSan pass on both macOS and a real Ubuntu-22.04/gcc-12 Docker container (exercising the actual Linux netlink code path). CI: all 13 checks green (Linux/macOS/Windows matrix, gcc-12 ASan+UBSan, cpp-FuSa full lifecycle).
Full changelog: https://github.com/SoundMatt/cpp-DDS/blob/main/CHANGELOG.md#0220--2026-07-28