The Moose and Squirrel Files

January 20, 2009

DSCP to Type of Service Mappings

Filed under: Code, Network — Tags: , , , — networknerd @ 11:45 am

When working with quality of service configurations you’ll inevitably come across the need to perform packet markings with DSCP.  With routers this is generally fairly simple.  Performing the same function on a host is not always that simple.  All the socket API’s were designed around type of service (ToS),as defined in RFC791, rather than DSCP as defined in RFC2474.

If you’re in a hurry, the conversion is simply ToS = DSCP * 4. If you have the time the rfc’s are full of interesting information. The DSCP field with the DS field contains six bits allowing for 64 possible codepoint values. RFC2474 defines 3 pools of DSCP values, one for standardised use and the other two for local/experimental use. The standardised pool has the least significant bit set to 0, which means only the even numbers from 0 to 62 are used. A cheat sheet with the standardised DSCP values and equivalent IP precedence and ToS values can be found here.

We can test the ToS/DSCP mapping using the ping program and specifying a ToS byte value. Using the windows ping program we specify the ToS byte as a numeric argument to the -v command line switch. In this example we specify the the ToS byte as 136 which corresponds to a DSCP value of 34  or AF41.

ping -n 1 -v 136 http://www.google.com

Performing a similar test for tcp connection requires a little bit of coding effort. Listing 1 shows some c# code to do a simple get request to http://www.google.com.au,  using the SetSocketOption function to set the ToS byte to 136.  The wireshark output for both tests is shown below.  The  lua script shown in listing 2 was used to extract the diffserv field and dscp values while running the capture with Tshark. It is worth noting that even though the socketoption is set prior to the connection, no dscp values are set on the two packets from the client during the TCP three way handshake (frame 5 and 7 below).

tshark  -X lua_script:getdscp.lua -i 2 host http://www.google.com.au
Frame #1    Diffserv Field: 136    DSCP: 34
192.168.0.7 -> 74.125.19.103 ICMP Echo (ping) request

Frame #2    Diffserv Field: 0    DSCP: 0
74.125.19.103 -> 192.168.0.7  ICMP Echo (ping) reply

Frame #3    Diffserv Field: 136    DSCP: 34
192.168.0.7 -> 74.125.19.103 ICMP Echo (ping) request

Frame #4    Diffserv Field: 0    DSCP: 0
74.125.19.103 -> 192.168.0.7  ICMP Echo (ping) reply

Frame #5    Diffserv Field: 0    DSCP: 0
192.168.0.7 -> 74.125.19.103 TCP linx > http [SYN] Seq=0 Win=16384 Len=0 MSS=1260

Frame #6    Diffserv Field: 0    DSCP: 0
74.125.19.103 -> 192.168.0.7  TCP http > linx [SYN, ACK] Seq=0 Ack=1 Win=5720 Len=0 MSS=1430

Frame #7    Diffserv Field: 0    DSCP: 0
192.168.0.7 -> 74.125.19.103 TCP linx > http [ACK] Seq=1 Ack=1 Win=17640 Len=0

Frame #8    Diffserv Field: 136    DSCP: 34
192.168.0.7 -> 74.125.19.103 HTTP GET / HTTP/1.0

Frame #9    Diffserv Field: 0    DSCP: 0
74.125.19.103 -> 192.168.0.7  TCP http > linx [ACK] Seq=1 Ack=41 Win=5720 Len=0

Frame #10    Diffserv Field: 0    DSCP: 0
74.125.19.103 -> 192.168.0.7  TCP [TCP segment of a reassembled PDU]

Frame #11    Diffserv Field: 0    DSCP: 0
74.125.19.103 -> 192.168.0.7  TCP [TCP segment of a reassembled PDU]

Frame #12    Diffserv Field: 136    DSCP: 34
192.168.0.7 -> 74.125.19.103 TCP linx > http [ACK] Seq=41 Ack=2521 Win=17640 Len=0

Frame #13    Diffserv Field: 0    DSCP: 0
74.125.19.103 -> 192.168.0.7  TCP [TCP segment of a reassembled PDU]

Frame #14    Diffserv Field: 0    DSCP: 0
74.125.19.103 -> 192.168.0.7  TCP [TCP segment of a reassembled PDU]

Frame #15    Diffserv Field: 136    DSCP: 34
192.168.0.7 -> 74.125.19.103 TCP linx > http [ACK] Seq=41 Ack=5041 Win=17640 Len=0

Frame #16    Diffserv Field: 0    DSCP: 0
74.125.19.103 -> 192.168.0.7  TCP [TCP segment of a reassembled PDU]

Frame #17    Diffserv Field: 0    DSCP: 0
74.125.19.103 -> 192.168.0.7  HTTP HTTP/1.0 200 OK  (text/html)

Frame #18    Diffserv Field: 136    DSCP: 34
192.168.0.7 -> 74.125.19.103 TCP linx > http [ACK] Seq=41 Ack=6611 Win=17640 Len=0

Frame #19    Diffserv Field: 136    DSCP: 34
192.168.0.7 -> 74.125.19.103 TCP linx > http [FIN, ACK] Seq=41 Ack=6611 Win=17640 Len=0

Frame #20    Diffserv Field: 0    DSCP: 0
74.125.19.103 -> 192.168.0.7  TCP http > linx [ACK] Seq=6611 Ack=42 Win=5720 Len=0
Listing  1

using System;
using System.Text;
using System.Net.Sockets;

namespace tcptos
{
	class Program
	{
		public static void Main(string[] args)
		{
			Console.WriteLine("Testing DSCP packet marking.Wireshark should already be running!\n");

			TcpClient cli = new TcpClient();
			cli.Client.SetSocketOption(SocketOptionLevel.IP,
			                           SocketOptionName.TypeOfService, 136);
			cli.Connect("www.google.com.au",80);
			byte[] buf = Encoding.ASCII.GetBytes("GET / HTTP/1.0\nHost: www.google.com.au\n\n");
			byte[] readbuf = new byte[4096];
			int bytesRead;
			StringBuilder response = new StringBuilder();
			NetworkStream mystream = cli.GetStream();
			mystream.Write(buf,0,buf.Length);
			do{
				bytesRead = mystream.Read(readbuf, 0, readbuf.Length);
				response.AppendFormat("{0}", Encoding.ASCII.GetString(readbuf, 0, bytesRead));
			}
			while(bytesRead > 0);
			Console.Write(response.ToString());
			Console.Write("\nPress any key to continue . . . ");
			Console.ReadKey(true);
			cli.Close();
		}
	}
}

Listing 2

local dsfield = Field.new("ip.dsfield")
local dscp = Field.new("ip.dsfield.dscp")
local fnum = Field.new("frame.number")
do
    packets = 0;
    local function init_listener()
        local tap = Listener.new("frame","ip.version == 4")

        function tap.reset()
        end
        function tap.packet(pinfo,tvb,ip)
            local fnumber = tostring(fnum())
            local diffserv = tostring(dsfield())
            local codepoint = tostring(dscp())
            local stroutput = "\nFrame #" .. fnumber .. "\tDiffserv Field: " ..
				diffserv .. "\tDSCP: " ..codepoint
            print(stroutput)
        end
        function tap.draw()

        end
    end
    init_listener()
end
Advertisements

January 1, 2009

Accessing Firefox 3 Discontinuous Selections with Javascript

Filed under: Code — Tags: , , — networknerd @ 1:02 pm

Firefox 3 now has the ability to highlight discontinuous sections of a web page by holding down the control key while making the selections. Very handy for note taking where you want to cut and paste only the relevant sections.

It occurred to me though that it might be useful to be able to access the individual parts of the selection.  My first guess was to use the window.getSelection() method and pass it an integer which refers to the part of the selection.  Bad guess, that just gave me all parts of the selection concatenated.  After referring to the documentation it seems that the selection object has the rangeCount property and the getRangeAt method for accessing individual parts of the selection.

I decided to use a bookmarklet as a quick and dirty way to check it out.  The code is listed below in a readable format or you can copy the whole url if you want to test it as is.

It’s worth pointing out that your mileage may vary here if your trying to extract a selection from an input control such as a text box.

javascript:
(
  function()
  {
    var sel=window.getSelection();
    var cnt=sel.rangeCount;
    var ranges=[];
    for(var i = 0; i < sel.rangeCount; i++)
    {
      ranges[i] = sel.getRangeAt(i);
      alert(ranges[i]);
    }
    alert(cnt);
  }()
);
javascript:(function(){var%20sel=window.getSelection();var%20cnt=sel.rangeCount;var%20ranges=[];for(var%20i%20=%200;%20i%20<%20sel.rangeCount;%20i++){ranges[i]%20=%20sel.getRangeAt(i);alert(ranges[i]);}alert(cnt);}());

Blog at WordPress.com.