flow: make flow use lookup3.c hashing algorithm. Improves hash table distribution.

remotes/origin/master
Victor Julien 14 years ago
parent 20c08ca47b
commit c10370907a

@ -40,6 +40,8 @@
#include "util-time.h"
#include "util-debug.h"
#include "util-hash-lookup3.h"
#define FLOW_DEFAULT_FLOW_PRUNE 5
SC_ATOMIC_EXTERN(unsigned int, flow_prune_idx);
@ -139,6 +141,54 @@ void FlowHashDebugDeinit(void) {
#endif /* FLOW_DEBUG_STATS */
/** \brief compare two raw ipv6 addrs
*
* \note we don't care about the real ipv6 ip's, this is just
* to consistently fill the FlowHashKey6 struct, without all
* the ntohl calls.
*
* \warning do not use elsewhere unless you know what you're doing.
* detect-engine-address-ipv6.c's AddressIPv6GtU32 is likely
* what you are looking for.
*/
static inline int FlowHashRawAddressIPv6GtU32(uint32_t *a, uint32_t *b)
{
int i;
for (i = 0; i < 4; i++) {
if (a[i] > b[i])
return 1;
if (a[i] < b[i])
break;
}
return 0;
}
typedef struct FlowHashKey4_ {
union {
struct {
uint32_t src, dst;
uint16_t sp, dp;
uint16_t proto; /**< u16 so proto and recur add up to u32 */
uint16_t recur; /**< u16 so proto and recur add up to u32 */
};
uint32_t u32[4];
};
} FlowHashKey4;
typedef struct FlowHashKey6_ {
union {
struct {
uint32_t src[4], dst[4];
uint16_t sp, dp;
uint16_t proto; /**< u16 so proto and recur add up to u32 */
uint16_t recur; /**< u16 so proto and recur add up to u32 */
};
uint32_t u32[10];
};
} FlowHashKey6;
/* calculate the hash key for this packet
*
* we're using:
@ -152,53 +202,107 @@ void FlowHashDebugDeinit(void) {
*
* For ICMP we only consider UNREACHABLE errors atm.
*/
uint32_t FlowGetKey(Packet *p) {
FlowKey *k = (FlowKey *)p;
static inline uint32_t FlowGetKey(Packet *p) {
uint32_t key;
if (p->ip4h != NULL) {
if (p->tcph != NULL || p->udph != NULL) {
key = (flow_config.hash_rand + k->proto + k->sp + k->dp + \
k->src.addr_data32[0] + k->dst.addr_data32[0] + \
k->recursion_level) % flow_config.hash_size;
/*
SCLogDebug("TCP/UCP key %"PRIu32, key);
SCLogDebug("proto %u, sp %u, dp %u, src %u, dst %u, reclvl %u",
k->proto, k->sp, k->dp, k->src.addr_data32[0], k->dst.addr_data32[0],
k->recursion_level);
*/
FlowHashKey4 fhk;
if (p->src.addr_data32[0] > p->dst.addr_data32[0]) {
fhk.src = p->src.addr_data32[0];
fhk.dst = p->dst.addr_data32[0];
} else {
fhk.src = p->dst.addr_data32[0];
fhk.dst = p->src.addr_data32[0];
}
if (p->sp > p->dp) {
fhk.sp = p->sp;
fhk.dp = p->dp;
} else {
fhk.sp = p->dp;
fhk.dp = p->sp;
}
fhk.proto = (uint16_t)p->proto;
fhk.recur = (uint16_t)p->recursion_level;
uint32_t hash = hashword(fhk.u32, 4, flow_config.hash_rand);
key = hash % flow_config.hash_size;
} else if (ICMPV4_DEST_UNREACH_IS_VALID(p)) {
// SCLogDebug("valid ICMPv4 DEST UNREACH error packet");
key = (flow_config.hash_rand + ICMPV4_GET_EMB_PROTO(p) +
p->icmpv4vars.emb_sport + \
p->icmpv4vars.emb_dport + \
IPV4_GET_RAW_IPSRC_U32(ICMPV4_GET_EMB_IPV4(p)) + \
IPV4_GET_RAW_IPDST_U32(ICMPV4_GET_EMB_IPV4(p)) + \
k->recursion_level) % flow_config.hash_size;
/*
SCLogDebug("ICMP DEST UNREACH key %"PRIu32, key);
SCLogDebug("proto %u, sp %u, dp %u, src %u, dst %u, reclvl %u",
ICMPV4_GET_EMB_PROTO(p), p->icmpv4vars.emb_sport,
p->icmpv4vars.emb_dport, IPV4_GET_RAW_IPSRC_U32(ICMPV4_GET_EMB_IPV4(p)),
IPV4_GET_RAW_IPDST_U32(ICMPV4_GET_EMB_IPV4(p)), k->recursion_level);
*/
uint32_t psrc = IPV4_GET_RAW_IPSRC_U32(ICMPV4_GET_EMB_IPV4(p));
uint32_t pdst = IPV4_GET_RAW_IPDST_U32(ICMPV4_GET_EMB_IPV4(p));
FlowHashKey4 fhk;
if (psrc > pdst) {
fhk.src = psrc;
fhk.dst = pdst;
} else {
fhk.src = pdst;
fhk.dst = psrc;
}
if (p->icmpv4vars.emb_sport > p->icmpv4vars.emb_dport) {
fhk.sp = p->icmpv4vars.emb_sport;
fhk.dp = p->icmpv4vars.emb_dport;
} else {
fhk.sp = p->icmpv4vars.emb_dport;
fhk.dp = p->icmpv4vars.emb_sport;
}
fhk.proto = (uint16_t)ICMPV4_GET_EMB_PROTO(p);
fhk.recur = (uint16_t)p->recursion_level;
uint32_t hash = hashword(fhk.u32, 4, flow_config.hash_rand);
key = hash % flow_config.hash_size;
} else {
key = (flow_config.hash_rand + k->proto + \
k->src.addr_data32[0] + k->dst.addr_data32[0] + \
k->recursion_level) % flow_config.hash_size;
FlowHashKey4 fhk;
if (p->src.addr_data32[0] > p->dst.addr_data32[0]) {
fhk.src = p->src.addr_data32[0];
fhk.dst = p->dst.addr_data32[0];
} else {
fhk.src = p->dst.addr_data32[0];
fhk.dst = p->src.addr_data32[0];
}
fhk.sp = 0xfeed;
fhk.dp = 0xbeef;
fhk.proto = (uint16_t)p->proto;
fhk.recur = (uint16_t)p->recursion_level;
uint32_t hash = hashword(fhk.u32, 4, flow_config.hash_rand);
key = hash % flow_config.hash_size;
}
} else if (p->ip6h != NULL) {
FlowHashKey6 fhk;
if (FlowHashRawAddressIPv6GtU32(p->src.addr_data32, p->dst.addr_data32)) {
fhk.src[0] = p->src.addr_data32[0];
fhk.src[1] = p->src.addr_data32[1];
fhk.src[2] = p->src.addr_data32[2];
fhk.src[3] = p->src.addr_data32[3];
fhk.dst[0] = p->dst.addr_data32[0];
fhk.dst[1] = p->dst.addr_data32[1];
fhk.dst[2] = p->dst.addr_data32[2];
fhk.dst[3] = p->dst.addr_data32[3];
} else {
fhk.src[0] = p->dst.addr_data32[0];
fhk.src[1] = p->dst.addr_data32[1];
fhk.src[2] = p->dst.addr_data32[2];
fhk.src[3] = p->dst.addr_data32[3];
fhk.dst[0] = p->src.addr_data32[0];
fhk.dst[1] = p->src.addr_data32[1];
fhk.dst[2] = p->src.addr_data32[2];
fhk.dst[3] = p->src.addr_data32[3];
}
} else if (p->ip6h != NULL)
key = (flow_config.hash_rand + k->proto + k->sp + k->dp + \
k->src.addr_data32[0] + k->src.addr_data32[1] + \
k->src.addr_data32[2] + k->src.addr_data32[3] + \
k->dst.addr_data32[0] + k->dst.addr_data32[1] + \
k->dst.addr_data32[2] + k->dst.addr_data32[3] + \
k->recursion_level) % flow_config.hash_size;
else
if (p->sp > p->dp) {
fhk.sp = p->sp;
fhk.dp = p->dp;
} else {
fhk.sp = p->dp;
fhk.dp = p->sp;
}
fhk.proto = (uint16_t)p->proto;
fhk.recur = (uint16_t)p->recursion_level;
uint32_t hash = hashword(fhk.u32, 10, flow_config.hash_rand);
key = hash % flow_config.hash_size;
} else
key = 0;
return key;

Loading…
Cancel
Save