Outcomming traffic dscp with QOS_DS_CLASS

Hi,

Hi, i have a problem with qos on winXp sp2.

I want to shape outcomming traffic. I use qos to set upper limit for outcomming bandwidth for my application. the code is follow.

My question is how i can do to test my server code, I have to create a client/customer whit a simple socket ? or may i have to add something else?

I hope sombody can help me ...

thank you

Code Snippet
int main() {
DWORD destPort;
PCHAR destAddress;

destAddress="172.18.100.37"; //IP_ADDRESS;
destPort = 0x1388;//5000;
// Intialization de Winsock API
int err;
WSADATA WSAData;

err = WSAStartup(MAKEWORD(2,2), &WSAData);

if (err) {
printf("WSAStartup Failed (%d) Exiting\n", err);
exit(err);
}

HANDLE ClientHandle;
HANDLE ifcHandle;
HANDLE flowHandle;
HANDLE FilterHandle;

// Initialize call back functions. pas besoin mais necessaire pour TcRegisterClient API
TCI_CLIENT_FUNC_LIST QoSFunctions;
QoSFunctions.ClAddFlowCompleteHandler = NULL;
QoSFunctions.ClDeleteFlowCompleteHandler = NULL;
QoSFunctions.ClModifyFlowCompleteHandler = NULL;
QoSFunctions.ClNotifyHandler = (TCI_NOTIFY_HANDLER)MyClNotifyHandler;

// enregistrement d'un client avec Traffic control interface.
long result = TcRegisterClient(CURRENT_TCI_VERSION, NULL, &QoSFunctions , &ClientHandle);
if (result == NO_ERROR) {
printf("no error TcRegisterClient.\n");
TC_IFC_DESCRIPTOR InterfaceBuffer[20];
PTC_IFC_DESCRIPTOR pInterfaceBuffer = &InterfaceBuffer[0];
//PTC_IFC_DESCRIPTOR nextInterface = (PTC_IFC_DESCRIPTOR)((char*)pInterfaceBuffer + pInterfaceBuffer->Length);
ULONG BufferSize = 20* sizeof(TC_IFC_DESCRIPTOR);

// Find traffic control enabled interfaces on the cmachine
result = TcEnumerateInterfaces(ClientHandle, &BufferSize,pInterfaceBuffer);
if (result == NO_ERROR) {
printf("no error TcEnumerateInterfaces.\n");
if (BufferSize == 0) {
printf("no traffic control interfaces are available\n");
}
TCHAR interfaceName[500];

// function maps a wide-character string to a new character string
WideCharToMultiByte(CP_ACP,0,InterfaceBuffer[0].pInterfaceName, -1,interfaceName, sizeof(interfaceName), 0, 0 );
// The TcOpenInterface function identifies and opens an interface based on its text
// string, which is available from a call to TcEnumerateInterfaces
result = TcOpenInterface( interfaceName, ClientHandle, NULL, &ifcHandle );
if( result == NO_ERROR ) {
// Creating of Traffic flow headers
printf("no error OpenInterfaces.\n");
int curSize = sizeof (TC_GEN_FLOW )+ sizeof (QOS_DS_CLASS) + sizeof(QOS_OBJECT_HDR);
char *bufFlow = new char[curSize];
PTC_GEN_FLOW newFlow = ( PTC_GEN_FLOW )bufFlow;

// Create the new temp flow.
LPQOS_OBJECT_HDR objHdr = NULL;

//Set the Flow Spec
newFlow->ReceivingFlowspec.DelayVariation = QOS_NOT_SPECIFIED;
newFlow->ReceivingFlowspec.Latency = QOS_NOT_SPECIFIED;
newFlow->ReceivingFlowspec.MaxSduSize = QOS_NOT_SPECIFIED;
newFlow->ReceivingFlowspec.MinimumPolicedSize = QOS_NOT_SPECIFIED;
newFlow->ReceivingFlowspec.PeakBandwidth = QOS_NOT_SPECIFIED;
newFlow->ReceivingFlowspec.ServiceType = SERVICETYPE_BESTEFFORT;//SERVICETYPE_CONTROLLEDLOAD;
newFlow->ReceivingFlowspec.TokenBucketSize = QOS_NOT_SPECIFIED;
newFlow->ReceivingFlowspec.TokenRate =QOS_NOT_SPECIFIED;

newFlow->SendingFlowspec.DelayVariation = QOS_NOT_SPECIFIED;
newFlow->SendingFlowspec.Latency = QOS_NOT_SPECIFIED;
newFlow->SendingFlowspec.MaxSduSize = QOS_NOT_SPECIFIED;
newFlow->SendingFlowspec.MinimumPolicedSize = QOS_NOT_SPECIFIED;
newFlow->SendingFlowspec.PeakBandwidth = QOS_NOT_SPECIFIED;//speed;//
newFlow->SendingFlowspec.ServiceType=SERVICETYPE_BESTEFFORT;//SERVICETYPE_CONTROLLEDLOAD;
newFlow->SendingFlowspec.TokenBucketSize = QOS_NOT_SPECIFIED;//speed;//
newFlow->SendingFlowspec.TokenRate = QOS_NOT_SPECIFIED;//10000;//speed;// if this value is greater than 1 mb than qos works as if it is 1 mb
newFlow->TcObjectsLength =sizeof QOS_DS_CLASS + sizeof QOS_OBJECT_HDR; //sizeof QOS_SD_MODE + sizeof QOS_SHAPING_RATE + sizeof QOS_OBJECT_HDR;//0;//sizeof QOS_DS_CLASS + sizeof QOS_OBJECT_HDR;
/****************************DSCP***********************************/
LPQOS_DS_CLASS pQOSClass = (LPQOS_DS_CLASS)(&(newFlow->TcObjects[0]));
pQOSClass->ObjectHdr.ObjectType = QOS_OBJECT_DS_CLASS;
pQOSClass->ObjectHdr.ObjectLength = sizeof QOS_DS_CLASS;
pQOSClass->DSField = 0x2E;
objHdr = (LPQOS_OBJECT_HDR)((char *)&(newFlow->TcObjects[0]) + sizeof(QOS_DS_CLASS));
// Set the end of the list
objHdr->ObjectType = QOS_OBJECT_END_OF_LIST;
objHdr->ObjectLength = sizeof QOS_OBJECT_HDR;
// adds a new flow on the specified interface. The flow is like a channel,
// that determines how to shape the traffic if it tunnelled through it.
int retCode = TcAddFlow( ifcHandle, /*ClientHandle*/NULL, 0, newFlow, &flowHandle );
if(retCode == NO_ERROR) {
printf("no error TcAddFlow\n");
} else {
printf("TcAddFlow: ERROR: %lu\n",retCode);
//printf("Handle %d\n", (int)IfcHandle);
switch(retCode) {
case ERROR_SIGNAL_PENDING:
printf("The function is being executed asynchronously; the client will be called back through the client-exposed ClAddFlowComplete function when the flow has been added or when the process has been completed..\n");
break;
case ERROR_INVALID_HANDLE:
printf("The interface handle is invalid.\n");
break;
case ERROR_NOT_ENOUGH_MEMORY:
printf("The system is out of memory.\n");
break;
case ERROR_INVALID_PARAMETER:
printf("A parameter is invalid.\n");
break;
case ERROR_INVALID_SERVICE_TYPE:
printf("An unspecified or bad INTSERV service type has been provided.\n");
break;
case ERROR_INVALID_TOKEN_RATE:
printf("An unspecified or bad TOKENRATE value has been provided.\n");
break;
case ERROR_INVALID_PEAK_RATE:
printf("The PEAKBANDWIDTH value is invalid.\n");
break;
case ERROR_INVALID_SD_MODE:
printf("The SHAPEDISCARDMODE is invalid.\n");
break;
case ERROR_INVALID_QOS_PRIORITY:
printf("The priority value is invalid.\n");
break;
case ERROR_INVALID_TRAFFIC_CLASS:
printf("The traffic class value is invalid.\n");
break;
case ERROR_NO_SYSTEM_RESOURCES:
printf("There are not enough resources to accommodate the requested flow.\n");
break;
case ERROR_TC_OBJECT_LENGTH_INVALID:
printf("Bad length specified for the TC objects.\n");
break;
case ERROR_INVALID_DIFFSERV_FLOW:
printf("Applies to Diffserv flows. Indicates that the QOS_DIFFSERV object was passed with an invalid parameter.\n");
break;
case ERROR_DS_MAPPING_EXISTS:
printf("Applies to Diffserv flows. Indicates that the QOS_DIFFSERV_RULE specified in TC_GEN_FLOW already applies to an existing flow on the interface.\n");
break;
case ERROR_INVALID_SHAPE_RATE:
printf("The QOS_SHAPING_RATE object was passed with an invalid ShapeRate.\n");
break;
case ERROR_INVALID_DS_CLASS:
printf("The QOS_DS_CLASS is invalid.\n");
break;
case ERROR_NETWORK_UNREACHABLE:
printf("The network cable is not plugged into the adapter.\n");
break;
}
//return -1;
}
// Create a filter. All traffic matching the filter will pass through the flow
TC_GEN_FILTER GenericFilter;
IP_PATTERN Pattern, Mask;
memset(&Pattern,0,sizeof(IP_PATTERN));
memset(&Mask,0,sizeof(IP_PATTERN));
GenericFilter.AddressType = NDIS_PROTOCOL_ID_TCP_IP; // Protocol stack is TCP/IP
GenericFilter.PatternSize = sizeof(IP_PATTERN);
GenericFilter.Pattern = &Pattern; // pattern to match, defined below
GenericFilter.Mask = &Mask;
// Filter pattern. This is where you can tweak the flow filter parameters
// configured to match on all outgoing UDP packets.
Pattern.Reserved1 = 0;
Pattern.Reserved2 = 0;
Pattern.SrcAddr = inet_addr("172.18.100.38"); //IP_ADDRESS;
Pattern.DstAddr = inet_addr("172.18.100.37"); //IP_ADDRESS;
Pattern.tcSrcPort = 0x1388;
Pattern.tcDstPort = 0x1388;//5000
Pattern.ProtocolId = IPPROTO_UDP;
Pattern.Reserved3[0] = 0;
Pattern.Reserved3[1] = 0;
Pattern.Reserved3[2] = 0;
// Patterns mask
Mask.Reserved1 = 0;
Mask.Reserved2 = 0;
Mask.SrcAddr = 0;//0xFFFFFFFF;
Mask.DstAddr = 0;//0xFFFFFFFF;
Mask.tcSrcPort = 0;//0xFFFF;
Mask.tcDstPort = 0xFFFF;
Mask.ProtocolId = 0xFF;
Mask.Reserved3[0] = 0;
Mask.Reserved3[1] = 0;
Mask.Reserved3[2] = 0;
// Add filter to the flow. This point onwards all traffic matching the filter, will pass through the flow.
retCode = TcAddFilter(flowHandle, &GenericFilter, &FilterHandle);
if(retCode != NO_ERROR) {
printf("TcAddFilter: ERROR: %lu\n",retCode);
switch(retCode) {
case ERROR_INVALID_HANDLE:
printf("The filter handle is invalid.\n");
break;
case ERROR_INVALID_PARAMETER:
printf("A parameter is invalid.\n");
break;
case ERROR_INVALID_ADDRESS_TYPE:
printf("An invalid address type has been provided.\n");
break;
case ERROR_DUPLICATE_FILTER:
printf("An identical filter exists on a flow on this interface.\n");
break;
case ERROR_NOT_ENOUGH_MEMORY:
printf("The system is out of memory.\n");
break;
case ERROR_NOT_READY:
printf("The flow is either being installed, modified, or deleted, and is not in a state that accepts filters.\n");
break;
}
//return -1;
} else {
printf("no error TcAddFilter.\n");
}
//check flows
//int EnumFlows(IfcHandle);
} else {
//////////////////////////////////////////test
switch(result) {
case ERROR_INVALID_PARAMETER:
printf("A parameter is invalid.\n");
break;
case ERROR_NOT_FOUND:
printf("An invalid address type has been provided.\n");
break;
case ERROR_NOT_ENOUGH_MEMORY:
printf("An identical filter exists on a flow on this interface.\n");
break;
case ERROR_INVALID_HANDLE:
printf("ERROR_INVALID_HANDLE: The client handle is invalid.\n");
break;
}
printf("TcOpenInterface returned 0x%x\n", result);
//return -1;
}
} else {
switch(result) {
case NO_ERROR:
printf("The function executed without errors.\n");
break;
case ERROR_INVALID_HANDLE:
printf("The client handle is invalid.\n");
break;
case ERROR_INVALID_PARAMETER:
printf("One of the parameters is NULL.\n");
break;
case ERROR_INSUFFICIENT_BUFFER:
printf("The buffer is too small to enumerate all interfaces. If this error is returned, the correct (required) size of the buffer is passed back in pBufferSize.\n");
printf("Size required: %d\n", BufferSize);
break;
case ERROR_NOT_ENOUGH_MEMORY:
printf("The system is out of memory.\n");
break;
}
printf("TcEnumerateInterfaces returned 0x%x\n", result);
//return -1;
}
} else {
printf("TcRegisterClient returned 0x%x\n", result);
//return -1;
}
// Create a normal UDP socket for sending data
SOCKET sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sd == INVALID_SOCKET) {
err = GetLastError();
printf("\"Socket\" failed with error %d\n", err);
//return 1;
}
SOCKADDR_IN destAddr;
memset (&destAddr, 0, sizeof(SOCKADDR_IN));
destAddr.sin_family = AF_INET;
destAddr.sin_port = htons(destPort);
destAddr.sin_addr.s_addr = inet_addr(destAddress); // this is our test destination IP
//char buf[1000];
int nRet;
nRet = sendto( sd, "hello the world", 20, 0, (sockaddr*)&destAddr,sizeof(SOCKADDR_IN));
//sendto( sd, buf, 1000, 0, (sockaddr*)&destAddr,sizeof(SOCKADDR_IN));
// nRet should have the number of bytes successfully sent.
//char buff[1000];
//scanf("%s",buff);
// CLEANUP
result = TcDeleteFilter(FilterHandle);
if (result != NO_ERROR) {
printf("Error deleting filter\n");
} else {
printf("no error TcDeleteFilter\n");
}
// Delete flow associated with the network interface
result = TcDeleteFlow(flowHandle);
if (result != NO_ERROR) {
printf("Error deleting flow\n");
} else {
printf("no error TcDeleteFlow\n");
}
// Close the Traffic control interface opened earlier.
result = TcCloseInterface(ifcHandle);
if (result != NO_ERROR) {
switch(result) {
case ERROR_INVALID_HANDLE:
printf("The interface handle is invalid.\n");
break;
case ERROR_TC_SUPPORTED_OBJECTS_EXIST:
printf("Not all flows have been deleted for this interface.");
}
printf("Error closing interface\n");
} else {
printf("no error TcCloseInterface\n");
}
// Unregister the client.
result = TcDeregisterClient(ClientHandle);
if (result != NO_ERROR) {
switch(result) {
case ERROR_INVALID_HANDLE:
printf("Invalid interface handle, or the handle was set to NULL.\n");
break;
case ERROR_TC_SUPPORTED_OBJECTS_EXIST:
printf("Interfaces are still open for this client. all interfaces must be closed to deregister a client.\n");
}
printf("Error degresitering client\n");
} else {
printf("no error TcDeregisterClient\n");
}
// shutdown the socket
shutdown(sd, SD_BOTH);
closesocket(sd);
WSACleanup();
return 0;
}

[14779 byte] By [Alineo] at [2008-2-19]
# 1
Hi everybody,
I try to test my previoulsy code to set the dscp of udp outcomming traffic with the tc api on xp.
I have not error, but when I look in packets, the dscp bit is '0'... so no change !
Why my code didn't run ?

Alineo at 2007-9-13 > top of Msdn Tech,Windows Networking Development,Network Quality of Service (QoS/qWAVE)...
# 2

Alineo,

this is a significant chunk of code. It would be helpful to us next time if you could narrow the problem down to a specific section for us to review and comment on.

From a cursory glance, the one thing that jumps out at is that you created a filter with a source/local port of 0x1388 however you did not bind your socket to that port. As a result, the source/local port is likely something else.

MathiasJourdain-MSFT at 2007-9-13 > top of Msdn Tech,Windows Networking Development,Network Quality of Service (QoS/qWAVE)...
# 3
Thank you for your answer Mathias and sorry for the significant chunk of code.
Now I success to mark dscp but, my problem it that all the packet are set...
I set my filter to a specific adress and specific port but if i send the soket on another adress or port, the packet is set, that it is not that I want.
There is the code i use to create my filter and the socket...
Code Snippet

///////////////////////////////FILTRE//////////////////////////////////////
TC_GEN_FILTER GenericFilter;
IP_PATTERN Pattern, Mask;
memset(&Pattern,0,sizeof(IP_PATTERN));
memset(&Mask,0,sizeof(IP_PATTERN));
GenericFilter.AddressType = NDIS_PROTOCOL_ID_TCP_IP; // Protocol stack is TCP/IP
GenericFilter.PatternSize = sizeof(IP_PATTERN);
GenericFilter.Pattern = &Pattern; // pattern to match, defined below
GenericFilter.Mask = &Mask;
// Filter pattern.
Pattern.Reserved1 = 0;
Pattern.Reserved2 = 0;
Pattern.SrcAddr = inet_addr("172.18.100.38");

Pattern.DstAddr = inet_addr("172.18.100.37");
Pattern.tcSrcPort = 0;
Pattern.tcDstPort = 0;0x1388;//destPort;
Pattern.ProtocolId = IPPROTO_UDP;
Pattern.Reserved3[0] = 0;
Pattern.Reserved3[1] = 0;
Pattern.Reserved3[2] = 0;
// Patterns mask
Mask.Reserved1 = 0;
Mask.Reserved2 = 0;
Mask.SrcAddr = 0;//0xFFFFFFFF;
Mask.DstAddr = 0;//0xFFFFFFFF;
Mask.tcSrcPort = 0;//0xFFFF;
Mask.tcDstPort = 0;//0xFFFF;
Mask.ProtocolId = 0;//0xFF;
Mask.Reserved3[0] = 0;
Mask.Reserved3[1] = 0;
Mask.Reserved3[2] = 0;

/////////////////////////SOCKET//////////////////
// Create a normal UDP socket for sending data
SOCKET sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sd == INVALID_SOCKET) {
err = GetLastError();
printf("\"Socket\" failed with error %d\n", err);
return 1;
}
SOCKADDR_IN destAddr;
memset (&destAddr, 0, sizeof(SOCKADDR_IN));
destAddr.sin_family = AF_INET;
destAddr.sin_port = htons(0x1388);
destAddr.sin_addr.s_addr = inet_addr(destAddress); // this is our test destination IP
bind(sd,(struct sockaddr*)&destAddr,sizeof(destAddr));

//char buf[1000];
int nRet;
nRet = sendto( sd, "TEST QOS windows", 30, 0, (sockaddr*)&destAddr,sizeof(SOCKADDR_IN));

If you see something wrong or a mistake...
My goal is to set dscp just for a specific adress...

thank you again for the time you will take.

Alineo at 2007-9-13 > top of Msdn Tech,Windows Networking Development,Network Quality of Service (QoS/qWAVE)...
# 4
Hi Alineo,
I cannot help you with your problem, but sure you can help me... hehe
I have been given an application writen in c++ and I have been told to include DSCP marking on the application... and I do not know where to start. Could you point me somewhere where I could read/learn about it? I'm really lost @_@!
Telejos at 2007-9-13 > top of Msdn Tech,Windows Networking Development,Network Quality of Service (QoS/qWAVE)...
# 5
I think the best is to look on the msdn documention about QOS_DS_CLASS...
If it can help you...
youss_75019 at 2007-9-13 > top of Msdn Tech,Windows Networking Development,Network Quality of Service (QoS/qWAVE)...
# 6

Hi Alineo,

You are using a Pattern Mask of 0. 0 leads to wildcard matching. If you need to match specific Addres/Port, you need to use a Mask of all 1s (0xFFFF). Also, in the code snippet,

Pattern.tcSrcPort = 0;
Pattern.tcDstPort = 0;

If you need specific port matching, you need to have the specific port specified above instead of the 0.

Hope this helps.

Thanks,

Hemant Banavar (MSFT)

Hemant(MSFT) at 2007-9-13 > top of Msdn Tech,Windows Networking Development,Network Quality of Service (QoS/qWAVE)...
# 7
Thank you for your answer, but I forgot to put the resolve tag....

tu dis merci pour ta reponse mais j'avais rsolu le probleme et j'ai oublier de marquer rsolu sur le post
on the other hand I have another problem with the 802.1p tagging.
I hope you can help me to resolve it.

Alineo at 2007-9-13 > top of Msdn Tech,Windows Networking Development,Network Quality of Service (QoS/qWAVE)...