How to configure DSCP ?

Mar 12, 2026
5
0
1
Hello everyone,

Following the latest release of Corosync, the totem.ip_dscp option was introduced. I would like to explore this feature and have implemented it on a 4-node cluster as follows:

I modified the /etc/corosync/corosync.conf file by adding
ip_dscp: 48 to the totem section. After that, I restarted the service because the logs indicated that this setting is not applied on the fly.

Next, I captured packets at the VLAN subinterface, the bridge, and the bond. None of these tcpdump captures showed my DSCP value of 48; strangely, it is set to 4.

1780317797267.png

Is there any official documentation from Proxmox on how to use DSCP with Corosync?

Thank you in advance.
 
Could it be due to the internal bit shift [0]?
ip_dscp This specifies the dscp (differentiated services code point) value to be used in the IP header's type of service (TOS) field according to RFC 2474. Allowed values are 0-63 and symbolic dscp names cs0, cs1, cs2, cs3, cs4, cs5, cs6, cs7, af11, af12, af13, af21, af22, af23, af31, af32, af33, af41, af42, af43 and ef. Value 0 disables the dscp support. Use of TOS field then depends on the used transport. If ip_dscp is set to a value not equal to zero, and an appropriate socket option (IP_TOS) is available, the value is put into the upper six bits of the TOS header field.

Could you test with ip_dscp 12? Remember to increase the config_version [1].

[0] https://manpages.debian.org/unstable/corosync/corosync.conf.5.en.html#ip_dscp
[1] https://pve.proxmox.com/pve-docs/pve-admin-guide.html#pvecm_edit_corosync_conf
 
Of course, I had already increased the config_version.
1780320872561.png
I ran the test again with a value of 12. As you can see in the screenshot, Corosync does take the configuration into account, but when I look at my dump, I still see the same thing...
1780321045899.png
 
Hello,

I can confirm the same behaviour reported earlier in this thread, on a different cluster, with additional diagnostic steps that rule out a "config not applied" or "service not restarted" explanation.

Environment
  • Proxmox VE: 9.2.4
  • Corosync: 3.1.10-pve2
  • Transport: knet
  • 5-node cluster, Corosync/Live Migration on a dedicated VLAN (bond0.121), separate from VM and storage traffic

Configuration

totem {
version: 2
config_version: X
cluster_name: ...
ip_dscp: ef
...
}

I also tested ip_dscp: 46 and ip_dscp: 0 (to rule out a symbolic-name parsing issue) — same result in all cases.

Step 1 — Config propagation via pmxcfs

The file is managed at /etc/pve/corosync.conf (replicated by pmxcfs to /etc/corosync/corosync.conf on all nodes). Editing it alone triggers an automatic hot-reload attempt from pmxcfs, which correctly logs:
Modified entry 'totem.ip_dscp' in corosync.conf cannot be changed at run-time
This confirms ip_dscp requires a full process restart, as documented.

Step 2 — Explicit cold restart, confirmed clean

To make sure the parameter was actually loaded fresh (not just reloaded), I ran systemctl restart corosync and checked the full journal for that specific PID transition:

Stopping corosync.service...
[MAIN ] Corosync Cluster Engine exiting normally
Stopped corosync.service.
Starting corosync.service...
[MAIN ] Corosync Cluster Engine starting up
[TOTEM ] Initializing transport (Kronosnet).
[TOTEM ] totemknet initialized
...
[QUORUM] Members[5]: 1 2 3 4 5
[MAIN ] Completed service synchronization, ready to provide service.

No cannot be changed at run-time warning appears in this cold-start sequence — this was a genuine fresh process start with a new PID, and the cluster regained full quorum normally afterwards (pvecm status confirmed 5/5 members quorate).

Step 3 — Capture after confirmed cold restart

Bash:
tcpdump -v -i bond0.121 udp portrange 5404-5412 -c 5

IP (tos 0x10, ttl 64, id 0, offset 0, flags [DF], proto UDP (17), length 108)
192.168.88.2.5405 > 192.168.88.5.5405: UDP, length 80

tos stays at 0x10 (DSCP 4) regardless of whether ip_dscp was set to ef, 46, or 0 — the value never changes, which suggests it isn't reading the config at all on the knet code path, rather than applying a wrong value.

Workaround in use

Since the native option doesn't seem to take effect with knet, I've marked the traffic at the netfilter layer instead, which works reliably:

Bash:
nft add table inet mangle
nft add chain inet mangle output { type filter hook output priority mangle \; }
nft add rule inet mangle output ip daddr 192.168.88.0/24 udp dport 5404-5412 ip dscp set ef

This confirms the DSCP marking itself isn't blocked anywhere downstream (switches, bonding, VLAN subinterfaces) — packets do leave with tos 0xb8 once marked this way, so the issue appears isolated to Corosync/knet not applying totem.ip_dscp to the socket.

Happy to provide further logs (journalctl -u corosync full startup, corosync-cfgtool -s, or anything else) if useful for tracking this down. Given this reproduces on two independent clusters with different hardware, it does look like a genuine bug rather than an environment-specific issue.
 
Hi everyone,

thank you for your patience!

I can happily report that with corosync 3.1.10-pve3 (currently on testing repo) and libknet1t64_1.34-pve1 (enterprise-stable) the DSCP value will be applied properly.
Support for this depended on the latter package update and needed a rebuild of corosync against this new package. That's why this took some time.

Best regards
Jonas
 
  • Like
Reactions: YaZoal
Hi everyone,

thank you for your patience!

I can happily report that with corosync 3.1.10-pve3 (currently on testing repo) and libknet1t64_1.34-pve1 (enterprise-stable) the DSCP value will be applied properly.
Support for this depended on the latter package update and needed a rebuild of corosync against this new package. That's why this took some time.

Best regards
Jonas


Hello,

Thank you for your response. Is the version now available?

Thanks again, @j.theisen, for the quick diagnosis you provided via the ticket.

I won’t hide the fact that I had to switch to prioritizing the entire VLAN via TC and disable the switch for production deployment purposes, but I’m glad I was able to report the issue so that other members can take advantage of this feature, which can be very useful.

Best regards
 
strangely, it is set to 4
Before DSCP / RFC 2474 there was the original TOS from RFC 1349. This still is in use in some places like iptables and apparently corosync. There the (set bit of the) observed value of 000-1000-0 means Minimize-Delay.
 
Last edited:
Hi all,

Closing the loop on this thread with good news: the issue is fixed.

After corosync and libknet1t64 were updated to 3.1.10-pve3 / 1.35-pve1 (available now in pve-no-subscription), ip_dscp works as documented. I tested on two separate 5-node clusters:

  1. Full apt update && apt upgrade on all nodes first (important — updating only corosync without the matching libknet1t64 won't fix it, since the fix depends on both).
  2. Set ip_dscp: 46 (or the symbolic name ef) in totem, bumped config_version.
  3. Restarted corosync node by node, confirming quorum with pvecm status between each.
  4. Verified with tcpdump -i <corosync_iface> udp portrange 5404-5412 — packets now consistently show tos 0xb8 from every node.

Per the Corosync devs' explanation, the older packages were compiled against a libknet version without HAVE_KNET_SETPRIO_DSCP support, so the config was accepted silently but never actually applied to the socket — hence the tos 0x10 (IPTOS_LOWDELAY) everyone here was seeing regardless of the configured value.

If anyone's still on pve2 and needs this working now, marking the traffic with nftables (inet mangle, output chain, ip dscp set ef) is a solid interim workaround — that's what got me through until this update landed.

Thanks to everyone who chimed in on this thread, and to the Corosync maintainers for tracking it down so quickly.
 
  • Like
Reactions: Johannes S
Just for the avoidance of doubt as the person who answered you over on GH - I am not one of corosync developers (just an occasional contributor) :)