A question about QOSAddSocketToFlow

In the Vista system, I write a program to test QOS and want to add a socket to the flow. But the QOSAddSocketToFlow function always return failed and the error code isERROR_NOT_SUPPORTED. Does anyone has idea about it?

My test program is listed as below.

// qostest.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <conio.h>
#include "qos2.h"

int _tmain(int argc, _TCHAR* argv[])
{
BOOL rc;
HANDLE hQOS;
QOS_VERSION verQoS;
QOS_FLOWID FlowId = 0;
WORD wPort;
DWORD dwIPAddr;
SOCKET sockQOS;
sockaddr_in sockDestAddr;
int errorcode;
char strIPAddr[20], strPort[10];

if(argc < 3)
{
printf("Usage: \n");
printf("qostest [ipaddr] [port]\n");
printf("qostest 10.100.1.137 10025\n");
return 0;
}

ZeroMemory(strIPAddr, sizeof(strIPAddr));
wcstombs(strIPAddr, argv[1], wcslen(argv[1]));
dwIPAddr = inet_addr(strIPAddr);
ZeroMemory(strPort, sizeof(strPort));
wcstombs(strPort, argv[2], wcslen(argv[2]));
sscanf_s(strPort, "%d", &wPort);

printf("start qos test...\n");

WORD wVersionRequested;
WSADATA wsaData;
int err;

wVersionRequested = MAKEWORD( 2, 2 );

err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 )
{
/* Tell the user that we could not find a usable */
/* WinSock DLL. */
printf("start winsock failed, rc=0x%x\n", err);
return 0;
}
/* Confirm that the WinSock DLL supports 2.2.*/
/* Note that if the DLL supports versions greater */
/* than 2.2 in addition to 2.2, it will still return */
/* 2.2 in wVersion since that is the version we */
/* requested. */

if ( LOBYTE( wsaData.wVersion ) != 2 ||
HIBYTE( wsaData.wVersion ) != 2 ) {
/* Tell the user that we could not find a usable */
/* WinSock DLL. */
WSACleanup( );
return 0;
}

/* The WinSock DLL is acceptable. Proceed. */
sockQOS = socket(AF_INET, SOCK_DGRAM, 0);
if(sockQOS == INVALID_SOCKET)
{
errorcode = WSAGetLastError();
printf("create socket failed, rc=0x%x\n", errorcode);
return 0;
}
sockDestAddr.sin_family = AF_INET;
sockDestAddr.sin_addr.s_addr = dwIPAddr;
sockDestAddr.sin_port = htons(wPort);

verQoS.MajorVersion = 1;
verQoS.MinorVersion = 0;
rc = QOSCreateHandle(&verQoS, &hQOS);
if(rc == 0)
{
errorcode = GetLastError();
printf("create qos handle failed, rc=0x%x\n", errorcode);
return 0;
}
rc = QOSAddSocketToFlow(hQOS, sockQOS, (PSOCKADDR)&sockDestAddr, QOSTrafficTypeVoice, 0, &FlowId);
if(rc == 0)
{
errorcode = GetLastError();
printf("add socket to flow failed, rc=0x%x\n", errorcode);
}
else
printf("add socket to flow successful.\n");

printf("Press any key to exit...");
_getch();

QOSCloseHandle(hQOS);

return 0;
}

Thanks.
[3413 byte] By [FrankZhong] at [2008-1-9]
# 1

By default, QOSAddSocketToFlow assumes you want to create an adaptive-flow, i.e. you want to do experiments with the destination host to estimate bottleneck bandwidth, available bandwidth, detect congestion, etc. These experiments are performed using the LLTD protocol, and are limited to the local subnet (link-local). Therefore, if your destination address is off-link (not on the same subnet as the sender), QOSAddSocketToFlow will return ERROR_NOT_SUPPORTED. If the destination is on the same local link as the sender, the LLTD Responder component must be listening. In Vista, this component is active only when the network profile of the NIC is set to "Private". Ensure that both the sender and receiver have their network profile as Private by going to the Network and Sharing Center. If the network lists "Public" or "Domain network", this component is not running, and ERROR_NOT_SUPPORTED will be returned. Please see the following blog post for more information about overriding default behavior of LLTD. http://blogs.msdn.com/wndp/archive/2006/11/03/enable_5F00_vista_5F00_network_5F00_map.aspx

If you do not intend to do any bandwidth estimation, etc., but rather are only interested in setting DSCP priority and/or throttling the send rate of the application, you can avoid all of this by setting the QOS_NON_ADAPTIVE_FLAG when calling QOSAddSocketToFlow. This will allow you to specify off-link destination addresses and get DSCP marking and throttling, but won't allow you to get information specific to adaptive-flows because LLTD will not be used.

A bug has been opened to get this flag documented correctly on MSDN.

GabeFrost[MSFT] at 2007-10-2 > top of Msdn Tech,Windows Networking Development,Network Quality of Service (QoS/qWAVE)...
# 2

Hi Gabe,

Thanks for your reply.

Now the QOSAddSocketToFlow function works by using QOS_NON_ADAPTIVE_FLAG. From captured UDP packet, I found the DSCP value was set to 0x38, the default value for voice.

Now I have another question, can I change this DSCP value to other value? It seemed no qWAVE APIs could be used to set this value.

Thanks,

Frank

FrankZhong at 2007-10-2 > top of Msdn Tech,Windows Networking Development,Network Quality of Service (QoS/qWAVE)...
# 3

There is currently no way with qWAVE to change the default value used. The default values are aligned with both WiFi WMM and DLNA standards. Check out the QoS category of the core networking blog for details. I've written about this in the past. http://blogs.msdn.com/wndp.

If you absolutely need to use another DSCP value, you would have to use either GQoS (qos.h/wshqos.dll) or traffic control (traffic.h/traffic.dll) with a filter. GQoS allows you to change the default values in the local Group Policy editor.

GabeFrost[MSFT] at 2007-10-2 > top of Msdn Tech,Windows Networking Development,Network Quality of Service (QoS/qWAVE)...
# 4

With some playing around I have noticed the following qWAVE traffic types map to these DSCP values

QOSTrafficTypeBestEffort = CS0

QOSTrafficTypeBackground = CS1

QOSTrafficTypeExcellentEffort = CS5

QOSTrafficTypeAudioVideo = CS5

QOSTrafficTypeVoice = CS7

QOSTrafficTypeControl = CS7

From this I conclude that qWAVE doesn't have access to CS2, CS3, CS4 or CS6. I am developing for IPv6, and need to use flows/filters, however GQoS traffic control doesn't support IPv6. Any plans to enhance qWAVE to include all DSCP?

fklassen at 2007-10-2 > top of Msdn Tech,Windows Networking Development,Network Quality of Service (QoS/qWAVE)...
# 5

We have an open work item in the next client release of Windows to allow an administrative caller to set an arbitrary DSCP value for both IPv4 and IPv6 sockets. The following blog post describes the default (currently non-changable) DSCP values for each traffic class: http://blogs.msdn.com/wndp/archive/2006/06/30/WiFi-QoS-Support-in-Windows-Vista-part-2.aspx

You are correct that traffic control (traffic.h/traffic.dll) does not support IPv6, thus you cannot set arbitrary DSCP for IPv6; however, GQoS does support IPv6 in Vista (not in XP). You can change the default conformant DSCP values used by GQoS in the PSched Group Policy settings. GQoS, while not ideal, is your only path to getting non-default DSCP values for IPv6 sockets until we add the ability to set arbitrary DSCP in qwave.

GabeFrost[MSFT] at 2007-10-2 > top of Msdn Tech,Windows Networking Development,Network Quality of Service (QoS/qWAVE)...
# 6

Hi Gabe,

I have a question about the WSAIoctl function. In Vista system, I call this function to add the RTP socket into the NETWORK_CONTROL flow. This function can be executed correctly. But I found the DSCP value was still 0 in the captured RTP packet, not the value of NETWORK_CONTROL flow. Do you know why?

My code is listed as below. Can you figure out some problem?

int rc;

QOS qos;
DWORD dwBytesRet;
ZeroMemory(&qos, sizeof(qos));
qos.SendingFlowspec.DelayVariation = QOS_NOT_SPECIFIED;
qos.SendingFlowspec.Latency = QOS_NOT_SPECIFIED;
qos.SendingFlowspec.MaxSduSize = QOS_NOT_SPECIFIED;
qos.SendingFlowspec.MinimumPolicedSize = QOS_NOT_SPECIFIED;
qos.SendingFlowspec.PeakBandwidth = QOS_NOT_SPECIFIED;
qos.SendingFlowspec.ServiceType = SERVICETYPE_NETWORK_CONTROL;
qos.SendingFlowspec.TokenBucketSize = QOS_NOT_SPECIFIED;
qos.SendingFlowspec.TokenRate = 15000;
qos.ReceivingFlowspec.DelayVariation = QOS_NOT_SPECIFIED;
qos.ReceivingFlowspec.Latency = QOS_NOT_SPECIFIED;
qos.ReceivingFlowspec.MaxSduSize = QOS_NOT_SPECIFIED;
qos.ReceivingFlowspec.MinimumPolicedSize = QOS_NOT_SPECIFIED;
qos.ReceivingFlowspec.PeakBandwidth = QOS_NOT_SPECIFIED;
qos.ReceivingFlowspec.ServiceType = SERVICETYPE_NETWORK_CONTROL;
qos.ReceivingFlowspec.TokenBucketSize = QOS_NOT_SPECIFIED;
qos.ReceivingFlowspec.TokenRate = 15000;

rc = WSAIoctl(m_sockRTP, SIO_SET_QOS, &qos, sizeof(qos), NULL, NULL, &dwBytesRet, NULL, NULL);
if(rc == SOCKET_ERROR)
{
DWORD dwError = WSAGetLastError();
TRACEOUT("Start QOS failed, rc=0x%x", dwError);
}

Thanks,

Frank

FrankZhong at 2007-10-2 > top of Msdn Tech,Windows Networking Development,Network Quality of Service (QoS/qWAVE)...