Шейпинг скорости на iproute2 с использованием hash-таблиц(без использования Manad)

Материал из BiTel WiKi

Перейти к: навигация, поиск

Статья написана пока еще с не совсем сложившимся пониманием как это работает,поэтому могут быть неточности .

С ростом количества правил шейпинга в iptoute2 уже нельзя использовать линейную структуру фильтрации, когда все фильтры( по одному или несколько на каждого абонента) добавляются на одном уровне . В худшем случае при поиске правила шейпинга система будет проверять все фильтры каждый раз. Поэтому надо использовать hash-таблицы. Общий принцип такой, вначале анализируется первый октет и на основе него выбирается какую таблицу дальше анализировать. Далее второй октет, третий и 4-ый. В худшем случае перебирают 255 фильтров для последнего октета.

Данный пример сделан без использования Manad. Номера классов шейпинга делают на основе ip-адреса.

Пусть у нас есть внешние сети такого вида xxx.yyy.0.0/16. xxx и yyy обычные 10-ные числа обозначающие часть ip-адреса.

Пусть xxx - это XX в 16-ом системе, а yyy - это YY в 16-ой системе.

Тут делаем определенную структуру фильтров. Для 3-го октета мы назначаем handle равный этому 3-ме октету. И вы выстраиваем все правила до 3-го октета:


#ROOT
 
tc qdisc del dev p514p1 handle ffff: ingress 2> /dev/null
tc qdisc del dev p514p1 root
tc qdisc del dev p514p1 root 2> /dev/null
tc qdisc add dev p514p1 root handle 1: htb r2q 15000
tc class add dev p514p1 classid 1:0 htb rate 2460Mbit
 
###
 
tc filter add dev p514p1 parent 1:0 prio 5 protocol ip u32
tc filter add dev p514p1 parent 1:0 prio 5 handle 10: protocol ip u32 divisor 256
tc filter add dev p514p1 protocol ip parent 1:0 prio 5 u32 ht 800:: match ip dst 0.0.0.0/0 hashkey mask 0xff000000 at 16 link 10: 
 
 
## entries for xxx.0.0.0/8 
 
tc filter add dev p514p1 parent 1:0 prio 5 handle 11: protocol ip u32 divisor 256
tc filter add dev p514p1 protocol ip parent 1:0 prio 5 u32 ht 10:XX: match ip dst 0.0.0.0/0 hashkey mask 0xff0000 at 16 link 11: 
 
## entries for xxx.yyy.0.0/16
tc filter add dev p514p1 parent 1:0 prio 5 handle 12: protocol ip u32 divisor 256
tc filter add dev p514p1 protocol ip parent 1:0 prio 5 u32 ht 11:YY: match ip dst 0.0.0.0/0 hashkey mask 0xff00 at 16 link 12: 
 
## entries for xxx.yyy.161.0/24
tc filter add dev p514p1 parent 1:0 prio 5 handle a1: protocol ip u32 divisor 256
tc filter add dev p514p1 protocol ip parent 1:0 prio 5 u32 ht 12:a1: match ip dst 0.0.0.0/0 hashkey mask 0xff at 16 link a1: 
 
## entries for xxx.yyy.162.0/24
tc filter add dev p514p1 parent 1:0 prio 5 handle a2: protocol ip u32 divisor 256
tc filter add dev p514p1 protocol ip parent 1:0 prio 5 u32 ht 12:a2: match ip dst 0.0.0.0/0 hashkey mask 0xff at 16 link a2: 
.......

Далее пусть у нас есть какой-то конкретный адрес для абонента xxx.yyy.161.155. Билинг( в данном случае access-сервер) должен добавить для него фильтры c handle равным последним октетам( 161.155). 161 - это A1 в 16-ной, 155 - 9B в 16-ной.

Команды добавления скорости от биллинга отправляется такие:

sudo tc filter add dev $param(iface) protocol ip parent 1:0 prio 5 u32 ht A1:9B: match ip dst 0.0.0.0/0 flowid 1:A19B
sudo tc class add dev $param(iface) parent 1:0 classid 1:0xA19B htb rate 4096Kbit ceil 20480Kbit quantum 2000 mtu 3000 burst 15k

Команды удаления скорости от биллинга отправляется такие:

sa.command.common.ancestor.inetOption.11.disable.1=sudo tc filter delete dev $param(iface) parent 1:0 protocol ip prio 5 handle $A1:9B:800 u32
sa.command.common.ancestor.inetOption.11.disable.2=sudo tc class delete dev $param(iface) parent 1:0 classid 1:0xA19B htb rate 4096Kbit ceil 20480Kbit quantum 2000 mtu 3000 burst 15k

Для этого мы забиваем в конфигурации такие команды:

speedRate=$param($option,speedRate,100)
speedCeil=$param($option,speedCeil,100)
sa.endSequence=$
 
sa.command.common.ancestor.inetOption.11.enable.1=sudo tc filter add dev $param(iface) protocol ip parent 1:0 prio 5 u32 ht $ip3:$ip4: match ip dst 0.0.0.0/0 flowid 1:$ip34
sa.command.common.ancestor.inetOption.11.enable.2=sudo tc class add dev $param(iface) parent 1:0 classid 1:0x$ip34 htb rate {@speedRate} ceil {@speedCeil} quantum 2000 mtu 3000 burst 15k
 
 
sa.command.common.ancestor.inetOption.11.disable.1=sudo tc filter delete dev $param(iface) parent 1:0 protocol ip prio 5 handle $ip3:$ip4:800 u32
sa.command.common.ancestor.inetOption.11.disable.2=sudo tc class delete dev $param(iface) parent 1:0 classid 1:0x$ip34 htb rate {@speedRate} ceil {@speedCeil} quantum 2000 mtu 3000 burst 15k


тут макросы $ip3 - 3-тий октет, $ip4 - 4-ый. $ip34 - 3 и 4 слепленные вместе. Данный команды рассчитаны на такое дерево в котором, все опции изменения скорости находятся в дереве опции ниже опции 11:

Медиа:shaper_options.png Файл:shaper_options.png

В конфигурации самих опции заносим значения скоростей:

speedRate=4096Kbit
speedCeil=20480Kbit


Чтобы эти команды отправить на устройство мы используем SSHServiceActivator, но для поддержки специфичных макросов мы наследуется от него и немного добавляем код:

package ru.bitel.bgbilling.custom.inet.dyn.device.terminal;
 
import ru.bitel.bgbilling.modules.inet.access.sa.ServiceActivator;
import ru.bitel.bgbilling.modules.inet.access.sa.ServiceActivatorAdapter;
import ru.bitel.bgbilling.modules.inet.access.sa.ServiceActivatorEvent;
import ru.bitel.bgbilling.modules.inet.api.common.bean.InetDevice;
import ru.bitel.bgbilling.modules.inet.api.common.bean.InetDeviceType;
import ru.bitel.bgbilling.server.util.Setup;
import ru.bitel.common.ParameterMap;
import ru.bitel.bgbilling.modules.inet.dyn.device.terminal.SSHServiceActivator;
import ru.bitel.bgbilling.modules.inet.api.common.bean.InetServ;
import ru.bitel.bgbilling.modules.inet.api.common.bean.InetConnection;
import java.util.Set;
import ru.bitel.common.Utils;
import org.apache.log4j.Logger;
import java.util.concurrent.TimeUnit;
import bitel.billing.server.util.ssh.SSHSession;
 
public class SSHLinuxServiceActivator 
	extends SSHServiceActivator
	implements ServiceActivator
{
	private static final Logger logger = Logger.getLogger( SSHLinuxServiceActivator.class );
 
	@Override
	protected Object getValue( ServiceActivatorEvent e, InetServ serv, InetConnection connection, Set<Integer> options, String macros, Object[] args, Object[] globalArgs )
	    throws Exception
	{
 
		if( "ip34".equals( macros ) )
		{
			String hex = Utils.bytesToHexString(  serv.getAddressFrom() );
 
			return hex.substring(4,8);
		}
		if( "ip3".equals( macros ) )
		{
			String hex = Utils.bytesToHexString(  serv.getAddressFrom() );
 
			return hex.substring(4,6);
		}
		if( "ip4".equals( macros ) )
		{
			String hex = Utils.bytesToHexString(  serv.getAddressFrom() );
 
			return hex.substring(6,8);
		}
		else
		{
			return super.getValue( e, serv, connection, options, macros, args, globalArgs );
		}
	}		
}
Личные инструменты