mirror of
https://github.com/librenms/librenms.git
synced 2024-10-07 16:52:45 +00:00
* Remove some lightly used or unused dbFacile functions ['NULL'] legacy behavior seems unsupported, replace with actual nulls * Fix refactor mishap * another * update baseline * these were very wrong... what happened?
194 lines
7.2 KiB
PHP
194 lines
7.2 KiB
PHP
<?php
|
|
|
|
use App\Models\BgpPeer;
|
|
use Carbon\Carbon;
|
|
|
|
$name = 'bird2';
|
|
|
|
if (! \LibreNMS\Config::get('enable_bgp')) {
|
|
echo PHP_EOL . $name . ': BGP is not enabled in config' . PHP_EOL;
|
|
|
|
return;
|
|
}
|
|
|
|
$birdOutput = snmp_get($device, 'nsExtendOutputFull.' . \LibreNMS\Util\Oid::ofString($name), '-Oqv', 'NET-SNMP-EXTEND-MIB');
|
|
|
|
// make sure we actually get something back
|
|
if (empty($birdOutput)) {
|
|
echo PHP_EOL . $name . ': has empty output' . PHP_EOL;
|
|
|
|
return;
|
|
}
|
|
|
|
// ========
|
|
// Process the actual BIRD2 output
|
|
$protocolsData = [];
|
|
|
|
// Remove headers
|
|
$birdOutput = trim(explode('Name Proto Table State Since Info', $birdOutput, 2)[1]);
|
|
$protocolSegments = explode("\n\n", $birdOutput);
|
|
|
|
// Remove the first title
|
|
unset($protocolSegments[0]);
|
|
|
|
foreach ($protocolSegments as $protocolSegment) {
|
|
// Deal with the title first
|
|
$protocolSegmentParts = explode("\n", $protocolSegment, 2);
|
|
$titleParts = preg_split("/\s+/", $protocolSegmentParts[0], 5);
|
|
|
|
// make sure we only look at BGP protocols
|
|
if ($titleParts[1] !== 'BGP') {
|
|
continue;
|
|
}
|
|
|
|
$protocolData = [
|
|
'name' => $titleParts[0],
|
|
'type' => $titleParts[1],
|
|
'table' => $titleParts[2],
|
|
'protocol_state' => $titleParts[3],
|
|
'since' => preg_split("/\s+/", $titleParts[4], 3)[0] . ' ' . preg_split("/\s+/", $titleParts[4], 3)[1],
|
|
];
|
|
|
|
// Deal with the rest of the body
|
|
$protocolBodys = preg_split("/^\s{2}([A-Z])/m", $protocolSegmentParts[1]);
|
|
|
|
// Loop through all BGP protocols
|
|
foreach ($protocolBodys as $protocolBody) {
|
|
// Deal with the BGP block
|
|
if (strpos($protocolBody, 'GP') === 0) {
|
|
foreach (explode("\n", 'B' . $protocolBody) as $protocolBodyLine) {
|
|
if (strpos($protocolBodyLine, ':') !== false) {
|
|
$lineParts = explode(':', $protocolBodyLine, 2);
|
|
$protocolData[str_replace(' ', '_', strtolower(trim($lineParts[0])))] = trim($lineParts[1]);
|
|
}
|
|
}
|
|
|
|
// Fix up the error string
|
|
if (isset($protocolData['last_error'])) {
|
|
// Trim the received
|
|
$protocolData['last_error'] = trim(str_ireplace('Received:', '', $protocolData['last_error']));
|
|
}
|
|
}
|
|
|
|
// Process the Ip channel (v4/v6)
|
|
$IpVersion = 4;
|
|
if (filter_var($protocolData['neighbor_address'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
|
|
$IpVersion = 6;
|
|
}
|
|
|
|
if (strpos($protocolBody, 'hannel ipv' . $IpVersion) === 0) {
|
|
foreach (explode("\n", 'C' . $protocolBody) as $protocolBodyLine) {
|
|
if (strpos($protocolBodyLine, ':') !== false) {
|
|
$lineParts = explode(':', $protocolBodyLine, 2);
|
|
$protocolData[str_replace(' ', '_', strtolower(trim($lineParts[0])))] = trim($lineParts[1]);
|
|
}
|
|
}
|
|
|
|
// Fix up the ROUTES
|
|
if (isset($protocolData['routes'])) {
|
|
$routeParts = explode(', ', $protocolData['routes']);
|
|
unset($protocolData['routes']);
|
|
foreach ($routeParts as $routePart) {
|
|
$routeDetail = explode(' ', $routePart);
|
|
$protocolData['routes'][$routeDetail[1]] = $routeDetail[0];
|
|
}
|
|
}
|
|
|
|
// Set the route updates
|
|
unset($protocolData['route_change_stats']);
|
|
foreach (['import_updates', 'import_withdraws', 'export_updates', 'export_withdraws'] as $key) {
|
|
if (! isset($protocolData[$key])) {
|
|
continue;
|
|
}
|
|
|
|
$routeChange_parts = preg_split("/\s+/", trim($protocolData[$key]));
|
|
|
|
unset($protocolData[$key]);
|
|
$protocolData['route_change_stats'][$key] = [
|
|
'received' => $routeChange_parts[0],
|
|
'rejected' => $routeChange_parts[1],
|
|
'filtered' => $routeChange_parts[2],
|
|
'ignored' => $routeChange_parts[3],
|
|
'accepted' => $routeChange_parts[4],
|
|
];
|
|
}
|
|
}
|
|
}
|
|
|
|
$protocolsData[] = $protocolData;
|
|
}
|
|
|
|
// ---
|
|
$deviceObj = DeviceCache::getPrimary();
|
|
|
|
if (empty($protocolsData)) {
|
|
echo PHP_EOL . $name . ': No BGP Peers found' . PHP_EOL;
|
|
$deviceObj->bgpLocalAs = null;
|
|
$deviceObj->save();
|
|
|
|
return;
|
|
}
|
|
|
|
// Do bgpLocalAs Update
|
|
// Get the most common localAS (in theory there *should* be only one, but not always
|
|
$localAsns = array_count_values(array_column($protocolsData, 'local_as'));
|
|
arsort($localAsns);
|
|
$bgpLocalAs = array_keys($localAsns)[0];
|
|
|
|
$deviceObj->bgpLocalAs = $bgpLocalAs;
|
|
$deviceObj->save();
|
|
|
|
// Going through all BGP Peers
|
|
$bgpPeerIds = [];
|
|
|
|
foreach ($protocolsData as $protocol) {
|
|
$bgpPeer = BgpPeer::firstOrNew([
|
|
'device_id' => $device['device_id'],
|
|
'bgpPeerRemoteAs' => $protocol['neighbor_as'],
|
|
'bgpLocalAddr' => $protocol['source_address'] ?: '0.0.0.0',
|
|
'bgpPeerRemoteAddr' => $protocol['neighbor_address'],
|
|
]);
|
|
|
|
$bgpPeer->device_id = $device['device_id'];
|
|
$bgpPeer->astext = \LibreNMS\Util\AutonomousSystem::get($protocol['neighbor_as'])->name();
|
|
$bgpPeer->bgpPeerIdentifier = $protocol['neighbor_id'] ?: '0.0.0.0';
|
|
$bgpPeer->bgpPeerRemoteAs = $protocol['neighbor_as'];
|
|
$bgpPeer->bgpPeerState = strtolower($protocol['bgp_state']);
|
|
$bgpPeer->bgpPeerAdminStatus = str_replace('up', 'start', strtolower($protocol['protocol_state']));
|
|
|
|
if (isset($protocolData['last_error'])) {
|
|
// Find the subcode if its there and set it
|
|
foreach (trans('bgp.error_subcodes') as $mainCode => $subCodes) {
|
|
foreach ($subCodes as $subCode => $message) {
|
|
if ($message == $protocolData['last_error']) {
|
|
$bgpPeer->bgpPeerLastErrorCode = $mainCode;
|
|
$bgpPeer->bgpPeerLastErrorSubCode = $subCode;
|
|
}
|
|
}
|
|
}
|
|
|
|
$bgpPeer->bgpPeerLastErrorText = $protocol['neighbor_id'] ?: '0.0.0.0';
|
|
}
|
|
|
|
$bgpPeer->bgpLocalAddr = $protocol['source_address'] ?: '0.0.0.0';
|
|
$bgpPeer->bgpPeerRemoteAddr = $protocol['neighbor_address'];
|
|
$bgpPeer->bgpPeerDescr = $protocol['description'] ?: $protocol['name'];
|
|
$bgpPeer->bgpPeerInUpdates = intval($protocol['route_change_stats']['import_updates']['accepted']);
|
|
$bgpPeer->bgpPeerOutUpdates = intval($protocol['route_change_stats']['export_updates']['accepted']);
|
|
$bgpPeer->bgpPeerInTotalMessages = intval($protocol['route_change_stats']['import_updates']['received']);
|
|
$bgpPeer->bgpPeerOutTotalMessages = intval($protocol['route_change_stats']['export_updates']['received']);
|
|
|
|
$bgpPeer->bgpPeerFsmEstablishedTime = Carbon::parse($protocol['since'])->diffInSeconds(Carbon::now());
|
|
$bgpPeer->bgpPeerInUpdateElapsedTime = Carbon::parse($protocol['since'])->diffInSeconds(Carbon::now());
|
|
$bgpPeer->save();
|
|
|
|
echo PHP_EOL . $name . ': Processed peer AS' . $bgpPeer->bgpPeerRemoteAs . ' (' . $bgpPeer->astext . ')';
|
|
|
|
$bgpPeerIds[] = $bgpPeer->bgpPeer_id;
|
|
}
|
|
|
|
echo PHP_EOL;
|
|
|
|
// Clean up any bgpPeers that arent on the list for this device
|
|
BgpPeer::where('device_id', $device['device_id'])->whereNotIn('bgpPeer_id', $bgpPeerIds)->delete();
|