From: Giuseppe Longo Date: Mon, 20 Nov 2017 14:02:32 +0000 (+0100) Subject: flow: get/set memcap value X-Git-Tag: suricata-4.1.0-beta1~442 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6fdad7d9e58bb07f085c262c998d2cc3f741c3a0;p=thirdparty%2Fsuricata.git flow: get/set memcap value This adds new functions that will be called through unix-socket and permit to update and show memcap value. The memcap value needs to be handled in a thread safe way, so for this reason it is declared as atomic var. FlowGetMemuse() function is made as public because the memuse value will be shown through unix-socket. --- diff --git a/src/flow-manager.c b/src/flow-manager.c index b0c9f95faf..77bfd9f6b6 100644 --- a/src/flow-manager.c +++ b/src/flow-manager.c @@ -803,12 +803,6 @@ static TmEcode FlowManager(ThreadVars *th_v, void *thread_data) return TM_ECODE_OK; } -static uint64_t FlowGetMemuse(void) -{ - uint64_t flow_memuse = SC_ATOMIC_GET(flow_memuse); - return flow_memuse; -} - /** \brief spawn the flow manager thread */ void FlowManagerThreadSpawn() { @@ -1366,7 +1360,7 @@ static int FlowMgrTest05 (void) uint32_t ini = 0; uint32_t end = flow_spare_q.len; - flow_config.memcap = 10000; + SC_ATOMIC_SET(flow_config.memcap, 10000); flow_config.prealloc = 100; /* Let's get the flow_spare_q empty */ diff --git a/src/flow-util.h b/src/flow-util.h index eac473e0a1..11109c3c5a 100644 --- a/src/flow-util.h +++ b/src/flow-util.h @@ -127,7 +127,7 @@ * \retval 0 no fit */ #define FLOW_CHECK_MEMCAP(size) \ - ((((uint64_t)SC_ATOMIC_GET(flow_memuse) + (uint64_t)(size)) <= flow_config.memcap)) + ((((uint64_t)SC_ATOMIC_GET(flow_memuse) + (uint64_t)(size)) <= SC_ATOMIC_GET(flow_config.memcap))) Flow *FlowAlloc(void); Flow *FlowAllocDirect(void); diff --git a/src/flow.c b/src/flow.c index ac8541f11f..683d456c2c 100644 --- a/src/flow.c +++ b/src/flow.c @@ -89,6 +89,38 @@ int FlowSetProtoFreeFunc(uint8_t, void (*Free)(void *)); /* Run mode selected at suricata.c */ extern int run_mode; +/** + * \brief Update memcap value + * + * \param size new memcap value + */ +int FlowSetMemcap(uint64_t size) +{ + if ((uint64_t)SC_ATOMIC_GET(flow_memuse) < size) { + SC_ATOMIC_SET(flow_config.memcap, size); + return 1; + } + + return 0; +} + +/** + * \brief Return memcap value + * + * \retval memcap value + */ +uint64_t FlowGetMemcap(void) +{ + uint64_t memcapcopy = SC_ATOMIC_GET(flow_config.memcap); + return memcapcopy; +} + +uint64_t FlowGetMemuse(void) +{ + uint64_t memusecopy = SC_ATOMIC_GET(flow_memuse); + return memusecopy; +} + void FlowCleanupAppLayer(Flow *f) { if (f == NULL || f->proto == 0) @@ -405,14 +437,15 @@ void FlowInitConfig(char quiet) SC_ATOMIC_INIT(flow_flags); SC_ATOMIC_INIT(flow_memuse); SC_ATOMIC_INIT(flow_prune_idx); + SC_ATOMIC_INIT(flow_config.memcap); FlowQueueInit(&flow_spare_q); FlowQueueInit(&flow_recycle_q); /* set defaults */ flow_config.hash_rand = (uint32_t)RandomGet(); flow_config.hash_size = FLOW_DEFAULT_HASHSIZE; - flow_config.memcap = FLOW_DEFAULT_MEMCAP; flow_config.prealloc = FLOW_DEFAULT_PREALLOC; + SC_ATOMIC_SET(flow_config.memcap, FLOW_DEFAULT_MEMCAP); /* If we have specific config, overwrite the defaults with them, * otherwise, leave the default values */ @@ -434,6 +467,7 @@ void FlowInitConfig(char quiet) uint32_t configval = 0; /** set config values for memcap, prealloc and hash_size */ + uint64_t flow_memcap_copy; if ((ConfGet("flow.memcap", &conf_val)) == 1) { if (conf_val == NULL) { @@ -441,11 +475,13 @@ void FlowInitConfig(char quiet) exit(EXIT_FAILURE); } - if (ParseSizeStringU64(conf_val, &flow_config.memcap) < 0) { + if (ParseSizeStringU64(conf_val, &flow_memcap_copy) < 0) { SCLogError(SC_ERR_SIZE_PARSE, "Error parsing flow.memcap " "from conf file - %s. Killing engine", conf_val); exit(EXIT_FAILURE); + } else { + SC_ATOMIC_SET(flow_config.memcap, flow_memcap_copy); } } if ((ConfGet("flow.hash-size", &conf_val)) == 1) @@ -473,7 +509,7 @@ void FlowInitConfig(char quiet) } } SCLogDebug("Flow config from suricata.yaml: memcap: %"PRIu64", hash-size: " - "%"PRIu32", prealloc: %"PRIu32, flow_config.memcap, + "%"PRIu32", prealloc: %"PRIu32, SC_ATOMIC_GET(flow_config.memcap), flow_config.hash_size, flow_config.prealloc); /* alloc hash memory */ @@ -483,7 +519,7 @@ void FlowInitConfig(char quiet) "max flow memcap is smaller than projected hash size. " "Memcap: %"PRIu64", Hash table size %"PRIu64". Calculate " "total hash size by multiplying \"flow.hash-size\" with %"PRIuMAX", " - "which is the hash bucket size.", flow_config.memcap, hash_size, + "which is the hash bucket size.", SC_ATOMIC_GET(flow_config.memcap), hash_size, (uintmax_t)sizeof(FlowBucket)); exit(EXIT_FAILURE); } @@ -513,7 +549,7 @@ void FlowInitConfig(char quiet) if (!(FLOW_CHECK_MEMCAP(sizeof(Flow) + FlowStorageSize()))) { SCLogError(SC_ERR_FLOW_INIT, "preallocating flows failed: " "max flow memcap reached. Memcap %"PRIu64", " - "Memuse %"PRIu64".", flow_config.memcap, + "Memuse %"PRIu64".", SC_ATOMIC_GET(flow_config.memcap), ((uint64_t)SC_ATOMIC_GET(flow_memuse) + (uint64_t)sizeof(Flow))); exit(EXIT_FAILURE); } @@ -531,7 +567,7 @@ void FlowInitConfig(char quiet) SCLogConfig("preallocated %" PRIu32 " flows of size %" PRIuMAX "", flow_spare_q.len, (uintmax_t)(sizeof(Flow) + + FlowStorageSize())); SCLogConfig("flow memory usage: %"PRIu64" bytes, maximum: %"PRIu64, - SC_ATOMIC_GET(flow_memuse), flow_config.memcap); + SC_ATOMIC_GET(flow_memuse), SC_ATOMIC_GET(flow_config.memcap)); } FlowInitFlowProto(); @@ -589,6 +625,7 @@ void FlowShutdown(void) FlowQueueDestroy(&flow_spare_q); FlowQueueDestroy(&flow_recycle_q); + SC_ATOMIC_DESTROY(flow_config.memcap); SC_ATOMIC_DESTROY(flow_prune_idx); SC_ATOMIC_DESTROY(flow_memuse); SC_ATOMIC_DESTROY(flow_flags); @@ -1079,7 +1116,7 @@ static int FlowTest07 (void) uint32_t ini = 0; uint32_t end = flow_spare_q.len; - flow_config.memcap = 10000; + SC_ATOMIC_SET(flow_config.memcap, 10000); flow_config.prealloc = 100; /* Let's get the flow_spare_q empty */ @@ -1126,7 +1163,7 @@ static int FlowTest08 (void) uint32_t ini = 0; uint32_t end = flow_spare_q.len; - flow_config.memcap = 10000; + SC_ATOMIC_SET(flow_config.memcap, 10000); flow_config.prealloc = 100; /* Let's get the flow_spare_q empty */ @@ -1173,7 +1210,7 @@ static int FlowTest09 (void) uint32_t ini = 0; uint32_t end = flow_spare_q.len; - flow_config.memcap = 10000; + SC_ATOMIC_SET(flow_config.memcap, 10000); flow_config.prealloc = 100; /* Let's get the flow_spare_q empty */ diff --git a/src/flow.h b/src/flow.h index f2aa47df01..a13aa5eb9f 100644 --- a/src/flow.h +++ b/src/flow.h @@ -245,7 +245,6 @@ typedef struct FlowCnf_ { uint32_t hash_rand; uint32_t hash_size; - uint64_t memcap; uint32_t max_flows; uint32_t prealloc; @@ -256,6 +255,7 @@ typedef struct FlowCnf_ uint32_t emerg_timeout_est; uint32_t emergency_recovery; + SC_ATOMIC_DECLARE(uint64_t, memcap); } FlowConfig; /* Hash key for the flow hash */ @@ -497,6 +497,10 @@ void FlowCleanupAppLayer(Flow *); void FlowUpdateState(Flow *f, enum FlowState s); +int FlowSetMemcap(uint64_t size); +uint64_t FlowGetMemcap(void); +uint64_t FlowGetMemuse(void); + /** ----- Inline functions ----- */ /** \brief Set the No Packet Inspection Flag without locking the flow.