[prev in list] [next in list] [prev in thread] [next in thread] 

List:       lartc
Subject:    Re: [LARTC] Tc Filter - Port Ranges Calculate Mask Value
From:       Peter Rabbitson <rabbit+list () rabbit ! us>
Date:       2007-10-23 14:38:12
Message-ID: 471E0754.3050408 () rabbit ! us
[Download RAW message or body]

anshul makkar wrote:
> Hi,
> 
> I need to support port ranges in tc filter rules.
> 
> I know how to formulate the rule but , I am not able to understand how
> to calculate the mask value for a perticular range so as to segregate
> the port values that lie within this range .
> 
> I got the following sample
> 
> "tc filter add dev eth1 parent 1:1 protocol ip prio 10 u32 match ip
> sport 0x1ae0 0x1ff0 flowid 1:10 This rule will match all ports from
> 6880 to 6895. "
> 
> This rule correctly matches port range from 6880 to 6895. But I am
> unable to figure out , how the mask value has been calculated.

First you need to have a good understanding of logical operations (and 
specifically AND). If you do not - do some reading until you at least 
can give the answer to something like 0b101 & 0b100.

Once you understand this is very easy if you convert all the numbers to 
binary (we use 16 bits, since the port numbers are 16bit). You have:
result 0x1AE0 == 0b0001101011100000
mask   0x1FF0 == 0b0001111111110000

So what happens is:
1) u32 extracts the sport
2) ANDs the extracted value with 0b0001111111110000
3) compares the result to 0b0001101011100000

This means that anything from
0b0001101011100000 to 0b0001101011101111 inclusive will result in a 
match (since the mask essentially strips the last 4 bits). If you 
convert this range back to decimal you get:
0b0001101011100000 == 6880
0b0001101011101111 == 6895

> I am picking up port ranges from GUI. So the range can be any and I
> need to calculte mask value so as to find out which ports lie within
> the entered range.

Unfortunately this is impossible.

As you probably noticed the range you are matching causes variation of 
only the last 4 bits in the entire number. The first bits always stay 
the same (0b000110101110xxxx). If your range is _continuous_ (i.e. 
without "holes" in it), and this is exactly your case - such a range 
_must_ be aligned so that the start has N least significant 0's and the 
end has N least significant 1's. What does this mean in practice:

The size of the range R must be of the form 2^N (to guarantee trailing 
0's). In your case 6895 - 6880 + 1 = 16[*] which is 2^4.

The start of the range S must be larger then R and also divisible by it. 
In your case 6880 / 16 = 430.

Based on the above you can easily calculate the end of the range E:
E = S + R - 1[*]. In your case: 6880 + 16 - 1 = 6895.

You might wonder why for a continuous range the last N bits of the mask 
must be 0. Think of it in decimal terms:
Assume we want the range of all numbers between 130 and 139. We can say 
- we change the last digit to 0, and we check if the number equals 130. 
  If we want a range between 100 and 199 - no problem again. Now what if 
we want the range between 130 and 149? We can say - we change the last 
digit to 0 and check if the number equals 130 or 140. Well there - a 
single mask does not work :)

HTH
Peter

[*] You might be wondering where the +1/-1 comes from. Well take the 
numbers from 3 to 6 inclusive, and count how many there actually are. 6 - 3?
_______________________________________________
LARTC mailing list
LARTC@mailman.ds9a.nl
http://mailman.ds9a.nl/cgi-bin/mailman/listinfo/lartc
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic