* We meant well but it turns out that the array unnest and join is
actually very slow, as the join arguments do not get pushed down
into the CTE (in Postgres 9/10 at least, later versions remove some
of the optimization barriers in that specifc type of query)
* This caused a seq scan on both device and device_port, and the query
is executed many times during macsuck
* The query is now rewritten to use ANY (macaddr[]) and without CTE,
which seems to be around 20x faster
Hi @ollyg! Unfortunately I have found some issues with the code we
finally released in #680:
* get_port_macs expects an array ref but values() returns array,
so the code was never called due to the return unless... check
* When fw_mac_list had exactly two entries, only the second value
was bound as a scalar to the parameter. This is probably due
to the shorthand bind formats described in
https://metacpan.org/pod/DBIx::Class::ResultSet#DBIC-BIND-VALUES,
but I'm not a 100% on this.
* return unless now checks for an entry in the list, with the old
check the statement was also executed for empty lists
In cases where only the device(_port)?.mac lookup worked for uplink
detection, users of 02.044005 - 010 might get a lot of uplinks not
labeled as such.
* Reduce macsuck bandwidth usage to database
get_port_macs transfers a full list of all device_port.(mac,ip) in every macsuck.
With 8k devices and 40k interfaces it takes up around 15MB. Transferring them 8k times
during an 1h macsuck cycle requires bandwidth in the 300 to 400 mbit/s range.
This patch changes get_port_macs to be called inside walk_fwtable and only transfer
the macs found in the current target device/vlan.