Você pode usar a máscara, mas é difícil:
u32 match ip sport 4096 0xf000 = sport 4096-8191
u32 match ip sport 8192 0xe000 = sport 8192-16383
0xf000 / 0xe000 é a máscara. A palavra extraída do pacote é bit-wise com essa máscara antes da comparação.
value = 0001000000000000
mask = 1111000000000000
start = 0001000000000000
end = 0001111111111111
Além disso, você pode criar muitos filtros para um classid:
tc filter add dev eth0 parent 1:0 prio 3 protocol ip u32 match ip protocol 6 0xff match ip sport 10000 0xffff classid 1:13
tc filter add dev eth0 parent 1:0 prio 3 protocol ip u32 match ip protocol 6 0xff match ip sport 10001 0xffff classid 1:13
tc filter add dev eth0 parent 1:0 prio 3 protocol ip u32 match ip protocol 6 0xff match ip sport 10002 0xffff classid 1:13
Para o seu exemplo, você precisa criar vários filtros 'tc':
first: sport 10000 0xfff0 (10000-10015)
second: sport 10016 0xffe0 (10016-10047)
.............
etc.
10000=10011100010000
0010011100010000
|
first not zero
1111111111111111
mask
1111111111110000=0xfff0
[Basicamente, pegue o primeiro número no intervalo (neste exemplo, 10.000) e convertê-lo em binário (0010011100010000); em seguida, digitalize este número binário da direita para a esquerda até encontrar o primeiro não 0 bit; então faça os bits da esquerda daquele bit todos em 1 inclusive, e todos os bits à direita dele em zeros. É assim que você sai para 0xfff0 como a máscara.]