Search code examples
c#.netnetwork-programmingipwinsock2

Allow Type of Service / DSCP Marking on Windows for a network socket


I'm looking to programatically mark the Type of Service / DSCP byte in packets from a network socket. The current implementation in C# is below:

UdpClient udpClient = new UdpClient();

string ipAddress = "xxx.xxx.xxx.xxx";
int port = 3999;

udpClient.Connect(ipAddress, port);

udpClient.Client.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.TypeOfService, 8);
Console.WriteLine(udpClient.Client.GetSocketOption(SocketOptionLevel.IP, SocketOptionName.TypeOfService)); // Gives value 8

udpClient.Send(Encoding.ASCII.GetBytes("Hello World!"));

udpClient.Close();

However, the output shows it has been set successfully but when inspecting the packets in Wireshark they still have a DSCP value of 0.

The solutions I have tried so far have been the following registry edits:

  • Set the Do not use NLA DWORD value to 1 in Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\QoS. (As per this Cisco guide.
  • Set the DisableUserTOSSetting DWORD value to 0 in HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\TcpIp\Parameters. (As per this old Microsoft page (archive.org)).
  • Change the `Advanced QoS Settings' in the group policy editor to allow applications to override the policy settings.

In an ideal world the solution would be programmatic and not require the user to edit their group policy as I wish for it to be controlled from the programs UI.


Solution

  • Final solution to setting the TOS value per socket was to use a raw socket.

    I found the winsockdotnetworkprogramming.com guides to be useful. It's worth noting that by using a RawSocket you loose a lot of the quality of life features that udpClient handles for you (e.g. setting the correct source ip and sending out via the correct interface). It also requires the program to be run as Administrator.