Дерево страниц

Сравнение версий

Ключ

  • Эта строка добавлена.
  • Эта строка удалена.
  • Изменено форматирование.

...

Для извлечения значения требуется указать код субопции, а также один или два regex - hex и string. hex указывает, что нужно выбрать в опции в 16-ричном формате (один байт - это два символа), string - указывает, что нужно выбрать в опции, преобразованной в строку.

Базовые значения

Предположим, у нас в DHCP-пакете присутствует такая option 82:

...

Блок кода
languageruby
dhcp.option82.agentSvlanId.code=1
dhcp.option82.agentSvlanId.hex=^(\w{2})

Логин

Или логин для поиска по логину (для схемы PON, когда в agentRemoteId приходит MAC-адрес ONU):

Блок кода
languageruby
dhcp.option82.login.code=2
dhcp.option82.login.hex=.*

Однако приходящие Извлеченный логин можно сохранить в сессии (сохранение сработает, если включен поиск по логину или логин был установлен в предобработке):

Блок кода
languageruby
dhcp.option82.login.save=1

Опции в виде HEX-строки

Приходящие значения могут представлять собой строку:

...

Блок кода
languageruby
dhcp.option82.interfaceId.code=1
dhcp.option82.interfaceId.hex=^.{4}(.+)$
dhcp.option82.interfaceId.string=port(\d+)

Разные форматы

Regex-ов можно указать несколько - это может быть удобно при наличии устройств разных марок - они могут посылать option 82 в разном формате:

...

Если же giaddr в DHCP-пакете relay agent'а, от которого получил запрос Cisco/SmartEdge, то для типа устройства relay agent'а нужно указать отдельный обработчик, см. выше.

Пример совмещения предобработки с конфигурацией (PON)

В данном примере из пакета извлекаются нужные значения, устанавливаются в запрос, а также формируется строка, которая далее окажется в поле "На номер" сессии (InetDhcpProcessor.CALLED_STATION_ID). Данную строку можно будет использовать как информационную (она отображается в клиенте биллинга), а также первом подключении (регистрации) абонента для заполнения полей сервиса договора.

Конфигурация:

Блок кода
languageruby
# Ищем по "логину"
dhcp.servSearchMode=0

# Извлечение логина из запроса - MAC-адрес или идентификатор PON
dhcp.option82.login.code=2
dhcp.option82.login.hex=.*
# сохраняем "логин" в сессии
dhcp.option82.login.save=1

# Не извлекаем agentRemoteId как идентификатор устройства (мы используем его как логин)
dhcp.option82.agentRemoteId.code=0
# Извлечение SVLAN
dhcp.option82.agentSvlanId.code=1
dhcp.option82.agentSvlanId.hex=^(\w{4})

# Данные параметры извлекаются в предобработке
# порт OLT
dhcp.option82.oltPort.code=1
dhcp.option82.oltPort.hex=^.{6}(\w{2})
# ont ID на порту OLT
dhcp.option82.ontId.code=1
dhcp.option82.ontId.hex=^.{8}(\w{2})

Предобработка:

Блок кода
languagejava
collapsetrue
package ru.provider.bgbilling.modules.inet.dyn.device;

import javax.annotation.Resource;

import org.apache.log4j.Logger;

import ru.bitel.bgbilling.kernel.network.dhcp.DhcpOption;
import ru.bitel.bgbilling.kernel.network.dhcp.DhcpPacket;
import ru.bitel.bgbilling.modules.inet.access.sa.ProtocolHandlerAdapter;
import ru.bitel.bgbilling.modules.inet.api.common.bean.InetDevice;
import ru.bitel.bgbilling.modules.inet.api.common.bean.InetDeviceType;
import ru.bitel.bgbilling.modules.inet.dhcp.InetDhcpProcessor;
import ru.bitel.bgbilling.modules.inet.runtime.device.PacketValueExtractor;
import ru.bitel.bgbilling.server.util.Setup;
import ru.bitel.common.ParameterMap;
import ru.bitel.common.io.BinaryValueExtractor;

public class PonDhcpRelayProtocolHandler
    extends ProtocolHandlerAdapter
{
    private static final Logger logger = Logger.getLogger( PonDhcpRelayProtocolHandler.class );

    @Resource
    private PacketValueExtractor packetValueExtractor;

    private byte oltPortCode;
    private BinaryValueExtractor oltPortExtractor;

    private byte ontIdPortCode;
    private BinaryValueExtractor ontIdPortExtractor;

    @Override
    public void init( Setup setup, int moduleId, InetDevice inetDevice, InetDeviceType inetDeviceType, ParameterMap deviceConfig )
        throws Exception
    {
        oltPortCode = (byte)deviceConfig.getInt( "dhcp.option82.oltPort.code", 1 );
        oltPortExtractor = packetValueExtractor.getExtractor( deviceConfig, "dhcp.option82.oltPort." );

        ontIdPortCode = (byte)deviceConfig.getInt( "dhcp.option82.ontId.code", 1 );
        ontIdPortExtractor = packetValueExtractor.getExtractor( deviceConfig, "dhcp.option82.ontId." );
    }

    @Override
    public void preprocessDhcpRequest( final DhcpPacket request, final DhcpPacket response )
        throws Exception
    {
        final int svlan = packetValueExtractor.getOption82AgentSvlanId( request, true );
        final int vlan = packetValueExtractor.getOption82VlanId( request, true );

        final int oltPort = extract( request, oltPortCode, oltPortExtractor );
        final int ontId = extract( request, ontIdPortCode, ontIdPortExtractor );

        final String onuIdentifier = (String)packetValueExtractor.getOption82Login( request, true );

        final String calledStationId = svlan + "." + vlan + "/" + oltPort + ":" + ontId + "/" + onuIdentifier;

        logger.info( calledStationId );

        // устанавливаем VLAN, чтобы он был досупен биллингу при обработке пакета
        request.setOption( InetDhcpProcessor.VLAN_ID, vlan );
        // устанавливаем VLAN в circuitId сессии
        request.setOption( InetDhcpProcessor.CIRCUIT_ID, vlan );
        // устанавливаем в calledStationId сессии, для информации
        request.setOption( InetDhcpProcessor.CALLED_STATION_ID, calledStationId );
    }

    private static int extract( final DhcpPacket request, final byte code, final BinaryValueExtractor extractor )
    {
        final DhcpOption subOption = request.getSubOption( code );
        if( subOption != null )
        {
            return extractor.extractInt( subOption.value, -1 );
        }

        return -1;
    }
}