встала задача по оптимизации правил в ipfw и переходу на таблицы
т.к. манад для этих целей не подходит (сильно привязан к № правил в ipfw) сделал свой скрипт на основе стандартных шлюзовых скриптов :
Код:
import java.util.*;
import bitel.billing.common.module.ipn.*;
import bitel.billing.server.ipn.bean.*;
import bitel.billing.server.util.*;
import bitel.billing.common.*;
import bitel.billing.server.ipn.UserStatus;
import java.util.regex.Pattern;
import bitel.billing.server.util.telnet.*;
import ru.bitel.bgbilling.common.DefaultSetup;
protected void doSync(){
log.info("Starting ipfw+tables over telnet session");
host = gate.getHost();
port = gate.getPort();
pswd = gate.getKeyword();
DefaultServerSetup gateSetup = new DefaultServerSetup( gate.getConfig(), "\r\n" );
login = gateSetup.getStringValue( "login", "root" );
timeout = gateSetup.getIntValue( "timeout", 0 );
debug = log.isDebugEnabled();
//debug = true;
if (debug){ log.debug( " gate: " + host + ":" + port + " login: " + login + " pswd: " + pswd ); }
session = new TelnetSession( host, port);
//session.setTimeout( timeout );
session.setLoginPromptSequence( ":" );
session.connect();
session.doCommand( login );
session.setLoginPromptSequence( ":" );
session.doCommand( pswd );
session.setLoginPromptSequence( "%" );
StringBuffer cmdBuff = new StringBuffer();
rulesCount = 0;
for ( UserStatus status : statusList ) {
cid = status.contractId;
cmdBuff.setLength(0);
if ( status.status > 0 ) {
// удаляем
if ( status.status == IPNContractStatus.STATUS_REMOVED ){
rules = getDeleteRules( status );
for ( String rule : rules ) { cmdBuff.append(";"); cmdBuff.append(rule); rulesCount++; }
}
// закрываем
else {
rules = getCloseRules( status );
for ( String rule : rules ) { cmdBuff.append(";"); cmdBuff.append(rule); rulesCount++; }
}
}
if ( status.status == IPNContractStatus.STATUS_OPEN ){
rules = getOpenRules( status );
for ( String rule : rules ) { cmdBuff.append(";"); cmdBuff.append(rule); rulesCount++; }
}
if (debug) { log.info("cid: " + status.contractId.toString() + " cmd: " + cmdBuff); }
session.doCommand(cmdBuff.toString());
}
session.doCommand("echo %; exit");
log.info("Ending ipfw+tables over telnet session, rules processed: " + rulesCount);
}
getOpenRules( status ) { return getRules( status, "\\[OPEN\\](.*)\\[/OPEN\\]" ); }
private getCloseRules( status ) { return getRules( status, "\\[CLOSE\\](.*)\\[/CLOSE\\]" ); }
private getDeleteRules( status ) { return getRules( status, "\\[DELETE\\](.*)\\[/DELETE\\]" ); }
private getRules( status, template ) {
// пользовательское правило, без типа - то все оставляем как есть
rule = status.rule.getRuleText();
// типизированное правило
if ( status.ruleType != null ) {
rule = generateRule( rule, status.gateType, status.ruleType );
}
pattern = Pattern.compile( template, Pattern.DOTALL );
m = pattern.matcher( rule );
if ( m.find() ) {
rule = m.group( 1 );
}
rule.replaceAll( "\r", "" );
return rule.split( "\n" );
}
generateRule( addresses, gateType, ruleType )
{
ruleText = ManadUtils.getRule( gateType, ruleType );
return ManadUtils.generateRule( ruleText, addresses, null, ruleType );
}
и соответственно команды для правил:
Код:
[DEFAULT]
[OPEN]
<LOOP>
/usr/local/bin/sudo -b /sbin/ipfw -q table ${queueIN} add {A} ${speedIN}
/usr/local/bin/sudo -b /sbin/ipfw -q table ${queueOUT} add {A} ${speedOUT}
</LOOP>
[/OPEN]
[CLOSE]
<LOOP>
/usr/local/bin/sudo -b /sbin/ipfw -q table ${queueIN} delete {A}
/usr/local/bin/sudo -b /sbin/ipfw -q table ${queueOUT} delete {A}
</LOOP>
[/CLOSE]
[DELETE]
<LOOP>
/usr/local/bin/sudo -b /sbin/ipfw -q table ${queueIN} delete {A}
/usr/local/bin/sudo -b /sbin/ipfw -q table ${queueOUT} delete {A}
</LOOP>
[/DELETE]
[/DEFAULT]
ну и в ipfw правила добавляем для обработки трафика на основе таблиц
алгоритм работы простой: шлюз открыт - добавляем ip в таблицу, шлюз закрыт - удаляем, проверку на то что ip уже есть в таблице не делаю, т.к. имхо это займет еще больше времени чем просто добавить/удалить ip в таблицу
так вот, у меня скрипт обрабатывает около 5,5 тыс. правил
и полная синхронизация со шлюзом проходит около 10 мин, этот же скрипт через ssh работает еще дольше (раза в два),
что очень много, т.к. манад при тех же условиях работает 1-2 мин, а обсчет трафика и синхронизацию шлюзов у себя я провожу каждые 5 мин
то ли класс TelnetSession такой тормозной, то ли я что-то упускаю
,
можно ли как-то это еще оптимизировать? поделитесь опытом плиз