Skip to content

IPv6 QoS fix#3622

Open
rdica wants to merge 5 commits intojamulussoftware:mainfrom
rdica:IPv6-QoS-fix
Open

IPv6 QoS fix#3622
rdica wants to merge 5 commits intojamulussoftware:mainfrom
rdica:IPv6-QoS-fix

Conversation

@rdica
Copy link
Contributor

@rdica rdica commented Feb 7, 2026

Short description of changes

When IPv6 is enabled, this provides a fix to properly typecast tos so setsockopt can properly add DSCP field value.
Also adds error checking for setsockopt() calls and ensures correct QoS operation for dual-protocol sockets.

CHANGELOG: Client+Server: Correct QoS setting for IPv6

Context: Fixes an issue?

Fixes: #3623

Does this change need documentation? What needs to be documented and how?
No, just a bugfix

Status of this Pull Request

What is missing until this pull request can be merged?

Needs testing on all but Linux OSes.

Checklist

  • I've verified that this Pull Request follows the general code principles
  • I tested my code and it does what I want
  • My code follows the style guide
  • I waited some time after this Pull Request was opened and all GitHub checks completed without errors.
  • I've filled all the content above

@ann0see ann0see requested a review from softins February 7, 2026 20:31
@ann0see ann0see added the bug Something isn't working label Feb 7, 2026
@github-project-automation github-project-automation bot moved this to Triage in Tracking Feb 7, 2026
@ann0see ann0see marked this pull request as draft February 7, 2026 20:48
@ann0see ann0see marked this pull request as ready for review February 8, 2026 10:24
Copy link
Member

@softins softins left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've been doing some tests of this on Linux (RPi), and it needs a little more investigation.

I verified that the setsockopt() previously returned an error, and that with this fix it succeeds.

I also tested it with different QoS values for server and client, running on the same machine connecting via localhost (::1) on IPv6, while monitoring the traffic with Wireshark. The correct QoS (DSCP+ECN) was sent from each end.

However, if the client initiated the connection to 127.0.0.1 instead, to force an IPv4 connection, both ends sent a QoS value of 0.

If I started the client without -6, and connected to 127.0.0.1 or to localhost, then the traffic from the client to the server carried the expected QoS value, but that from the server (still running with -6, so a dual-protocol socket) back to the client sent QoS of 0.

So I need to check how to get a dual-stack socket to send the correct QoS value when it has an IPv4 connection. Maybe it will also accept the setsockopt ( UdpSocket, IPPROTO_IP, IP_TOS, ...) call?

@softins
Copy link
Member

softins commented Feb 8, 2026

So I need to check how to get a dual-stack socket to send the correct QoS value when it has an IPv4 connection. Maybe it will also accept the setsockopt ( UdpSocket, IPPROTO_IP, IP_TOS, ...) call?

Yes, it works. I'll update the PR directly.

@softins softins self-assigned this Feb 8, 2026
@softins softins added this to the Release 3.12.0 milestone Feb 8, 2026
@softins
Copy link
Member

softins commented Feb 9, 2026

I have done some builds on Windows. Here are my findings:

  1. IPV6_TCLASS is not supported on Windows and returns an error from setsockopt()
  2. IP_TOS is supported on Windows, but appears to do nothing. Whatever value I give it, the Differentiated Services Field in the IPv4 header is always zero.

Looking at https://learn.microsoft.com/en-us/previous-versions/windows/desktop/qos/sending-qos-enabled-data it would appear that setting QoS in Windows uses a completely different API from that on Linux.

For 3.12.0, I would suggest that we just specify QoS is not supported on Windows. We may want to reject -Q or emit a warning that it is ignored.

It would be worth checking on Mac too, but hopefully that should be ok, as Mac is Unix-based.

@pljones pljones moved this from Triage to Waiting on Team in Tracking Feb 9, 2026
@pljones
Copy link
Collaborator

pljones commented Feb 9, 2026

I vaguely remember a long and detailed explanation of what was needed to explain to Windows (10 at the time, IIRC) that QoS/TOS should be respected. This was either on the original PR or in the issue or discussion it was related to. It's probably worth digging that up and reviewing it.

@pljones pljones moved this from Waiting on Team to In Progress in Tracking Feb 9, 2026
@softins
Copy link
Member

softins commented Feb 9, 2026

It would be worth checking on Mac too, but hopefully that should be ok, as Mac is Unix-based.

Sadly, it doesn't work completely on macOS. Using IP_TOS on an AF_INET socket works to set TOS for IPv4, and using IPV6_TCLASS works to set TOS for IPv6 traffic. But macOS doesn't accept the IP_TOS call on an AF_INET6 socket in the way that Linux does, so there is no way on macOS or iOS, when IPv6 is enabled, to set the default TOS for IPv4 traffic.

ChatGPT confirmed this is the case, and suggested the best way round it would be to create a drop-in replacement for sendto() called sendto_with_tos(), that uses sendmsg() to set the TOS for each outgoing packet. It said this would be compatible with Linux too. Although not with Windows.

@softins
Copy link
Member

softins commented Feb 9, 2026

Well so far, I have #if-ed out the calls that will error on Windows and Apple. With this change, the following are true:

  1. On Linux and Android, QoS will be correctly sent for all traffic whether or not the -6 option was given, including traffic sent to an IPv4 address via an IPv6 socket (-6 given).
  2. On macOS and iOS, QoS will be correctly sent for all (IPv4) traffic if -6 was not given. If -6 was given to enable IPv6 support, QoS will be correctly sent for traffic to an IPv6 address, but is not sent (field is always zero) with traffic to an IPv4 address.
  3. On Windows, QoS is never sent - the field is always zero.

@pljones
Copy link
Collaborator

pljones commented Feb 10, 2026

Gemini says for Windows (though I didn't check versions):
...

qWAVE (Quality Windows Audio/Video Experience)
This is the modern, recommended API for Windows applications (especially multimedia) to handle QoS. It handles both the marking of packets and the "bandwidth admission" (checking if the network can handle the stream).
Header: qos2.h
Library: Qwave.dll
Functionality: It uses "Traffic Types" rather than raw hex values:

Traffic Type Description DSCP Value (Approx)
QOSTrafficTypeBestEffort Standard traffic 0
QOSTrafficTypeBackground Low priority 8
QOSTrafficTypeVideo Video streaming 34 (AF41)
QOSTrafficTypeVoice VoIP/Audio 46 (EF)
QOSTrafficTypeControl Network control 48

Sounds like it's very version specific but originated around Windows Vista/7 and was fully supported in Windows 10 onwards. (Not Windows Server, though.)

It did also reference the "hack" I vaguely remembered:

The Registry "Fix": To make Windows respect the user-defined TOS value via Winsock, you must often set a registry key:
Path: HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Tcpip\Parameters
Value: DisableUserTOSSetting (DWORD) set to 0.

And then "Socket Option: IPPROTO_IP level, option IP_TOS", so long as Group Policy allows it.

I think I went with group policy:

"Any traffic from 'MyApp.exe' should be marked with DSCP 46."

I'd imagine the NSIS installer has a Group Policy hook? Maybe it could be done there.

@pljones
Copy link
Collaborator

pljones commented Feb 10, 2026

And it found the original discussion for me: https://github.com/orgs/jamulussoftware/discussions/1072
And that has the PR linked: #1310

The original discussion makes a good point: the application itself should know the right value -- it shouldn't be the user picking numbers at random from the command line.

@softins
Copy link
Member

softins commented Feb 11, 2026

Interesting stuff. So what to do with this PR, and what to defer to another? This one has already improved a bit on @rdica's original, without much radical change, and now fully works on Linux. It seems to me that this is worth merging now for 3.12.0, and then we raise two more separate PRs for after 3.12.0:

  1. Add use of sendmsg() when required for correct sending of TOS for IPv4 over an AF_INET6 socket on macOS and iOS.
  2. Implementation of TOS in the right way for Windows.

Comments?

@softins
Copy link
Member

softins commented Feb 11, 2026

The original discussion makes a good point: the application itself should know the right value -- it shouldn't be the user picking numbers at random from the command line.

Yes, agreed. Although if -Q is not specified, the default number in Jamulus is 0x80, which is DSCP of CS4 and ECN of 0, giving improved priority over untagged traffic.

It would be worth understanding which other values are useful for Jamulus, and providing useful names for the user to specify them. Again, post-3.12

@pljones
Copy link
Collaborator

pljones commented Feb 12, 2026

On Linux, it looks like I use -Q 184 for Servers and -Q 96 for Directories (with -u 1 - not intended for real-time audio). So I guess it does need to be flexible.

On Windows, it looks like my move from Windows 10 to Windows 11 lost the QoS/TOS settings. I will have to rectify that.


image

Hm. So "Windows Group Policy Editor, Computer Configuration, Windows Settings, Policy-based QoS, (right-click) Advanced QoS Settings, DSCP Marking Override" claims to be able to allow DSCP from applications...

https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-R2-and-2012/jj159288(v=ws.11)#advanced-qos-settings-dscp-marking-override

"Last updated on 08/31/2016" -- so presumably wrong.

Trying to find any new documentation on this proved impossible...


https://learn.microsoft.com/en-us/windows/configuration/wcd/wcd-networkqospolicy

https://learn.microsoft.com/en-us/windows/client-management/mdm/networkqospolicy-csp

It looks like there's some kind of support for QoS still but it's buried...

@pljones
Copy link
Collaborator

pljones commented Feb 12, 2026

Personally, if we're going to be making changes, I'd rather they were complete. I'm not seeing a pressing need to include it in 3.12.0 yet.

All the below are subject to the carrier respecting QoS:

Will Clients see benefit for traffic from Servers with QoS enabled, whether or not the Client has it enabled?

Will Clients with QoS enabled see benefit for traffic to Servers, whether or not the Server has it enabled?

Server operators as a whole don't "get benefit", they just offer service. We're seeing a growing take up of new versions but there is still a large number of legacy servers out there. Obviously, the IPv6 server operators are more likely to be ones who update but that's not a given.

I'd imagine the user base of the Client is Windows > macOS > Linux with Windows pretty dominant, with that applying regardless of IPv6 use or not.

So does that means most users won't get any further benefit from this other than what a Server can offer?

How does it stack up for macOS and Linux Client users?

@ann0see
Copy link
Member

ann0see commented Feb 12, 2026

I believe QOS is mostly helpful in theory but not so much in practice. I don't have sources on this though.
On the other hand:
IPv6 is very important IMO and should not be handled as second citizen.

@pljones
Copy link
Collaborator

pljones commented Feb 12, 2026

I believe QOS is mostly helpful in theory but not so much in practice. I don't have sources on this though. On the other hand: IPv6 is very important IMO and should not be handled as second citizen.

Quite, so all users should expect to see the benefit from any change, not see it limited to a subset with some feeling sidelined.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

QoS argument not applying specified value to differentiated services field in packets when IPv6 enabled - linux clients

4 participants