[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