mirror of
https://github.com/librenms/librenms.git
synced 2024-10-07 16:52:45 +00:00
FDB Tables improve performance (#15333)
* FDB Tables improve performance Reduce unnecessary sql queries, by using a relationship Cache vendor oui lookups * Oui already "clean" * Fix typo
This commit is contained in:
@@ -27,6 +27,7 @@ namespace LibreNMS\Util;
|
|||||||
|
|
||||||
use App\Models\Device;
|
use App\Models\Device;
|
||||||
use Illuminate\Support\Arr;
|
use Illuminate\Support\Arr;
|
||||||
|
use Illuminate\Support\Facades\Cache;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use LibreNMS\Config;
|
use LibreNMS\Config;
|
||||||
|
|
||||||
@@ -158,10 +159,12 @@ class Rewrite
|
|||||||
{
|
{
|
||||||
$oui = substr($mac, 0, 6);
|
$oui = substr($mac, 0, 6);
|
||||||
|
|
||||||
$results = DB::table('vendor_ouis')
|
$results = Cache::remember($oui, 21600, function () use ($oui) {
|
||||||
->where('oui', 'like', "$oui%") // possible matches
|
return DB::table('vendor_ouis')
|
||||||
->orderBy('oui', 'desc') // so we can check longer ones first if we have them
|
->where('oui', 'like', "$oui%") // possible matches
|
||||||
->pluck('vendor', 'oui');
|
->orderBy('oui', 'desc') // so we can check longer ones first if we have them
|
||||||
|
->pluck('vendor', 'oui');
|
||||||
|
});
|
||||||
|
|
||||||
if (count($results) == 1) {
|
if (count($results) == 1) {
|
||||||
return Arr::first($results);
|
return Arr::first($results);
|
||||||
|
@@ -31,6 +31,7 @@ use App\Models\PortsFdb;
|
|||||||
use App\Models\Vlan;
|
use App\Models\Vlan;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use LibreNMS\Util\IP;
|
use LibreNMS\Util\IP;
|
||||||
use LibreNMS\Util\Rewrite;
|
use LibreNMS\Util\Rewrite;
|
||||||
@@ -39,7 +40,6 @@ use LibreNMS\Util\Url;
|
|||||||
class FdbTablesController extends TableController
|
class FdbTablesController extends TableController
|
||||||
{
|
{
|
||||||
protected $macCountCache = [];
|
protected $macCountCache = [];
|
||||||
protected $ipCache = [];
|
|
||||||
|
|
||||||
protected function rules()
|
protected function rules()
|
||||||
{
|
{
|
||||||
@@ -67,7 +67,8 @@ class FdbTablesController extends TableController
|
|||||||
*/
|
*/
|
||||||
protected function baseQuery($request)
|
protected function baseQuery($request)
|
||||||
{
|
{
|
||||||
return PortsFdb::hasAccess($request->user())->with(['device', 'port', 'vlan'])->select('ports_fdb.*');
|
return PortsFdb::hasAccess($request->user())
|
||||||
|
->with(['device', 'port', 'vlan', 'ipv4Addresses']);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -158,17 +159,15 @@ class FdbTablesController extends TableController
|
|||||||
*/
|
*/
|
||||||
public function formatItem($fdb_entry)
|
public function formatItem($fdb_entry)
|
||||||
{
|
{
|
||||||
$ip_info = $this->findIps($fdb_entry->mac_address);
|
|
||||||
|
|
||||||
$item = [
|
$item = [
|
||||||
'device' => $fdb_entry->device ? Url::deviceLink($fdb_entry->device) : '',
|
'device' => $fdb_entry->device ? Url::deviceLink($fdb_entry->device) : '',
|
||||||
'mac_address' => Rewrite::readableMac($fdb_entry->mac_address),
|
'mac_address' => Rewrite::readableMac($fdb_entry->mac_address),
|
||||||
'mac_oui' => Rewrite::readableOUI($fdb_entry->mac_address),
|
'mac_oui' => Rewrite::readableOUI($fdb_entry->mac_address),
|
||||||
'ipv4_address' => $ip_info['ips']->implode(', '),
|
'ipv4_address' => $fdb_entry->ipv4Addresses->implode(', '),
|
||||||
'interface' => '',
|
'interface' => '',
|
||||||
'vlan' => $fdb_entry->vlan ? $fdb_entry->vlan->vlan_vlan : '',
|
'vlan' => $fdb_entry->vlan ? $fdb_entry->vlan->vlan_vlan : '',
|
||||||
'description' => '',
|
'description' => '',
|
||||||
'dnsname' => $ip_info['dns'],
|
'dnsname' => $this->resolveDns($fdb_entry->ipv4Addresses),
|
||||||
'first_seen' => 'unknown',
|
'first_seen' => 'unknown',
|
||||||
'last_seen' => 'unknown',
|
'last_seen' => 'unknown',
|
||||||
];
|
];
|
||||||
@@ -198,9 +197,9 @@ class FdbTablesController extends TableController
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $ip
|
* @param string $ip
|
||||||
* @return \Illuminate\Support\Collection
|
* @return Collection
|
||||||
*/
|
*/
|
||||||
protected function findMacs($ip): \Illuminate\Support\Collection
|
protected function findMacs($ip): Collection
|
||||||
{
|
{
|
||||||
$port_id = \Request::get('port_id');
|
$port_id = \Request::get('port_id');
|
||||||
$device_id = \Request::get('device_id');
|
$device_id = \Request::get('device_id');
|
||||||
@@ -217,9 +216,9 @@ class FdbTablesController extends TableController
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $vlan
|
* @param string $vlan
|
||||||
* @return \Illuminate\Support\Collection
|
* @return Collection
|
||||||
*/
|
*/
|
||||||
protected function findVlans($vlan): \Illuminate\Support\Collection
|
protected function findVlans($vlan): Collection
|
||||||
{
|
{
|
||||||
$port_id = \Request::get('port_id');
|
$port_id = \Request::get('port_id');
|
||||||
$device_id = \Request::get('device_id');
|
$device_id = \Request::get('device_id');
|
||||||
@@ -238,9 +237,9 @@ class FdbTablesController extends TableController
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $ifAlias
|
* @param string $ifAlias
|
||||||
* @return \Illuminate\Support\Collection
|
* @return Collection
|
||||||
*/
|
*/
|
||||||
protected function findPorts($ifAlias): \Illuminate\Support\Collection
|
protected function findPorts($ifAlias): Collection
|
||||||
{
|
{
|
||||||
$port_id = \Request::get('port_id');
|
$port_id = \Request::get('port_id');
|
||||||
$device_id = \Request::get('device_id');
|
$device_id = \Request::get('device_id');
|
||||||
@@ -255,38 +254,22 @@ class FdbTablesController extends TableController
|
|||||||
->pluck('port_id');
|
->pluck('port_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private function resolveDns(Collection $ips): string
|
||||||
* @param string $mac_address
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
protected function findIps($mac_address): array
|
|
||||||
{
|
{
|
||||||
if (! isset($this->ipCache[$mac_address])) {
|
$dns = 'N/A';
|
||||||
$ips = Ipv4Mac::where('mac_address', $mac_address)
|
|
||||||
->groupBy('ipv4_address')
|
|
||||||
->pluck('ipv4_address');
|
|
||||||
|
|
||||||
$dns = 'N/A';
|
// only fetch DNS if the column is visible
|
||||||
|
if (\Request::get('dns') == 'true') {
|
||||||
// only fetch DNS if the column is visible
|
// don't try too many dns queries, this is the slowest part
|
||||||
if (\Request::get('dns') == 'true') {
|
foreach ($ips->take(3) as $ip) {
|
||||||
// don't try too many dns queries, this is the slowest part
|
$hostname = gethostbyaddr($ip);
|
||||||
foreach ($ips->take(3) as $ip) {
|
if (! IP::isValid($hostname)) {
|
||||||
$hostname = gethostbyaddr($ip);
|
return $hostname;
|
||||||
if (! IP::isValid($hostname)) {
|
|
||||||
$dns = $hostname;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->ipCache[$mac_address] = [
|
|
||||||
'ips' => $ips,
|
|
||||||
'dns' => $dns,
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->ipCache[$mac_address];
|
return $dns;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -308,31 +291,24 @@ class FdbTablesController extends TableController
|
|||||||
* @param string $vendor
|
* @param string $vendor
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
protected function ouisFromVendor($vendor)
|
protected function ouisFromVendor(string $vendor): array
|
||||||
{
|
{
|
||||||
$matching_ouis = DB::table('vendor_ouis')
|
return DB::table('vendor_ouis')
|
||||||
->where('vendor', 'LIKE', '%' . $vendor . '%')
|
->where('vendor', 'LIKE', '%' . $vendor . '%')
|
||||||
->pluck('oui')
|
->pluck('oui')
|
||||||
->toArray();
|
->toArray();
|
||||||
|
|
||||||
return $matching_ouis;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all port ids from vendor OUIs
|
* Get all port ids from vendor OUIs
|
||||||
*
|
|
||||||
* @param array $vendor_ouis
|
|
||||||
* @return Builder
|
|
||||||
*/
|
*/
|
||||||
protected function findPortsByOui($vendor_ouis, $query)
|
protected function findPortsByOui(array $vendor_ouis, Builder $query): Builder
|
||||||
{
|
{
|
||||||
$condition = '';
|
$query->where(function (Builder $query) use ($vendor_ouis) {
|
||||||
foreach ($vendor_ouis as $oui) {
|
foreach ($vendor_ouis as $oui) {
|
||||||
$clean_oui = str_replace(':', '', $oui);
|
$query->orWhere('ports_fdb.mac_address', 'LIKE', "$oui%");
|
||||||
$condition .= " ports_fdb.mac_address LIKE '$clean_oui%' OR";
|
}
|
||||||
}
|
});
|
||||||
$condition = rtrim($condition, ' OR');
|
|
||||||
$query->whereRaw($condition);
|
|
||||||
|
|
||||||
return $query; // Return the query builder instance
|
return $query; // Return the query builder instance
|
||||||
}
|
}
|
||||||
|
@@ -3,6 +3,7 @@
|
|||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
|
|
||||||
class PortsFdb extends PortRelatedModel
|
class PortsFdb extends PortRelatedModel
|
||||||
{
|
{
|
||||||
@@ -21,4 +22,9 @@ class PortsFdb extends PortRelatedModel
|
|||||||
{
|
{
|
||||||
return $this->belongsTo(\App\Models\Vlan::class, 'vlan_id', 'vlan_id');
|
return $this->belongsTo(\App\Models\Vlan::class, 'vlan_id', 'vlan_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function ipv4Addresses(): HasMany
|
||||||
|
{
|
||||||
|
return $this->hasMany(\App\Models\Ipv4Mac::class, 'mac_address', 'mac_address');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user