#include "collectd.h"
-#include "common.h"
#include "plugin.h"
+#include "utils/common/common.h"
+#include "utils/ignorelist/ignorelist.h"
#include "utils_complain.h"
-#include "utils_ignorelist.h"
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
c_complain_t complaint;
data_definition_t **data_list;
int data_list_len;
+ int bulk_size;
};
typedef struct host_definition_s host_definition_t;
char *oid_str_ptr[MAX_OID_LEN];
for (size_t i = 0; i < o->oid_len; i++) {
- snprintf(oid_str[i], sizeof(oid_str[i]), "%lu", (unsigned long)o->oid[i]);
+ ssnprintf(oid_str[i], sizeof(oid_str[i]), "%lu", (unsigned long)o->oid[i]);
oid_str_ptr[i] = oid_str[i];
}
/* These mean that we have not set a timeout or retry value */
hd->timeout = 0;
hd->retries = -1;
+ hd->bulk_size = 0;
for (int i = 0; i < ci->children_num; i++) {
oconfig_item_t *option = ci->children + i;
status = csnmp_config_add_host_security_level(hd, option);
else if (strcasecmp("Context", option->key) == 0)
status = cf_util_get_string(option, &hd->context);
+ else if (strcasecmp("BulkSize", option->key) == 0)
+ status = cf_util_get_int(option, &hd->bulk_size);
else {
WARNING(
"snmp plugin: csnmp_config_add_host: Option `%s' not allowed here.",
status = -1;
break;
}
+ if (hd->bulk_size > 0 && hd->version < 2) {
+ WARNING("snmp plugin: Bulk transfers is only available for SNMP v2 and "
+ "later, host '%s' is configured as version '%d'",
+ hd->name, hd->version);
+ }
if (hd->version == 3) {
if (hd->username == NULL) {
WARNING("snmp plugin: `Username' not given for host `%s'", hd->name);
"= %i }",
hd->name, hd->address, hd->community, hd->version);
- snprintf(cb_name, sizeof(cb_name), "snmp-%s", hd->name);
+ ssnprintf(cb_name, sizeof(cb_name), "snmp-%s", hd->name);
status = plugin_register_complex_read(
/* group = */ NULL, cb_name, csnmp_read_host, interval,
&(user_data_t){
- .data = hd, .free_func = csnmp_host_definition_destroy,
+ .data = hd,
+ .free_func = csnmp_host_definition_destroy,
});
if (status != 0) {
ERROR("snmp plugin: Registering complex read function failed.");
for (size_t i = 0; i < vb->val_len; i++) {
int status;
- status = snprintf(buffer_ptr, buffer_free, (i == 0) ? "%02x" : ":%02x",
- (unsigned int)vb->val.bitstring[i]);
+ status = ssnprintf(buffer_ptr, buffer_free, (i == 0) ? "%02x" : ":%02x",
+ (unsigned int)vb->val.bitstring[i]);
assert(status >= 0);
if (((size_t)status) >= buffer_free) /* truncated */
{
- dst[dst_size - 1] = 0;
+ dst[dst_size - 1] = '\0';
return ENOMEM;
} else /* if (status < buffer_free) */
{
else if (vb->type == ASN_BIT_STR)
src = (char *)vb->val.bitstring;
else if (vb->type == ASN_IPADDRESS) {
- return snprintf(dst, dst_size,
- "%" PRIu8 ".%" PRIu8 ".%" PRIu8 ".%" PRIu8 "",
- (uint8_t)vb->val.string[0], (uint8_t)vb->val.string[1],
- (uint8_t)vb->val.string[2], (uint8_t)vb->val.string[3]);
+ return ssnprintf(dst, dst_size,
+ "%" PRIu8 ".%" PRIu8 ".%" PRIu8 ".%" PRIu8 "",
+ (uint8_t)vb->val.string[0], (uint8_t)vb->val.string[1],
+ (uint8_t)vb->val.string[2], (uint8_t)vb->val.string[3]);
} else {
dst[0] = 0;
return EINVAL;
dst[i] = src[i];
}
dst[num_chars] = 0;
- dst[dst_size - 1] = 0;
+ dst[dst_size - 1] = '\0';
if (dst_size <= vb->val_len)
return ENOMEM;
value_t val = csnmp_value_list_to_value(
vb, DS_TYPE_COUNTER,
/* scale = */ 1.0, /* shift = */ 0.0, hd->name, dd->name);
- snprintf(il->value, sizeof(il->value), "%" PRIu64, (uint64_t)val.counter);
+ ssnprintf(il->value, sizeof(il->value), "%" PRIu64, (uint64_t)val.counter);
}
return il;
if (data->host.prefix == NULL)
sstrncpy(vl.host, temp, sizeof(vl.host));
else
- snprintf(vl.host, sizeof(vl.host), "%s%s", data->host.prefix, temp);
+ ssnprintf(vl.host, sizeof(vl.host), "%s%s", data->host.prefix, temp);
} else {
sstrncpy(vl.host, host->name, sizeof(vl.host));
}
if (data->type_instance.prefix == NULL)
sstrncpy(vl.type_instance, temp, sizeof(vl.type_instance));
else
- snprintf(vl.type_instance, sizeof(vl.type_instance), "%s%s",
- data->type_instance.prefix, temp);
+ ssnprintf(vl.type_instance, sizeof(vl.type_instance), "%s%s",
+ data->type_instance.prefix, temp);
} else if (data->type_instance.value) {
sstrncpy(vl.type_instance, data->type_instance.value,
sizeof(vl.type_instance));
if (data->plugin_instance.prefix == NULL)
sstrncpy(vl.plugin_instance, temp, sizeof(vl.plugin_instance));
else
- snprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%s%s",
- data->plugin_instance.prefix, temp);
+ ssnprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%s%s",
+ data->plugin_instance.prefix, temp);
} else if (data->plugin_instance.value) {
sstrncpy(vl.plugin_instance, data->plugin_instance.value,
sizeof(vl.plugin_instance));
status = 0;
while (status == 0) {
- req = snmp_pdu_create(SNMP_MSG_GETNEXT);
+ /* If SNMP v2 and later and bulk transfers enabled, use GETBULK PDU */
+ if (host->version > 1 && host->bulk_size > 0) {
+ req = snmp_pdu_create(SNMP_MSG_GETBULK);
+ req->non_repeaters = 0;
+ req->max_repetitions = host->bulk_size;
+ } else {
+ req = snmp_pdu_create(SNMP_MSG_GETNEXT);
+ }
if (req == NULL) {
ERROR("snmp plugin: snmp_pdu_create failed.");
status = -1;
break;
}
+ if (req->command == SNMP_MSG_GETBULK) {
+ /* In bulk mode the host will send 'max_repetitions' values per
+ requested variable, so we need to split it per number of variable
+ to stay 'in budget' */
+ req->max_repetitions = floor(host->bulk_size / oid_list_todo_num);
+ }
+
res = NULL;
status = snmp_sess_synch_response(host->sess_handle, req, &res);
continue;
}
- for (vb = res->variables, i = 0; (vb != NULL);
- vb = vb->next_variable, i++) {
+ size_t j;
+ for (vb = res->variables, j = 0; (vb != NULL);
+ vb = vb->next_variable, j++) {
+ i = j;
+ /* If bulk request is active convert value index of the extra value */
+ if (host->version > 1 && host->bulk_size > 0) {
+ i %= oid_list_todo_num;
+ }
/* Calculate value index from todo list */
while ((i < oid_list_len) && !oid_list_todo[i]) {
i++;
+ j++;
}
if (i >= oid_list_len) {
break;