1*76404edcSAsim Jamshed #include <stdio.h>
2*76404edcSAsim Jamshed #include <stdlib.h>
3*76404edcSAsim Jamshed #include <string.h>
4*76404edcSAsim Jamshed #include <assert.h>
5*76404edcSAsim Jamshed #include <math.h>
6*76404edcSAsim Jamshed #include <netinet/in.h>
7*76404edcSAsim Jamshed #include <arpa/inet.h>
8*76404edcSAsim Jamshed #include <sys/queue.h>
9*76404edcSAsim Jamshed
10*76404edcSAsim Jamshed #include "debug.h"
11*76404edcSAsim Jamshed #include "fhash.h"
12*76404edcSAsim Jamshed
13*76404edcSAsim Jamshed //#include "stdint.h" /* Replace with <stdint.h> if appropriate */
14*76404edcSAsim Jamshed #undef get16bits
15*76404edcSAsim Jamshed #if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
16*76404edcSAsim Jamshed || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
17*76404edcSAsim Jamshed #define get16bits(d) (*((const uint16_t *) (d)))
18*76404edcSAsim Jamshed #endif
19*76404edcSAsim Jamshed
20*76404edcSAsim Jamshed #if !defined (get16bits)
21*76404edcSAsim Jamshed #define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\
22*76404edcSAsim Jamshed +(uint32_t)(((const uint8_t *)(d))[0]) )
23*76404edcSAsim Jamshed #endif
24*76404edcSAsim Jamshed
25*76404edcSAsim Jamshed inline uint32_t
SuperFastHash(const char * data,int len)26*76404edcSAsim Jamshed SuperFastHash (const char * data, int len) {
27*76404edcSAsim Jamshed register uint32_t hash = len, tmp;
28*76404edcSAsim Jamshed int rem;
29*76404edcSAsim Jamshed
30*76404edcSAsim Jamshed if (len <= 0 || data == NULL) return 0;
31*76404edcSAsim Jamshed
32*76404edcSAsim Jamshed rem = len & 3;
33*76404edcSAsim Jamshed len >>= 2;
34*76404edcSAsim Jamshed
35*76404edcSAsim Jamshed /* Main loop */
36*76404edcSAsim Jamshed for (;len > 0; len--) {
37*76404edcSAsim Jamshed hash += get16bits (data);
38*76404edcSAsim Jamshed tmp = (get16bits (data+2) << 11) ^ hash;
39*76404edcSAsim Jamshed hash = (hash << 16) ^ tmp;
40*76404edcSAsim Jamshed data += 2*sizeof (uint16_t);
41*76404edcSAsim Jamshed hash += hash >> 11;
42*76404edcSAsim Jamshed }
43*76404edcSAsim Jamshed
44*76404edcSAsim Jamshed /* Handle end cases */
45*76404edcSAsim Jamshed switch (rem) {
46*76404edcSAsim Jamshed case 3: hash += get16bits (data);
47*76404edcSAsim Jamshed hash ^= hash << 16;
48*76404edcSAsim Jamshed hash ^= ((signed char)data[sizeof (uint16_t)]) << 18;
49*76404edcSAsim Jamshed hash += hash >> 11;
50*76404edcSAsim Jamshed break;
51*76404edcSAsim Jamshed case 2: hash += get16bits (data);
52*76404edcSAsim Jamshed hash ^= hash << 11;
53*76404edcSAsim Jamshed hash += hash >> 17;
54*76404edcSAsim Jamshed break;
55*76404edcSAsim Jamshed case 1: hash += (signed char)*data;
56*76404edcSAsim Jamshed hash ^= hash << 10;
57*76404edcSAsim Jamshed hash += hash >> 1;
58*76404edcSAsim Jamshed }
59*76404edcSAsim Jamshed
60*76404edcSAsim Jamshed /* Force "avalanching" of final 127 bits */
61*76404edcSAsim Jamshed hash ^= hash << 3;
62*76404edcSAsim Jamshed hash += hash >> 5;
63*76404edcSAsim Jamshed hash ^= hash << 4;
64*76404edcSAsim Jamshed hash += hash >> 17;
65*76404edcSAsim Jamshed hash ^= hash << 25;
66*76404edcSAsim Jamshed hash += hash >> 6;
67*76404edcSAsim Jamshed
68*76404edcSAsim Jamshed return hash;
69*76404edcSAsim Jamshed }
70*76404edcSAsim Jamshed
71*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
72*76404edcSAsim Jamshed inline unsigned int
HashFlow(const tcp_stream * flow)73*76404edcSAsim Jamshed HashFlow(const tcp_stream *flow)
74*76404edcSAsim Jamshed {
75*76404edcSAsim Jamshed #if 0
76*76404edcSAsim Jamshed register unsigned int hash, i;
77*76404edcSAsim Jamshed char *key = (char *)&flow->saddr;
78*76404edcSAsim Jamshed
79*76404edcSAsim Jamshed for (hash = i = 0; i < 12; ++i) {
80*76404edcSAsim Jamshed hash += key[i];
81*76404edcSAsim Jamshed hash += (hash << 10);
82*76404edcSAsim Jamshed hash ^= (hash >> 6);
83*76404edcSAsim Jamshed }
84*76404edcSAsim Jamshed hash += (hash << 3);
85*76404edcSAsim Jamshed hash ^= (hash >> 11);
86*76404edcSAsim Jamshed hash += (hash << 15);
87*76404edcSAsim Jamshed
88*76404edcSAsim Jamshed return hash & (NUM_BINS - 1);
89*76404edcSAsim Jamshed #else
90*76404edcSAsim Jamshed return SuperFastHash((const char *)&flow->saddr, 12) & (NUM_BINS - 1);
91*76404edcSAsim Jamshed #endif
92*76404edcSAsim Jamshed }
93*76404edcSAsim Jamshed /*---------------------------------------------------------------------------*/
94*76404edcSAsim Jamshed #define EQUAL_FLOW(flow1, flow2) \
95*76404edcSAsim Jamshed (flow1->saddr == flow2->saddr && flow1->sport == flow2->sport && \
96*76404edcSAsim Jamshed flow1->daddr == flow2->daddr && flow1->dport == flow2->dport)
97*76404edcSAsim Jamshed /*---------------------------------------------------------------------------*/
98*76404edcSAsim Jamshed struct hashtable *
CreateHashtable(void)99*76404edcSAsim Jamshed CreateHashtable(void) // equality
100*76404edcSAsim Jamshed {
101*76404edcSAsim Jamshed int i;
102*76404edcSAsim Jamshed struct hashtable* ht = calloc(1, sizeof(struct hashtable));
103*76404edcSAsim Jamshed if (!ht){
104*76404edcSAsim Jamshed TRACE_ERROR("calloc: CreateHashtable");
105*76404edcSAsim Jamshed return 0;
106*76404edcSAsim Jamshed }
107*76404edcSAsim Jamshed
108*76404edcSAsim Jamshed /* init the tables */
109*76404edcSAsim Jamshed for (i = 0; i < NUM_BINS; i++)
110*76404edcSAsim Jamshed TAILQ_INIT(&ht->ht_table[i]);
111*76404edcSAsim Jamshed return ht;
112*76404edcSAsim Jamshed }
113*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
114*76404edcSAsim Jamshed void
DestroyHashtable(struct hashtable * ht)115*76404edcSAsim Jamshed DestroyHashtable(struct hashtable *ht)
116*76404edcSAsim Jamshed {
117*76404edcSAsim Jamshed free(ht);
118*76404edcSAsim Jamshed }
119*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
120*76404edcSAsim Jamshed int
HTInsert(struct hashtable * ht,tcp_stream * item,unsigned int * hash)121*76404edcSAsim Jamshed HTInsert(struct hashtable *ht, tcp_stream *item, unsigned int *hash)
122*76404edcSAsim Jamshed {
123*76404edcSAsim Jamshed /* create an entry*/
124*76404edcSAsim Jamshed int idx;
125*76404edcSAsim Jamshed
126*76404edcSAsim Jamshed assert(ht);
127*76404edcSAsim Jamshed assert(ht->ht_count <= 65535); // uint16_t ht_count
128*76404edcSAsim Jamshed
129*76404edcSAsim Jamshed if (hash)
130*76404edcSAsim Jamshed idx = (int)*hash;
131*76404edcSAsim Jamshed else
132*76404edcSAsim Jamshed idx = HashFlow(item);
133*76404edcSAsim Jamshed
134*76404edcSAsim Jamshed assert(idx >=0 && idx < NUM_BINS);
135*76404edcSAsim Jamshed
136*76404edcSAsim Jamshed #if STATIC_TABLE
137*76404edcSAsim Jamshed int i;
138*76404edcSAsim Jamshed for (i = 0; i < TCP_AR_CNT; i++) {
139*76404edcSAsim Jamshed // insert into empty array slot
140*76404edcSAsim Jamshed if (!ht->ht_array[idx][i]) {
141*76404edcSAsim Jamshed ht->ht_array[idx][i] = item;
142*76404edcSAsim Jamshed item->ht_idx = i;
143*76404edcSAsim Jamshed ht->ht_count++;
144*76404edcSAsim Jamshed return 0;
145*76404edcSAsim Jamshed }
146*76404edcSAsim Jamshed }
147*76404edcSAsim Jamshed
148*76404edcSAsim Jamshed TRACE_INFO("[WARNING] HTSearch() cnt: %d!!\n", TCP_AR_CNT);
149*76404edcSAsim Jamshed #endif
150*76404edcSAsim Jamshed
151*76404edcSAsim Jamshed TAILQ_INSERT_TAIL(&ht->ht_table[idx], item, rcvvar->he_link);
152*76404edcSAsim Jamshed item->rcvvar->he_mybucket = &ht->ht_table[idx];
153*76404edcSAsim Jamshed item->ht_idx = TCP_AR_CNT;
154*76404edcSAsim Jamshed ht->ht_count++;
155*76404edcSAsim Jamshed
156*76404edcSAsim Jamshed return 0;
157*76404edcSAsim Jamshed }
158*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
159*76404edcSAsim Jamshed void*
HTRemove(struct hashtable * ht,tcp_stream * item)160*76404edcSAsim Jamshed HTRemove(struct hashtable *ht, tcp_stream *item)
161*76404edcSAsim Jamshed {
162*76404edcSAsim Jamshed hash_bucket_head *head;
163*76404edcSAsim Jamshed //int idx = HashFlow(item);
164*76404edcSAsim Jamshed
165*76404edcSAsim Jamshed #if STATIC_TABLE
166*76404edcSAsim Jamshed if (item->ht_idx < TCP_AR_CNT) {
167*76404edcSAsim Jamshed assert(ht_array[idx][item->ht_idx]);
168*76404edcSAsim Jamshed ht->ht_array[idx][item->ht_idx] = NULL;
169*76404edcSAsim Jamshed } else {
170*76404edcSAsim Jamshed #endif
171*76404edcSAsim Jamshed //head = &ht->ht_table[idx];
172*76404edcSAsim Jamshed head = item->rcvvar->he_mybucket;
173*76404edcSAsim Jamshed assert(head);
174*76404edcSAsim Jamshed TAILQ_REMOVE(head, item, rcvvar->he_link);
175*76404edcSAsim Jamshed #if STATIC_TABLE
176*76404edcSAsim Jamshed }
177*76404edcSAsim Jamshed #endif
178*76404edcSAsim Jamshed
179*76404edcSAsim Jamshed ht->ht_count--;
180*76404edcSAsim Jamshed return (item);
181*76404edcSAsim Jamshed }
182*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
183*76404edcSAsim Jamshed tcp_stream*
HTSearch(struct hashtable * ht,const tcp_stream * item,unsigned int * hash)184*76404edcSAsim Jamshed HTSearch(struct hashtable *ht, const tcp_stream *item, unsigned int *hash)
185*76404edcSAsim Jamshed {
186*76404edcSAsim Jamshed tcp_stream *walk;
187*76404edcSAsim Jamshed hash_bucket_head *head;
188*76404edcSAsim Jamshed int idx;
189*76404edcSAsim Jamshed
190*76404edcSAsim Jamshed #if STATIC_TABLE
191*76404edcSAsim Jamshed int i;
192*76404edcSAsim Jamshed
193*76404edcSAsim Jamshed idx = HashFlow(item);
194*76404edcSAsim Jamshed
195*76404edcSAsim Jamshed for (i = 0; i < TCP_AR_CNT; i++) {
196*76404edcSAsim Jamshed if (ht->ht_array[idx][i]) {
197*76404edcSAsim Jamshed if (EQUAL_FLOW(ht->ht_array[idx][i], item))
198*76404edcSAsim Jamshed return ht->ht_array[idx][i];
199*76404edcSAsim Jamshed }
200*76404edcSAsim Jamshed }
201*76404edcSAsim Jamshed #endif
202*76404edcSAsim Jamshed
203*76404edcSAsim Jamshed idx = HashFlow(item);
204*76404edcSAsim Jamshed *hash = idx;
205*76404edcSAsim Jamshed
206*76404edcSAsim Jamshed head = &ht->ht_table[idx];
207*76404edcSAsim Jamshed
208*76404edcSAsim Jamshed TAILQ_FOREACH(walk, head, rcvvar->he_link) {
209*76404edcSAsim Jamshed if (EQUAL_FLOW(walk, item))
210*76404edcSAsim Jamshed return walk;
211*76404edcSAsim Jamshed }
212*76404edcSAsim Jamshed
213*76404edcSAsim Jamshed return NULL;
214*76404edcSAsim Jamshed }
215*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
216