aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorIvan Nardi <12729895+IvanNardi@users.noreply.github.com>2024-02-01 15:33:11 +0100
committerGitHub <noreply@github.com>2024-02-01 15:33:11 +0100
commit400cd516b5fbc6137feb73c377a944e3dc64f53b (patch)
treecd86a570dbde39fb286a5521f3c165ef4e68cf60 /src
parent44c2e59661b34f7b9004a98ddd31e7b3e514e6ec (diff)
Allow multiple `struct ndpi_detection_module_struct` to share some state (#2271)
Add the concept of "global context". Right now every instance of `struct ndpi_detection_module_struct` (we will call it "local context" in this description) is completely independent from each other. This provide optimal performances in multithreaded environment, where we pin each local context to a thread, and each thread to a specific CPU core: we don't have any data shared across the cores. Each local context has, internally, also some information correlating **different** flows; something like: ``` if flow1 (PeerA <-> Peer B) is PROTOCOL_X; then flow2 (PeerC <-> PeerD) will be PROTOCOL_Y ``` To get optimal classification results, both flow1 and flow2 must be processed by the same local context. This is not an issue at all in the far most common scenario where there is only one local context, but it might be impractical in some more complex scenarios. Create the concept of "global context": multiple local contexts can use the same global context and share some data (structures) using it. This way the data correlating multiple flows can be read/write from different local contexts. This is an optional feature, disabled by default. Obviously data structures shared in a global context must be thread safe. This PR updates the code of the LRU implementation to be, optionally, thread safe. Right now, only the LRU caches can be shared; the other main structures (trees and automas) are basically read-only: there is little sense in sharing them. Furthermore, these structures don't have any information correlating multiple flows. Every LRU cache can be shared, independently from the others, via `ndpi_set_config(ndpi_struct, NULL, "lru.$CACHE_NAME.scope", "1")`. It's up to the user to find the right trade-off between performances (i.e. without shared data) and classification results (i.e. with some shared data among the local contexts), depending on the specific traffic patterns and on the algorithms used to balance the flows across the threads/cores/local contexts. Add some basic examples of library initialization in `doc/library_initialization.md`. This code needs libpthread as external dependency. It shouldn't be a big issue; however a configure flag has been added to disable global context support. A new CI job has been added to test it. TODO: we should need to find a proper way to add some tests on multithreaded enviroment... not an easy task... *** API changes *** If you are not interested in this feature, simply add a NULL parameter to any `ndpi_init_detection_module()` calls.
Diffstat (limited to 'src')
-rw-r--r--src/include/ndpi_api.h24
-rw-r--r--src/include/ndpi_private.h37
-rw-r--r--src/include/ndpi_typedefs.h17
-rw-r--r--src/lib/ndpi_main.c276
4 files changed, 309 insertions, 45 deletions
diff --git a/src/include/ndpi_api.h b/src/include/ndpi_api.h
index abef7ad34..ea40927bf 100644
--- a/src/include/ndpi_api.h
+++ b/src/include/ndpi_api.h
@@ -202,6 +202,22 @@ extern "C" {
ndpi_protocol_match const * const match);
/**
+ * Returns a new initialized global context.
+ *
+ * @return the initialized global context
+ *
+ */
+ struct ndpi_global_context *ndpi_global_init(void);
+
+ /**
+ * Deinit a properly initialized global context.
+ *
+ * @par g_ctx = global context to free/deinit
+ *
+ */
+ void ndpi_global_deinit(struct ndpi_global_context *g_ctx);
+
+ /**
* Returns a new initialized detection module
* Note that before you can use it you can still load
* hosts and do other things. As soon as you are ready to use
@@ -211,10 +227,11 @@ extern "C" {
* indipendent detection contexts) but all these calls MUST NOT run
* in parallel
*
+ * @g_ctx = global context associated to the new detection module; NULL if no global context is needed
* @return the initialized detection module
*
*/
- struct ndpi_detection_module_struct *ndpi_init_detection_module(void);
+ struct ndpi_detection_module_struct *ndpi_init_detection_module(struct ndpi_global_context *g_ctx);
/**
* Completes the initialization (2nd step)
@@ -1038,14 +1055,15 @@ extern "C" {
u_int32_t ndpi_get_current_time(struct ndpi_flow_struct *flow);
/* LRU cache */
- struct ndpi_lru_cache* ndpi_lru_cache_init(u_int32_t num_entries, u_int32_t ttl);
+ struct ndpi_lru_cache* ndpi_lru_cache_init(u_int32_t num_entries, u_int32_t ttl, int shared);
void ndpi_lru_free_cache(struct ndpi_lru_cache *c);
u_int8_t ndpi_lru_find_cache(struct ndpi_lru_cache *c, u_int32_t key,
u_int16_t *value, u_int8_t clean_key_when_found, u_int32_t now_sec);
void ndpi_lru_add_to_cache(struct ndpi_lru_cache *c, u_int32_t key, u_int16_t value, u_int32_t now_sec);
void ndpi_lru_get_stats(struct ndpi_lru_cache *c, struct ndpi_lru_cache_stats *stats);
- int ndpi_get_lru_cache_stats(struct ndpi_detection_module_struct *ndpi_struct,
+ int ndpi_get_lru_cache_stats(struct ndpi_global_context *g_ctx,
+ struct ndpi_detection_module_struct *ndpi_struct,
lru_cache_type cache_type,
struct ndpi_lru_cache_stats *stats);
diff --git a/src/include/ndpi_private.h b/src/include/ndpi_private.h
index 0721f2db1..efaafb67a 100644
--- a/src/include/ndpi_private.h
+++ b/src/include/ndpi_private.h
@@ -144,6 +144,34 @@ typedef struct {
} nbpf_filter;
#endif
+struct ndpi_global_context {
+
+ /* LRU caches */
+
+ /* NDPI_PROTOCOL_OOKLA */
+ int ookla_cache_is_global;
+ struct ndpi_lru_cache *ookla_global_cache;
+
+ /* NDPI_PROTOCOL_BITTORRENT */
+ struct ndpi_lru_cache *bittorrent_global_cache;
+
+ /* NDPI_PROTOCOL_ZOOM */
+ struct ndpi_lru_cache *zoom_global_cache;
+
+ /* NDPI_PROTOCOL_STUN and subprotocols */
+ struct ndpi_lru_cache *stun_global_cache;
+ struct ndpi_lru_cache *stun_zoom_global_cache;
+
+ /* NDPI_PROTOCOL_TLS and subprotocols */
+ struct ndpi_lru_cache *tls_cert_global_cache;
+
+ /* NDPI_PROTOCOL_MINING and subprotocols */
+ struct ndpi_lru_cache *mining_global_cache;
+
+ /* NDPI_PROTOCOL_MSTEAMS */
+ struct ndpi_lru_cache *msteams_global_cache;
+};
+
#define CFG_MAX_LEN 256
struct ndpi_detection_module_config_struct {
@@ -177,20 +205,28 @@ struct ndpi_detection_module_config_struct {
int ookla_cache_num_entries;
int ookla_cache_ttl;
+ int ookla_cache_scope;
int bittorrent_cache_num_entries;
int bittorrent_cache_ttl;
+ int bittorrent_cache_scope;
int zoom_cache_num_entries;
int zoom_cache_ttl;
+ int zoom_cache_scope;
int stun_cache_num_entries;
int stun_cache_ttl;
+ int stun_cache_scope;
int tls_cert_cache_num_entries;
int tls_cert_cache_ttl;
+ int tls_cert_cache_scope;
int mining_cache_num_entries;
int mining_cache_ttl;
+ int mining_cache_scope;
int msteams_cache_num_entries;
int msteams_cache_ttl;
+ int msteams_cache_scope;
int stun_zoom_cache_num_entries;
int stun_zoom_cache_ttl;
+ int stun_zoom_cache_scope;
/* Protocols */
@@ -301,6 +337,7 @@ struct ndpi_detection_module_struct {
u_int8_t ip_version_limit;
+ struct ndpi_global_context *g_ctx;
struct ndpi_detection_module_config_struct cfg;
/* NDPI_PROTOCOL_TINC */
diff --git a/src/include/ndpi_typedefs.h b/src/include/ndpi_typedefs.h
index 72e2cd704..ebad711f1 100644
--- a/src/include/ndpi_typedefs.h
+++ b/src/include/ndpi_typedefs.h
@@ -24,6 +24,11 @@ E * ndpi_typedefs.h
#ifndef __NDPI_TYPEDEFS_H__
#define __NDPI_TYPEDEFS_H__
+#ifndef NDPI_CFFI_PREPROCESSING
+#define HAVE_STRUCT_TIMESPEC
+#include <pthread.h>
+#endif
+
#include "ndpi_define.h"
#ifndef NDPI_CFFI_PREPROCESSING
#include "ndpi_includes.h"
@@ -743,6 +748,11 @@ typedef enum {
NDPI_LRUCACHE_MAX /* Last one! */
} lru_cache_type;
+typedef enum {
+ NDPI_LRUCACHE_SCOPE_LOCAL = 0,
+ NDPI_LRUCACHE_SCOPE_GLOBAL,
+} lru_cache_scope;
+
struct ndpi_lru_cache_entry {
u_int32_t key; /* Store the whole key to avoid ambiguities */
u_int32_t is_full:1, value:16, pad:15;
@@ -757,7 +767,10 @@ struct ndpi_lru_cache_stats {
struct ndpi_lru_cache {
u_int32_t num_entries;
- u_int32_t ttl;
+ u_int32_t ttl : 31, shared : 1;
+#ifndef NDPI_CFFI_PREPROCESSING
+ pthread_mutex_t mutex;
+#endif
struct ndpi_lru_cache_stats stats;
struct ndpi_lru_cache_entry *entries;
};
@@ -947,6 +960,8 @@ struct ndpi_flow_udp_struct {
/* ************************************************** */
+
+struct ndpi_global_context;
struct ndpi_detection_module_struct;
struct ndpi_flow_struct;
diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c
index ab2470aaa..0870bcbc1 100644
--- a/src/lib/ndpi_main.c
+++ b/src/lib/ndpi_main.c
@@ -3088,9 +3088,60 @@ static void free_ptree_data(void *data) {
}
}
+struct ndpi_global_context *ndpi_global_init(void) {
+
+#ifndef USE_GLOBAL_CONTEXT
+ return NULL;
+#endif
+
+ struct ndpi_global_context *g_ctx = ndpi_calloc(1, sizeof(struct ndpi_global_context));
+
+ if(g_ctx == NULL)
+ return(NULL);
+
+ /* Global caches (if any) are initialized during the initialization
+ of the local context(s) */
+
+ /* Note that we don't have yet an easy way to log from this function */
+
+ return g_ctx;
+}
+
/* ******************************************************************** */
-struct ndpi_detection_module_struct *ndpi_init_detection_module(void) {
+void ndpi_global_deinit(struct ndpi_global_context *g_ctx) {
+
+ /* Note that we don't have yet an easy way to log from this function */
+
+ if(g_ctx) {
+
+ /* Global caches are freed here, so that we are able to get statistics even
+ after the uninitialization of all the local contexts */
+
+ if(g_ctx->ookla_global_cache)
+ ndpi_lru_free_cache(g_ctx->ookla_global_cache);
+ if(g_ctx->bittorrent_global_cache)
+ ndpi_lru_free_cache(g_ctx->bittorrent_global_cache);
+ if(g_ctx->zoom_global_cache)
+ ndpi_lru_free_cache(g_ctx->zoom_global_cache);
+ if(g_ctx->stun_global_cache)
+ ndpi_lru_free_cache(g_ctx->stun_global_cache);
+ if(g_ctx->stun_zoom_global_cache)
+ ndpi_lru_free_cache(g_ctx->stun_zoom_global_cache);
+ if(g_ctx->tls_cert_global_cache)
+ ndpi_lru_free_cache(g_ctx->tls_cert_global_cache);
+ if(g_ctx->mining_global_cache)
+ ndpi_lru_free_cache(g_ctx->mining_global_cache);
+ if(g_ctx->msteams_global_cache)
+ ndpi_lru_free_cache(g_ctx->msteams_global_cache);
+
+ ndpi_free(g_ctx);
+ }
+}
+
+/* ******************************************************************** */
+
+struct ndpi_detection_module_struct *ndpi_init_detection_module(struct ndpi_global_context *g_ctx) {
struct ndpi_detection_module_struct *ndpi_str = ndpi_malloc(sizeof(struct ndpi_detection_module_struct));
int i;
@@ -3126,6 +3177,7 @@ struct ndpi_detection_module_struct *ndpi_init_detection_module(void) {
ndpi_str->ip_risk_mask_ptree = ndpi_patricia_new(32 /* IPv4 */);
ndpi_str->ip_risk_mask_ptree6 = ndpi_patricia_new(128 /* IPv6 */);
+ ndpi_str->g_ctx = g_ctx;
set_default_config(&ndpi_str->cfg);
NDPI_BITMASK_SET_ALL(ndpi_str->detection_bitmask);
@@ -3546,64 +3598,128 @@ int ndpi_finalize_initialization(struct ndpi_detection_module_struct *ndpi_str)
ndpi_add_domain_risk_exceptions(ndpi_str);
if(ndpi_str->cfg.ookla_cache_num_entries > 0) {
- ndpi_str->ookla_cache = ndpi_lru_cache_init(ndpi_str->cfg.ookla_cache_num_entries,
- ndpi_str->cfg.ookla_cache_ttl);
+ if(ndpi_str->cfg.ookla_cache_scope == NDPI_LRUCACHE_SCOPE_GLOBAL) {
+ if(!ndpi_str->g_ctx->ookla_global_cache) {
+ ndpi_str->g_ctx->ookla_global_cache = ndpi_lru_cache_init(ndpi_str->cfg.ookla_cache_num_entries,
+ ndpi_str->cfg.ookla_cache_ttl, 1);
+ }
+ ndpi_str->ookla_cache = ndpi_str->g_ctx->ookla_global_cache;
+ } else {
+ ndpi_str->ookla_cache = ndpi_lru_cache_init(ndpi_str->cfg.ookla_cache_num_entries,
+ ndpi_str->cfg.ookla_cache_ttl, 0);
+ }
if(!ndpi_str->ookla_cache) {
NDPI_LOG_ERR(ndpi_str, "Error allocating lru cache (num_entries %u)\n",
ndpi_str->cfg.ookla_cache_num_entries);
}
}
if(ndpi_str->cfg.bittorrent_cache_num_entries > 0) {
- ndpi_str->bittorrent_cache = ndpi_lru_cache_init(ndpi_str->cfg.bittorrent_cache_num_entries,
- ndpi_str->cfg.bittorrent_cache_ttl);
+ if(ndpi_str->cfg.bittorrent_cache_scope == NDPI_LRUCACHE_SCOPE_GLOBAL) {
+ if(!ndpi_str->g_ctx->bittorrent_global_cache) {
+ ndpi_str->g_ctx->bittorrent_global_cache = ndpi_lru_cache_init(ndpi_str->cfg.bittorrent_cache_num_entries,
+ ndpi_str->cfg.bittorrent_cache_ttl, 1);
+ }
+ ndpi_str->bittorrent_cache = ndpi_str->g_ctx->bittorrent_global_cache;
+ } else {
+ ndpi_str->bittorrent_cache = ndpi_lru_cache_init(ndpi_str->cfg.bittorrent_cache_num_entries,
+ ndpi_str->cfg.bittorrent_cache_ttl, 0);
+ }
if(!ndpi_str->bittorrent_cache) {
NDPI_LOG_ERR(ndpi_str, "Error allocating lru cache (num_entries %u)\n",
ndpi_str->cfg.bittorrent_cache_num_entries);
}
}
if(ndpi_str->cfg.zoom_cache_num_entries > 0) {
- ndpi_str->zoom_cache = ndpi_lru_cache_init(ndpi_str->cfg.zoom_cache_num_entries,
- ndpi_str->cfg.zoom_cache_ttl);
+ if(ndpi_str->cfg.zoom_cache_scope == NDPI_LRUCACHE_SCOPE_GLOBAL) {
+ if(!ndpi_str->g_ctx->zoom_global_cache) {
+ ndpi_str->g_ctx->zoom_global_cache = ndpi_lru_cache_init(ndpi_str->cfg.zoom_cache_num_entries,
+ ndpi_str->cfg.zoom_cache_ttl, 1);
+ }
+ ndpi_str->zoom_cache = ndpi_str->g_ctx->zoom_global_cache;
+ } else {
+ ndpi_str->zoom_cache = ndpi_lru_cache_init(ndpi_str->cfg.zoom_cache_num_entries,
+ ndpi_str->cfg.zoom_cache_ttl, 0);
+ }
if(!ndpi_str->zoom_cache) {
NDPI_LOG_ERR(ndpi_str, "Error allocating lru cache (num_entries %u)\n",
ndpi_str->cfg.zoom_cache_num_entries);
}
}
if(ndpi_str->cfg.stun_cache_num_entries > 0) {
- ndpi_str->stun_cache = ndpi_lru_cache_init(ndpi_str->cfg.stun_cache_num_entries,
- ndpi_str->cfg.stun_cache_ttl);
+ if(ndpi_str->cfg.stun_cache_scope == NDPI_LRUCACHE_SCOPE_GLOBAL) {
+ if(!ndpi_str->g_ctx->stun_global_cache) {
+ ndpi_str->g_ctx->stun_global_cache = ndpi_lru_cache_init(ndpi_str->cfg.stun_cache_num_entries,
+ ndpi_str->cfg.stun_cache_ttl, 1);
+ }
+ ndpi_str->stun_cache = ndpi_str->g_ctx->stun_global_cache;
+ } else {
+ ndpi_str->stun_cache = ndpi_lru_cache_init(ndpi_str->cfg.stun_cache_num_entries,
+ ndpi_str->cfg.stun_cache_ttl, 0);
+ }
if(!ndpi_str->stun_cache) {
NDPI_LOG_ERR(ndpi_str, "Error allocating lru cache (num_entries %u)\n",
ndpi_str->cfg.stun_cache_num_entries);
}
}
if(ndpi_str->cfg.tls_cert_cache_num_entries > 0) {
- ndpi_str->tls_cert_cache = ndpi_lru_cache_init(ndpi_str->cfg.tls_cert_cache_num_entries,
- ndpi_str->cfg.tls_cert_cache_ttl);
+ if(ndpi_str->cfg.tls_cert_cache_scope == NDPI_LRUCACHE_SCOPE_GLOBAL) {
+ if(!ndpi_str->g_ctx->tls_cert_global_cache) {
+ ndpi_str->g_ctx->tls_cert_global_cache = ndpi_lru_cache_init(ndpi_str->cfg.tls_cert_cache_num_entries,
+ ndpi_str->cfg.tls_cert_cache_ttl, 1);
+ }
+ ndpi_str->tls_cert_cache = ndpi_str->g_ctx->tls_cert_global_cache;
+ } else {
+ ndpi_str->tls_cert_cache = ndpi_lru_cache_init(ndpi_str->cfg.tls_cert_cache_num_entries,
+ ndpi_str->cfg.tls_cert_cache_ttl, 0);
+ }
if(!ndpi_str->tls_cert_cache) {
NDPI_LOG_ERR(ndpi_str, "Error allocating lru cache (num_entries %u)\n",
ndpi_str->cfg.tls_cert_cache_num_entries);
}
}
if(ndpi_str->cfg.mining_cache_num_entries > 0) {
- ndpi_str->mining_cache = ndpi_lru_cache_init(ndpi_str->cfg.mining_cache_num_entries,
- ndpi_str->cfg.mining_cache_ttl);
+ if(ndpi_str->cfg.mining_cache_scope == NDPI_LRUCACHE_SCOPE_GLOBAL) {
+ if(!ndpi_str->g_ctx->mining_global_cache) {
+ ndpi_str->g_ctx->mining_global_cache = ndpi_lru_cache_init(ndpi_str->cfg.mining_cache_num_entries,
+ ndpi_str->cfg.mining_cache_ttl, 1);
+ }
+ ndpi_str->mining_cache = ndpi_str->g_ctx->mining_global_cache;
+ } else {
+ ndpi_str->mining_cache = ndpi_lru_cache_init(ndpi_str->cfg.mining_cache_num_entries,
+ ndpi_str->cfg.mining_cache_ttl, 0);
+ }
if(!ndpi_str->mining_cache) {
NDPI_LOG_ERR(ndpi_str, "Error allocating lru cache (num_entries %u)\n",
ndpi_str->cfg.mining_cache_num_entries);
}
}
if(ndpi_str->cfg.msteams_cache_num_entries > 0) {
- ndpi_str->msteams_cache = ndpi_lru_cache_init(ndpi_str->cfg.msteams_cache_num_entries,
- ndpi_str->cfg.msteams_cache_ttl);
+ if(ndpi_str->cfg.msteams_cache_scope == NDPI_LRUCACHE_SCOPE_GLOBAL) {
+ if(!ndpi_str->g_ctx->msteams_global_cache) {
+ ndpi_str->g_ctx->msteams_global_cache = ndpi_lru_cache_init(ndpi_str->cfg.msteams_cache_num_entries,
+ ndpi_str->cfg.msteams_cache_ttl, 1);
+ }
+ ndpi_str->msteams_cache = ndpi_str->g_ctx->msteams_global_cache;
+ } else {
+ ndpi_str->msteams_cache = ndpi_lru_cache_init(ndpi_str->cfg.msteams_cache_num_entries,
+ ndpi_str->cfg.msteams_cache_ttl, 0);
+ }
if(!ndpi_str->msteams_cache) {
NDPI_LOG_ERR(ndpi_str, "Error allocating lru cache (num_entries %u)\n",
ndpi_str->cfg.msteams_cache_num_entries);
}
}
if(ndpi_str->cfg.stun_zoom_cache_num_entries > 0) {
- ndpi_str->stun_zoom_cache = ndpi_lru_cache_init(ndpi_str->cfg.stun_zoom_cache_num_entries,
- ndpi_str->cfg.stun_zoom_cache_ttl);
+ if(ndpi_str->cfg.stun_zoom_cache_scope == NDPI_LRUCACHE_SCOPE_GLOBAL) {
+ if(!ndpi_str->g_ctx->stun_zoom_global_cache) {
+ ndpi_str->g_ctx->stun_zoom_global_cache = ndpi_lru_cache_init(ndpi_str->cfg.stun_zoom_cache_num_entries,
+ ndpi_str->cfg.stun_zoom_cache_ttl, 1);
+ }
+ ndpi_str->stun_zoom_cache = ndpi_str->g_ctx->stun_zoom_global_cache;
+ } else {
+ ndpi_str->stun_zoom_cache = ndpi_lru_cache_init(ndpi_str->cfg.stun_zoom_cache_num_entries,
+ ndpi_str->cfg.stun_zoom_cache_ttl, 0);
+ }
if(!ndpi_str->stun_zoom_cache) {
NDPI_LOG_ERR(ndpi_str, "Error allocating lru cache (num_entries %u)\n",
ndpi_str->cfg.stun_zoom_cache_num_entries);
@@ -3910,28 +4026,36 @@ void ndpi_exit_detection_module(struct ndpi_detection_module_struct *ndpi_str) {
if(ndpi_str->tinc_cache)
cache_free((cache_t)(ndpi_str->tinc_cache));
- if(ndpi_str->ookla_cache)
+ if(!ndpi_str->cfg.ookla_cache_scope &&
+ ndpi_str->ookla_cache)
ndpi_lru_free_cache(ndpi_str->ookla_cache);
- if(ndpi_str->bittorrent_cache)
+ if(!ndpi_str->cfg.bittorrent_cache_scope &&
+ ndpi_str->bittorrent_cache)
ndpi_lru_free_cache(ndpi_str->bittorrent_cache);
- if(ndpi_str->zoom_cache)
+ if(!ndpi_str->cfg.zoom_cache_scope &&
+ ndpi_str->zoom_cache)
ndpi_lru_free_cache(ndpi_str->zoom_cache);
- if(ndpi_str->stun_cache)
+ if(!ndpi_str->cfg.stun_cache_scope &&
+ ndpi_str->stun_cache)
ndpi_lru_free_cache(ndpi_str->stun_cache);
- if(ndpi_str->stun_zoom_cache)
+ if(!ndpi_str->cfg.stun_zoom_cache_scope &&
+ ndpi_str->stun_zoom_cache)
ndpi_lru_free_cache(ndpi_str->stun_zoom_cache);
- if(ndpi_str->tls_cert_cache)
+ if(!ndpi_str->cfg.tls_cert_cache_scope &&
+ ndpi_str->tls_cert_cache)
ndpi_lru_free_cache(ndpi_str->tls_cert_cache);
- if(ndpi_str->mining_cache)
+ if(!ndpi_str->cfg.mining_cache_scope &&
+ ndpi_str->mining_cache)
ndpi_lru_free_cache(ndpi_str->mining_cache);
- if(ndpi_str->msteams_cache)
+ if(!ndpi_str->cfg.msteams_cache_scope &&
+ ndpi_str->msteams_cache)
ndpi_lru_free_cache(ndpi_str->msteams_cache);
if(ndpi_str->protocols_ptree)
@@ -9283,7 +9407,7 @@ void ndpi_generate_options(u_int opt, FILE *options_out) {
u_int i;
if (!options_out) return;
- ndpi_str = ndpi_init_detection_module();
+ ndpi_str = ndpi_init_detection_module(NULL);
if (!ndpi_str) return;
NDPI_BITMASK_SET_ALL(all);
@@ -9729,13 +9853,20 @@ u_int32_t ndpi_get_current_time(struct ndpi_flow_struct *flow)
/* ******************************************************************** */
/* LRU cache */
-struct ndpi_lru_cache *ndpi_lru_cache_init(u_int32_t num_entries, u_int32_t ttl) {
+struct ndpi_lru_cache *ndpi_lru_cache_init(u_int32_t num_entries, u_int32_t ttl, int shared) {
struct ndpi_lru_cache *c = (struct ndpi_lru_cache *) ndpi_calloc(1, sizeof(struct ndpi_lru_cache));
if(!c)
return(NULL);
- c->ttl = ttl;
+ c->ttl = ttl & 0x7FFFFFFF;
+ c->shared = !!shared;
+ if(c->shared) {
+ if(pthread_mutex_init(&c->mutex, NULL) != 0) {
+ ndpi_free(c);
+ return(NULL);
+ }
+ }
c->entries = (struct ndpi_lru_cache_entry *) ndpi_calloc(num_entries, sizeof(struct ndpi_lru_cache_entry));
if(!c->entries) {
@@ -9752,9 +9883,26 @@ void ndpi_lru_free_cache(struct ndpi_lru_cache *c) {
ndpi_free(c);
}
+static void __lru_cache_lock(struct ndpi_lru_cache *c)
+{
+ if(c->shared) {
+ pthread_mutex_lock(&c->mutex);
+ }
+}
+
+static void __lru_cache_unlock(struct ndpi_lru_cache *c)
+{
+ if(c->shared) {
+ pthread_mutex_unlock(&c->mutex);
+ }
+}
+
u_int8_t ndpi_lru_find_cache(struct ndpi_lru_cache *c, u_int32_t key,
u_int16_t *value, u_int8_t clean_key_when_found, u_int32_t now_sec) {
u_int32_t slot = key % c->num_entries;
+ u_int8_t ret;
+
+ __lru_cache_lock(c);
c->stats.n_search++;
if(c->entries[slot].is_full && c->entries[slot].key == key &&
@@ -9764,16 +9912,24 @@ u_int8_t ndpi_lru_find_cache(struct ndpi_lru_cache *c, u_int32_t key,
if(clean_key_when_found)
c->entries[slot].is_full = 0;
c->stats.n_found++;
- return(1);
+ ret = 1;
} else
- return(0);
+ ret = 0;
+
+ __lru_cache_unlock(c);
+
+ return ret;
}
void ndpi_lru_add_to_cache(struct ndpi_lru_cache *c, u_int32_t key, u_int16_t value, u_int32_t now_sec) {
u_int32_t slot = key % c->num_entries;
+ __lru_cache_lock(c);
+
c->stats.n_insert++;
c->entries[slot].is_full = 1, c->entries[slot].key = key, c->entries[slot].value = value, c->entries[slot].timestamp = now_sec;
+
+ __lru_cache_unlock(c);
}
void ndpi_lru_get_stats(struct ndpi_lru_cache *c, struct ndpi_lru_cache_stats *stats) {
@@ -9788,37 +9944,53 @@ void ndpi_lru_get_stats(struct ndpi_lru_cache *c, struct ndpi_lru_cache_stats *s
}
}
-int ndpi_get_lru_cache_stats(struct ndpi_detection_module_struct *ndpi_struct,
+int ndpi_get_lru_cache_stats(struct ndpi_global_context *g_ctx,
+ struct ndpi_detection_module_struct *ndpi_struct,
lru_cache_type cache_type,
struct ndpi_lru_cache_stats *stats)
{
- if(!ndpi_struct || !stats)
+ int scope, is_local = 1;
+ char param[64], buf[8];
+
+ if(!stats || (!ndpi_struct && !g_ctx))
return -1;
+ if(!ndpi_struct) {
+ is_local = 0;
+ } else {
+ snprintf(param, sizeof(param), "lru.%s.scope", ndpi_lru_cache_idx_to_name(cache_type));
+ ndpi_get_config(ndpi_struct, NULL, param, buf, sizeof(buf));
+ scope = atoi(buf);
+ if(scope == NDPI_LRUCACHE_SCOPE_GLOBAL) {
+ is_local = 0;
+ if(!g_ctx)
+ return -1;
+ }
+ }
switch(cache_type) {
case NDPI_LRUCACHE_OOKLA:
- ndpi_lru_get_stats(ndpi_struct->ookla_cache, stats);
+ ndpi_lru_get_stats(is_local ? ndpi_struct->ookla_cache : g_ctx->ookla_global_cache, stats);
return 0;
case NDPI_LRUCACHE_BITTORRENT:
- ndpi_lru_get_stats(ndpi_struct->bittorrent_cache, stats);
+ ndpi_lru_get_stats(is_local ? ndpi_struct->bittorrent_cache : g_ctx->bittorrent_global_cache, stats);
return 0;
case NDPI_LRUCACHE_ZOOM:
- ndpi_lru_get_stats(ndpi_struct->zoom_cache, stats);
+ ndpi_lru_get_stats(is_local ? ndpi_struct->zoom_cache : g_ctx->zoom_global_cache, stats);
return 0;
case NDPI_LRUCACHE_STUN:
- ndpi_lru_get_stats(ndpi_struct->stun_cache, stats);
+ ndpi_lru_get_stats(is_local ? ndpi_struct->stun_cache : g_ctx->stun_global_cache, stats);
return 0;
case NDPI_LRUCACHE_TLS_CERT:
- ndpi_lru_get_stats(ndpi_struct->tls_cert_cache, stats);
+ ndpi_lru_get_stats(is_local ? ndpi_struct->tls_cert_cache : g_ctx->tls_cert_global_cache, stats);
return 0;
case NDPI_LRUCACHE_MINING:
- ndpi_lru_get_stats(ndpi_struct->mining_cache, stats);
+ ndpi_lru_get_stats(is_local ? ndpi_struct->mining_cache : g_ctx->mining_global_cache, stats);
return 0;
case NDPI_LRUCACHE_MSTEAMS:
- ndpi_lru_get_stats(ndpi_struct->msteams_cache, stats);
+ ndpi_lru_get_stats(is_local ? ndpi_struct->msteams_cache : g_ctx->msteams_global_cache, stats);
return 0;
case NDPI_LRUCACHE_STUN_ZOOM:
- ndpi_lru_get_stats(ndpi_struct->stun_zoom_cache, stats);
+ ndpi_lru_get_stats(is_local ? ndpi_struct->stun_zoom_cache : g_ctx->stun_zoom_global_cache, stats);
return 0;
default:
return -1;
@@ -10487,7 +10659,7 @@ static u_int16_t __get_proto_id(const char *proto_name_or_id)
/* Try to decode the string as protocol name */
/* Use a temporary module with all protocols enabled */
- module = ndpi_init_detection_module();
+ module = ndpi_init_detection_module(NULL);
if(!module)
return NDPI_PROTOCOL_UNKNOWN;
NDPI_BITMASK_SET_ALL(all);
@@ -10661,6 +10833,20 @@ static ndpi_cfg_error _set_param_protocol_enable_disable(struct ndpi_detection_m
return NDPI_CFG_INVALID_PARAM;
}
+static int clbk_only_with_global_ctx(struct ndpi_detection_module_struct *ndpi_str,
+ void *_variable, const char *proto,
+ const char *param)
+{
+ int *variable = (int *)_variable;
+
+ /* Integer set > 0 only if there is a global context */
+ if(*variable > 0 && !ndpi_str->g_ctx) {
+ *variable = 0;
+ return -1;
+ }
+ return 0;
+}
+
enum cfg_param_type {
CFG_PARAM_ENABLE_DISABLE = 0,
@@ -10749,27 +10935,35 @@ static const struct cfg_param {
{ NULL, "lru.ookla.size", "1024", "0", "16777215", CFG_PARAM_INT, __OFF(ookla_cache_num_entries), NULL },
{ NULL, "lru.ookla.ttl", "120", "0", "16777215", CFG_PARAM_INT, __OFF(ookla_cache_ttl), NULL },
+ { NULL, "lru.ookla.scope", "0", "0", "1", CFG_PARAM_INT, __OFF(ookla_cache_scope), clbk_only_with_global_ctx },
{ NULL, "lru.bittorrent.size", "32768", "0", "16777215", CFG_PARAM_INT, __OFF(bittorrent_cache_num_entries), NULL },
{ NULL, "lru.bittorrent.ttl", "0", "0", "16777215", CFG_PARAM_INT, __OFF(bittorrent_cache_ttl), NULL },
+ { NULL, "lru.bittorrent.scope", "0", "0", "1", CFG_PARAM_INT, __OFF(bittorrent_cache_scope), clbk_only_with_global_ctx },
{ NULL, "lru.zoom.size", "512", "0", "16777215", CFG_PARAM_INT, __OFF(zoom_cache_num_entries), NULL },
{ NULL, "lru.zoom.ttl", "0", "0", "16777215", CFG_PARAM_INT, __OFF(zoom_cache_ttl), NULL },
+ { NULL, "lru.zoom.scope", "0", "0", "1", CFG_PARAM_INT, __OFF(zoom_cache_scope), clbk_only_with_global_ctx },
{ NULL, "lru.stun.size", "1024", "0", "16777215", CFG_PARAM_INT, __OFF(stun_cache_num_entries), NULL },
{ NULL, "lru.stun.ttl", "0", "0", "16777215", CFG_PARAM_INT, __OFF(stun_cache_ttl), NULL },
+ { NULL, "lru.stun.scope", "0", "0", "1", CFG_PARAM_INT, __OFF(stun_cache_scope), clbk_only_with_global_ctx },
{ NULL, "lru.tls_cert.size", "1024", "0", "16777215", CFG_PARAM_INT, __OFF(tls_cert_cache_num_entries), NULL },
{ NULL, "lru.tls_cert.ttl", "0", "0", "16777215", CFG_PARAM_INT, __OFF(tls_cert_cache_ttl), NULL },
+ { NULL, "lru.tls_cert.scope", "0", "0", "1", CFG_PARAM_INT, __OFF(tls_cert_cache_scope), clbk_only_with_global_ctx },
{ NULL, "lru.mining.size", "1024", "0", "16777215", CFG_PARAM_INT, __OFF(mining_cache_num_entries), NULL },
{ NULL, "lru.mining.ttl", "0", "0", "16777215", CFG_PARAM_INT, __OFF(mining_cache_ttl), NULL },
+ { NULL, "lru.mining.scope", "0", "0", "1", CFG_PARAM_INT, __OFF(mining_cache_scope), clbk_only_with_global_ctx },
{ NULL, "lru.msteams.size", "1024", "0", "16777215", CFG_PARAM_INT, __OFF(msteams_cache_num_entries), NULL },
{ NULL, "lru.msteams.ttl", "60", "0", "16777215", CFG_PARAM_INT, __OFF(msteams_cache_ttl), NULL },
+ { NULL, "lru.msteams.scope", "0", "0", "1", CFG_PARAM_INT, __OFF(msteams_cache_scope), clbk_only_with_global_ctx },
{ NULL, "lru.stun_zoom.size", "1024", "0", "16777215", CFG_PARAM_INT, __OFF(stun_zoom_cache_num_entries), NULL },
{ NULL, "lru.stun_zoom.ttl", "60", "0", "16777215", CFG_PARAM_INT, __OFF(stun_zoom_cache_ttl), NULL },
+ { NULL, "lru.stun_zoom.scope", "0", "0", "1", CFG_PARAM_INT, __OFF(stun_zoom_cache_scope), clbk_only_with_global_ctx },
{ NULL, NULL, NULL, NULL, NULL, 0, -1, NULL },