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.
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.
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