Skip to main content

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
info

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

MethodDescription
.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 ValueNameDescription
0Best Effort (BE)Default, no special treatment
10Assured Forwarding 1 (AF11)Low priority assured
18Assured Forwarding 2 (AF21)Medium priority assured
26Assured Forwarding 3 (AF31)Medium-high priority assured
34Assured Forwarding 4 (AF41)High priority assured
46Expedited 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

PriorityReliabilityBehavior
Highreliable()Prioritized packets + guaranteed delivery
Highbest_effort()Prioritized packets, may still be lost
Lowreliable()Lower network priority but delivery guaranteed

Transport Priority + Latency Budget

Both are transport-layer hints:

PriorityBudgetNet Effect
High0msImmediate send with preferential network handling
High100msMay batch but packets get priority when sent
Low0msImmediate 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

  1. 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.

  2. 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.

  3. IntraProcess mode: Transport priority has no effect in IntraProcess transport mode since there are no network packets to prioritize.

  4. Root/CAP_NET_ADMIN: On Linux, setting high DSCP values may require elevated privileges (CAP_NET_ADMIN capability).

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