176 lines
5.1 KiB
PHP
176 lines
5.1 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Pfatt\Service;
|
|
|
|
use Psr\Log\LoggerAwareInterface;
|
|
use Psr\Log\LoggerInterface;
|
|
use Symfony\Component\Process\Process;
|
|
|
|
class NgCtl implements LoggerAwareInterface
|
|
{
|
|
private LoggerInterface $logger;
|
|
|
|
public function __construct(LoggerInterface $logger)
|
|
{
|
|
$this->logger = $logger;
|
|
}
|
|
|
|
/**
|
|
* Use ngctl to check connection.
|
|
*/
|
|
public function ngIsConnected(): bool
|
|
{
|
|
return $this->exec(['show', 'laneapfilter:eapout']);
|
|
}
|
|
|
|
/**
|
|
* Remove the eapout connection between laneapfilter and waneapfilter.
|
|
*/
|
|
public function ngRmHook(): void
|
|
{
|
|
$this->logger->info('Disconnecting netgraph node ...');
|
|
$this->exec(['rmhook', 'laneapfilter:', 'eapout']) ?
|
|
$this->logger->info('OK!') :
|
|
$this->logger->error('ERROR!');
|
|
}
|
|
|
|
/**
|
|
* Connect laneapfilter and waneapfilter with eapout.
|
|
*/
|
|
public function ngConnect(): void
|
|
{
|
|
$this->logger->info('Connecting netgraph node ...');
|
|
$this->exec(['connect', 'waneapfilter:', 'laneapfilter:', 'eapout', 'eapout']) ?
|
|
$this->logger->info('OK!') :
|
|
$this->logger->error('ERROR!');
|
|
}
|
|
|
|
/**
|
|
* Use ngctl to setup virtual connection.
|
|
*
|
|
* @param string $ont
|
|
* ONT network connection interface.
|
|
* @param string $rg
|
|
* Residential Gateway network connection interface.
|
|
* @param string $rgMac
|
|
* Residential Gateway MAC address.
|
|
* @return void
|
|
*/
|
|
public function createNodes(string $ont, string $rg, string $rgMac): void
|
|
{
|
|
$this->logger->info('Building netgraph nodes.');
|
|
|
|
$this->logger->info(' creating ng_one2many...');
|
|
$this->exec(['mkpeer', $ont . ':', 'one2many', 'lower', 'one']);
|
|
$this->exec(['name', $ont . ':lower', 'o2m']);
|
|
$this->logger->info('OK!');
|
|
|
|
$this->logger->info(' creating vlan node and interface...');
|
|
$this->exec(['mkpeer', 'o2m:', 'vlan', 'many0', ' downstream']);
|
|
$this->exec(['name', 'o2m:many0', 'vlan0']);
|
|
$this->exec(['mkpeer', 'vlan0:', 'eiface', 'vlan0', 'ether']);
|
|
$this->exec([
|
|
'msg',
|
|
'vlan0:',
|
|
'\'addfilter { vlan=0 hook="vlan0" }\''
|
|
]);
|
|
$this->exec(['msg', 'ngeth0:', 'set', $rgMac]);
|
|
$this->logger->info('OK!');
|
|
|
|
$this->logger->info(" defining etf for $ont (ONT)...");
|
|
$this->exec(['mkpeer', 'o2m:', 'etf', 'many1', 'downstream']);
|
|
$this->exec(['name', 'o2m:many1', 'waneapfilter']);
|
|
$this->exec([
|
|
'connect',
|
|
'waneapfilter:',
|
|
$ont . ':',
|
|
'nomatch',
|
|
'upper'
|
|
]);
|
|
$this->logger->info('OK!');
|
|
|
|
$this->logger->info(" defining etf for $rg (RG)...");
|
|
$this->exec(['mkpeer', $rg . ':', 'etf', 'lower', 'downstream']);
|
|
$this->exec(['name', $rg . ':', 'lower', 'laneapfilter']);
|
|
$this->exec([
|
|
'connect',
|
|
'laneapfilter:',
|
|
$rg . ':',
|
|
'nomatch',
|
|
'upper'
|
|
]);
|
|
$this->logger->info('OK!');
|
|
|
|
$this->logger->info(" bridging etf for $ont <-> $rg...");
|
|
$this->exec([
|
|
'connect',
|
|
'waneapfilter:',
|
|
'laneapfilter:',
|
|
'eapout',
|
|
'eapout'
|
|
]);
|
|
$this->logger->info('OK!');
|
|
|
|
$this->logger->info(" defining filters for EAP traffic...");
|
|
$this->exec([
|
|
'msg',
|
|
'waneapfilter:',
|
|
'\'setfilter { matchhook="eapout" ethertype=0x888e }\''
|
|
]);
|
|
$this->exec([
|
|
'msg',
|
|
'laneapfilter:',
|
|
'\'setfilter { matchhook="eapout" ethertype=0x888e }\''
|
|
]);
|
|
$this->logger->info('OK!');
|
|
|
|
$this->logger->info(" enabling one2many links...");
|
|
$this->exec([
|
|
'msg',
|
|
'o2m:',
|
|
'setconfig',
|
|
'"{ xmitAlg=2 failAlg=1 enabledLinks=[ 1 1 ] }"'
|
|
]);
|
|
$this->logger->info('OK!');
|
|
|
|
$this->logger->info(" removing waneapfilter:nomatch hook...");
|
|
$this->exec(['rmhook', 'waneapfilter:', 'nomatch']);
|
|
$this->logger->info('OK!');
|
|
}
|
|
|
|
public function removeNodes(string $ont, string $rg): void
|
|
{
|
|
$this->exec(['shutdown', 'waneapfilter:']);
|
|
$this->exec(['shutdown', 'laneapfilter:']);
|
|
$this->exec(['shutdown', $ont . ':']);
|
|
$this->exec(['shutdown', $rg . ':']);
|
|
$this->exec(['shutdown', 'o2m:']);
|
|
$this->exec(['shutdown', 'vlan0:']);
|
|
$this->exec(['shutdown', 'ngeth0:']);
|
|
}
|
|
|
|
/**
|
|
* Run a ngctl command.
|
|
*
|
|
* @param array<int, string> $args
|
|
* Additional arguments to pass to ngctl.
|
|
*
|
|
* @return bool
|
|
* True on success, false on failure.
|
|
*/
|
|
private function exec(array $args): bool
|
|
{
|
|
$process = new Process(['/usr/sbin/ngctl', ...$args], '/tmp');
|
|
return !$process->run();
|
|
}
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
*/
|
|
public function setLogger(LoggerInterface $logger): void
|
|
{
|
|
$this->logger = $logger;
|
|
}
|
|
}
|