From 38bd9828f75eb5785748656121e62da990d15ed7 Mon Sep 17 00:00:00 2001 From: Graham McIntire Date: Sun, 4 Jan 2026 13:28:53 -0600 Subject: [PATCH] Improve Counter64 decoder to handle 16-byte values Some SNMP implementations return 16-byte binaries for Counter64 values instead of the standard 8 bytes. Updated decoder to: - Handle 8-byte standard Counter64 - Handle 16-byte values by reading last 8 bytes - Handle any size > 8 bytes by reading last 8 bytes - Add debug/warning logging for non-standard sizes This fixes DBConnection.EncodeError when polling interface statistics from devices that return non-standard Counter64 encodings. --- lib/towerops/snmp/poller_worker.ex | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/lib/towerops/snmp/poller_worker.ex b/lib/towerops/snmp/poller_worker.ex index ed200279..c5e7c910 100644 --- a/lib/towerops/snmp/poller_worker.ex +++ b/lib/towerops/snmp/poller_worker.ex @@ -245,15 +245,32 @@ defmodule Towerops.Snmp.PollerWorker do defp decode_snmp_value(value) when is_number(value), do: value defp decode_snmp_value(value) when is_binary(value) do - # Try to decode as Counter64 (8 bytes, big-endian unsigned integer) + # Try to decode based on byte size case byte_size(value) do 8 -> + # Standard Counter64 (8 bytes, big-endian unsigned integer) <> = value counter + 16 -> + # Some SNMP implementations return 16-byte values + # Try reading last 8 bytes as Counter64 + <<_prefix::binary-size(8), counter::unsigned-big-integer-size(64)>> = value + counter + + size when size > 8 -> + # Large binary, try reading last 8 bytes + offset = size - 8 + <<_prefix::binary-size(offset), counter::unsigned-big-integer-size(64)>> = value + Logger.debug("Decoded #{size}-byte SNMP value as Counter64 from last 8 bytes: #{counter}") + counter + _ -> - # Unknown binary format, return nil - Logger.debug("Unknown SNMP binary value format, size: #{byte_size(value)}") + # Unknown binary format or too small + Logger.warning( + "Unknown SNMP binary value format, size: #{byte_size(value)}, bytes: #{inspect(value)}" + ) + nil end end