runmode-unix-socket: add commands for memcap handling

This permits to handle memcap values through
unix socket for:
- stream
- stream-reassembly
- flow
- applayer-proto-http
- defrag
- ippair
- host

It will be possible to show or change a memcap value
for a specified configuration and list all memcap values
available.

The following commands are registered for unix-socket:
- memcap-set
- memcap-show
- memcap-list

Output:
>>> memcap-show flow
Success:
{
    "value": "64mb"
}

>>> memcap-set flow 64mb
Success:
"memcap value for 'flow' updated: 67108864"

Command with invalid memcap key:
>>> memcap-set udp 32mb
Error:
"Available config: stream stream-reassembly flow applayer-proto-http defrag ippair host"

Command with an invalid memcap value:
>>> memcap-set http 32mmb
Error:
"error parsing memcap specified, value not changed"
pull/3104/head
Giuseppe Longo 7 years ago committed by Victor Julien
parent bba8cfb626
commit 3668ea2522

@ -33,12 +33,16 @@
#include "flow-manager.h"
#include "flow-timeout.h"
#include "stream-tcp.h"
#include "stream-tcp-reassemble.h"
#include "host.h"
#include "defrag.h"
#include "defrag-hash.h"
#include "ippair.h"
#include "app-layer.h"
#include "app-layer-htp-mem.h"
#include "host-bit.h"
#include "util-misc.h"
#include "util-profiling.h"
#include "conf-yaml-loader.h"
@ -63,6 +67,13 @@ typedef struct PcapCommand_ {
PcapFiles *current_file;
} PcapCommand;
typedef struct MemcapCommand_ {
const char *name;
int (*SetFunc)(uint64_t);
uint64_t (*GetFunc)(void);
uint64_t (*GetMemuseFunc)(void);
} MemcapCommand;
const char *RunModeUnixSocketGetDefaultMode(void)
{
return default_mode;
@ -70,6 +81,52 @@ const char *RunModeUnixSocketGetDefaultMode(void)
#ifdef BUILD_UNIX_SOCKET
#define MEMCAPS_MAX 7
static MemcapCommand memcaps[MEMCAPS_MAX] = {
{
"stream",
StreamTcpSetMemcap,
StreamTcpGetMemcap,
StreamTcpMemuseCounter,
},
{
"stream-reassembly",
StreamTcpReassembleSetMemcap,
StreamTcpReassembleGetMemcap,
StreamTcpReassembleMemuseGlobalCounter
},
{
"flow",
FlowSetMemcap,
FlowGetMemcap,
FlowGetMemuse
},
{
"applayer-proto-http",
HTPSetMemcap,
HTPGetMemcap,
HTPMemuseGlobalCounter
},
{
"defrag",
DefragTrackerSetMemcap,
DefragTrackerGetMemcap,
DefragTrackerGetMemuse
},
{
"ippair",
IPPairSetMemcap,
IPPairGetMemcap,
IPPairGetMemuse
},
{
"host",
HostSetMemcap,
HostGetMemcap,
HostGetMemuse
},
};
static int RunModeUnixSocketMaster(void);
static int unix_manager_pcap_task_running = 0;
static int unix_manager_pcap_task_failed = 0;
@ -1136,6 +1193,164 @@ TmEcode UnixSocketHostbitList(json_t *cmd, json_t* answer, void *data_unused)
json_object_set_new(answer, "message", jdata);
return TM_ECODE_OK;
}
static void MemcapBuildValue(uint64_t val, char *str, uint32_t str_len)
{
if ((val / (1024 * 1024 * 1024)) != 0) {
snprintf(str, str_len, "%"PRIu64"gb", val / (1024*1024*1024));
} else if ((val / (1024 * 1024)) != 0) {
snprintf(str, str_len, "%"PRIu64"mb", val / (1024*1024));
} else {
snprintf(str, str_len, "%"PRIu64"kb", val / (1024));
}
}
TmEcode UnixSocketSetMemcap(json_t *cmd, json_t* answer, void *data)
{
char *memcap = NULL;
char *value_str = NULL;
uint64_t value;
int i;
json_t *jarg = json_object_get(cmd, "config");
if (!json_is_string(jarg)) {
json_object_set_new(answer, "message", json_string("memcap key is not a string"));
return TM_ECODE_FAILED;
}
memcap = (char *)json_string_value(jarg);
jarg = json_object_get(cmd, "memcap");
if (!json_is_string(jarg)) {
json_object_set_new(answer, "message", json_string("memcap value is not a string"));
return TM_ECODE_FAILED;
}
value_str = (char *)json_string_value(jarg);
if (ParseSizeStringU64(value_str, &value) < 0) {
SCLogError(SC_ERR_SIZE_PARSE, "Error parsing "
"memcap from unix socket: %s", value_str);
json_object_set_new(answer, "message",
json_string("error parsing memcap specified, "
"value not changed"));
return TM_ECODE_FAILED;
}
for (i = 0; i < MEMCAPS_MAX; i++) {
if (strcmp(memcaps[i].name, memcap) == 0 && memcaps[i].SetFunc) {
int updated = memcaps[i].SetFunc(value);
char message[150];
if (updated) {
snprintf(message, sizeof(message),
"memcap value for '%s' updated: %"PRIu64" %s",
memcaps[i].name, value,
(value == 0) ? "(unlimited)" : "");
json_object_set_new(answer, "message", json_string(message));
return TM_ECODE_OK;
} else {
if (value == 0) {
snprintf(message, sizeof(message),
"Unlimited value is not allowed for '%s'", memcaps[i].name);
} else {
if (memcaps[i].GetMemuseFunc()) {
char memuse[50];
MemcapBuildValue(memcaps[i].GetMemuseFunc(), memuse, sizeof(memuse));
snprintf(message, sizeof(message),
"memcap value specified for '%s' is less than the memory in use: %s",
memcaps[i].name, memuse);
} else {
snprintf(message, sizeof(message),
"memcap value specified for '%s' is less than the memory in use",
memcaps[i].name);
}
}
json_object_set_new(answer, "message", json_string(message));
return TM_ECODE_FAILED;
}
}
}
json_object_set_new(answer, "message",
json_string("Memcap value not found. Use 'memcap-list' to show all"));
return TM_ECODE_FAILED;
}
TmEcode UnixSocketShowMemcap(json_t *cmd, json_t *answer, void *data)
{
char *memcap = NULL;
int i;
json_t *jarg = json_object_get(cmd, "config");
if (!json_is_string(jarg)) {
json_object_set_new(answer, "message", json_string("memcap name is not a string"));
return TM_ECODE_FAILED;
}
memcap = (char *)json_string_value(jarg);
for (i = 0; i < MEMCAPS_MAX; i++) {
if (strcmp(memcaps[i].name, memcap) == 0 && memcaps[i].GetFunc) {
char str[50];
uint64_t val = memcaps[i].GetFunc();
json_t *jobj = json_object();
if (jobj == NULL) {
json_object_set_new(answer, "message",
json_string("internal error at json object creation"));
return TM_ECODE_FAILED;
}
if (val == 0) {
strlcpy(str, "unlimited", sizeof(str));
} else {
MemcapBuildValue(val, str, sizeof(str));
}
json_object_set_new(jobj, "value", json_string(str));
json_object_set_new(answer, "message", jobj);
return TM_ECODE_OK;
}
}
json_object_set_new(answer, "message",
json_string("Memcap value not found. Use 'memcap-list' to show all"));
return TM_ECODE_FAILED;
}
TmEcode UnixSocketShowAllMemcap(json_t *cmd, json_t *answer, void *data)
{
json_t *jmemcaps = json_array();
int i;
if (jmemcaps == NULL) {
json_object_set_new(answer, "message",
json_string("internal error at json array creation"));
return TM_ECODE_FAILED;
}
for (i = 0; i < MEMCAPS_MAX; i++) {
json_t *jobj = json_object();
if (jobj == NULL) {
json_decref(jmemcaps);
json_object_set_new(answer, "message",
json_string("internal error at json object creation"));
return TM_ECODE_FAILED;
}
char str[50];
uint64_t val = memcaps[i].GetFunc();
if (val == 0) {
strlcpy(str, "unlimited", sizeof(str));
} else {
MemcapBuildValue(val, str, sizeof(str));
}
json_object_set_new(jobj, "name", json_string(memcaps[i].name));
json_object_set_new(jobj, "value", json_string(str));
json_array_append_new(jmemcaps, jobj);
}
json_object_set_new(answer, "message", jmemcaps);
SCReturnInt(TM_ECODE_OK);
}
#endif /* BUILD_UNIX_SOCKET */
#ifdef BUILD_UNIX_SOCKET

@ -39,6 +39,9 @@ TmEcode UnixSocketUnregisterTenant(json_t *cmd, json_t* answer, void *data);
TmEcode UnixSocketHostbitAdd(json_t *cmd, json_t* answer, void *data);
TmEcode UnixSocketHostbitRemove(json_t *cmd, json_t* answer, void *data);
TmEcode UnixSocketHostbitList(json_t *cmd, json_t* answer, void *data);
TmEcode UnixSocketSetMemcap(json_t *cmd, json_t* answer, void *data);
TmEcode UnixSocketShowMemcap(json_t *cmd, json_t *answer, void *data);
TmEcode UnixSocketShowAllMemcap(json_t *cmd, json_t *answer, void *data);
#endif
#endif /* __RUNMODE_UNIX_SOCKET_H__ */

@ -839,7 +839,6 @@ static TmEcode UnixManagerListCommand(json_t *cmd,
SCReturnInt(TM_ECODE_OK);
}
static TmEcode UnixManagerReopenLogFiles(json_t *cmd, json_t *server_msg, void *data)
{
OutputNotifyFileRotation();
@ -1007,6 +1006,9 @@ int UnixManagerInit(void)
UnixManagerRegisterCommand("remove-hostbit", UnixSocketHostbitRemove, &command, UNIX_CMD_TAKE_ARGS);
UnixManagerRegisterCommand("list-hostbit", UnixSocketHostbitList, &command, UNIX_CMD_TAKE_ARGS);
UnixManagerRegisterCommand("reopen-log-files", UnixManagerReopenLogFiles, NULL, 0);
UnixManagerRegisterCommand("memcap-set", UnixSocketSetMemcap, &command, UNIX_CMD_TAKE_ARGS);
UnixManagerRegisterCommand("memcap-show", UnixSocketShowMemcap, &command, UNIX_CMD_TAKE_ARGS);
UnixManagerRegisterCommand("memcap-list", UnixSocketShowAllMemcap, NULL, 0);
return 0;
}

Loading…
Cancel
Save