diff --git a/include/ArpStatsMatrixElement.h b/include/ArpStatsMatrixElement.h index e68c74ce43..712981f2b1 100644 --- a/include/ArpStatsMatrixElement.h +++ b/include/ArpStatsMatrixElement.h @@ -55,7 +55,6 @@ class ArpStatsMatrixElement : public GenericHashEntry { bool equal(const u_int8_t _src_mac[6], const u_int32_t _src_ip, const u_int32_t _dst_ip, bool * const src2dst); - bool is_hash_entry_state_idle_transition_ready(); u_int32_t key(); void lua(lua_State* vm); void print(char *msg) const; diff --git a/include/AutonomousSystem.h b/include/AutonomousSystem.h index 3c5851ff54..d6c70aa1ed 100644 --- a/include/AutonomousSystem.h +++ b/include/AutonomousSystem.h @@ -62,7 +62,6 @@ class AutonomousSystem : public GenericHashEntry, public GenericTrafficElement, } void updateRoundTripTime(u_int32_t rtt_msecs); - bool is_hash_entry_state_idle_transition_ready(); void lua(lua_State* vm, DetailsLevel details_level, bool asListElement); inline void deserialize(json_object *obj) { diff --git a/include/Country.h b/include/Country.h index 6d799823e4..0f5cbaa7ea 100644 --- a/include/Country.h +++ b/include/Country.h @@ -62,7 +62,6 @@ class Country : public GenericHashEntry, public GenericTrafficElement, public Se dirstats.incInner(t, num_pkts, num_bytes, broadcast); } - bool is_hash_entry_state_idle_transition_ready(); void lua(lua_State* vm, DetailsLevel details_level, bool asListElement); void deserialize(json_object *obj); diff --git a/include/Flow.h b/include/Flow.h index ba51cbb310..efa6ec3c80 100644 --- a/include/Flow.h +++ b/include/Flow.h @@ -418,7 +418,7 @@ class Flow : public GenericHashEntry { /* Methods to handle the flow in-memory lifecycle */ void set_hash_entry_state_idle(); - bool is_hash_entry_state_idle_transition_ready(); + bool is_hash_entry_state_idle_transition_ready() const; virtual void set_to_purge(time_t t); bool is_acknowledged_to_purge() const; void set_acknowledge_to_purge(); diff --git a/include/GenericHashEntry.h b/include/GenericHashEntry.h index ba551d2659..04b74d342e 100644 --- a/include/GenericHashEntry.h +++ b/include/GenericHashEntry.h @@ -190,25 +190,29 @@ class GenericHashEntry { hash_entry_state = hash_entry_state_allocated; }; -/** + /** * @brief Determine whether this entry is ready for the transition to the idle state * */ - virtual bool is_hash_entry_state_idle_transition_ready() = 0; + virtual bool is_hash_entry_state_idle_transition_ready() const; + /** + * @brief Determine whether it is possible to perform the idle transition for this entry + * + */ + bool is_hash_entry_state_idle_transition_possible() const; HashEntryState get_state() const; void updateSeen(); void updateSeen(time_t _last_seen); bool equal(GenericHashEntry *b) { return((this == b) ? true : false); }; inline NetworkInterface* getInterface() { return(iface); }; bool idle() const; - bool walkable() const; virtual void housekeep(time_t t) { return; }; inline u_int get_duration() { return((u_int)(1+last_seen-first_seen)); }; virtual u_int32_t key() { return(0); }; virtual char* get_string_key(char *buf, u_int buf_len) const { buf[0] = '\0'; return(buf); }; void incUses() { num_uses++; } void decUses() { num_uses--; } - u_int16_t getUses() { return num_uses; } + u_int16_t getUses() const { return num_uses; } virtual void deserialize(json_object *obj); virtual void getJSONObject(json_object *obj, DetailsLevel details_level); diff --git a/include/HTTPstats.h b/include/HTTPstats.h index 7b4bc2a771..995d4d5da8 100644 --- a/include/HTTPstats.h +++ b/include/HTTPstats.h @@ -99,7 +99,7 @@ class HTTPstats { inline u_int16_t makeRate(u_int16_t v, float tdiff) { return((u_int16_t)((((float)v* 1000)/tdiff) + .5f)); } public: - HTTPstats(HostHash *_h); + HTTPstats(NetworkInterface *_iface); ~HTTPstats(); inline u_int32_t get_num_virtual_hosts() { return(virtualHosts ? virtualHosts->getNumEntries() : 0); } diff --git a/include/Host.h b/include/Host.h index c141bda39b..0622503e71 100644 --- a/include/Host.h +++ b/include/Host.h @@ -216,7 +216,7 @@ class Host : public GenericHashEntry, public AlertableEntity { char* get_hostkey(char *buf, u_int buf_len, bool force_vlan=false); char* get_tskey(char *buf, size_t bufsize); - bool is_hash_entry_state_idle_transition_ready(); + bool is_hash_entry_state_idle_transition_ready() const; virtual void incICMP(u_int8_t icmp_type, u_int8_t icmp_code, bool sent, Host *peer) {}; virtual void lua(lua_State* vm, AddressTree * ptree, bool host_details, diff --git a/include/Mac.h b/include/Mac.h index ab087ff049..f31f6a9afe 100644 --- a/include/Mac.h +++ b/include/Mac.h @@ -113,7 +113,6 @@ class Mac : public GenericHashEntry, public SerializableElement { inline DeviceType getDeviceType() { return (device_type); } char * getDHCPName(char * const buf, ssize_t buf_size); void set_hash_entry_state_idle(); - bool is_hash_entry_state_idle_transition_ready(); void lua(lua_State* vm, bool show_details, bool asListElement); virtual char* get_string_key(char *buf, u_int buf_len) const { return(Utils::formatMac(mac, buf, buf_len)); }; inline int16_t findAddress(AddressTree *ptree) { return ptree ? ptree->findMac(mac) : -1; }; diff --git a/src/ArpStatsMatrixElement.cpp b/src/ArpStatsMatrixElement.cpp index 594bea16c6..48fa0365f5 100644 --- a/src/ArpStatsMatrixElement.cpp +++ b/src/ArpStatsMatrixElement.cpp @@ -44,19 +44,6 @@ ArpStatsMatrixElement::~ArpStatsMatrixElement() { /* *************************************** */ -bool ArpStatsMatrixElement::is_hash_entry_state_idle_transition_ready() { - bool rc; - - if((num_uses > 0) || (!iface->is_purge_idle_interface())) - return(false); - - rc = isIdle(MAX_LOCAL_HOST_IDLE); - - return(rc); -} - -/* *************************************** */ - bool ArpStatsMatrixElement::equal(const u_int8_t _src_mac[6], const u_int32_t _src_ip, const u_int32_t _dst_ip, bool * const src2dst) { diff --git a/src/AutonomousSystem.cpp b/src/AutonomousSystem.cpp index 549cb898ab..5d9dbab96e 100644 --- a/src/AutonomousSystem.cpp +++ b/src/AutonomousSystem.cpp @@ -74,26 +74,6 @@ void AutonomousSystem::updateRoundTripTime(u_int32_t rtt_msecs) { /* *************************************** */ -bool AutonomousSystem::is_hash_entry_state_idle_transition_ready() { - bool rc; - - if((num_uses > 0) || (!iface->is_purge_idle_interface())) - return(false); - - rc = isIdle(MAX_LOCAL_HOST_IDLE); - -#ifdef AS_DEBUG - ntop->getTrace()->traceEvent(TRACE_NORMAL, "Autonomous System %u is idle [uses %u][%s][last: %u][diff: %d]", - asn, num_uses, - rc ? "Idle" : "Not Idle", - last_seen, iface->getTimeLastPktRcvd() - (last_seen+MAX_LOCAL_HOST_IDLE)); -#endif - - return(rc); -} - -/* *************************************** */ - void AutonomousSystem::lua(lua_State* vm, DetailsLevel details_level, bool asListElement) { lua_newtable(vm); diff --git a/src/AutonomousSystemHash.cpp b/src/AutonomousSystemHash.cpp index 923767f98d..a32d3afc74 100644 --- a/src/AutonomousSystemHash.cpp +++ b/src/AutonomousSystemHash.cpp @@ -50,7 +50,7 @@ AutonomousSystem* AutonomousSystemHash::get(IpAddress *ipa, bool is_inline_call, head = (AutonomousSystem*)table[hash]; while(head != NULL) { - if((!head->walkable()) && head->equal(asn)) + if(!head->idle() && head->equal(asn)) break; else head = (AutonomousSystem*)head->next(); diff --git a/src/Country.cpp b/src/Country.cpp index f6cf0344bd..426401b0b5 100644 --- a/src/Country.cpp +++ b/src/Country.cpp @@ -47,26 +47,6 @@ Country::~Country() { /* *************************************** */ -bool Country::is_hash_entry_state_idle_transition_ready() { - bool rc; - - if((num_uses > 0) || (!iface->is_purge_idle_interface())) - return(false); - - rc = isIdle(MAX_LOCAL_HOST_IDLE); - -#ifdef COUNTRY_DEBUG - ntop->getTrace()->traceEvent(TRACE_NORMAL, "Country %s is idle [uses %u][%s][last: %u][diff: %d]", - country_name, num_uses, - rc ? "Idle" : "Not Idle", - last_seen, iface->getTimeLastPktRcvd() - (last_seen+MAX_LOCAL_HOST_IDLE)); -#endif - - return(rc); -} - -/* *************************************** */ - void Country::lua(lua_State* vm, DetailsLevel details_level, bool asListElement) { lua_newtable(vm); diff --git a/src/Flow.cpp b/src/Flow.cpp index ea7e214607..800c2638e1 100644 --- a/src/Flow.cpp +++ b/src/Flow.cpp @@ -2007,15 +2007,12 @@ void Flow::set_hash_entry_state_idle() { /* *************************************** */ -bool Flow::is_hash_entry_state_idle_transition_ready() { +bool Flow::is_hash_entry_state_idle_transition_ready() const { #ifdef HAVE_NEDGE if(iface->getIfType() == interface_type_NETFILTER) return(isNetfilterIdleFlow()); #endif - if(!iface->is_purge_idle_interface()) - return(false); - if(protocol == IPPROTO_TCP) { u_int8_t tcp_flags = src2dst_tcp_flags | dst2src_tcp_flags; diff --git a/src/GenericHash.cpp b/src/GenericHash.cpp index 1a78fe9f2b..6422111020 100644 --- a/src/GenericHash.cpp +++ b/src/GenericHash.cpp @@ -148,7 +148,7 @@ bool GenericHash::walk(u_int32_t *begin_slot, * overriden (e.g. Flow), leading to wolking entries that are actually * idle even with walk_idle = false, what about using idle() here? */ - if(head->walkable() + if(!head->idle() || (walk_idle && (head->get_state() == hash_entry_state_idle))) { bool matched = false; bool rc = walker(head, user_data, &matched); @@ -201,20 +201,20 @@ bool GenericHash::walk(u_int32_t *begin_slot, Bucket Lifecycle Active -> Idle -> Ready to be Purged -> Purged - */ +*/ u_int GenericHash::purgeIdle(bool force_idle) { u_int i, num_purged = 0, buckets_checked = 0; time_t now = time(NULL); /* Visit all entries when force_idle is true */ - u_int visit_fraction = !force_idle ? purge_step : num_hashes; + u_int visit_fraction = !force_idle ? purge_step : num_hashes; #if WALK_DEBUG - ntop->getTrace()->traceEvent(TRACE_NORMAL, "[%s @ %s] Begin purgeIdle() [begin index: %u][purge step: %u][force_idle: %u]", - name, iface->get_name(), last_purged_hash, visit_fraction, force_idle ? 1 : 0); + ntop->getTrace()->traceEvent(TRACE_NORMAL, "[%s @ %s] Begin purgeIdle() [begin index: %u][purge step: %u][force_idle: %u]", + name, iface->get_name(), last_purged_hash, visit_fraction, force_idle ? 1 : 0); #endif - for(u_int j = 0; j < visit_fraction; j++) { + for(u_int j = 0; j < visit_fraction; j++) { if(++last_purged_hash == num_hashes) last_purged_hash = 0; i = last_purged_hash; @@ -235,41 +235,42 @@ u_int GenericHash::purgeIdle(bool force_idle) { GenericHashEntry *next = head->next(); buckets_checked++; - if(head_state == hash_entry_state_ready_to_be_purged) { - if(prev == NULL) { + + switch(head_state) { + case hash_entry_state_ready_to_be_purged: + if(!prev) table[i] = next; - } else { + else prev->set_next(next); - } num_purged++, current_size--; delete(head); head = next; - } else { - switch(head_state) { - case hash_entry_state_allocated: - /* TCP flows with 3WH not yet completed fall here */ - break; + continue; - case hash_entry_state_flow_notyetdetected: - head->housekeep(now); - break; - - case hash_entry_state_flow_protocoldetected: - case hash_entry_state_idle: - case hash_entry_state_ready_to_be_purged: - /* Skip as this is handled by periodic activities thread */ - break; + case hash_entry_state_allocated: + /* TCP flows with 3WH not yet completed fall here */ + break; - case hash_entry_state_active: - if(force_idle || head->is_hash_entry_state_idle_transition_ready()) - head->set_hash_entry_state_idle(); - break; - } + case hash_entry_state_flow_notyetdetected: + head->housekeep(now); + break; - prev = head; - head = next; + case hash_entry_state_flow_protocoldetected: + case hash_entry_state_idle: + /* Skip as this is handled by periodic activities thread */ + break; + + case hash_entry_state_active: + if(force_idle + || (head->is_hash_entry_state_idle_transition_possible() + && head->is_hash_entry_state_idle_transition_ready())) + head->set_hash_entry_state_idle(); + break; } + + prev = head; + head = next; } /* while */ locks[i]->unlock(__FILE__, __LINE__); @@ -298,7 +299,7 @@ GenericHashEntry* GenericHash::findByKey(u_int32_t key) { locks[hash]->rdlock(__FILE__, __LINE__); while(head) { - if(head->walkable() && head->key() == key) + if(!head->idle() && head->key() == key) break; else head = head->next(); diff --git a/src/GenericHashEntry.cpp b/src/GenericHashEntry.cpp index 6447931279..e6142626e0 100644 --- a/src/GenericHashEntry.cpp +++ b/src/GenericHashEntry.cpp @@ -74,15 +74,23 @@ HashEntryState GenericHashEntry::get_state() const { /* ***************************************** */ -/* This entry can be walked by the user interface */ -bool GenericHashEntry::walkable() const { - return((get_state() < hash_entry_state_idle) ? true : false); +bool GenericHashEntry::is_hash_entry_state_idle_transition_ready() const { + return isIdle(MAX_LOCAL_HOST_IDLE); +} + +/* ***************************************** */ + +bool GenericHashEntry::is_hash_entry_state_idle_transition_possible() const { + if(getUses() > 0 || !iface->is_purge_idle_interface()) + return false; + + return true; }; /* ***************************************** */ bool GenericHashEntry::idle() const { - return((get_state() >= hash_entry_state_idle) ? true : false); + return(get_state() > hash_entry_state_active); }; /* ***************************************** */ diff --git a/src/HTTPstats.cpp b/src/HTTPstats.cpp index 361d46c916..6e02a29418 100644 --- a/src/HTTPstats.cpp +++ b/src/HTTPstats.cpp @@ -30,10 +30,10 @@ struct http_walk_info { /* *************************************** */ -HTTPstats::HTTPstats(HostHash *_h) { +HTTPstats::HTTPstats(NetworkInterface *_iface) { struct timeval tv; - h = _h, warning_shown = false; + h =_iface->get_hosts_hash(), warning_shown = false; memset(&query, 0, sizeof(query)); memset(&response, 0, sizeof(response)); memset(&query_rate, 0, sizeof(query_rate)); @@ -43,7 +43,7 @@ HTTPstats::HTTPstats(HostHash *_h) { gettimeofday(&tv, NULL); memcpy(&last_update_time, &tv, sizeof(struct timeval)); - if((virtualHosts = new (std::nothrow) VirtualHostHash(NULL, 1, 4096)) == NULL) { + if((virtualHosts = new (std::nothrow) VirtualHostHash(_iface, 1, 4096)) == NULL) { ntop->getTrace()->traceEvent(TRACE_WARNING, "Internal error: are you running out of memory?"); } } diff --git a/src/Host.cpp b/src/Host.cpp index 5bc3676a61..9124a35717 100644 --- a/src/Host.cpp +++ b/src/Host.cpp @@ -622,10 +622,7 @@ const char * Host::getOSDetail(char * const buf, ssize_t buf_len) { /* ***************************************** */ -bool Host::is_hash_entry_state_idle_transition_ready() { - if((getUses() > 0) || (!iface->is_purge_idle_interface())) - return(false); - +bool Host::is_hash_entry_state_idle_transition_ready() const { switch(ntop->getPrefs()->get_host_stickiness()) { case location_broadcast_domain_only: case location_none: diff --git a/src/LocalHostStats.cpp b/src/LocalHostStats.cpp index ecfb916d65..000a9f90cb 100644 --- a/src/LocalHostStats.cpp +++ b/src/LocalHostStats.cpp @@ -27,7 +27,7 @@ LocalHostStats::LocalHostStats(Host *_host) : HostStats(_host) { top_sites = new FrequentStringItems(HOST_SITES_TOP_NUMBER); old_sites = strdup("{}"); dns = new DnsStats(); - http = new HTTPstats(iface->get_hosts_hash()); + http = NULL; // TODO: re-enable new HTTPstats(_host->getInterface()); icmp = NULL; nextSitesUpdate = 0; diff --git a/src/Mac.cpp b/src/Mac.cpp index 169fa3f799..b216569e95 100644 --- a/src/Mac.cpp +++ b/src/Mac.cpp @@ -136,31 +136,6 @@ void Mac::set_hash_entry_state_idle() { /* *************************************** */ -bool Mac::is_hash_entry_state_idle_transition_ready() { - bool rc; - - if(getUses() > 0 || !iface->is_purge_idle_interface()) - return(false); - - rc = isIdle(MAX_LOCAL_HOST_IDLE); - -#ifdef DEBUG - if(true) { - char buf[32]; - - ntop->getTrace()->traceEvent(TRACE_NORMAL, "Is idle %s [uses %u][%s][last: %u][diff: %d]", - Utils::formatMac(mac, buf, sizeof(buf)), - getUses(), - rc ? "Idle" : "Not Idle", - last_seen, iface->getTimeLastPktRcvd() - (last_seen+MAX_LOCAL_HOST_IDLE)); - } -#endif - - return(rc); -} - -/* *************************************** */ - static const char* location2str(MacLocation location) { switch(location) { case located_on_lan_interface: return "lan"; diff --git a/src/ParserInterface.cpp b/src/ParserInterface.cpp index d2dd877371..193a463487 100755 --- a/src/ParserInterface.cpp +++ b/src/ParserInterface.cpp @@ -307,7 +307,9 @@ void ParserInterface::processFlow(ParsedFlow *zflow) { p.app_protocol = zflow->l7_proto.app_protocol, p.master_protocol = zflow->l7_proto.master_protocol; p.category = NDPI_PROTOCOL_CATEGORY_UNSPECIFIED; - flow->setDetectedProtocol(p, true); + + if(!flow->isDetectionCompleted()) + flow->setDetectedProtocol(p, true); flow->setJSONInfo(zflow->getAdditionalFieldsJSON()); flow->setTLVInfo(zflow->getAdditionalFieldsTLV());