suricata
ippair.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2012 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  * Information about ippairs.
24  */
25 
26 #include "suricata-common.h"
27 #include "conf.h"
28 
29 #include "util-debug.h"
30 #include "ippair.h"
31 #include "ippair-storage.h"
32 
33 #include "util-random.h"
34 #include "util-misc.h"
35 #include "util-byte.h"
36 #include "util-validate.h"
37 
38 #include "ippair-queue.h"
39 
40 #include "detect-tag.h"
41 #include "detect-engine-tag.h"
43 
44 #include "util-hash-lookup3.h"
45 
46 static IPPair *IPPairGetUsedIPPair(void);
47 
48 /** ippair hash table */
49 IPPairHashRow *ippair_hash;
50 /** queue with spare ippairs */
51 static IPPairQueue ippair_spare_q;
53 SC_ATOMIC_DECLARE(uint64_t,ippair_memuse);
54 SC_ATOMIC_DECLARE(uint32_t,ippair_counter);
55 SC_ATOMIC_DECLARE(uint32_t,ippair_prune_idx);
56 
57 /** size of the ippair object. Maybe updated in IPPairInitConfig to include
58  * the storage APIs additions. */
59 static uint16_t g_ippair_size = sizeof(IPPair);
60 
61 /**
62  * \brief Update memcap value
63  *
64  * \param size new memcap value
65  */
66 int IPPairSetMemcap(uint64_t size)
67 {
68  if ((uint64_t)SC_ATOMIC_GET(ippair_memuse) < size) {
69  SC_ATOMIC_SET(ippair_config.memcap, size);
70  return 1;
71  }
72 
73  return 0;
74 }
75 
76 /**
77  * \brief Return memcap value
78  *
79  * \retval memcap value
80  */
81 uint64_t IPPairGetMemcap(void)
82 {
83  uint64_t memcapcopy = SC_ATOMIC_GET(ippair_config.memcap);
84  return memcapcopy;
85 }
86 
87 /**
88  * \brief Return memuse value
89  *
90  * \retval memuse value
91  */
92 uint64_t IPPairGetMemuse(void)
93 {
94  uint64_t memusecopy = SC_ATOMIC_GET(ippair_memuse);
95  return memusecopy;
96 }
97 
99 {
100  IPPairEnqueue(&ippair_spare_q, h);
101  (void) SC_ATOMIC_SUB(ippair_counter, 1);
102 }
103 
105 {
106  if (!(IPPAIR_CHECK_MEMCAP(g_ippair_size))) {
107  return NULL;
108  }
109 
110  (void) SC_ATOMIC_ADD(ippair_memuse, g_ippair_size);
111 
112  IPPair *h = SCCalloc(1, g_ippair_size);
113  if (unlikely(h == NULL))
114  goto error;
115 
116  SCMutexInit(&h->m, NULL);
117  SC_ATOMIC_INIT(h->use_cnt);
118  return h;
119 
120 error:
121  return NULL;
122 }
123 
125 {
126  if (h != NULL) {
128  SCMutexDestroy(&h->m);
129  SCFree(h);
130  (void) SC_ATOMIC_SUB(ippair_memuse, g_ippair_size);
131  }
132 }
133 
134 static IPPair *IPPairNew(Address *a, Address *b)
135 {
136  IPPair *p = IPPairAlloc();
137  if (p == NULL)
138  goto error;
139 
140  /* copy addresses */
141  COPY_ADDRESS(a, &p->a[0]);
142  COPY_ADDRESS(b, &p->a[1]);
143 
144  return p;
145 
146 error:
147  return NULL;
148 }
149 
151 {
152  if (SCIPPairStorageSize() > 0)
154 }
155 
156 #define IPPAIR_DEFAULT_HASHSIZE 4096
157 #define IPPAIR_DEFAULT_MEMCAP 16777216
158 #define IPPAIR_DEFAULT_PREALLOC 1000
159 
160 /** \brief initialize the configuration
161  * \warning Not thread safe */
162 void IPPairInitConfig(bool quiet)
163 {
164  SCLogDebug("initializing ippair engine...");
165  if (SCIPPairStorageSize() > 0) {
166  DEBUG_VALIDATE_BUG_ON(sizeof(IPPair) + SCIPPairStorageSize() > UINT16_MAX);
167  g_ippair_size = (uint16_t)(sizeof(IPPair) + SCIPPairStorageSize());
168  }
169 
170  memset(&ippair_config, 0, sizeof(ippair_config));
171  //SC_ATOMIC_INIT(flow_flags);
172  SC_ATOMIC_INIT(ippair_counter);
173  SC_ATOMIC_INIT(ippair_memuse);
174  SC_ATOMIC_INIT(ippair_prune_idx);
176  IPPairQueueInit(&ippair_spare_q);
177 
178  /* set defaults */
179  ippair_config.hash_rand = (uint32_t)RandomGet();
183 
184  /* Check if we have memcap and hash_size defined at config */
185  const char *conf_val;
186  uint32_t configval = 0;
187 
188  /** set config values for memcap, prealloc and hash_size */
189  uint64_t ippair_memcap;
190  if ((SCConfGetNonNull("ippair.memcap", &conf_val)) == 1) {
191  if (ParseSizeStringU64(conf_val, &ippair_memcap) < 0) {
192  SCLogError("Error parsing ippair.memcap "
193  "from conf file - %s. Killing engine",
194  conf_val);
195  exit(EXIT_FAILURE);
196  } else {
197  SC_ATOMIC_SET(ippair_config.memcap, ippair_memcap);
198  }
199  }
200  if ((SCConfGetNonNull("ippair.hash-size", &conf_val)) == 1) {
201  if (StringParseUint32(&configval, 10, strlen(conf_val),
202  conf_val) > 0) {
203  ippair_config.hash_size = configval;
204  }
205  }
206 
207  if ((SCConfGetNonNull("ippair.prealloc", &conf_val)) == 1) {
208  if (StringParseUint32(&configval, 10, strlen(conf_val),
209  conf_val) > 0) {
210  ippair_config.prealloc = configval;
211  } else {
212  WarnInvalidConfEntry("ippair.prealloc", "%"PRIu32, ippair_config.prealloc);
213  }
214  }
215  SCLogDebug("IPPair config from suricata.yaml: memcap: %"PRIu64", hash-size: "
216  "%"PRIu32", prealloc: %"PRIu32, SC_ATOMIC_GET(ippair_config.memcap),
218 
219  /* alloc hash memory */
220  uint64_t hash_size = ippair_config.hash_size * sizeof(IPPairHashRow);
221  if (!(IPPAIR_CHECK_MEMCAP(hash_size))) {
222  SCLogError("allocating ippair hash failed: "
223  "max ippair memcap is smaller than projected hash size. "
224  "Memcap: %" PRIu64 ", Hash table size %" PRIu64 ". Calculate "
225  "total hash size by multiplying \"ippair.hash-size\" with %" PRIuMAX ", "
226  "which is the hash bucket size.",
227  SC_ATOMIC_GET(ippair_config.memcap), hash_size, (uintmax_t)sizeof(IPPairHashRow));
228  exit(EXIT_FAILURE);
229  }
230  ippair_hash = SCMallocAligned(ippair_config.hash_size * sizeof(IPPairHashRow), CLS);
231  if (unlikely(ippair_hash == NULL)) {
232  FatalError("Fatal error encountered in IPPairInitConfig. Exiting...");
233  }
234  memset(ippair_hash, 0, ippair_config.hash_size * sizeof(IPPairHashRow));
235 
236  uint32_t i = 0;
237  for (i = 0; i < ippair_config.hash_size; i++) {
239  }
240  (void) SC_ATOMIC_ADD(ippair_memuse, (ippair_config.hash_size * sizeof(IPPairHashRow)));
241 
242  if (!quiet) {
243  SCLogConfig("allocated %"PRIu64" bytes of memory for the ippair hash... "
244  "%" PRIu32 " buckets of size %" PRIuMAX "",
245  SC_ATOMIC_GET(ippair_memuse), ippair_config.hash_size,
246  (uintmax_t)sizeof(IPPairHashRow));
247  }
248 
249  /* pre allocate ippairs */
250  for (i = 0; i < ippair_config.prealloc; i++) {
251  if (!(IPPAIR_CHECK_MEMCAP(g_ippair_size))) {
252  SCLogError("preallocating ippairs failed: "
253  "max ippair memcap reached. Memcap %" PRIu64 ", "
254  "Memuse %" PRIu64 ".",
256  ((uint64_t)SC_ATOMIC_GET(ippair_memuse) + g_ippair_size));
257  exit(EXIT_FAILURE);
258  }
259 
260  IPPair *h = IPPairAlloc();
261  if (h == NULL) {
262  SCLogError("preallocating ippair failed: %s", strerror(errno));
263  exit(EXIT_FAILURE);
264  }
265  IPPairEnqueue(&ippair_spare_q,h);
266  }
267 
268  if (!quiet) {
269  SCLogConfig("preallocated %" PRIu32 " ippairs of size %" PRIu16 "",
270  ippair_spare_q.len, g_ippair_size);
271  SCLogConfig("ippair memory usage: %"PRIu64" bytes, maximum: %"PRIu64,
272  SC_ATOMIC_GET(ippair_memuse), SC_ATOMIC_GET(ippair_config.memcap));
273  }
274 }
275 
276 /** \brief print some ippair stats
277  * \warning Not thread safe */
278 void IPPairPrintStats (void)
279 {
280 #ifdef IPPAIRBITS_STATS
281  SCLogPerf("ippairbits added: %" PRIu32 ", removed: %" PRIu32 ", max memory usage: %" PRIu32 "",
282  ippairbits_added, ippairbits_removed, ippairbits_memuse_max);
283 #endif /* IPPAIRBITS_STATS */
284  SCLogPerf("ippair memory usage: %" PRIu64 " bytes, maximum: %" PRIu64,
285  SC_ATOMIC_GET(ippair_memuse), SC_ATOMIC_GET(ippair_config.memcap));
286 }
287 
288 /** \brief shutdown the flow engine
289  * \warning Not thread safe */
290 void IPPairShutdown(void)
291 {
292  IPPair *h;
293  uint32_t u;
294 
296 
297  /* free spare queue */
298  while((h = IPPairDequeue(&ippair_spare_q))) {
299  BUG_ON(SC_ATOMIC_GET(h->use_cnt) > 0);
300  IPPairFree(h);
301  }
302 
303  /* clear and free the hash */
304  if (ippair_hash != NULL) {
305  for (u = 0; u < ippair_config.hash_size; u++) {
306  h = ippair_hash[u].head;
307  while (h) {
308  IPPair *n = h->hnext;
309  IPPairFree(h);
310  h = n;
311  }
312 
314  }
316  ippair_hash = NULL;
317  }
318  (void) SC_ATOMIC_SUB(ippair_memuse, ippair_config.hash_size * sizeof(IPPairHashRow));
319  IPPairQueueDestroy(&ippair_spare_q);
320 }
321 
322 /** \brief Cleanup the ippair engine
323  *
324  * Cleanup the ippair engine from tag and threshold.
325  *
326  */
327 void IPPairCleanup(void)
328 {
329  if (ippair_hash != NULL) {
330  for (uint32_t u = 0; u < ippair_config.hash_size; u++) {
331  IPPairHashRow *hb = &ippair_hash[u];
332  HRLOCK_LOCK(hb);
333  IPPair *h = ippair_hash[u].head;
334  while (h) {
335  if ((SC_ATOMIC_GET(h->use_cnt) > 0)) {
336  /* iprep is attached to ippair only clear local storage */
338  h = h->hnext;
339  } else {
340  IPPair *n = h->hnext;
341  /* remove from the hash */
342  if (h->hprev != NULL)
343  h->hprev->hnext = h->hnext;
344  if (h->hnext != NULL)
345  h->hnext->hprev = h->hprev;
346  if (hb->head == h)
347  hb->head = h->hnext;
348  if (hb->tail == h)
349  hb->tail = h->hprev;
350  h->hnext = NULL;
351  h->hprev = NULL;
354  h = n;
355  }
356  }
357  HRLOCK_UNLOCK(hb);
358  }
359  }
360 }
361 
362 /** \brief compare two raw ipv6 addrs
363  *
364  * \note we don't care about the real ipv6 ip's, this is just
365  * to consistently fill the FlowHashKey6 struct, without all
366  * the SCNtohl calls.
367  *
368  * \warning do not use elsewhere unless you know what you're doing.
369  * detect-engine-address-ipv6.c's AddressIPv6GtU32 is likely
370  * what you are looking for.
371  * Copied from FlowHashRawAddressIPv6GtU32
372  */
373 static inline int IPPairHashRawAddressIPv6GtU32(const uint32_t *a, const uint32_t *b)
374 {
375  int i;
376 
377  for (i = 0; i < 4; i++) {
378  if (a[i] > b[i])
379  return 1;
380  if (a[i] < b[i])
381  break;
382  }
383 
384  return 0;
385 }
386 
387 /* calculate the hash key for this packet
388  *
389  * we're using:
390  * hash_rand -- set at init time
391  * source address
392  */
393 static uint32_t IPPairGetKey(Address *a, Address *b)
394 {
395  uint32_t key;
396 
397  if (a->family == AF_INET) {
398  uint32_t addrs[2] = { MIN(a->addr_data32[0], b->addr_data32[0]),
399  MAX(a->addr_data32[0], b->addr_data32[0]) };
400  uint32_t hash = hashword(addrs, 2, ippair_config.hash_rand);
401  key = hash % ippair_config.hash_size;
402  } else if (a->family == AF_INET6) {
403  uint32_t addrs[8];
404  if (IPPairHashRawAddressIPv6GtU32(&a->addr_data32[0],&b->addr_data32[0])) {
405  addrs[0] = b->addr_data32[0];
406  addrs[1] = b->addr_data32[1];
407  addrs[2] = b->addr_data32[2];
408  addrs[3] = b->addr_data32[3];
409  addrs[4] = a->addr_data32[0];
410  addrs[5] = a->addr_data32[1];
411  addrs[6] = a->addr_data32[2];
412  addrs[7] = a->addr_data32[3];
413  } else {
414  addrs[0] = a->addr_data32[0];
415  addrs[1] = a->addr_data32[1];
416  addrs[2] = a->addr_data32[2];
417  addrs[3] = a->addr_data32[3];
418  addrs[4] = b->addr_data32[0];
419  addrs[5] = b->addr_data32[1];
420  addrs[6] = b->addr_data32[2];
421  addrs[7] = b->addr_data32[3];
422  }
423  uint32_t hash = hashword(addrs, 8, ippair_config.hash_rand);
424  key = hash % ippair_config.hash_size;
425  } else
426  key = 0;
427 
428  return key;
429 }
430 
431 /* Since two or more ippairs can have the same hash key, we need to compare
432  * the ippair with the current addresses. */
433 static inline int IPPairCompare(IPPair *p, Address *a, Address *b)
434 {
435  /* compare in both directions */
436  if ((CMP_ADDR(&p->a[0], a) && CMP_ADDR(&p->a[1], b)) ||
437  (CMP_ADDR(&p->a[0], b) && CMP_ADDR(&p->a[1], a))) {
438  if (p->a[0].family == a->family) {
439  return 1;
440  }
441  }
442  return 0;
443 }
444 
445 /**
446  * \brief Get a new ippair
447  *
448  * Get a new ippair. We're checking memcap first and will try to make room
449  * if the memcap is reached.
450  *
451  * \retval h *LOCKED* ippair on succes, NULL on error.
452  */
453 static IPPair *IPPairGetNew(Address *a, Address *b)
454 {
455  IPPair *h = NULL;
456 
457  /* get a ippair from the spare queue */
458  h = IPPairDequeue(&ippair_spare_q);
459  if (h == NULL) {
460  /* If we reached the max memcap, we get a used ippair */
461  if (!(IPPAIR_CHECK_MEMCAP(g_ippair_size))) {
462  /* declare state of emergency */
463  //if (!(SC_ATOMIC_GET(ippair_flags) & IPPAIR_EMERGENCY)) {
464  // SC_ATOMIC_OR(ippair_flags, IPPAIR_EMERGENCY);
465 
466  /* under high load, waking up the flow mgr each time leads
467  * to high cpu usage. Flows are not timed out much faster if
468  * we check a 1000 times a second. */
469  // FlowWakeupFlowManagerThread();
470  //}
471 
472  h = IPPairGetUsedIPPair();
473  if (h == NULL) {
474  return NULL;
475  }
476 
477  /* freed a ippair, but it's unlocked */
478  } else {
479  /* now see if we can alloc a new ippair */
480  h = IPPairNew(a,b);
481  if (h == NULL) {
482  return NULL;
483  }
484 
485  /* ippair is initialized but *unlocked* */
486  }
487  } else {
488  /* ippair has been recycled before it went into the spare queue */
489 
490  /* ippair is initialized (recycled) but *unlocked* */
491  }
492 
493  (void) SC_ATOMIC_ADD(ippair_counter, 1);
494  SCMutexLock(&h->m);
495  return h;
496 }
497 
498 static void IPPairInit(IPPair *h, Address *a, Address *b)
499 {
500  COPY_ADDRESS(a, &h->a[0]);
501  COPY_ADDRESS(b, &h->a[1]);
502  (void) IPPairIncrUsecnt(h);
503 }
504 
506 {
507  (void) IPPairDecrUsecnt(h);
508  SCMutexUnlock(&h->m);
509 }
510 
512 {
513  SCMutexUnlock(&h->m);
514 }
515 
516 /* IPPairGetIPPairFromHash
517  *
518  * Hash retrieval function for ippairs. Looks up the hash bucket containing the
519  * ippair pointer. Then compares the packet with the found ippair to see if it is
520  * the ippair we need. If it isn't, walk the list until the right ippair is found.
521  *
522  * returns a *LOCKED* ippair or NULL
523  */
525 {
526  IPPair *h = NULL;
527 
528  /* get the key to our bucket */
529  uint32_t key = IPPairGetKey(a, b);
530  /* get our hash bucket and lock it */
531  IPPairHashRow *hb = &ippair_hash[key];
532  HRLOCK_LOCK(hb);
533 
534  /* see if the bucket already has a ippair */
535  if (hb->head == NULL) {
536  h = IPPairGetNew(a,b);
537  if (h == NULL) {
538  HRLOCK_UNLOCK(hb);
539  return NULL;
540  }
541 
542  /* ippair is locked */
543  hb->head = h;
544  hb->tail = h;
545 
546  /* got one, now lock, initialize and return */
547  IPPairInit(h,a,b);
548 
549  HRLOCK_UNLOCK(hb);
550  return h;
551  }
552 
553  /* ok, we have a ippair in the bucket. Let's find out if it is our ippair */
554  h = hb->head;
555 
556  /* see if this is the ippair we are looking for */
557  if (IPPairCompare(h, a, b) == 0) {
558  IPPair *ph = NULL; /* previous ippair */
559 
560  while (h) {
561  ph = h;
562  h = h->hnext;
563 
564  if (h == NULL) {
565  h = ph->hnext = IPPairGetNew(a,b);
566  if (h == NULL) {
567  HRLOCK_UNLOCK(hb);
568  return NULL;
569  }
570  hb->tail = h;
571 
572  /* ippair is locked */
573 
574  h->hprev = ph;
575 
576  /* initialize and return */
577  IPPairInit(h,a,b);
578 
579  HRLOCK_UNLOCK(hb);
580  return h;
581  }
582 
583  if (IPPairCompare(h, a, b) != 0) {
584  /* we found our ippair, lets put it on top of the
585  * hash list -- this rewards active ippairs */
586  if (h->hnext) {
587  h->hnext->hprev = h->hprev;
588  }
589  if (h->hprev) {
590  h->hprev->hnext = h->hnext;
591  }
592  if (h == hb->tail) {
593  hb->tail = h->hprev;
594  }
595 
596  h->hnext = hb->head;
597  h->hprev = NULL;
598  hb->head->hprev = h;
599  hb->head = h;
600 
601  /* found our ippair, lock & return */
602  SCMutexLock(&h->m);
603  (void) IPPairIncrUsecnt(h);
604  HRLOCK_UNLOCK(hb);
605  return h;
606  }
607  }
608  }
609 
610  /* lock & return */
611  SCMutexLock(&h->m);
612  (void) IPPairIncrUsecnt(h);
613  HRLOCK_UNLOCK(hb);
614  return h;
615 }
616 
617 /** \brief look up a ippair in the hash
618  *
619  * \param a address to look up
620  *
621  * \retval h *LOCKED* ippair or NULL
622  */
624 {
625  IPPair *h = NULL;
626 
627  /* get the key to our bucket */
628  uint32_t key = IPPairGetKey(a, b);
629  /* get our hash bucket and lock it */
630  IPPairHashRow *hb = &ippair_hash[key];
631  HRLOCK_LOCK(hb);
632 
633  /* see if the bucket already has a ippair */
634  if (hb->head == NULL) {
635  HRLOCK_UNLOCK(hb);
636  return h;
637  }
638 
639  /* ok, we have a ippair in the bucket. Let's find out if it is our ippair */
640  h = hb->head;
641 
642  /* see if this is the ippair we are looking for */
643  if (IPPairCompare(h, a, b) == 0) {
644  while (h) {
645  h = h->hnext;
646 
647  if (h == NULL) {
648  HRLOCK_UNLOCK(hb);
649  return h;
650  }
651 
652  if (IPPairCompare(h, a, b) != 0) {
653  /* we found our ippair, lets put it on top of the
654  * hash list -- this rewards active ippairs */
655  if (h->hnext) {
656  h->hnext->hprev = h->hprev;
657  }
658  if (h->hprev) {
659  h->hprev->hnext = h->hnext;
660  }
661  if (h == hb->tail) {
662  hb->tail = h->hprev;
663  }
664 
665  h->hnext = hb->head;
666  h->hprev = NULL;
667  hb->head->hprev = h;
668  hb->head = h;
669 
670  /* found our ippair, lock & return */
671  SCMutexLock(&h->m);
672  (void) IPPairIncrUsecnt(h);
673  HRLOCK_UNLOCK(hb);
674  return h;
675  }
676  }
677  }
678 
679  /* lock & return */
680  SCMutexLock(&h->m);
681  (void) IPPairIncrUsecnt(h);
682  HRLOCK_UNLOCK(hb);
683  return h;
684 }
685 
686 /** \internal
687  * \brief Get a ippair from the hash directly.
688  *
689  * Called in conditions where the spare queue is empty and memcap is reached.
690  *
691  * Walks the hash until a ippair can be freed. "ippair_prune_idx" atomic int makes
692  * sure we don't start at the top each time since that would clear the top of
693  * the hash leading to longer and longer search times under high pressure (observed).
694  *
695  * \retval h ippair or NULL
696  */
697 static IPPair *IPPairGetUsedIPPair(void)
698 {
699  uint32_t idx = SC_ATOMIC_GET(ippair_prune_idx) % ippair_config.hash_size;
700  uint32_t cnt = ippair_config.hash_size;
701 
702  while (cnt--) {
703  if (++idx >= ippair_config.hash_size)
704  idx = 0;
705 
706  IPPairHashRow *hb = &ippair_hash[idx];
707 
708  if (HRLOCK_TRYLOCK(hb) != 0)
709  continue;
710 
711  IPPair *h = hb->tail;
712  if (h == NULL) {
713  HRLOCK_UNLOCK(hb);
714  continue;
715  }
716 
717  if (SCMutexTrylock(&h->m) != 0) {
718  HRLOCK_UNLOCK(hb);
719  continue;
720  }
721 
722  /** never prune a ippair that is used by a packets
723  * we are currently processing in one of the threads */
724  if (SC_ATOMIC_GET(h->use_cnt) > 0) {
725  HRLOCK_UNLOCK(hb);
726  SCMutexUnlock(&h->m);
727  continue;
728  }
729 
730  /* remove from the hash */
731  if (h->hprev != NULL)
732  h->hprev->hnext = h->hnext;
733  if (h->hnext != NULL)
734  h->hnext->hprev = h->hprev;
735  if (hb->head == h)
736  hb->head = h->hnext;
737  if (hb->tail == h)
738  hb->tail = h->hprev;
739 
740  h->hnext = NULL;
741  h->hprev = NULL;
742  HRLOCK_UNLOCK(hb);
743 
744  IPPairClearMemory (h);
745 
746  SCMutexUnlock(&h->m);
747 
748  (void) SC_ATOMIC_ADD(ippair_prune_idx, (ippair_config.hash_size - cnt));
749  return h;
750  }
751 
752  return NULL;
753 }
754 
756 {
758 }
HRLOCK_DESTROY
#define HRLOCK_DESTROY(fb)
Definition: host.h:50
util-byte.h
ippair.h
IPPairQueue_::len
uint32_t len
Definition: ippair-queue.h:45
IPPairInitConfig
void IPPairInitConfig(bool quiet)
initialize the configuration
Definition: ippair.c:162
hashword
uint32_t hashword(const uint32_t *k, size_t length, uint32_t initval)
Definition: util-hash-lookup3.c:172
IPPAIR_DEFAULT_HASHSIZE
#define IPPAIR_DEFAULT_HASHSIZE
Definition: ippair.c:156
IPPair_::a
Address a[2]
Definition: ippair.h:63
SC_ATOMIC_INIT
#define SC_ATOMIC_INIT(name)
wrapper for initializing an atomic variable.
Definition: util-atomic.h:314
SC_ATOMIC_DECLARE
SC_ATOMIC_DECLARE(uint64_t, ippair_memuse)
IPPairRelease
void IPPairRelease(IPPair *h)
Definition: ippair.c:505
CLS
#define CLS
Definition: suricata-common.h:77
IPPAIR_DEFAULT_PREALLOC
#define IPPAIR_DEFAULT_PREALLOC
Definition: ippair.c:158
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
SC_ATOMIC_SET
#define SC_ATOMIC_SET(name, val)
Set the value for the atomic variable.
Definition: util-atomic.h:386
IPPairIncrUsecnt
#define IPPairIncrUsecnt(h)
Definition: ippair.h:108
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:282
ParseSizeStringU64
int ParseSizeStringU64(const char *size, uint64_t *res)
Definition: util-misc.c:191
IPPairQueueInit
IPPairQueue * IPPairQueueInit(IPPairQueue *q)
Definition: ippair-queue.c:33
IPPairRegisterUnittests
void IPPairRegisterUnittests(void)
Definition: ippair.c:755
SC_ATOMIC_ADD
#define SC_ATOMIC_ADD(name, val)
add a value to our atomic variable
Definition: util-atomic.h:332
IPPAIR_CHECK_MEMCAP
#define IPPAIR_CHECK_MEMCAP(size)
check if a memory alloc would fit in the memcap
Definition: ippair.h:105
IPPairDecrUsecnt
#define IPPairDecrUsecnt(h)
Definition: ippair.h:110
SCMutexLock
#define SCMutexLock(mut)
Definition: threads-debug.h:117
MIN
#define MIN(x, y)
Definition: suricata-common.h:416
Address_
Definition: decode.h:113
IPPairDequeue
IPPair * IPPairDequeue(IPPairQueue *q)
remove a ippair from the queue
Definition: ippair-queue.c:102
RandomGet
long int RandomGet(void)
Definition: util-random.c:130
IPPairAlloc
IPPair * IPPairAlloc(void)
Definition: ippair.c:104
p
Packet * p
Definition: fuzz_iprep.c:21
detect-tag.h
IPPairMoveToSpare
void IPPairMoveToSpare(IPPair *h)
Definition: ippair.c:98
MAX
#define MAX(x, y)
Definition: suricata-common.h:420
IPPair_::m
SCMutex m
Definition: ippair.h:60
HRLOCK_LOCK
#define HRLOCK_LOCK(fb)
Definition: host.h:51
IPPairFree
void IPPairFree(IPPair *h)
Definition: ippair.c:124
IPPairShutdown
void IPPairShutdown(void)
shutdown the flow engine
Definition: ippair.c:290
IPPairConfig_::prealloc
uint32_t prealloc
Definition: ippair.h:95
HRLOCK_UNLOCK
#define HRLOCK_UNLOCK(fb)
Definition: host.h:53
util-debug.h
ippair_config
IPPairConfig ippair_config
Definition: ippair.c:52
IPPairCleanup
void IPPairCleanup(void)
Cleanup the ippair engine.
Definition: ippair.c:327
SCMutexUnlock
#define SCMutexUnlock(mut)
Definition: threads-debug.h:120
SCRegisterIPPairStorageTests
void SCRegisterIPPairStorageTests(void)
Definition: ippair-storage.c:218
IPPairGetMemcap
uint64_t IPPairGetMemcap(void)
Return memcap value.
Definition: ippair.c:81
SCConfGetNonNull
int SCConfGetNonNull(const char *name, const char **vptr)
Retrieve the non-null value of a configuration node.
Definition: conf.c:381
StringParseUint32
int StringParseUint32(uint32_t *res, int base, size_t len, const char *str)
Definition: util-byte.c:269
IPPairGetIPPairFromHash
IPPair * IPPairGetIPPairFromHash(Address *a, Address *b)
Definition: ippair.c:524
IPPairEnqueue
void IPPairEnqueue(IPPairQueue *q, IPPair *h)
add a ippair to a queue
Definition: ippair-queue.c:69
IPPairQueue_
Definition: ippair-queue.h:42
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:325
IPPAIR_DEFAULT_MEMCAP
#define IPPAIR_DEFAULT_MEMCAP
Definition: ippair.c:157
detect-engine-tag.h
IPPairUnlock
void IPPairUnlock(IPPair *h)
Definition: ippair.c:511
SC_ATOMIC_SUB
#define SC_ATOMIC_SUB(name, val)
sub a value from our atomic variable
Definition: util-atomic.h:341
SCFreeAligned
#define SCFreeAligned(p)
Definition: util-mem.h:77
conf.h
HRLOCK_INIT
#define HRLOCK_INIT(fb)
Definition: host.h:49
SCMutexInit
#define SCMutexInit(mut, mutattrs)
Definition: threads-debug.h:116
WarnInvalidConfEntry
#define WarnInvalidConfEntry(param_name, format, value)
Generic API that can be used by all to log an invalid conf entry.
Definition: util-misc.h:35
cnt
uint32_t cnt
Definition: tmqh-packetpool.h:7
CMP_ADDR
#define CMP_ADDR(a1, a2)
Definition: decode.h:223
suricata-common.h
IPPair_
Definition: ippair.h:58
IPPairConfig_::hash_size
uint32_t hash_size
Definition: ippair.h:94
SCMallocAligned
#define SCMallocAligned(size, align)
Definition: util-mem.h:68
SCLogPerf
#define SCLogPerf(...)
Definition: util-debug.h:241
IPPairGetMemuse
uint64_t IPPairGetMemuse(void)
Return memuse value.
Definition: ippair.c:92
IPPairClearMemory
void IPPairClearMemory(IPPair *h)
Definition: ippair.c:150
FatalError
#define FatalError(...)
Definition: util-debug.h:517
util-hash-lookup3.h
IPPair_::hprev
struct IPPair_ * hprev
Definition: ippair.h:70
util-validate.h
SCLogConfig
struct SCLogConfig_ SCLogConfig
Holds the config state used by the logging api.
IPPairConfig_
Definition: ippair.h:91
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:274
IPPair_::hnext
struct IPPair_ * hnext
Definition: ippair.h:69
SCFree
#define SCFree(p)
Definition: util-mem.h:61
ippair-queue.h
util-random.h
HRLOCK_TRYLOCK
#define HRLOCK_TRYLOCK(fb)
Definition: host.h:52
IPPairQueueDestroy
void IPPairQueueDestroy(IPPairQueue *q)
Destroy a ippair queue.
Definition: ippair-queue.c:58
IPPairSetMemcap
int IPPairSetMemcap(uint64_t size)
Update memcap value.
Definition: ippair.c:66
Address_::family
char family
Definition: decode.h:114
IPPairLookupIPPairFromHash
IPPair * IPPairLookupIPPairFromHash(Address *a, Address *b)
look up a ippair in the hash
Definition: ippair.c:623
IPPair
struct IPPair_ IPPair
SCIPPairStorageSize
unsigned int SCIPPairStorageSize(void)
Definition: ippair-storage.c:30
SC_ATOMIC_GET
#define SC_ATOMIC_GET(name)
Get the value from the atomic variable.
Definition: util-atomic.h:375
util-misc.h
COPY_ADDRESS
#define COPY_ADDRESS(a, b)
Definition: decode.h:128
IPPairConfig_::hash_rand
uint32_t hash_rand
Definition: ippair.h:93
ippair-storage.h
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
ippair_hash
IPPairHashRow * ippair_hash
Definition: ippair.c:49
SCMutexDestroy
#define SCMutexDestroy
Definition: threads-debug.h:121
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:109
IPPairPrintStats
void IPPairPrintStats(void)
print some ippair stats
Definition: ippair.c:278
SCMutexTrylock
#define SCMutexTrylock(mut)
Definition: threads-debug.h:118
detect-engine-threshold.h
SCIPPairFreeStorage
void SCIPPairFreeStorage(IPPair *h)
Definition: ippair-storage.c:45