From 8edbc20a07e2fe5692889db1f7fbcd7cc87127b9 Mon Sep 17 00:00:00 2001 From: Jason Ish Date: Thu, 10 Mar 2016 14:32:06 -0600 Subject: [PATCH] flow: record the flow hash for use as the output flow id Provides a consistent hash for a flow, as well as a better distribution than using a memory address. --- src/flow-hash.c | 36 +++++++++++++++++------------------- src/flow.h | 13 ++++++++----- src/output-json.c | 7 +------ 3 files changed, 26 insertions(+), 30 deletions(-) diff --git a/src/flow-hash.c b/src/flow-hash.c index 9ddb3713c4..c17e6e4f09 100644 --- a/src/flow-hash.c +++ b/src/flow-hash.c @@ -218,9 +218,9 @@ typedef struct FlowHashKey6_ { * * For ICMP we only consider UNREACHABLE errors atm. */ -static inline uint32_t FlowGetKey(const Packet *p) +static inline uint32_t FlowGetHash(const Packet *p) { - uint32_t key; + uint32_t hash = 0; if (p->ip4h != NULL) { if (p->tcph != NULL || p->udph != NULL) { @@ -244,8 +244,7 @@ static inline uint32_t FlowGetKey(const Packet *p) fhk.vlan_id[0] = p->vlan_id[0]; fhk.vlan_id[1] = p->vlan_id[1]; - uint32_t hash = hashword(fhk.u32, 5, flow_config.hash_rand); - key = hash % flow_config.hash_size; + hash = hashword(fhk.u32, 5, flow_config.hash_rand); } else if (ICMPV4_DEST_UNREACH_IS_VALID(p)) { uint32_t psrc = IPV4_GET_RAW_IPSRC_U32(ICMPV4_GET_EMB_IPV4(p)); @@ -270,8 +269,7 @@ static inline uint32_t FlowGetKey(const Packet *p) fhk.vlan_id[0] = p->vlan_id[0]; fhk.vlan_id[1] = p->vlan_id[1]; - uint32_t hash = hashword(fhk.u32, 5, flow_config.hash_rand); - key = hash % flow_config.hash_size; + hash = hashword(fhk.u32, 5, flow_config.hash_rand); } else { FlowHashKey4 fhk; @@ -289,8 +287,7 @@ static inline uint32_t FlowGetKey(const Packet *p) fhk.vlan_id[0] = p->vlan_id[0]; fhk.vlan_id[1] = p->vlan_id[1]; - uint32_t hash = hashword(fhk.u32, 5, flow_config.hash_rand); - key = hash % flow_config.hash_size; + hash = hashword(fhk.u32, 5, flow_config.hash_rand); } } else if (p->ip6h != NULL) { FlowHashKey6 fhk; @@ -325,12 +322,10 @@ static inline uint32_t FlowGetKey(const Packet *p) fhk.vlan_id[0] = p->vlan_id[0]; fhk.vlan_id[1] = p->vlan_id[1]; - uint32_t hash = hashword(fhk.u32, 11, flow_config.hash_rand); - key = hash % flow_config.hash_size; - } else - key = 0; + hash = hashword(fhk.u32, 11, flow_config.hash_rand); + } - return key; + return hash; } /* Since two or more flows can have the same hash key, we need to compare @@ -523,9 +518,9 @@ Flow *FlowGetFlowFromHashByPacket(const Packet *p) Flow *f = NULL; /* get the key to our bucket */ - uint32_t key = FlowGetKey(p); + uint32_t hash = FlowGetHash(p); /* get our hash bucket and lock it */ - FlowBucket *fb = &flow_hash[key]; + FlowBucket *fb = &flow_hash[hash % flow_config.hash_size]; FBLOCK_LOCK(fb); SCLogDebug("fb %p fb->head %p", fb, fb->head); @@ -544,6 +539,7 @@ Flow *FlowGetFlowFromHashByPacket(const Packet *p) /* got one, now lock, initialize and return */ FlowInit(f, p); + f->flow_hash = hash; f->fb = fb; /* update the last seen timestamp of this flow */ COPY_TIMESTAMP(&p->ts,&f->lastts); @@ -567,9 +563,9 @@ Flow *FlowLookupFlowFromHash(const Packet *p) Flow *f = NULL; /* get the key to our bucket */ - uint32_t key = FlowGetKey(p); + uint32_t hash = FlowGetHash(p); /* get our hash bucket and lock it */ - FlowBucket *fb = &flow_hash[key]; + FlowBucket *fb = &flow_hash[hash % flow_config.hash_size]; FBLOCK_LOCK(fb); SCLogDebug("fb %p fb->head %p", fb, fb->head); @@ -656,9 +652,9 @@ Flow *FlowGetFlowFromHash(ThreadVars *tv, DecodeThreadVars *dtv, const Packet *p FlowHashCountInit; /* get the key to our bucket */ - uint32_t key = FlowGetKey(p); + uint32_t hash = FlowGetHash(p); /* get our hash bucket and lock it */ - FlowBucket *fb = &flow_hash[key]; + FlowBucket *fb = &flow_hash[hash % flow_config.hash_size]; FBLOCK_LOCK(fb); SCLogDebug("fb %p fb->head %p", fb, fb->head); @@ -680,6 +676,7 @@ Flow *FlowGetFlowFromHash(ThreadVars *tv, DecodeThreadVars *dtv, const Packet *p /* got one, now lock, initialize and return */ FlowInit(f, p); + f->flow_hash = hash; f->fb = fb; /* update the last seen timestamp of this flow */ @@ -718,6 +715,7 @@ Flow *FlowGetFlowFromHash(ThreadVars *tv, DecodeThreadVars *dtv, const Packet *p /* initialize and return */ FlowInit(f, p); + f->flow_hash = hash; f->fb = fb; /* update the last seen timestamp of this flow */ diff --git a/src/flow.h b/src/flow.h index eab7377609..5953b55fcf 100644 --- a/src/flow.h +++ b/src/flow.h @@ -314,6 +314,14 @@ typedef struct Flow_ uint8_t recursion_level; uint16_t vlan_id[2]; + /** flow hash - the flow hash before hash table size mod. */ + uint32_t flow_hash; + + /* time stamp of last update (last packet). Set/updated under the + * flow and flow hash row locks, safe to read under either the + * flow lock or flow hash row lock. */ + struct timeval lastts; + /* end of flow "header" */ SC_ATOMIC_DECLARE(FlowStateType, flow_state); @@ -338,11 +346,6 @@ typedef struct Flow_ uint32_t flags; - /* time stamp of last update (last packet). Set/updated under the - * flow and flow hash row locks, safe to read under either the - * flow lock or flow hash row lock. */ - struct timeval lastts; - #ifdef FLOWLOCK_RWLOCK SCRWLock r; #elif defined FLOWLOCK_MUTEX diff --git a/src/output-json.c b/src/output-json.c index 658ac473d7..bcc4784053 100644 --- a/src/output-json.c +++ b/src/output-json.c @@ -167,12 +167,7 @@ void CreateJSONFlowId(json_t *js, const Flow *f) { if (f == NULL) return; -#if __WORDSIZE == 64 - uint64_t addr = (uint64_t)f; -#else - uint32_t addr = (uint32_t)f; -#endif - json_object_set_new(js, "flow_id", json_integer(addr)); + json_object_set_new(js, "flow_id", json_integer(f->flow_hash)); } json_t *CreateJSONHeader(const Packet *p, int direction_sensitive,