Transport Priority QoS Policy
The Transport Priority policy provides a hint to the DDS middleware about the importance of data, which can be used to control network-level prioritization through DSCP (Differentiated Services Code Point) or ToS (Type of Service) IP header fields.
Purpose
Transport Priority enables traffic differentiation:
- High-priority data (alarms, commands) gets preferential network treatment
- Normal data (sensors, status) uses default network handling
- Low-priority data (logs, diagnostics) yields to other traffic
Transport Priority is a hint to the middleware. Actual network prioritization depends on OS socket options (SO_PRIORITY, IP_TOS), NIC capabilities, and network infrastructure (DSCP-aware switches and routers).
Configuration
use hdds::{Participant, QoS, TransportMode};
let participant = Participant::builder("priority_app")
.domain_id(0)
.with_transport(TransportMode::UdpMulticast)
.build()?;
// High-priority alarm writer
let alarm_writer = participant
.topic::<Alert>("system/alarms")?
.writer()
.qos(QoS::reliable().transport_priority(10))
.build()?;
// Normal-priority telemetry writer
let telemetry_writer = participant
.topic::<SensorData>("sensors/temperature")?
.writer()
.qos(QoS::best_effort().transport_priority(0))
.build()?;
// Low-priority log writer
let log_writer = participant
.topic::<LogEntry>("system/logs")?
.writer()
.qos(QoS::best_effort().transport_priority_low())
.build()?;
#include <hdds.h>
/* High-priority alarm writer */
struct HddsQoS* qos_alarm = hdds_qos_reliable();
hdds_qos_set_transport_priority(qos_alarm, 10);
struct HddsDataWriter* alarm_writer = hdds_writer_create_with_qos(
participant, "system/alarms", qos_alarm);
hdds_qos_destroy(qos_alarm);
/* Low-priority telemetry writer */
struct HddsQoS* qos_telem = hdds_qos_reliable();
hdds_qos_set_transport_priority(qos_telem, 0);
struct HddsDataWriter* telem_writer = hdds_writer_create_with_qos(
participant, "sensors/temperature", qos_telem);
hdds_qos_destroy(qos_telem);
Default Value
Default is 0 (normal priority):
let qos = QoS::reliable();
// transport_priority.value = 0 (normal)
Fluent Builder Methods
| Method | Description |
|---|---|
.transport_priority(value) | Set custom priority value (higher = more important) |
.transport_priority_high() | Set high priority (value: 50) |
.transport_priority_low() | Set low priority (value: -50) |
.transport_priority_normal() | Set normal priority (value: 0) |
Priority Values and DSCP Mapping
The value field is an integer where higher values indicate more important data. The middleware maps this to network-level priority mechanisms:
Common DSCP Values
| DSCP Value | Name | Description |
|---|---|---|
| 0 | Best Effort (BE) | Default, no special treatment |
| 10 | Assured Forwarding 1 (AF11) | Low priority assured |
| 18 | Assured Forwarding 2 (AF21) | Medium priority assured |
| 26 | Assured Forwarding 3 (AF31) | Medium-high priority assured |
| 34 | Assured Forwarding 4 (AF41) | High priority assured |
| 46 | Expedited Forwarding (EF) | Low latency, low loss |
Priority Queue Diagram
Priority Queues
+------------------+
Alarm (pri=10) -->| HIGH [A][A][A] |---> Network (DSCP EF)
+------------------+
| |
Telemetry (0) -->| LOW [T][T][T] |---> Network (DSCP BE)
+------------------+
Under congestion, high-priority traffic is sent first.
OS and NIC must support traffic classification for full effect.
Compatibility Rules
Transport Priority does not affect compatibility. Writers and readers always match regardless of their priority settings.
Use Cases
Emergency Data Prioritization
use hdds::{Participant, QoS, TransportMode};
let participant = Participant::builder("safety_system")
.domain_id(0)
.with_transport(TransportMode::UdpMulticast)
.build()?;
// Emergency stop: highest priority
let e_stop_writer = participant
.topic::<EmergencyStop>("safety/e_stop")?
.writer()
.qos(QoS::reliable().transport_priority(100))
.build()?;
// Normal sensor: default priority
let sensor_writer = participant
.topic::<SensorData>("sensors/data")?
.writer()
.qos(QoS::best_effort().transport_priority(0))
.build()?;
Multi-Tier Traffic Classification
use hdds::{Participant, QoS, TransportMode};
let participant = Participant::builder("classified_app")
.domain_id(0)
.with_transport(TransportMode::UdpMulticast)
.build()?;
// Tier 1: Safety-critical (highest)
let safety = participant
.topic::<SafetyData>("safety/data")?
.writer()
.qos(QoS::reliable().transport_priority(100))
.build()?;
// Tier 2: Control commands (high)
let control = participant
.topic::<ControlData>("control/commands")?
.writer()
.qos(QoS::reliable().transport_priority_high())
.build()?;
// Tier 3: Telemetry (normal)
let telemetry = participant
.topic::<SensorData>("sensors/data")?
.writer()
.qos(QoS::best_effort().transport_priority_normal())
.build()?;
// Tier 4: Logging (low)
let logs = participant
.topic::<LogEntry>("system/logs")?
.writer()
.qos(QoS::best_effort().transport_priority_low())
.build()?;
DSCP-Aware Network Integration
use hdds::{Participant, QoS, TransportMode};
let participant = Participant::builder("dscp_app")
.domain_id(0)
.with_transport(TransportMode::UdpMulticast)
.build()?;
// Map to DSCP Expedited Forwarding (46)
let ef_writer = participant
.topic::<VoiceData>("voice/stream")?
.writer()
.qos(QoS::best_effort().transport_priority(46))
.build()?;
// Map to DSCP Assured Forwarding (26)
let af_writer = participant
.topic::<VideoData>("video/stream")?
.writer()
.qos(QoS::best_effort().transport_priority(26))
.build()?;
Interaction with Other Policies
Transport Priority + Reliability
| Priority | Reliability | Behavior |
|---|---|---|
| High | reliable() | Prioritized packets + guaranteed delivery |
| High | best_effort() | Prioritized packets, may still be lost |
| Low | reliable() | Lower network priority but delivery guaranteed |
Transport Priority + Latency Budget
Both are transport-layer hints:
| Priority | Budget | Net Effect |
|---|---|---|
| High | 0ms | Immediate send with preferential network handling |
| High | 100ms | May batch but packets get priority when sent |
| Low | 0ms | Immediate send but lower network priority |
OS Configuration for DSCP
For Transport Priority to have real effect, the operating system must be configured:
Linux
# Set DSCP marking via tc (traffic control)
tc qdisc add dev eth0 root handle 1: prio
# Or via iptables
iptables -t mangle -A OUTPUT -p udp --dport 7400:7500 \
-m tos --tos 0xB8 -j MARK --set-mark 1
Socket-Level
The middleware maps the priority value to IP_TOS or SO_PRIORITY socket options:
int tos = 0xB8; /* DSCP EF (46) << 2 */
setsockopt(sock, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
Common Pitfalls
-
No OS/network support: Without DSCP-aware infrastructure, transport priority has no effect on actual delivery. The middleware sets the appropriate socket options, but switches and routers must honor them.
-
Negative priority values: HDDS supports negative values (e.g., -50 for
low()), which map to below-normal handling. Some network stacks may not support negative priorities. -
IntraProcess mode: Transport priority has no effect in IntraProcess transport mode since there are no network packets to prioritize.
-
Root/CAP_NET_ADMIN: On Linux, setting high DSCP values may require elevated privileges (
CAP_NET_ADMINcapability).
Performance Notes
- Transport Priority adds zero runtime overhead (set once at entity creation)
- Actual prioritization depends on OS network stack and hardware
- On QoS-aware networks, priority can significantly reduce latency for critical traffic
- Without network support, all traffic is treated equally regardless of priority setting
Next Steps
- Latency Budget - Delivery latency hints
- Resource Limits - Memory bounds
- Overview - All QoS policies