/** * \brief time out hosts from the hash * * \param ts timestamp * * \retval cnt number of timed out host */ uint32_t HostTimeoutHash(struct timeval *ts) { uint32_t idx = 0; uint32_t cnt = 0; for (idx = 0; idx < host_config.hash_size; idx++) { HostHashRow *hb = &host_hash[idx]; if (hb == NULL) continue; if (HRLOCK_TRYLOCK(hb) != 0) continue; /* host hash bucket is now locked */ if (hb->tail == NULL) { HRLOCK_UNLOCK(hb); continue; } /* we have a host, or more than one */ cnt += HostHashRowTimeout(hb, hb->tail, ts); HRLOCK_UNLOCK(hb); } return cnt; }
/** \internal * \brief Get a host from the hash directly. * * Called in conditions where the spare queue is empty and memcap is reached. * * Walks the hash until a host can be freed. "host_prune_idx" atomic int makes * sure we don't start at the top each time since that would clear the top of * the hash leading to longer and longer search times under high pressure (observed). * * \retval h host or NULL */ static Host *HostGetUsedHost(void) { uint32_t idx = SC_ATOMIC_GET(host_prune_idx) % host_config.hash_size; uint32_t cnt = host_config.hash_size; while (cnt--) { if (++idx >= host_config.hash_size) idx = 0; HostHashRow *hb = &host_hash[idx]; if (hb == NULL) continue; if (HRLOCK_TRYLOCK(hb) != 0) continue; Host *h = hb->tail; if (h == NULL) { HRLOCK_UNLOCK(hb); continue; } if (SCMutexTrylock(&h->m) != 0) { HRLOCK_UNLOCK(hb); continue; } /** never prune a host that is used by a packets * we are currently processing in one of the threads */ if (SC_ATOMIC_GET(h->use_cnt) > 0) { HRLOCK_UNLOCK(hb); SCMutexUnlock(&h->m); continue; } /* remove from the hash */ if (h->hprev != NULL) h->hprev->hnext = h->hnext; if (h->hnext != NULL) h->hnext->hprev = h->hprev; if (hb->head == h) hb->head = h->hnext; if (hb->tail == h) hb->tail = h->hprev; h->hnext = NULL; h->hprev = NULL; HRLOCK_UNLOCK(hb); HostClearMemory (h); SCMutexUnlock(&h->m); (void) SC_ATOMIC_ADD(host_prune_idx, (host_config.hash_size - cnt)); return h; } return NULL; }
/** \brief Cleanup the host engine * * Cleanup the host engine from tag and threshold. * */ void HostCleanup(void) { Host *h; uint32_t u; if (host_hash != NULL) { for (u = 0; u < host_config.hash_size; u++) { h = host_hash[u].head; HostHashRow *hb = &host_hash[u]; HRLOCK_LOCK(hb); while (h) { if ((SC_ATOMIC_GET(h->use_cnt) > 0) && (h->iprep != NULL)) { /* iprep is attached to host only clear tag and threshold */ if (h->tag != NULL) { DetectTagDataListFree(h->tag); h->tag = NULL; } if (h->threshold != NULL) { ThresholdListFree(h->threshold); h->threshold = NULL; } h = h->hnext; } else { Host *n = h->hnext; /* remove from the hash */ if (h->hprev != NULL) h->hprev->hnext = h->hnext; if (h->hnext != NULL) h->hnext->hprev = h->hprev; if (hb->head == h) hb->head = h->hnext; if (hb->tail == h) hb->tail = h->hprev; h->hnext = NULL; h->hprev = NULL; HostClearMemory(h); HostMoveToSpare(h); h = n; } } HRLOCK_UNLOCK(hb); } } return; }
/** \brief Cleanup the ippair engine * * Cleanup the ippair engine from tag and threshold. * */ void IPPairCleanup(void) { IPPair *h; uint32_t u; if (ippair_hash != NULL) { for (u = 0; u < ippair_config.hash_size; u++) { h = ippair_hash[u].head; IPPairHashRow *hb = &ippair_hash[u]; HRLOCK_LOCK(hb); while (h) { if ((SC_ATOMIC_GET(h->use_cnt) > 0)) { /* iprep is attached to ippair only clear local storage */ IPPairFreeStorage(h); h = h->hnext; } else { IPPair *n = h->hnext; /* remove from the hash */ if (h->hprev != NULL) h->hprev->hnext = h->hnext; if (h->hnext != NULL) h->hnext->hprev = h->hprev; if (hb->head == h) hb->head = h->hnext; if (hb->tail == h) hb->tail = h->hprev; h->hnext = NULL; h->hprev = NULL; IPPairClearMemory(h); IPPairMoveToSpare(h); h = n; } } HRLOCK_UNLOCK(hb); } } return; }
/** \brief look up a host in the hash * * \param a address to look up * * \retval h *LOCKED* host or NULL */ Host *HostLookupHostFromHash (Address *a) { Host *h = NULL; /* get the key to our bucket */ uint32_t key = HostGetKey(a); /* get our hash bucket and lock it */ HostHashRow *hb = &host_hash[key]; HRLOCK_LOCK(hb); /* see if the bucket already has a host */ if (hb->head == NULL) { HRLOCK_UNLOCK(hb); return h; } /* ok, we have a host in the bucket. Let's find out if it is our host */ h = hb->head; /* see if this is the host we are looking for */ if (HostCompare(h, a) == 0) { while (h) { h = h->hnext; if (h == NULL) { HRLOCK_UNLOCK(hb); return h; } if (HostCompare(h, a) != 0) { /* we found our host, lets put it on top of the * hash list -- this rewards active hosts */ if (h->hnext) { h->hnext->hprev = h->hprev; } if (h->hprev) { h->hprev->hnext = h->hnext; } if (h == hb->tail) { hb->tail = h->hprev; } h->hnext = hb->head; h->hprev = NULL; hb->head->hprev = h; hb->head = h; /* found our host, lock & return */ SCMutexLock(&h->m); (void) HostIncrUsecnt(h); HRLOCK_UNLOCK(hb); return h; } } } /* lock & return */ SCMutexLock(&h->m); (void) HostIncrUsecnt(h); HRLOCK_UNLOCK(hb); return h; }
/** \brief look up a ippair in the hash * * \param a address to look up * * \retval h *LOCKED* ippair or NULL */ IPPair *IPPairLookupIPPairFromHash (Address *a, Address *b) { IPPair *h = NULL; /* get the key to our bucket */ uint32_t key = IPPairGetKey(a, b); /* get our hash bucket and lock it */ IPPairHashRow *hb = &ippair_hash[key]; HRLOCK_LOCK(hb); /* see if the bucket already has a ippair */ if (hb->head == NULL) { HRLOCK_UNLOCK(hb); return h; } /* ok, we have a ippair in the bucket. Let's find out if it is our ippair */ h = hb->head; /* see if this is the ippair we are looking for */ if (IPPairCompare(h, a, b) == 0) { while (h) { h = h->hnext; if (h == NULL) { HRLOCK_UNLOCK(hb); return h; } if (IPPairCompare(h, a, b) != 0) { /* we found our ippair, lets put it on top of the * hash list -- this rewards active ippairs */ if (h->hnext) { h->hnext->hprev = h->hprev; } if (h->hprev) { h->hprev->hnext = h->hnext; } if (h == hb->tail) { hb->tail = h->hprev; } h->hnext = hb->head; h->hprev = NULL; hb->head->hprev = h; hb->head = h; /* found our ippair, lock & return */ SCMutexLock(&h->m); (void) IPPairIncrUsecnt(h); HRLOCK_UNLOCK(hb); return h; } } } /* lock & return */ SCMutexLock(&h->m); (void) IPPairIncrUsecnt(h); HRLOCK_UNLOCK(hb); return h; }