Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IP Differentiated Services on Windows #61

Open
paullouisageneau opened this issue Nov 21, 2020 · 5 comments
Open

IP Differentiated Services on Windows #61

paullouisageneau opened this issue Nov 21, 2020 · 5 comments
Labels
enhancement New feature or request

Comments

@paullouisageneau
Copy link
Owner

IP Differentiated Services by setting the IPv4 ToS field or the IPv6 Traffic Class field are not supported on Microsoft Windows. Microsoft has a proprietary API called qWave for QoS, it should be investigated to establish whether the DSCP can be set without administrator flow configuration.

// TODO: Investigate if DSCP can be still set directly without administrator flow configuration.

@paullouisageneau paullouisageneau added the enhancement New feature or request label Nov 21, 2020
@paullouisageneau paullouisageneau changed the title IP Differentiated Services are not supported on Windows IP Differentiated Service on Windows Nov 21, 2020
@paullouisageneau paullouisageneau changed the title IP Differentiated Service on Windows IP Differentiated Services on Windows Nov 21, 2020
@edbek
Copy link

edbek commented Jan 3, 2022

Explain, please. Does it happen that the libjuice does not work on Windows and I only need to use Linux?

@paullouisageneau
Copy link
Owner Author

paullouisageneau commented Jan 3, 2022

As advertised in the Readme, libjuice works fine on Windows.

Differentiated Services allow to set the proper priority on packets, allowing to optimize latency for real-time traffic. The feature is not available on Windows for now, so performance can be slightly lower for some use cases. Nothing serious, though.

@impromptu1583
Copy link

impromptu1583 commented Jan 5, 2025

I've successfully deployed some experimental testing on another project and wanted to share what I learned.

If the qwave service is already running then you can add a socket to one of the existing traffic classes (see QOSTrafficType) without admin elevation. Admin flow is only needed for setting arbitrary dscp values, using adaptive flow, or starting the service if it's not already started (in which case you could just log an error requesting the user install/start the service or set it to start on boot. See here)

A basic implementation would be:

edit: So the win32 section of udp_set_diffserv could look something like this:

#ifdef _WIN32
	HANDLE qos_handle = 0; // TODO: QOSCreateHandle in the winsock init code
	QOS_FLOWID flow_id = 0; // TODO: this would be stored in juice_agent probably
	QOS_TRAFFIC_TYPE qos_type; // TODO: this would be stored in juice_agent probably
	
	// convert arbitrary ds value to appropriate bucketed default class
	QOS_TRAFFIC_TYPE new_qos_type = QOSTrafficTypeBestEffort;
	if (0 < ds < 0x29) {
		new_qos_type = QOSTrafficTypeAudioVideo; // dscp = 0x28, 802.1p = 5 if needed
	}
	else if (ds) {
		new_qos_type = QOSTrafficTypeControl; // dscp = 0x38, 802.1p = 7 if needed
	}
	if (qos_type == new_qos_type) {
		return 0; // already assigned correct flow
	}
	if(flow_id) {
		// remove from existing flow  ID, not sure if this is required
		QOSRemoveSocketFromFlow(qos_handle, sock, flow_id, 0);
		flow_id = 0;
	}
	if(!QOSAddSocketToFlow(qos_handle, sock, 0, new_qos_type, QOS_NON_ADAPTIVE_FLOW, &flow_id)){
		JLOG_ERROR("Adding socket to QWAVE failed, errno=%d",GetLastError());
		return -1;
	}
	return 0;
#else

@paullouisageneau
Copy link
Owner Author

Thank you for sharing! The API design is ludicrous to me, all other OSes simply have a setsocketopt with an int argument. Is the service running by default with correct default classes?

Expedited Forwarding (DSCP 46 = 0x2e) is also used for audio, I guess it should be mapped to QOSTrafficTypeVoice.

@impromptu1583
Copy link

impromptu1583 commented Jan 7, 2025

I did some additional testing and at least on my windows 11 laptop the service seems to be running on boot by default with all the listed classes available. Definitely agree about the design, seems both needlessly complex and strangely inflexible at the same time.

I'm really not sure what the difference is between QOSTrafficTypeVoice and QOSTrafficTypeControl. (and between QOSTrafficTypeExcellentEffort and QOSTrafficTypeAudioVideo) When I read that they use the same DSCP and 802.1q tags for both flows I thought there must be a mistake in the documentation but I validated via wireshark and they do indeed use the same codepoints. I suppose there's maybe some prioritization that happens on the local machine that goes beyond the DSCP tag.

I notice mumble tries to load the DLL before calling QOSCreateHandle, perhaps to address this issue so that's something to think about as well. I don't know if that's actually necessary - seems like there should be a more elegant way to handle it.

Also in my testing QOSRemoveSocketFromFlow does not seem to be necessary before changing flows or cleanup.

So you can probably get away with not storing the flow_id as long as you're not planning to try to implement the adaptive flow features. That might make things quite a bit simpler to implement:

#ifdef _WIN32
	HANDLE qos_handle = 0; // TODO: QOSCreateHandle in the winsock init code
	
	// convert arbitrary ds value to appropriate bucketed default class
	QOS_TRAFFIC_TYPE qos_type = QOSTrafficTypeBestEffort;
	if (0 < ds < 0x29) {
		qos_type = QOSTrafficTypeAudioVideo; // dscp = 0x28, 802.1p = 5 if needed
	}
	else if (ds) {
		qos_type = QOSTrafficTypeControl; // dscp = 0x38, 802.1p = 7 if needed
	}

	QOS_FLOWID flow_id = 0;
	if(!QOSAddSocketToFlow(qos_handle, sock, 0, new_qos_type, QOS_NON_ADAPTIVE_FLOW, &flow_id)){
		JLOG_ERROR("Adding socket to QWAVE failed, errno=%d",GetLastError());
		return -1;
	}
	return 0;
#else

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants