A two-camera vehicle: marks or flow rules opt-in · needs [qos]
A vehicle with a primary camera and a thermal camera sends both into the Video lane. When the bond narrows, the lane sheds — and unless the two streams carry different precedence levels, it sheds them alike. This guide gives the primary camera level 0 and the second camera level 1, so the second one absorbs the loss, and shows how to confirm it from the counters.
[qos] enabled = true on the sending node (levels are set where traffic enters the tunnel; receivers and relays need nothing new), the cameras' tunnel-side addresses and stream ports, and access to GET /api/qos or the dashboard's QoS tab.When the camera can mark its packets
Many IP cameras and encoders let you set a DSCP value for their stream. Use the Assured Forwarding class 4 marks, which the classifier reads as Video with a level:
AF41(DSCP 34) — Video, level 0, primaryAF42(DSCP 36) — Video, level 1, secondaryAF43(DSCP 38) — Video, level 2, tertiary
Set AF41 on the primary camera and AF42 on the second. Nothing in the Atlas configuration changes. The same scheme exists for telemetry with AF31 to AF33. Marks are the better choice whenever they are available: they travel with the stream, so a camera that changes address keeps its level.
When it cannot: flow rules
A camera without a DSCP setting, or one whose marks something on the path rewrites, gets its level from a [[qos.flow]] rule on the node it sends through. A rule matches a source prefix, a destination port, or both, and names a class and a level. Rules are tried before marks, so a rule also overrides a mark you do not trust.
[qos]
enabled = true
# Primary camera on a fixed address
[[qos.flow]]
src = "10.0.9.20/32"
class = "Video"
level = 0
# Thermal camera on the same vehicle
[[qos.flow]]
src = "10.0.9.21/32"
class = "Video"
level = 1
Match on src alone when each camera has its own address — the usual case for cameras on the vehicle LAN. Add dst_port when one device sends several streams and only one of them should change level, or use dst_port alone when the ground side assigns each camera its own port. Run atlasd config check before restarting: it rejects an unknown class name, a level above 2, a malformed prefix, and a rule with neither src nor dst_port.
Levels share the class budget unless you set one per level. A secondary feed that is only useful when fresh can be given a tighter budget, and a tertiary one a looser one, with budget_by_level_ms under [qos.classes.Video]; without it the levels get 1, 1.5 and 2 times the class budget.
Checking it with per-level counters
Once the second camera has carried traffic, GET /api/qos shows a levels array under the Video class — primary, secondary, tertiary — and the QoS tab shows the same figures as a table:
curl -s -H "Authorization: Bearer $TOKEN" http://node-a:9800/api/qos \
| jq '.classes[] | select(.class == "Video") | .levels'
Each entry carries enqueued, sent and the drops by reason (dropped_late, dropped_aqm, dropped_infeasible, dropped_queue_full). Under congestion the secondary entry should take the drops while the primary's sent keeps pace with its enqueued. If both levels lose packets alike, the levels are not being set: a levels array that never appears means everything still arrives at level 0, so check the rule's prefix against the camera's real source address, or the camera's DSCP setting. For dashboards, atlas_qos_level_dropped_packets_total carries the same figures with level and reason labels.
The video governor
If the cameras' bitrates are steered by the Atlas video governor, run one instance per camera and give each its level with --camera-level 0 or --camera-level 1. Each instance reads the per-level drop counters: while only a lower level is being shed it holds its camera's profile, whatever the link health says; when its own level is being shed it steps its camera down at once. The thermal camera's encoder therefore backs off first, which frees capacity before the primary is touched. Without --camera-level an instance follows link health alone.
Boundaries
Levels order loss inside one class; they do not move traffic between classes or reserve capacity for a camera. Flow rules match source prefix and destination port only. Levels are set on the node where the stream enters the tunnel, so the rule belongs on the vehicle, not on the ground station.