# <EAL>
# Coremask "0x1"
# MemoryChannels "4"
-# ProcessType "secondary"
# FilePrefix "rte"
# </EAL>
# <Event "link_status">
# <EAL>
# Coremask "0x2"
# MemoryChannels "4"
-# ProcessType "secondary"
# FilePrefix "rte"
# </EAL>
# SharedMemObj "dpdk_collectd_stats_0"
<EAL>
Coremask "0x1"
MemoryChannels "4"
- ProcessType "secondary"
FilePrefix "rte"
</EAL>
<Event "link_status">
=head3 The EAL block
-=over 5
+=over 4
=item B<Coremask> I<Mask>
Number of memory channels per processor socket.
-=item B<ProcessType> I<type>
-
-The type of DPDK process instance.
-
=item B<FilePrefix> I<File>
The prefix text used for hugepage filenames. The filename will be set to
=head4 Link Status event
-=over 5
+=over 4
=item B<SendEventOnUpdate> I<true|false>
=head4 Keep Alive event
-=over 5
+=over 4
=item B<SendEventOnUpdate> I<true|false>
<EAL>
Coremask "0x4"
MemoryChannels "4"
- ProcessType "secondary"
FilePrefix "rte"
SocketMemory "1024"
</EAL>
=head3 The EAL block
-=over 5
+=over 4
=item B<Coremask> I<Mask>
A string containing a number of memory channels per processor socket.
-=item B<ProcessType> I<type>
-
-A string containing the type of DPDK process instance.
-
=item B<FilePrefix> I<File>
The prefix text used for hugepage filenames. The filename will be set to
=over 3
=item B<SharedMemObj> I<Mask>
+
A string containing the name of the shared memory object that should be used to
share stats from the DPDK secondary process to the collectd dpdkstat plugin.
Defaults to dpdk_collectd_stats if no other value is configured.
typedef struct dpdk_link_status_config_s {
int enabled;
- int send_updated;
+ _Bool send_updated;
uint32_t enabled_port_mask;
char port_name[RTE_MAX_ETHPORTS][DATA_MAX_NAME_LEN];
- int notify;
+ _Bool notify;
} dpdk_link_status_config_t;
typedef struct dpdk_keep_alive_config_s {
int enabled;
- int send_updated;
+ _Bool send_updated;
uint128_t lcore_mask;
dpdk_keepalive_shm_t *shm;
char shm_name[DATA_MAX_NAME_LEN];
- int notify;
+ _Bool notify;
int fd;
} dpdk_keep_alive_config_t;
dpdk_ka_monitor_t core_info[RTE_KEEPALIVE_MAXCORES];
} dpdk_events_ctx_t;
+typedef enum {
+ DPDK_EVENTS_STATE_CFG_ERR = 1 << 0,
+ DPDK_EVENTS_STATE_KA_CFG_ERR = 1 << 1,
+ DPDK_EVENTS_STATE_LS_CFG_ERR = 1 << 2,
+
+} dpdk_events_cfg_status;
+
#define DPDK_EVENTS_CTX_GET(a) ((dpdk_events_ctx_t *)dpdk_helper_priv_get(a))
#define DPDK_EVENTS_TRACE() \
DEBUG("%s:%s:%d pid=%u", DPDK_EVENTS_PLUGIN, __FUNCTION__, __LINE__, getpid())
static dpdk_helper_ctx_t *g_hc;
+static dpdk_events_cfg_status g_state;
static int dpdk_event_keep_alive_shm_open(void) {
dpdk_events_ctx_t *ec = DPDK_EVENTS_CTX_GET(g_hc);
oconfig_item_t *child = ci->children + i;
if (strcasecmp("EnabledPortMask", child->key) == 0) {
- ec->config.link_status.enabled_port_mask =
- (uint32_t)child->values[0].value.number;
+ if (cf_util_get_int(child,
+ (int *)&ec->config.link_status.enabled_port_mask))
+ return -1;
DEBUG(DPDK_EVENTS_PLUGIN ": LinkStatus:Enabled Port Mask 0x%X",
ec->config.link_status.enabled_port_mask);
} else if (strcasecmp("SendEventsOnUpdate", child->key) == 0) {
- ec->config.link_status.send_updated = child->values[0].value.boolean;
+ if (cf_util_get_boolean(child, &ec->config.link_status.send_updated))
+ return -1;
DEBUG(DPDK_EVENTS_PLUGIN ": LinkStatus:SendEventsOnUpdate %d",
- (int)child->values[0].value.boolean);
+ ec->config.link_status.send_updated);
} else if (strcasecmp("SendNotification", child->key) == 0) {
- ec->config.link_status.notify = child->values[0].value.boolean;
+ if (cf_util_get_boolean(child, &ec->config.link_status.notify))
+ return -1;
+
DEBUG(DPDK_EVENTS_PLUGIN ": LinkStatus:SendNotification %d",
- (int)child->values[0].value.boolean);
+ ec->config.link_status.notify);
+ } else if (strcasecmp("PortName", child->key) != 0) {
+ ERROR(DPDK_EVENTS_PLUGIN ": unrecognized configuration option %s.",
+ child->key);
+ return -1;
}
}
if (strcasecmp("PortName", child->key) == 0) {
while (!(ec->config.link_status.enabled_port_mask & (1 << port_num)))
port_num++;
- ssnprintf(ec->config.link_status.port_name[port_num], DATA_MAX_NAME_LEN,
- "%s", child->values[0].value.string);
+
+ if (cf_util_get_string_buffer(
+ child, ec->config.link_status.port_name[port_num],
+ sizeof(ec->config.link_status.port_name[port_num]))) {
+ return -1;
+ }
DEBUG(DPDK_EVENTS_PLUGIN ": LinkStatus:Port %d Name: %s", port_num,
ec->config.link_status.port_name[port_num]);
port_num++;
oconfig_item_t *child = ci->children + i;
if (strcasecmp("SendEventsOnUpdate", child->key) == 0) {
- ec->config.keep_alive.send_updated = child->values[0].value.boolean;
+ if (cf_util_get_boolean(child, &ec->config.keep_alive.send_updated))
+ return -1;
+
DEBUG(DPDK_EVENTS_PLUGIN ": KeepAlive:SendEventsOnUpdate %d",
- (int)child->values[0].value.boolean);
+ ec->config.keep_alive.send_updated);
} else if (strcasecmp("LCoreMask", child->key) == 0) {
char lcore_mask[DATA_MAX_NAME_LEN];
- ssnprintf(lcore_mask, sizeof(lcore_mask), "%s",
- child->values[0].value.string);
+
+ if (cf_util_get_string_buffer(child, lcore_mask, sizeof(lcore_mask)))
+ return -1;
ec->config.keep_alive.lcore_mask =
str_to_uint128(lcore_mask, strlen(lcore_mask));
DEBUG(DPDK_EVENTS_PLUGIN ": KeepAlive:LCoreMask 0x%" PRIX64 "%" PRIX64 "",
ec->config.keep_alive.lcore_mask.high,
ec->config.keep_alive.lcore_mask.low);
} else if (strcasecmp("KeepAliveShmName", child->key) == 0) {
- ssnprintf(ec->config.keep_alive.shm_name,
- sizeof(ec->config.keep_alive.shm_name), "%s",
- child->values[0].value.string);
+ if (cf_util_get_string_buffer(child, ec->config.keep_alive.shm_name,
+ sizeof(ec->config.keep_alive.shm_name)))
+ return -1;
+
DEBUG(DPDK_EVENTS_PLUGIN ": KeepAlive:KeepAliveShmName %s",
ec->config.keep_alive.shm_name);
} else if (strcasecmp("SendNotification", child->key) == 0) {
- ec->config.keep_alive.notify = child->values[0].value.boolean;
+ if (cf_util_get_boolean(child, &ec->config.keep_alive.notify))
+ return -1;
+
DEBUG(DPDK_EVENTS_PLUGIN ": KeepAlive:SendNotification %d",
- (int)child->values[0].value.boolean);
+ ec->config.keep_alive.notify);
+ } else {
+ ERROR(DPDK_EVENTS_PLUGIN ": unrecognized configuration option %s.",
+ child->key);
+ return -1;
}
}
static int dpdk_events_config(oconfig_item_t *ci) {
DPDK_EVENTS_TRACE();
int ret = dpdk_events_preinit();
- if (ret)
- return ret;
+ if (ret) {
+ g_state |= DPDK_EVENTS_STATE_CFG_ERR;
+ return 0;
+ }
dpdk_events_ctx_t *ec = DPDK_EVENTS_CTX_GET(g_hc);
for (int i = 0; i < ci->children_num; i++) {
oconfig_item_t *child = ci->children + i;
- if (strcasecmp("EAL", child->key) == 0) {
- dpdk_helper_eal_config_parse(g_hc, child);
- } else if (strcasecmp("Event", child->key) == 0) {
- if (strcasecmp(child->values[0].value.string, "link_status") == 0) {
- dpdk_events_link_status_config(ec, child);
- } else if (strcasecmp(child->values[0].value.string, "keep_alive") == 0) {
- dpdk_events_keep_alive_config(ec, child);
+
+ if (strcasecmp("EAL", child->key) == 0)
+ ret = dpdk_helper_eal_config_parse(g_hc, child);
+ else if (strcasecmp("Event", child->key) == 0) {
+ char event_type[DATA_MAX_NAME_LEN];
+
+ if (cf_util_get_string_buffer(child, event_type, sizeof(event_type)))
+ ret = -1;
+ else if (strcasecmp(event_type, "link_status") == 0) {
+ ret = dpdk_events_link_status_config(ec, child);
+ if (ret) {
+ g_state |= DPDK_EVENTS_STATE_LS_CFG_ERR;
+ continue;
+ }
+ } else if (strcasecmp(event_type, "keep_alive") == 0) {
+ ret = dpdk_events_keep_alive_config(ec, child);
+ if (ret) {
+ g_state |= DPDK_EVENTS_STATE_KA_CFG_ERR;
+ continue;
+ }
} else {
ERROR(DPDK_EVENTS_PLUGIN ": The selected event \"%s\" is unknown.",
- child->values[0].value.string);
+ event_type);
+ ret = -1;
}
+ } else {
+ ERROR(DPDK_EVENTS_PLUGIN ": unrecognized configuration option %s.",
+ child->key);
+ ret = -1;
+ }
+
+ if (ret != 0) {
+ g_state |= DPDK_EVENTS_STATE_CFG_ERR;
+ return 0;
}
}
+ if (g_state & DPDK_EVENTS_STATE_KA_CFG_ERR) {
+ ERROR(DPDK_EVENTS_PLUGIN
+ ": Invalid keep alive configuration. Event disabled.");
+ ec->config.keep_alive.enabled = 0;
+ }
+
+ if (g_state & DPDK_EVENTS_STATE_LS_CFG_ERR) {
+ ERROR(DPDK_EVENTS_PLUGIN
+ ": Invalid link status configuration. Event disabled.");
+ ec->config.link_status.enabled = 0;
+ }
+
if (!ec->config.keep_alive.enabled && !ec->config.link_status.enabled) {
ERROR(DPDK_EVENTS_PLUGIN ": At least one type of events should be "
"configured for collecting. Plugin misconfigured");
- return -1;
+ g_state |= DPDK_EVENTS_STATE_CFG_ERR;
+ return 0;
}
- return ret;
+ return 0;
}
static int dpdk_helper_link_status_get(dpdk_helper_ctx_t *phc) {
return 0;
}
-static int dpdk_events_init(void) {
- DPDK_EVENTS_TRACE();
-
- int ret = dpdk_events_preinit();
- if (ret)
- return ret;
-
- return 0;
-}
-
static int dpdk_events_shutdown(void) {
DPDK_EVENTS_TRACE();
- int ret;
+
+ if (g_hc == NULL)
+ return 0;
dpdk_events_ctx_t *ec = DPDK_EVENTS_CTX_GET(g_hc);
if (ec->config.keep_alive.enabled) {
}
}
- ret = dpdk_helper_shutdown(g_hc);
+ dpdk_helper_shutdown(g_hc);
g_hc = NULL;
+
+ return 0;
+}
+
+static int dpdk_events_init(void) {
+ DPDK_EVENTS_TRACE();
+
+ if (g_state & DPDK_EVENTS_STATE_CFG_ERR) {
+ dpdk_events_shutdown();
+ return -1;
+ }
+
+ int ret = dpdk_events_preinit();
if (ret)
- ERROR(DPDK_EVENTS_PLUGIN ": failed to cleanup %s helper", DPDK_EVENTS_NAME);
+ return ret;
- return ret;
+ return 0;
}
void module_register(void) {
};
typedef struct dpdk_stats_ctx_s dpdk_stats_ctx_t;
+typedef enum {
+ DPDK_STAT_STATE_OKAY = 0,
+ DPDK_STAT_STATE_CFG_ERR,
+} dpdk_stat_cfg_status;
+
#define DPDK_STATS_CTX_GET(a) ((dpdk_stats_ctx_t *)dpdk_helper_priv_get(a))
dpdk_helper_ctx_t *g_hc = NULL;
static char g_shm_name[DATA_MAX_NAME_LEN] = DPDK_STATS_NAME;
+static dpdk_stat_cfg_status g_state = DPDK_STAT_STATE_OKAY;
+
static int dpdk_stats_reinit_helper();
static void dpdk_stats_default_config(void) {
dpdk_stats_ctx_t *ec = DPDK_STATS_CTX_GET(g_hc);
DPDK_STATS_TRACE();
int ret = dpdk_stats_preinit();
- if (ret)
- return ret;
+ if (ret) {
+ g_state = DPDK_STAT_STATE_CFG_ERR;
+ return 0;
+ }
dpdk_stats_ctx_t *ctx = DPDK_STATS_CTX_GET(g_hc);
for (int i = 0; i < ci->children_num; i++) {
oconfig_item_t *child = ci->children + i;
- if ((strcasecmp("EnabledPortMask", child->key) == 0) &&
- (child->values[0].type == OCONFIG_TYPE_NUMBER)) {
- ctx->config.enabled_port_mask = child->values[0].value.number;
- DEBUG("%s: Enabled Port Mask 0x%X", DPDK_STATS_PLUGIN,
- ctx->config.enabled_port_mask);
- } else if (strcasecmp("SharedMemObj", child->key) == 0) {
- cf_util_get_string_buffer(child, g_shm_name, sizeof(g_shm_name));
- DEBUG("%s: Shared memory object %s", DPDK_STATS_PLUGIN, g_shm_name);
- dpdk_stats_reinit_helper();
- } else if (strcasecmp("EAL", child->key) == 0) {
+ if (strcasecmp("EnabledPortMask", child->key) == 0)
+ ret = cf_util_get_int(child, (int *)&ctx->config.enabled_port_mask);
+ else if (strcasecmp("SharedMemObj", child->key) == 0) {
+ ret = cf_util_get_string_buffer(child, g_shm_name, sizeof(g_shm_name));
+ if (ret == 0)
+ ret = dpdk_stats_reinit_helper();
+ } else if (strcasecmp("EAL", child->key) == 0)
ret = dpdk_helper_eal_config_parse(g_hc, child);
- if (ret)
- return ret;
+ else if (strcasecmp("PortName", child->key) != 0) {
+ ERROR(DPDK_STATS_PLUGIN ": unrecognized configuration option %s",
+ child->key);
+ ret = -1;
+ }
+
+ if (ret != 0) {
+ g_state = DPDK_STAT_STATE_CFG_ERR;
+ return 0;
}
}
+ DEBUG(DPDK_STATS_PLUGIN ": Enabled Port Mask 0x%X",
+ ctx->config.enabled_port_mask);
+ DEBUG(DPDK_STATS_PLUGIN ": Shared memory object %s", g_shm_name);
+
int port_num = 0;
/* parse port names after EnabledPortMask was parsed */
while (!(ctx->config.enabled_port_mask & (1 << port_num)))
port_num++;
- cf_util_get_string_buffer(child, ctx->config.port_name[port_num],
- sizeof(ctx->config.port_name[port_num]));
- DEBUG("%s: Port %d Name: %s", DPDK_STATS_PLUGIN, port_num,
+ if (cf_util_get_string_buffer(child, ctx->config.port_name[port_num],
+ sizeof(ctx->config.port_name[port_num]))) {
+ g_state = DPDK_STAT_STATE_CFG_ERR;
+ return 0;
+ }
+
+ DEBUG(DPDK_STATS_PLUGIN ": Port %d Name: %s", port_num,
ctx->config.port_name[port_num]);
port_num++;
}
}
- return ret;
+ return 0;
}
static int dpdk_helper_stats_get(dpdk_helper_ctx_t *phc) {
return 0;
}
-static int dpdk_stats_init(void) {
+static int dpdk_stats_shutdown(void) {
DPDK_STATS_TRACE();
- int ret = 0;
- ret = dpdk_stats_preinit();
- if (ret != 0) {
- return ret;
- }
+ dpdk_helper_shutdown(g_hc);
+ g_hc = NULL;
return 0;
}
-static int dpdk_stats_shutdown(void) {
+static int dpdk_stats_init(void) {
DPDK_STATS_TRACE();
-
int ret = 0;
- ret = dpdk_helper_shutdown(g_hc);
- g_hc = NULL;
+ if (g_state != DPDK_STAT_STATE_OKAY) {
+ dpdk_stats_shutdown();
+ return -1;
+ }
+
+ ret = dpdk_stats_preinit();
if (ret != 0) {
- ERROR("%s: failed to cleanup %s helper", DPDK_STATS_PLUGIN, g_shm_name);
return ret;
}
- return ret;
+ return 0;
}
void module_register(void) {
int eal_initialized;
size_t shm_size;
- const char *shm_name;
+ char shm_name[DATA_MAX_NAME_LEN];
sem_t sema_cmd_start;
sem_t sema_cmd_complete;
ssnprintf(phc->eal_config.coremask, DATA_MAX_NAME_LEN, "%s", "0xf");
ssnprintf(phc->eal_config.memory_channels, DATA_MAX_NAME_LEN, "%s", "1");
- ssnprintf(phc->eal_config.process_type, DATA_MAX_NAME_LEN, "%s", "secondary");
ssnprintf(phc->eal_config.file_prefix, DATA_MAX_NAME_LEN, "%s",
DPDK_DEFAULT_RTE_CONFIG);
}
int status = 0;
for (int i = 0; i < ci->children_num; i++) {
oconfig_item_t *child = ci->children + i;
+
if (strcasecmp("Coremask", child->key) == 0) {
status = cf_util_get_string_buffer(child, phc->eal_config.coremask,
sizeof(phc->eal_config.coremask));
status = cf_util_get_string_buffer(child, phc->eal_config.socket_memory,
sizeof(phc->eal_config.socket_memory));
DEBUG("dpdk_common: EAL:Socket memory %s", phc->eal_config.socket_memory);
- } else if (strcasecmp("ProcessType", child->key) == 0) {
- status = cf_util_get_string_buffer(child, phc->eal_config.process_type,
- sizeof(phc->eal_config.process_type));
- DEBUG("dpdk_common: EAL:Process type %s", phc->eal_config.process_type);
- } else if ((strcasecmp("FilePrefix", child->key) == 0) &&
- (child->values[0].type == OCONFIG_TYPE_STRING)) {
- ssnprintf(phc->eal_config.file_prefix, DATA_MAX_NAME_LEN,
- "/var/run/.%s_config", child->values[0].value.string);
- DEBUG("dpdk_common: EAL:File prefix %s", phc->eal_config.file_prefix);
+ } else if (strcasecmp("FilePrefix", child->key) == 0) {
+ char prefix[DATA_MAX_NAME_LEN];
+
+ status = cf_util_get_string_buffer(child, prefix, sizeof(prefix));
+ if (status == 0) {
+ ssnprintf(phc->eal_config.file_prefix, DATA_MAX_NAME_LEN,
+ "/var/run/.%s_config", prefix);
+ DEBUG("dpdk_common: EAL:File prefix %s", phc->eal_config.file_prefix);
+ }
} else {
ERROR("dpdk_common: Invalid '%s' configuration option", child->key);
status = -EINVAL;
DPDK_HELPER_TRACE(name);
char errbuf[ERR_BUF_SIZE];
+ /*
+ * Call shm_unlink first, as 'name' might be no longer accessible after munmap
+ */
+ if (shm_unlink(name))
+ ERROR("shm_unlink failure %s", sstrerror(errno, errbuf, sizeof(errbuf)));
+
if (map != NULL) {
if (munmap(map, size))
ERROR("munmap failure %s", sstrerror(errno, errbuf, sizeof(errbuf)));
}
-
- if (shm_unlink(name))
- ERROR("shm_unlink failure %s", sstrerror(errno, errbuf, sizeof(errbuf)));
}
void *dpdk_helper_priv_get(dpdk_helper_ctx_t *phc) {
}
phc->shm_size = shm_size;
- phc->shm_name = name;
+ sstrncpy(phc->shm_name, name, sizeof(phc->shm_name));
dpdk_helper_config_default(phc);
return 0;
}
-int dpdk_helper_shutdown(dpdk_helper_ctx_t *phc) {
- if (phc == NULL) {
- ERROR("%s:Invalid argument(phc)", __FUNCTION__);
- return -EINVAL;
- }
+void dpdk_helper_shutdown(dpdk_helper_ctx_t *phc) {
+ if (phc == NULL)
+ return;
DPDK_HELPER_TRACE(phc->shm_name);
sem_destroy(&phc->sema_cmd_start);
sem_destroy(&phc->sema_cmd_complete);
dpdk_shm_cleanup(phc->shm_name, phc->shm_size, (void *)phc);
-
- return 0;
}
static int dpdk_helper_spawn(dpdk_helper_ctx_t *phc) {
/* EAL config must be initialized */
assert(phc->eal_config.coremask[0] != 0);
assert(phc->eal_config.memory_channels[0] != 0);
- assert(phc->eal_config.process_type[0] != 0);
assert(phc->eal_config.file_prefix[0] != 0);
argp[argc++] = "collectd-dpdk";
}
argp[argc++] = "--proc-type";
- argp[argc++] = phc->eal_config.process_type;
+ argp[argc++] = "secondary";
assert(argc <= (DPDK_EAL_ARGC * 2 + 1));
char coremask[DATA_MAX_NAME_LEN];
char memory_channels[DATA_MAX_NAME_LEN];
char socket_memory[DATA_MAX_NAME_LEN];
- char process_type[DATA_MAX_NAME_LEN];
char file_prefix[DATA_MAX_NAME_LEN];
};
typedef struct dpdk_eal_config_s dpdk_eal_config_t;
int dpdk_helper_init(const char *name, size_t data_size,
dpdk_helper_ctx_t **pphc);
-int dpdk_helper_shutdown(dpdk_helper_ctx_t *phc);
+void dpdk_helper_shutdown(dpdk_helper_ctx_t *phc);
int dpdk_helper_eal_config_parse(dpdk_helper_ctx_t *phc, oconfig_item_t *ci);
int dpdk_helper_eal_config_set(dpdk_helper_ctx_t *phc, dpdk_eal_config_t *ec);
int dpdk_helper_eal_config_get(dpdk_helper_ctx_t *phc, dpdk_eal_config_t *ec);