/** * \brief Get a new host * * Get a new host. We're checking memcap first and will try to make room * if the memcap is reached. * * \retval h *LOCKED* host on succes, NULL on error. */ static Host *HostGetNew(Address *a) { Host *h = NULL; /* get a host from the spare queue */ h = HostDequeue(&host_spare_q); if (h == NULL) { /* If we reached the max memcap, we get a used host */ if (!(HOST_CHECK_MEMCAP(sizeof(Host)))) { /* declare state of emergency */ //if (!(SC_ATOMIC_GET(host_flags) & HOST_EMERGENCY)) { // SC_ATOMIC_OR(host_flags, HOST_EMERGENCY); /* under high load, waking up the flow mgr each time leads * to high cpu usage. Flows are not timed out much faster if * we check a 1000 times a second. */ // FlowWakeupFlowManagerThread(); //} h = HostGetUsedHost(); if (h == NULL) { return NULL; } /* freed a host, but it's unlocked */ } else { /* now see if we can alloc a new host */ h = HostNew(a); if (h == NULL) { return NULL; } /* host is initialized but *unlocked* */ } } else { /* host has been recycled before it went into the spare queue */ /* host is initialized (recylced) but *unlocked* */ } (void) SC_ATOMIC_ADD(host_counter, 1); SCMutexLock(&h->m); return h; }
Host *HostAlloc(void) { if (!(HOST_CHECK_MEMCAP(sizeof(Host)))) { return NULL; } (void) SC_ATOMIC_ADD(host_memuse, sizeof(Host)); Host *h = SCMalloc(sizeof(Host)); if (unlikely(h == NULL)) goto error; memset(h, 0x00, sizeof(Host)); SCMutexInit(&h->m, NULL); SC_ATOMIC_INIT(h->use_cnt); return h; error: return NULL; }
/** \brief initialize the configuration * \warning Not thread safe */ void HostInitConfig(char quiet) { SCLogDebug("initializing host engine..."); memset(&host_config, 0, sizeof(host_config)); //SC_ATOMIC_INIT(flow_flags); SC_ATOMIC_INIT(host_counter); SC_ATOMIC_INIT(host_memuse); SC_ATOMIC_INIT(host_prune_idx); HostQueueInit(&host_spare_q); unsigned int seed = RandomTimePreseed(); /* set defaults */ host_config.hash_rand = (int)( HOST_DEFAULT_HASHSIZE * (rand_r(&seed) / RAND_MAX + 1.0)); host_config.hash_size = HOST_DEFAULT_HASHSIZE; host_config.memcap = HOST_DEFAULT_MEMCAP; host_config.prealloc = HOST_DEFAULT_PREALLOC; /* Check if we have memcap and hash_size defined at config */ char *conf_val; uint32_t configval = 0; /** set config values for memcap, prealloc and hash_size */ if ((ConfGet("host.memcap", &conf_val)) == 1) { if (ParseSizeStringU64(conf_val, &host_config.memcap) < 0) { SCLogError(SC_ERR_SIZE_PARSE, "Error parsing host.memcap " "from conf file - %s. Killing engine", conf_val); exit(EXIT_FAILURE); } } if ((ConfGet("host.hash-size", &conf_val)) == 1) { if (ByteExtractStringUint32(&configval, 10, strlen(conf_val), conf_val) > 0) { host_config.hash_size = configval; } } if ((ConfGet("host.prealloc", &conf_val)) == 1) { if (ByteExtractStringUint32(&configval, 10, strlen(conf_val), conf_val) > 0) { host_config.prealloc = configval; } } SCLogDebug("Host config from suricata.yaml: memcap: %"PRIu64", hash-size: " "%"PRIu32", prealloc: %"PRIu32, host_config.memcap, host_config.hash_size, host_config.prealloc); /* alloc hash memory */ uint64_t hash_size = host_config.hash_size * sizeof(HostHashRow); if (!(HOST_CHECK_MEMCAP(hash_size))) { SCLogError(SC_ERR_HOST_INIT, "allocating host hash failed: " "max host memcap is smaller than projected hash size. " "Memcap: %"PRIu64", Hash table size %"PRIu64". Calculate " "total hash size by multiplying \"host.hash-size\" with %"PRIuMAX", " "which is the hash bucket size.", host_config.memcap, hash_size, (uintmax_t)sizeof(HostHashRow)); exit(EXIT_FAILURE); } host_hash = SCCalloc(host_config.hash_size, sizeof(HostHashRow)); if (unlikely(host_hash == NULL)) { SCLogError(SC_ERR_FATAL, "Fatal error encountered in HostInitConfig. Exiting..."); exit(EXIT_FAILURE); } memset(host_hash, 0, host_config.hash_size * sizeof(HostHashRow)); uint32_t i = 0; for (i = 0; i < host_config.hash_size; i++) { HRLOCK_INIT(&host_hash[i]); } (void) SC_ATOMIC_ADD(host_memuse, (host_config.hash_size * sizeof(HostHashRow))); if (quiet == FALSE) { SCLogInfo("allocated %llu bytes of memory for the host hash... " "%" PRIu32 " buckets of size %" PRIuMAX "", SC_ATOMIC_GET(host_memuse), host_config.hash_size, (uintmax_t)sizeof(HostHashRow)); } /* pre allocate hosts */ for (i = 0; i < host_config.prealloc; i++) { if (!(HOST_CHECK_MEMCAP(sizeof(Host)))) { SCLogError(SC_ERR_HOST_INIT, "preallocating hosts failed: " "max host memcap reached. Memcap %"PRIu64", " "Memuse %"PRIu64".", host_config.memcap, ((uint64_t)SC_ATOMIC_GET(host_memuse) + (uint64_t)sizeof(Host))); exit(EXIT_FAILURE); } Host *h = HostAlloc(); if (h == NULL) { SCLogError(SC_ERR_HOST_INIT, "preallocating host failed: %s", strerror(errno)); exit(EXIT_FAILURE); } HostEnqueue(&host_spare_q,h); } if (quiet == FALSE) { SCLogInfo("preallocated %" PRIu32 " hosts of size %" PRIuMAX "", host_spare_q.len, (uintmax_t)sizeof(Host)); SCLogInfo("host memory usage: %llu bytes, maximum: %"PRIu64, SC_ATOMIC_GET(host_memuse), host_config.memcap); } return; }