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