я так понимаю, что:
- на сервере таки только NAT и нарезка скорости по IP клиента?
в этом случае:
- учитывай, что rate - это скорость, которую мы "гарантируем" клиенту.
Сумма rate в классах пользователей не должна превышать rate корневого класса.
Для того чтобы задать лимит пользователю, нужно использовать ceil.
то есть, ставишь ceil - это лимит, а rate - скажем, раз в 100 меньше.
- классы для пользователей должны иметь parent'ом корневой класс, а не qdisc.
- уже к классам для пользователей можно прилепить например SFQ qdisc чтобы у пользователя программы друг другу меньше гадили.
вообще, у меня нарезается так:
- qdisc HTB для интерфейса,
в нём классы:
- корневой растёт из qdisc
- дефолтный растёт из корневого
- по классу на пользователя - растут из корневого.
к каждому пользовательскому классу пришит qdisc SFQ
фильтры:
поскольку пользователей много (~2500 сейчас), а divisor в случае использования хэширования может быть не больше 256, то таким путём:
- берём подсеть класса B, например 172.16.0.0/16
- представляем её как 256 сетей класса C
- делаем хэш по 3-му октету адресов - получаем 256 "корзин" для подсетей
- к каждой "корзине" пришиваем хэш по 4-му октету - получаем 256 "корзин" для пользователей в каждой подсети.
- к каждой "корзине" пользователя пришиваем единственный фильтр, направляющий трафик в нужный класс.
iptables в классификации не участвует вообще - используем u32 classifier.
тестовый скрипт, демонтстрирующий вышеописанное, выглядит так:
#!/bin/bash
DEV=eth2
# root HTB qdisc
tc qdisc add dev $DEV root handle 0001: htb default 00ff r2q 10000
# root class in root HTB qdisc
tc class add dev $DEV parent 0001: classid 0001:0001 htb rate 1000Mbit ceil 1000Mbit quantum 32768
# default class in root HTB qdisc
tc class add dev $DEV parent 0001:0001 classid 0001:00ff htb rate 32Kbit ceil 64Kbit prio 7 quantum 8192
# default class SFQ qdisc in root HTB qdisc
tc qdisc add dev $DEV parent 0001:00ff handle 00ff: sfq perturb 10
# server own traffic class in root HTB qdisc
tc class add dev $DEV parent 0001:0001 classid 0001:0002 htb rate 1Mbit ceil 10Mbit prio 1 quantum 16384
# server own traffic SFQ qdisc in root HTB qdisc
tc qdisc add dev $DEV parent 0001:0002 handle 0002: sfq perturb 10
# client classes - 2 classes per sector == 2 clients per sector (clients IP .8, .123 in each sector)
# sector id=1
tc class add dev $DEV parent 0001:0001 classid 0001:0108 htb rate 100kbit ceil 1000kbit prio 4 quantum 4096
tc class add dev $DEV parent 0001:0001 classid 0001:017b htb rate 100kbit ceil 1000kbit prio 4 quantum 4096
# sector id=2
tc class add dev $DEV parent 0001:0001 classid 0001:0208 htb rate 100kbit ceil 1000kbit prio 4 quantum 4096
tc class add dev $DEV parent 0001:0001 classid 0001:027b htb rate 100kbit ceil 1000kbit prio 4 quantum 4096
# sector id=3
tc class add dev $DEV parent 0001:0001 classid 0001:0308 htb rate 100kbit ceil 1000kbit prio 4 quantum 4096
tc class add dev $DEV parent 0001:0001 classid 0001:037b htb rate 100kbit ceil 1000kbit prio 4 quantum 4096
# ...
# sector id=239
tc class add dev $DEV parent 0001:0001 classid 0001:ef08 htb rate 100kbit ceil 1000kbit prio 4 quantum 4096
tc class add dev $DEV parent 0001:0001 classid 0001:ef7b htb rate 100kbit ceil 1000kbit prio 4 quantum 4096
# SFQ qdiscs for client classes
# sector id=1
tc qdisc add dev $DEV parent 0001:0108 handle 0108: sfq perturb 10
tc qdisc add dev $DEV parent 0001:017b handle 017b: sfq perturb 10
# sector id=2
tc qdisc add dev $DEV parent 0001:0208 handle 0208: sfq perturb 10
tc qdisc add dev $DEV parent 0001:027b handle 027b: sfq perturb 10
# sector id=3
tc qdisc add dev $DEV parent 0001:0308 handle 0308: sfq perturb 10
tc qdisc add dev $DEV parent 0001:037b handle 037b: sfq perturb 10
# ...
# sector id=239
tc qdisc add dev $DEV parent 0001:ef08 handle ef08: sfq perturb 10
tc qdisc add dev $DEV parent 0001:ef7b handle ef7b: sfq perturb 10
# hashes for sectors
# root
/sbin/tc filter add dev $DEV parent 1: prio 4 protocol ip u32
/sbin/tc filter add dev $DEV parent 1: prio 4 handle 1: protocol ip u32 divisor 256
/sbin/tc filter add dev $DEV protocol ip parent 1: prio 4 u32 ht 800:: match ip dst 172.16.0.0/16 hashkey mask 0x0000ff00 at 16 link 1:
# sector id=1
/sbin/tc filter add dev $DEV parent 1: prio 4 handle 0f01: protocol ip u32 divisor 256
tc filter add dev $DEV protocol ip parent 0001:0 prio 4 u32 ht 1:1: match ip dst 172.16.1.0/24 hashkey mask 0x000000ff at 16 link f01:
# sector id=2
/sbin/tc filter add dev $DEV parent 1: prio 4 handle 0f02: protocol ip u32 divisor 256
tc filter add dev $DEV protocol ip parent 0001:0 prio 4 u32 ht 1:2: match ip dst 172.16.2.0/24 hashkey mask 0x000000ff at 16 link f02:
# sector id=3
/sbin/tc filter add dev $DEV parent 1: prio 4 handle 0f03: protocol ip u32 divisor 256
tc filter add dev $DEV protocol ip parent 0001:0 prio 4 u32 ht 1:3: match ip dst 172.16.3.0/24 hashkey mask 0x000000ff at 16 link f03:
# ...
# sector id=239
/sbin/tc filter add dev $DEV parent 1: prio 4 handle 0fef: protocol ip u32 divisor 256
tc filter add dev $DEV protocol ip parent 0001:0 prio 4 u32 ht 1:ef: match ip dst 172.16.239.0/24 hashkey mask 0x000000ff at 16 link fef:
# filter for server own traffic
tc filter add dev $DEV parent 0001: prio 1 protocol ip u32 match ip src 192.168.254.1/32 classid 0001:0002
# filters for clients (clients IP .8, .123 in each sector)
# sector id=1
tc filter add dev $DEV protocol ip parent 0001:0 handle 0f01:08:800 prio 4 u32 ht f01:8: match ip dst 172.16.1.8 flowid 0001:0108
tc filter add dev $DEV protocol ip parent 0001:0 handle 0f01:7b:800 prio 4 u32 ht f01:7b: match ip dst 172.16.1.123 flowid 0001:017b
# sector id=2
tc filter add dev $DEV protocol ip parent 0001:0 handle 0f02:08:800 prio 4 u32 ht f02:8: match ip dst 172.16.2.8 flowid 0001:0208
tc filter add dev $DEV protocol ip parent 0001:0 handle 0f02:7b:800 prio 4 u32 ht f02:7b: match ip dst 172.16.2.123 flowid 0001:027b
# sector id=3
tc filter add dev $DEV protocol ip parent 0001:0 handle 0f03:08:800 prio 4 u32 ht f03:8: match ip dst 172.16.3.8 flowid 0001:0308
tc filter add dev $DEV protocol ip parent 0001:0 handle 0f03:7b:800 prio 4 u32 ht f03:7b: match ip dst 172.16.3.123 flowid 0001:037b
# ...
# sector id=239
tc filter add dev $DEV protocol ip parent 0001:0 handle 0fef:08:800 prio 4 u32 ht fef:8: match ip dst 172.16.239.8 flowid 0001:ef08
tc filter add dev $DEV protocol ip parent 0001:0 handle 0fef:7b:800 prio 4 u32 ht fef:7b: match ip dst 172.16.239.123 flowid 0001:ef7b
хэндлы фильтрам лучше задавать явно - весьма пользительно для последующего разбора скриптами, а также в сбойных ситуациях.
"нулевой" подсети в данном примере быть не может - соответствующие идентификаторы используются для всяких "специальных" классов и т. д.
а так - в теории, можно нарезать почти 64К пользователей.
если же сервер - ещё и NAS для PPTP, то там ведь получается по отдельному интерфейсу на пользователя - в этом случае шейпим на интерфейсе pppX да и всё, не надо таких сложностей.
правда, даже на очень хорошей машине в случае PPTP "узкое" место - это большое количество процессов (связка pppd+pptpd => 2 процесса на пользователя => большой load average => нестабильные задержки в прохождении пакетов).
здесь важно не менее одного "честного" ядра процессора на сетевуху и тщательно курить /proc/interrupts и /proc/irq/irqN/smp_affinity
хотя больше 600-700 одновременных сессий даже на хорошем сервере - проблематично.
потому мы уходим от этого на контроль доступа на оконечке и шлюзу остаётся только NAT и нарезка скорости, без всяких PPTP - результат пока весьма удовлетворительный.