/src/suricata8/src/util-thash.h
Line | Count | Source |
1 | | /* Copyright (C) 2007-2024 Open Information Security Foundation |
2 | | * |
3 | | * You can copy, redistribute or modify this Program under the terms of |
4 | | * the GNU General Public License version 2 as published by the Free |
5 | | * Software Foundation. |
6 | | * |
7 | | * This program is distributed in the hope that it will be useful, |
8 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
9 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
10 | | * GNU General Public License for more details. |
11 | | * |
12 | | * You should have received a copy of the GNU General Public License |
13 | | * version 2 along with this program; if not, write to the Free Software |
14 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
15 | | * 02110-1301, USA. |
16 | | */ |
17 | | |
18 | | /** |
19 | | * \file |
20 | | * |
21 | | * \author Victor Julien <victor@inliniac.net> |
22 | | * |
23 | | * thash -> thread hash. Hash table with locking handling. |
24 | | */ |
25 | | |
26 | | #ifndef SURICATA_THASH_H |
27 | | #define SURICATA_THASH_H |
28 | | |
29 | | #include "threads.h" |
30 | | |
31 | | /** Spinlocks or Mutex for the buckets. */ |
32 | | //#define HRLOCK_SPIN |
33 | | #define HRLOCK_MUTEX |
34 | | |
35 | | #ifdef HRLOCK_SPIN |
36 | | #ifdef HRLOCK_MUTEX |
37 | | #error Cannot enable both HRLOCK_SPIN and HRLOCK_MUTEX |
38 | | #endif |
39 | | #endif |
40 | | |
41 | | #ifdef HRLOCK_SPIN |
42 | | #define HRLOCK_TYPE SCSpinlock |
43 | | #define HRLOCK_INIT(fb) SCSpinInit(&(fb)->lock, 0) |
44 | | #define HRLOCK_DESTROY(fb) SCSpinDestroy(&(fb)->lock) |
45 | | #define HRLOCK_LOCK(fb) SCSpinLock(&(fb)->lock) |
46 | | #define HRLOCK_TRYLOCK(fb) SCSpinTrylock(&(fb)->lock) |
47 | | #define HRLOCK_UNLOCK(fb) SCSpinUnlock(&(fb)->lock) |
48 | | #elif defined HRLOCK_MUTEX |
49 | | #define HRLOCK_TYPE SCMutex |
50 | 49.8M | #define HRLOCK_INIT(fb) SCMutexInit(&(fb)->lock, NULL) |
51 | 44.5M | #define HRLOCK_DESTROY(fb) SCMutexDestroy(&(fb)->lock) |
52 | 214k | #define HRLOCK_LOCK(fb) SCMutexLock(&(fb)->lock) |
53 | 0 | #define HRLOCK_TRYLOCK(fb) SCMutexTrylock(&(fb)->lock) |
54 | 214k | #define HRLOCK_UNLOCK(fb) SCMutexUnlock(&(fb)->lock) |
55 | | #else |
56 | | #error Enable HRLOCK_SPIN or HRLOCK_MUTEX |
57 | | #endif |
58 | | |
59 | | /** Spinlocks or Mutex for the queues. */ |
60 | | //#define HQLOCK_SPIN |
61 | | #define HQLOCK_MUTEX |
62 | | |
63 | | #ifdef HQLOCK_SPIN |
64 | | #ifdef HQLOCK_MUTEX |
65 | | #error Cannot enable both HQLOCK_SPIN and HQLOCK_MUTEX |
66 | | #endif |
67 | | #endif |
68 | | |
69 | | #ifdef HQLOCK_SPIN |
70 | | #define HQLOCK_INIT(q) SCSpinInit(&(q)->s, 0) |
71 | | #define HQLOCK_DESTROY(q) SCSpinDestroy(&(q)->s) |
72 | | #define HQLOCK_LOCK(q) SCSpinLock(&(q)->s) |
73 | | #define HQLOCK_TRYLOCK(q) SCSpinTrylock(&(q)->s) |
74 | | #define HQLOCK_UNLOCK(q) SCSpinUnlock(&(q)->s) |
75 | | #elif defined HQLOCK_MUTEX |
76 | 18.1k | #define HQLOCK_INIT(q) SCMutexInit(&(q)->m, NULL) |
77 | 17.0k | #define HQLOCK_DESTROY(q) SCMutexDestroy(&(q)->m) |
78 | 34.6M | #define HQLOCK_LOCK(q) SCMutexLock(&(q)->m) |
79 | | #define HQLOCK_TRYLOCK(q) SCMutexTrylock(&(q)->m) |
80 | 34.6M | #define HQLOCK_UNLOCK(q) SCMutexUnlock(&(q)->m) |
81 | | #else |
82 | | #error Enable HQLOCK_SPIN or HQLOCK_MUTEX |
83 | | #endif |
84 | | |
85 | | typedef struct THashData_ { |
86 | | /** ippair mutex */ |
87 | | SCMutex m; |
88 | | |
89 | | /** use cnt, reference counter */ |
90 | | SC_ATOMIC_DECLARE(unsigned int, use_cnt); |
91 | | |
92 | | void *data; |
93 | | |
94 | | struct THashData_ *next; |
95 | | struct THashData_ *prev; |
96 | | } THashData; |
97 | | |
98 | | typedef struct THashHashRow_ { |
99 | | HRLOCK_TYPE lock; |
100 | | THashData *head; |
101 | | THashData *tail; |
102 | | } __attribute__((aligned(CLS))) THashHashRow; |
103 | | |
104 | | typedef struct THashDataQueue_ |
105 | | { |
106 | | THashData *top; |
107 | | THashData *bot; |
108 | | uint32_t len; |
109 | | #ifdef DBG_PERF |
110 | | uint32_t dbg_maxlen; |
111 | | #endif /* DBG_PERF */ |
112 | | #ifdef HQLOCK_MUTEX |
113 | | SCMutex m; |
114 | | #elif defined HQLOCK_SPIN |
115 | | SCSpinlock s; |
116 | | #else |
117 | | #error Enable HQLOCK_SPIN or HQLOCK_MUTEX |
118 | | #endif |
119 | | } THashDataQueue; |
120 | | |
121 | | typedef int (*THashOutputFunc)(void *output_ctx, const uint8_t *data, const uint32_t data_len); |
122 | | typedef int (*THashFormatFunc)(const void *in_data, char *output, size_t output_size); |
123 | | |
124 | | typedef struct THashDataConfig_ { |
125 | | SC_ATOMIC_DECLARE(uint64_t, memcap); |
126 | | uint32_t hash_rand; |
127 | | uint32_t hash_size; |
128 | | uint32_t prealloc; |
129 | | |
130 | | uint32_t data_size; |
131 | | int (*DataSet)(void *dst, void *src); |
132 | | void (*DataFree)(void *); |
133 | | uint32_t (*DataHash)(uint32_t, void *); |
134 | | bool (*DataCompare)(void *, void *); |
135 | | bool (*DataExpired)(void *, SCTime_t ts); |
136 | | uint32_t (*DataSize)(void *); |
137 | | } THashConfig; |
138 | | |
139 | 17.8M | #define THASH_DATA_SIZE(ctx) (sizeof(THashData) + (ctx)->config.data_size) |
140 | | |
141 | | typedef struct THashTableContext_ { |
142 | | /* array of rows indexed by the hash value % hash size */ |
143 | | THashHashRow *array; |
144 | | |
145 | | SC_ATOMIC_DECLARE(uint64_t, memuse); |
146 | | SC_ATOMIC_DECLARE(uint32_t, counter); |
147 | | SC_ATOMIC_DECLARE(uint32_t, prune_idx); |
148 | | |
149 | | THashDataQueue spare_q; |
150 | | |
151 | | THashConfig config; |
152 | | |
153 | | /* flag set if memcap was reached at least once. */ |
154 | | SC_ATOMIC_DECLARE(bool, memcap_reached); |
155 | | } THashTableContext; |
156 | | |
157 | | /** \brief check if a memory alloc would fit in the memcap |
158 | | * |
159 | | * \param size memory allocation size to check |
160 | | * |
161 | | * \retval 1 it fits |
162 | | * \retval 0 no fit |
163 | | */ |
164 | | #define THASH_CHECK_MEMCAP(ctx, size) \ |
165 | 35.7M | ((((uint64_t)SC_ATOMIC_GET((ctx)->memuse) + (uint64_t)(size)) <= \ |
166 | 35.7M | SC_ATOMIC_GET((ctx)->config.memcap))) |
167 | | |
168 | | #define THashIncrUsecnt(h) \ |
169 | 212k | (void)SC_ATOMIC_ADD((h)->use_cnt, 1) |
170 | | #define THashDecrUsecnt(h) \ |
171 | 178k | (void)SC_ATOMIC_SUB((h)->use_cnt, 1) |
172 | | |
173 | | THashTableContext *THashInit(const char *cnf_prefix, uint32_t data_size, |
174 | | int (*DataSet)(void *dst, void *src), void (*DataFree)(void *), |
175 | | uint32_t (*DataHash)(uint32_t, void *), bool (*DataCompare)(void *, void *), |
176 | | bool (*DataExpired)(void *, SCTime_t), uint32_t (*DataSize)(void *), bool reset_memcap, |
177 | | uint64_t memcap, uint32_t hashsize); |
178 | | |
179 | | void THashShutdown(THashTableContext *ctx); |
180 | | |
181 | | static inline void THashDataLock(THashData *d) |
182 | 10.8k | { |
183 | 10.8k | SCMutexLock(&d->m); |
184 | 10.8k | } Unexecuted instantiation: detect-engine-register.c:THashDataLock Unexecuted instantiation: detect-engine.c:THashDataLock Unexecuted instantiation: suricata.c:THashDataLock Unexecuted instantiation: util-lua-dataset.c:THashDataLock Unexecuted instantiation: app-layer-htp.c:THashDataLock Unexecuted instantiation: app-layer.c:THashDataLock Unexecuted instantiation: datasets.c:THashDataLock Unexecuted instantiation: detect-datarep.c:THashDataLock Unexecuted instantiation: detect-dataset.c:THashDataLock Unexecuted instantiation: detect-engine-content-inspection.c:THashDataLock Unexecuted instantiation: detect-engine-threshold.c:THashDataLock Unexecuted instantiation: flow-manager.c:THashDataLock Unexecuted instantiation: runmode-unix-socket.c:THashDataLock Unexecuted instantiation: rust-context.c:THashDataLock Unexecuted instantiation: util-thash.c:THashDataLock app-layer-htp-file.c:THashDataLock Line | Count | Source | 182 | 10.8k | { | 183 | 10.8k | SCMutexLock(&d->m); | 184 | 10.8k | } |
Unexecuted instantiation: datasets-context-json.c:THashDataLock Unexecuted instantiation: datasets-ipv4.c:THashDataLock Unexecuted instantiation: datasets-ipv6.c:THashDataLock Unexecuted instantiation: datasets-md5.c:THashDataLock Unexecuted instantiation: datasets-sha256.c:THashDataLock Unexecuted instantiation: datasets-string.c:THashDataLock |
185 | | |
186 | | static inline void THashDataUnlock(THashData *d) |
187 | 241k | { |
188 | 241k | SCMutexUnlock(&d->m); |
189 | 241k | } Unexecuted instantiation: detect-engine-register.c:THashDataUnlock Unexecuted instantiation: detect-engine.c:THashDataUnlock Unexecuted instantiation: suricata.c:THashDataUnlock Unexecuted instantiation: util-lua-dataset.c:THashDataUnlock app-layer-htp-range.c:THashDataUnlock Line | Count | Source | 187 | 89.6k | { | 188 | 89.6k | SCMutexUnlock(&d->m); | 189 | 89.6k | } |
Unexecuted instantiation: app-layer-htp.c:THashDataUnlock Unexecuted instantiation: app-layer.c:THashDataUnlock datasets.c:THashDataUnlock Line | Count | Source | 187 | 133k | { | 188 | 133k | SCMutexUnlock(&d->m); | 189 | 133k | } |
Unexecuted instantiation: detect-datarep.c:THashDataUnlock Unexecuted instantiation: detect-dataset.c:THashDataUnlock Unexecuted instantiation: detect-engine-content-inspection.c:THashDataUnlock detect-engine-threshold.c:THashDataUnlock Line | Count | Source | 187 | 7.30k | { | 188 | 7.30k | SCMutexUnlock(&d->m); | 189 | 7.30k | } |
Unexecuted instantiation: flow-manager.c:THashDataUnlock Unexecuted instantiation: runmode-unix-socket.c:THashDataUnlock Unexecuted instantiation: rust-context.c:THashDataUnlock Unexecuted instantiation: util-thash.c:THashDataUnlock app-layer-htp-file.c:THashDataUnlock Line | Count | Source | 187 | 10.8k | { | 188 | 10.8k | SCMutexUnlock(&d->m); | 189 | 10.8k | } |
Unexecuted instantiation: datasets-context-json.c:THashDataUnlock Unexecuted instantiation: datasets-ipv4.c:THashDataUnlock Unexecuted instantiation: datasets-ipv6.c:THashDataUnlock Unexecuted instantiation: datasets-md5.c:THashDataUnlock Unexecuted instantiation: datasets-sha256.c:THashDataUnlock Unexecuted instantiation: datasets-string.c:THashDataUnlock |
190 | | |
191 | | struct THashDataGetResult { |
192 | | THashData *data; |
193 | | bool is_new; |
194 | | }; |
195 | | |
196 | | struct THashDataGetResult THashGetFromHash (THashTableContext *ctx, void *data); |
197 | | THashData *THashLookupFromHash (THashTableContext *ctx, void *data); |
198 | | THashDataQueue *THashDataQueueNew(void); |
199 | | void THashCleanup(THashTableContext *ctx); |
200 | | int THashWalk(THashTableContext *, THashFormatFunc, THashOutputFunc, void *); |
201 | | int THashRemoveFromHash (THashTableContext *ctx, void *data); |
202 | | void THashConsolidateMemcap(THashTableContext *ctx); |
203 | | void THashDataMoveToSpare(THashTableContext *ctx, THashData *h); |
204 | | uint32_t THashExpire(THashTableContext *ctx, const SCTime_t ts); |
205 | | |
206 | | #endif /* SURICATA_THASH_H */ |