Home > Protocol Analysis, QoS > Using TCPDUMP to Filter on DSCP

Using TCPDUMP to Filter on DSCP

January 29th, 2012

The TCPDUMP filter to match a DSCP is a little tricky to construct. I need to explain how the filter works and also what TCPDUMP sees in the ToS Byte of the IP header and then how to filter on just the DiffServ extensions.

The IP ToS Byte (DSCP and IP ECN)

The IP ToS Byte (DSCP and IP ECN)

FIRST THE ANSWER:
(in case it is not important to understand how the filter is constructed)

an example filtering on DSCP decimal 20 (AF22):
tcpdump -i eth0 (ip and (ip[1] & 0xfc) >> 2 == 20) -vvv

An example filtering on DSCP Hex 14 (also decimal 20 or AF22):
tcpdump -i eth0 (ip and (ip[1] & 0xfc) >> 2 == 0x14) –vvv

When traffic is marked with a DSCP (6 bits) , TCPDUMP will interpret all 8 bits used by the ToS Byte in the IP header.

1. EXAMPLE CAPTURE

I set my LAN to mark traffic with DSCP 20. Notice that traffic captured showed the second byte ( or “byte offset 1” as we count from 0) of the IP header, which is set to 0x50 (hex 50).  (This is the value of the whole ToS Byte).

Why 0x50 and not 0x14, which is the Hex equivalent of DSCP 20 (AF22)?
This is because DSCP 20 (six bits = 010100) = Hex 14 but using all 8 bits of the second byte (DS field of IP header) the value is 0x50

6 bits = 010100 = Decimal 20 = Hex 14
8 bits = 01010000 = Decimal 80 = Hex 50

Linux # tcpdump -i eth0 -vvv (ip and (ip[1] & 0xfc) >> 2 == 20)
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 300 bytes
11:00:20.363070 IP (tos 0x50, ttl 128, id 7903, offset 0, flags [DF], proto TCP (6), length 68)
10.63.64.165.57018 > 79.73.127.147.http: Flags [S], cksum 0x43c7 (correct), seq 1610776870, win 8192, options [mss 1460,nop,wscale 2,nop,nop,sackOK,Unknown Option 7601010a3f40f60005,Unknown Option 760c01,nop,eol], length 0
11:00:20.364257 IP (tos 0x50, ttl 126, id 7903, offset 0, flags [DF], proto TCP (6), length 60)
79.73.127.147.http > 10.63.64.165.57018: Flags [S.], cksum 0x7ca9 (correct), seq 20020520, ack 1610776871, win 8192, options [mss 1460,nop,wscale 2,nop,nop,sackOK,Unknown Option 760c01,nop,nop,nop,eol], length 0

2 packets captured
2 packets received by filter
0 packets dropped by kernel
Linux #

2. TCPDUMP FILTER:

There are two ways to filter. You can match the hex value of the entire 8 bits of the DS field, so you would need to calculate the 8-bit hex value of a six bit DSCP, like this:

Steelhead # tcpdump -i eth0 (ip and ip[1] & 0xfc == 0x50) –vvv

Or you can “right-shift” to ‘eliminate’ the two extraneous bits (the ECN) and use the correct hex value (or decimal) of the DSCP:
Linux # tcpdump -i eth0 (ip and (ip[1] & 0xfc) >> 2 == 20) -vvv
Or
Linux # tcpdump -i eth0 (ip and (ip[1] & 0xfc) >> 2 == 0x14) –vvv

What this does is this:
– ip[1] refers to the Head byte 1 (second byte “BYTE OFFSET 1”, the TOS byte) of the IP header
– & means a Bitwise “AND”
– 0xfc = 11111100 is the mask to use for the AND

IP-Header

The “>>” means “right shift” (or move bits the specified number of places to the RIGHT), which is EQUIVALENT TO a divide by 2 the specified number of times, OR EQUIVALENT TO a divide by (2 to the power of the specified number). Examples of right shifting:

Original:
01010000 (0x50 / 80)
>> 0 (divide by 1)
01010000 (0x50 / 80)
>> 1 (divide by 2)
00101000 (0x28 / 40)
>> 2 (divide by 2 then by 2, or divide by 4)
00010100 (0x14 / 20)
>> 3 (divide by 2 three times, or divide by 8)
00001010 (0x0a / 10)

This is an example of the logical AND: (i.e. 0 and 0 = 0, 1 and 0 = 0, 1 and 1 = 1)

01010000 original value (0x50 using all 8 bits)
11111100 bitwise mask (0xfc)
01010000 result of bitwise AND

So:
>> 0 would be 01010000 or 0x50
>> 2 would be 010100 or 0x20

In Summary:
Using the right-shift would enable you to use the correct DSCP value in the TCPDUMP filter:
Linux # tcpdump -i eth0 (ip and (ip[1] & 0xfc) >> 2 == 20) -vvv
Or
Linux # tcpdump -i eth0 (ip and (ip[1] & 0xfc) >> 2 == 0x14) –vvv

NOT using the right-shift means that you need to convert the 6-bit DSCP to an 8-bit value and use this in your TCPDUMP filter:
Linux # tcpdump -i eth0 (ip and ip[1] & 0xfc == 0x50) –vvv

Categories: Protocol Analysis, QoS Tags: , ,
Comments are closed.