On 31/10/12 07:40, ryanL wrote:
i've seen discussion on this in the archive, particularly well
documented by Mark (gajillion), but haven't seen a subsequent solution.
hoping someone can point me in the right direction.
the error:
collectd[12476]: snmp plugin: I don't know the ASN type #130
Hi Ryan,
I experienced the same problem as the one you describe when polling the
temperature for Juniper EX4200 switches. The only way I got it to work
was to patch the snmp.c file. I found the patch somewhere but can't
remember where.
Attached you'll find the diff between the Debian testing package source.
Hope it helps!
Gerry
--- snmp.c 2012-04-02 08:04:58.000000000 +0000
+++ /usr/src/collectd-5.1.0/src/snmp.c 2012-10-25 11:31:45.218847157 +0000
@@ -1,6 +1,6 @@
/**
* collectd - src/snmp.c
- * Copyright (C) 2007 Florian octo Forster
+ * Copyright (C) 2007-2012 Florian octo Forster
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -16,7 +16,7 @@
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* Authors:
- * Florian octo Forster <octo at verplant.org>
+ * Florian octo Forster <octo at collectd.org>
**/
#include "collectd.h"
@@ -79,7 +79,7 @@
* gaps in tables. */
struct csnmp_list_instances_s
{
- oid subid;
+ oid_t suffix;
char instance[DATA_MAX_NAME_LEN];
struct csnmp_list_instances_s *next;
};
@@ -87,7 +87,7 @@
struct csnmp_table_values_s
{
- oid subid;
+ oid_t suffix;
value_t value;
struct csnmp_table_values_s *next;
};
@@ -106,6 +106,54 @@
/*
* Private functions
*/
+static void csnmp_oid_init (oid_t *dst, oid const *src, size_t n)
+{
+ assert (n <= STATIC_ARRAY_LEN (dst->oid));
+ memcpy (dst->oid, src, sizeof (*src) * n);
+ dst->oid_len = n;
+}
+
+static int csnmp_oid_compare (oid_t const *left, oid_t const *right)
+{
+ return (snmp_oid_compare (left->oid, left->oid_len,
+ right->oid, right->oid_len));
+}
+
+static int csnmp_oid_suffix (oid_t *dst, oid_t const *src,
+ oid_t const *root)
+{
+ /* Make sure "src" is in "root"s subtree. */
+ if (src->oid_len <= root->oid_len)
+ return (EINVAL);
+ if (snmp_oid_ncompare (root->oid, root->oid_len,
+ src->oid, src->oid_len,
+ /* n = */ root->oid_len) != 0)
+ return (EINVAL);
+
+ memset (dst, 0, sizeof (*dst));
+ dst->oid_len = src->oid_len - root->oid_len;
+ memcpy (dst->oid, &src->oid[root->oid_len],
+ dst->oid_len * sizeof (dst->oid[0]));
+ return (0);
+}
+
+static int csnmp_oid_to_string (char *buffer, size_t buffer_size,
+ oid_t const *o)
+{
+ char oid_str[MAX_OID_LEN][16];
+ char *oid_str_ptr[MAX_OID_LEN];
+ size_t i;
+
+ for (i = 0; i < o->oid_len; i++)
+ {
+ ssnprintf (oid_str[i], sizeof (oid_str[i]), "%lu", (unsigned long) o->oid[i]);
+ oid_str_ptr[i] = oid_str[i];
+ }
+
+ return (strjoin (buffer, buffer_size,
+ oid_str_ptr, o->oid_len, /* separator = */ "."));
+}
+
static void csnmp_host_close_session (host_definition_t *host) /* {{{ */
{
if (host->sess_handle == NULL)
@@ -301,7 +349,7 @@
if ((ci->values_num != 1)
|| (ci->values[0].type != OCONFIG_TYPE_NUMBER))
{
- WARNING ("snmp plugin: The `Scale' config option needs exactly one number argument.");
+ WARNING ("snmp plugin: The `Shift' config option needs exactly one number argument.");
return (-1);
}
@@ -871,10 +919,12 @@
vb = vb->next_variable, i++)
{
num_checked++;
- if (snmp_oid_ncompare (data->values[i].oid,
+
+ if ((vb->type == SNMP_ENDOFMIBVIEW)
+ || (snmp_oid_ncompare (data->values[i].oid,
data->values[i].oid_len,
vb->name, vb->name_length,
- data->values[i].oid_len) != 0)
+ data->values[i].oid_len) != 0))
num_left_subtree++;
}
@@ -984,6 +1034,8 @@
{
csnmp_list_instances_t *il;
struct variable_list *vb;
+ oid_t vb_name;
+ int status;
/* Set vb on the last variable */
for (vb = res->variables;
@@ -993,15 +1045,24 @@
if (vb == NULL)
return (-1);
- il = (csnmp_list_instances_t *) malloc (sizeof (csnmp_list_instances_t));
+ csnmp_oid_init (&vb_name, vb->name, vb->name_length);
+
+ il = malloc (sizeof (*il));
if (il == NULL)
{
ERROR ("snmp plugin: malloc failed.");
return (-1);
}
- il->subid = vb->name[vb->name_length - 1];
+ memset (il, 0, sizeof (*il));
il->next = NULL;
+ status = csnmp_oid_suffix (&il->suffix, &vb_name, &dd->instance.oid);
+ if (status != 0)
+ {
+ sfree (il);
+ return (status);
+ }
+
/* Get instance name */
if ((vb->type == ASN_OCTET_STR) || (vb->type == ASN_BIT_STR))
{
@@ -1048,8 +1109,8 @@
csnmp_table_values_t **value_table_ptr;
int i;
- oid subid;
- int have_more;
+ _Bool have_more;
+ oid_t current_suffix;
ds = plugin_get_ds (data->type);
if (!ds)
@@ -1061,15 +1122,14 @@
instance_list_ptr = instance_list;
- value_table_ptr = (csnmp_table_values_t **) malloc (sizeof (csnmp_table_values_t *)
- * data->values_len);
+ value_table_ptr = malloc (sizeof (*value_table_ptr) * data->values_len);
if (value_table_ptr == NULL)
return (-1);
for (i = 0; i < data->values_len; i++)
value_table_ptr[i] = value_table[i];
vl.values_len = ds->ds_num;
- vl.values = (value_t *) malloc (sizeof (value_t) * vl.values_len);
+ vl.values = malloc (sizeof (*vl.values) * vl.values_len);
if (vl.values == NULL)
{
ERROR ("snmp plugin: malloc failed.");
@@ -1082,33 +1142,41 @@
vl.interval = host->interval;
- subid = 0;
have_more = 1;
-
- while (have_more != 0)
+ memset (¤t_suffix, 0, sizeof (current_suffix));
+ while (have_more)
{
+ _Bool suffix_skipped = 0;
+
+ /* Determine next suffix to handle. */
if (instance_list != NULL)
{
- while ((instance_list_ptr != NULL)
- && (instance_list_ptr->subid < subid))
- instance_list_ptr = instance_list_ptr->next;
-
if (instance_list_ptr == NULL)
{
have_more = 0;
continue;
}
- else if (instance_list_ptr->subid > subid)
+
+ memcpy (¤t_suffix, &instance_list_ptr->suffix, sizeof (current_suffix));
+ }
+ else /* no instance configured */
+ {
+ csnmp_table_values_t *ptr = value_table_ptr[0];
+ if (ptr == NULL)
{
- subid = instance_list_ptr->subid;
+ have_more = 0;
continue;
}
- } /* if (instance_list != NULL) */
+ memcpy (¤t_suffix, &ptr->suffix, sizeof (current_suffix));
+ }
+
+ /* Update all the value_table_ptr to point at the entry with the same
+ * trailing partial OID */
for (i = 0; i < data->values_len; i++)
{
while ((value_table_ptr[i] != NULL)
- && (value_table_ptr[i]->subid < subid))
+ && (csnmp_oid_compare (&value_table_ptr[i]->suffix, ¤t_suffix) < 0))
value_table_ptr[i] = value_table_ptr[i]->next;
if (value_table_ptr[i] == NULL)
@@ -1116,16 +1184,28 @@
have_more = 0;
break;
}
- else if (value_table_ptr[i]->subid > subid)
+ else if (csnmp_oid_compare (&value_table_ptr[i]->suffix, ¤t_suffix) > 0)
{
- subid = value_table_ptr[i]->subid;
+ /* This suffix is missing in the subtree. Indicate this with the
+ * "suffix_skipped" flag and try the next instance / suffix. */
+ suffix_skipped = 1;
break;
}
} /* for (i = 0; i < columns; i++) */
- /* The subid has been increased - start scanning from the beginning
- * again.. */
- if (i < data->values_len)
+
+ if (!have_more)
+ break;
+
+ /* Matching the values failed. Start from the beginning again. */
+ if (suffix_skipped)
+ {
+ if (instance_list != NULL)
+ instance_list_ptr = instance_list_ptr->next;
+ else
+ value_table_ptr[0] = value_table_ptr[0]->next;
+
continue;
+ }
/* if we reach this line, all value_table_ptr[i] are non-NULL and are set
* to the same subid. instance_list_ptr is either NULL or points to the
@@ -1134,10 +1214,12 @@
for (i = 1; i < data->values_len; i++)
{
assert (value_table_ptr[i] != NULL);
- assert (value_table_ptr[i-1]->subid == value_table_ptr[i]->subid);
+ assert (csnmp_oid_compare (&value_table_ptr[i-1]->suffix,
+ &value_table_ptr[i]->suffix) == 0);
}
assert ((instance_list_ptr == NULL)
- || (instance_list_ptr->subid == value_table_ptr[0]->subid));
+ || (csnmp_oid_compare (&instance_list_ptr->suffix,
+ &value_table_ptr[0]->suffix) == 0));
#endif
sstrncpy (vl.type, data->type, sizeof (vl.type));
@@ -1146,7 +1228,7 @@
char temp[DATA_MAX_NAME_LEN];
if (instance_list_ptr == NULL)
- ssnprintf (temp, sizeof (temp), "%"PRIu32, (uint32_t) subid);
+ csnmp_oid_to_string (temp, sizeof (temp), ¤t_suffix);
else
sstrncpy (temp, instance_list_ptr->instance, sizeof (temp));
@@ -1163,8 +1245,11 @@
/* If we get here `vl.type_instance' and all `vl.values' have been set */
plugin_dispatch_values (&vl);
- subid++;
- } /* while (have_more != 0) */
+ if (instance_list != NULL)
+ instance_list_ptr = instance_list_ptr->next;
+ else
+ value_table_ptr[0] = value_table_ptr[0]->next;
+ } /* while (have_more) */
sfree (vl.values);
sfree (value_table_ptr);
@@ -1185,13 +1270,13 @@
int status;
int i;
- /* `value_table' and `value_table_ptr' implement a linked list for each
- * value. `instance_list' and `instance_list_ptr' implement a linked list of
+ /* `value_list_head' and `value_list_tail' implement a linked list for each
+ * value. `instance_list_head' and `instance_list_tail' implement a linked list of
* instance names. This is used to jump gaps in the table. */
- csnmp_list_instances_t *instance_list;
- csnmp_list_instances_t *instance_list_ptr;
- csnmp_table_values_t **value_table;
- csnmp_table_values_t **value_table_ptr;
+ csnmp_list_instances_t *instance_list_head;
+ csnmp_list_instances_t *instance_list_tail;
+ csnmp_table_values_t **value_list_head;
+ csnmp_table_values_t **value_list_tail;
DEBUG ("snmp plugin: csnmp_read_table (host = %s, data = %s)",
host->name, data->name);
@@ -1230,20 +1315,22 @@
else
oid_list_len--;
- /* Allocate the `value_table' */
- value_table = (csnmp_table_values_t **) malloc (sizeof (csnmp_table_values_t *)
- * 2 * data->values_len);
- if (value_table == NULL)
+ /* We're going to construct n linked lists, one for each "value".
+ * value_list_head will contain pointers to the heads of these linked lists,
+ * value_list_tail will contain pointers to the tail of the lists. */
+ value_list_head = calloc (data->values_len, sizeof (*value_list_head));
+ value_list_tail = calloc (data->values_len, sizeof (*value_list_tail));
+ if ((value_list_head == NULL) || (value_list_tail == NULL))
{
- ERROR ("snmp plugin: csnmp_read_table: malloc failed.");
+ ERROR ("snmp plugin: csnmp_read_table: calloc failed.");
sfree (oid_list);
+ sfree (value_list_head);
+ sfree (value_list_tail);
return (-1);
}
- memset (value_table, '\0', sizeof (csnmp_table_values_t *) * 2 * data->values_len);
- value_table_ptr = value_table + data->values_len;
- instance_list = NULL;
- instance_list_ptr = NULL;
+ instance_list_head = NULL;
+ instance_list_tail = NULL;
status = 0;
while (status == 0)
@@ -1303,12 +1390,13 @@
break;
}
- /* if an instance-OID is configured.. */
+ /* Copy the OID of the value used as instance to oid_list, if an instance
+ * is configured. */
if (data->instance.oid.oid_len > 0)
{
/* Allocate a new `csnmp_list_instances_t', insert the instance name and
* add it to the list */
- if (csnmp_instance_list_add (&instance_list, &instance_list_ptr,
+ if (csnmp_instance_list_add (&instance_list_head, &instance_list_tail,
res, host, data) != 0)
{
ERROR ("snmp plugin: csnmp_instance_list_add failed.");
@@ -1316,63 +1404,76 @@
break;
}
- /* Set vb on the last variable */
+ /* The instance OID is added to the list of OIDs to GET from the
+ * snmp agent last, so set vb on the last variable returned and copy
+ * that OID. */
for (vb = res->variables;
(vb != NULL) && (vb->next_variable != NULL);
vb = vb->next_variable)
/* do nothing */;
assert (vb != NULL);
- /* Copy OID to oid_list[data->values_len] */
+ /* Copy the OID of the instance value to oid_list[data->values_len].
+ * "oid_list" is used for the next GETNEXT request. */
memcpy (oid_list[data->values_len].oid, vb->name,
sizeof (oid) * vb->name_length);
oid_list[data->values_len].oid_len = vb->name_length;
}
+ /* Iterate over all the (non-instance) values returned by the agent. The
+ * (i < value_len) check will make sure we're not handling the instance OID
+ * twice. */
for (vb = res->variables, i = 0;
(vb != NULL) && (i < data->values_len);
vb = vb->next_variable, i++)
{
csnmp_table_values_t *vt;
+ oid_t vb_name;
+ oid_t suffix;
- /* Check if we left the subtree */
- if (snmp_oid_ncompare (data->values[i].oid,
- data->values[i].oid_len,
- vb->name, vb->name_length,
- data->values[i].oid_len) != 0)
+ csnmp_oid_init (&vb_name, vb->name, vb->name_length);
+
+ /* Calculate the current suffix. This is later used to check that the
+ * suffix is increasing. This also checks if we left the subtree */
+ status = csnmp_oid_suffix (&suffix, &vb_name, data->values + i);
+ if (status != 0)
{
- DEBUG ("snmp plugin: host = %s; data = %s; Value %i left its subtree.",
+ DEBUG ("snmp plugin: host = %s; data = %s; Value %i failed. "
+ "It probably left its subtree.",
host->name, data->name, i);
continue;
}
- if ((value_table_ptr[i] != NULL)
- && (vb->name[vb->name_length - 1] <= value_table_ptr[i]->subid))
+ /* Make sure the OIDs returned by the agent are increasing. Otherwise our
+ * table matching algorithm will get confused. */
+ if ((value_list_tail[i] != NULL)
+ && (csnmp_oid_compare (&suffix, &value_list_tail[i]->suffix) <= 0))
{
DEBUG ("snmp plugin: host = %s; data = %s; i = %i; "
- "SUBID is not increasing.",
+ "Suffix is not increasing.",
host->name, data->name, i);
continue;
}
- vt = (csnmp_table_values_t *) malloc (sizeof (csnmp_table_values_t));
+ vt = malloc (sizeof (*vt));
if (vt == NULL)
{
ERROR ("snmp plugin: malloc failed.");
status = -1;
break;
}
+ memset (vt, 0, sizeof (*vt));
- vt->subid = vb->name[vb->name_length - 1];
vt->value = csnmp_value_list_to_value (vb, ds->ds[i].type,
data->scale, data->shift, host->name, data->name);
+ memcpy (&vt->suffix, &suffix, sizeof (vt->suffix));
vt->next = NULL;
- if (value_table_ptr[i] == NULL)
- value_table[i] = vt;
+ if (value_list_tail[i] == NULL)
+ value_list_head[i] = vt;
else
- value_table_ptr[i]->next = vt;
- value_table_ptr[i] = vt;
+ value_list_tail[i]->next = vt;
+ value_list_tail[i] = vt;
/* Copy OID to oid_list[i + 1] */
memcpy (oid_list[i].oid, vb->name, sizeof (oid) * vb->name_length);
@@ -1389,28 +1490,28 @@
res = NULL;
if (status == 0)
- csnmp_dispatch_table (host, data, instance_list, value_table);
+ csnmp_dispatch_table (host, data, instance_list_head, value_list_head);
/* Free all allocated variables here */
- while (instance_list != NULL)
+ while (instance_list_head != NULL)
{
- instance_list_ptr = instance_list->next;
- sfree (instance_list);
- instance_list = instance_list_ptr;
+ csnmp_list_instances_t *next = instance_list_head->next;
+ sfree (instance_list_head);
+ instance_list_head = next;
}
for (i = 0; i < data->values_len; i++)
{
- csnmp_table_values_t *tmp;
- while (value_table[i] != NULL)
+ while (value_list_head[i] != NULL)
{
- tmp = value_table[i]->next;
- sfree (value_table[i]);
- value_table[i] = tmp;
+ csnmp_table_values_t *next = value_list_head[i]->next;
+ sfree (value_list_head[i]);
+ value_list_head[i] = next;
}
}
- sfree (value_table);
+ sfree (value_list_head);
+ sfree (value_list_tail);
sfree (oid_list);
return (0);
_______________________________________________
collectd mailing list
collectd@verplant.org
http://mailman.verplant.org/listinfo/collectd