Схема DHCP+Manad
Используется BGDHCP и свичи с функционалом DHCP Opt.82 + L3 DHCP relay в управляющем VLAN,
поддерживает 1IP на порт. Дочерним шлюзом к выступает шлюз который выполняет 2 задачи,
1) это редактор IP адреса и порта, в нем настройки релея для DHCP
2) он передает данные Linux шлюзу с Manad, где происходит шейпинг
DHCP работающий с дочерним манадом
На основе этого скрипта из викиКонфиг для типа шлюза
Код:
user_rule.editor.class=bitel.billing.module.services.ipn.editor.EmptyContractRuleEditor
gate_manager.class=bitel.billing.server.ipn.DHCPGateWorker
use.script=1
gate.cache.script=1
Скрипт для типа шлюза
Код:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Pattern;
import org.apache.xml.serializer.ToXMLStream;
import org.xml.sax.SAXException;
import ru.bitel.bgbilling.common.DefaultSetup;
//GatePortManager
import ru.bitel.bgbilling.modules.ipn.server.bean.GatePortManager;
import bitel.billing.common.module.ipn.IPNContractStatus;
import bitel.billing.server.ipn.bean.Gate;
import bitel.billing.server.ipn.UserPortStatus;
import bitel.billing.server.ipn.UserStatus;
// AddressRangeManager
import bitel.billing.server.ipn.bean.AddressRangeManager;
import bitel.billing.server.ipn.bean.AddressRange;
//void parentSync(..)
import bitel.billing.server.ipn.GateWorker;
import bitel.billing.server.ipn.dlink.UserPortStatus;
import bitel.billing.server.ipn.dlink.UserPortStatus.UserPortStatusParser;
import bitel.billing.server.util.Utils;
import bitel.billing.common.IPUtils;
void parentSync( Gate child, GateWorker childWorker )
{
log.debug( "parentSync Manad-BGDHCP" );
String host = gate.getHost();
int port = gate.getPort();
int gid = gate.getId();
String childhost = child.getHost();
int childport = child.getPort();
int childgid = child.getId();
if( Utils.isEmptyString( host ) || port <= 0 )
{
log.error( "Can't get IP/port for BGDHCP for this gate! " );
gateErrors.append( "Не указан адрес сервера dhcp для данного шлюза!" );
return;
}
if( log.isDebugEnabled() )
log.debug( gid + " gate: " + host + ":" + port );
if( log.isDebugEnabled() )
log.debug( childgid + " childgate: " + childhost + ":" + childport );
Socket socket = null;
try
{
socket = new Socket( host, port );
InputStreamReader isr = new InputStreamReader( socket.getInputStream() );
BufferedReader in = new BufferedReader( isr );
ToXMLStream stream = new ToXMLStream();
stream.setOutputStream( socket.getOutputStream() );
stream.setEncoding( "UTF-8" );
stream.startDocument();
stream.startElement( "sync" );
stream.addAttribute( "type", "dhcp" );
Gate gate = child;
syncGate( gate, stream );
stream.startElement( "list" );
stream.addAttribute( "gateId", String.valueOf( gate.getId() ) );
stream.endElement( "list" );
stream.flushPending();
stream.getWriter().flush();
Map portStatusMap = new HashMap();
String line = in.readLine();
Pattern TabPattern=Pattern.compile("[\t]");
while( line != null && !"".equals( line ) )
{
String[] p = TabPattern.split( line );
if( p.length > 1 )
{
UserPortStatus st = new UserPortStatus();
st.ipAddr = p[1];
st.port = Utils.parseIntString( p[0], -1 );
portStatusMap.put( st.port, st );
}
line = in.readLine();
}
String gateId = String.valueOf( gate.getId() );
AddressRangeManager IPManager = new AddressRangeManager(con, mid);
GatePortManager PortManager = new GatePortManager( con, mid );
for( UserStatus status : statusList )
{
List IPRange=IPManager.getContractAddressRange(status.contractId);
AddressRange IP1 = null;
numIP=0;
// IP1.getAddr1() - long
// TODO Utils -> IPUtils
for( AddressRange IP : IPRange )
{
log.debug("cid="+status.contractId + " IP="+IPUtils.convertLongIpToString(IP.getAddr1())+ "-" +IPUtils.convertLongIpToString(IP.getAddr2()));
if (IP.getAddr1()==IP.getAddr2())
{
IP1=IP;
numIP++;
}
}
if ( (IP1 == null) || (numIP > 1) )
{
log.error("cid="+ status.contractId+" IP configuration Eror" );
}
Ports = PortManager.getGatePorts( status.contractId, gate.getId() );
Port=null;
for( Port : Ports )
{
log.debug("cid="+ status.contractId+" port=" +String.valueOf(Port) );
}
UserPortStatus s = portStatusMap.remove( Port );
IPhex= Utils.bytesToString( Utils.convertIntToBytes ( (int)IP1.getAddr1() ) );
log.debug("cid="+ status.contractId + " IPhex=" + IPhex);
if( (s == null || !s.ipAddr.equals(IPhex )) && status.status != IPNContractStatus.STATUS_REMOVED )
{
log.debug("cid="+ status.contractId+" adding IP to DHCP");
stream.startElement( "port" );
stream.addAttribute( "gateId", gateId );
stream.addAttribute( "id", String.valueOf( Port ) );
stream.addAttribute( "ip", IPhex );
stream.endElement( "port" );
}
//удаляем в одном месте
if( s != null && status.status == IPNContractStatus.STATUS_REMOVED )
{
log.debug("cid="+ status.contractId+" removing IP from DHCP");
stream.startElement( "removePort" );
stream.addAttribute( "gateId", gateId );
stream.addAttribute( "id", String.valueOf(Port) );
stream.addAttribute( "ip", IPhex );
stream.endElement( "removePort" );
}
} // for
stream.flushPending();
stream.getWriter().flush();
stream.endElement( "sync" );
stream.endDocument();
stream.getWriter().flush();
} // try
finally
{
if( socket != null )
{
try
{
socket.close();
}
catch (Exception e)
{}
}
}
}
protected void syncGates( Gate gate, ToXMLStream stream )
{
try
{
if( gate != null )
{
stream.startElement( "gate" );
stream.addAttribute( "id", String.valueOf( gate.getId() ) );
stream.addAttribute( "host", gate.getHost() );
DefaultSetup gateSetup = new DefaultSetup( gate.getConfig(), "\n" );
Map params = gateSetup.getHashValuesWithPrefix( "dhcp." );
for( Entry e : params.entrySet() )
{
stream.startElement( "param" );
stream.addAttribute( "id", "dhcp." + e.getKey() );
stream.addAttribute( "value", e.getValue() );
stream.endElement( "param" );
}
if( gate.getChildren() != null )
for( Gate g : gate.getChildren() )
{
syncGates( g, stream );
}
stream.endElement( "gate" );
}
}
catch( SAXException e )
{
e.printStackTrace();
}
}
protected void syncGate( Gate gate, ToXMLStream stream )
{
try
{
if( gate != null )
{
List gateList = new ArrayList();
gateList.add( gate );
Gate g = gate;
while( g != null )
{
gateList.add( g );
g = g.getParent();
}
HashMap params = new HashMap();
for( int i = gateList.size() - 1; i >= 0; i-- )
{
DefaultSetup gateSetup = new DefaultSetup( gateList.get( i ).getConfig(), "\n" );
Map p = gateSetup.getHashValuesWithPrefix( "dhcp." );
for( Entry e : p.entrySet() )
{
params.put( e.getKey(), e.getValue() );
}
}
log.debug("sync gate start");
stream.startElement( "gate" );
log.debug("id="+String.valueOf( gate.getId() ) );
stream.addAttribute( "id", String.valueOf( gate.getId() ) );
log.debug("host="+gate.getHost() );
stream.addAttribute( "host", gate.getHost() );
for( Entry e : params.entrySet() )
{
stream.startElement( "param" );
log.debug("dhcp."+e.getKey());
stream.addAttribute( "id", "dhcp." + e.getKey() );
log.debug("value="+e.getValue());
stream.addAttribute( "value", e.getValue() );
stream.endElement( "param" );
}
stream.endElement( "gate" );
log.debug("sync gate end");
}
}
catch( SAXException e )
{
e.printStackTrace();
}
}
Конфиг шлюза, хост=BGDHCP порт=BGDHCP у меня 1868
Код:
processor.class=bitel.billing.server.ext.dhcp.DHCPRelayProcessor
#Номер субопции в Option 82, в которой хранится порт клиента(нумерация с 1)
dhcp.82.key.option.code=1
#Позиция(номер байта) внутри субопции, в которой хранится порт клиента(нумерация с 0).
dhcp.82.key.position=6