-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhash.c
153 lines (134 loc) · 3.38 KB
/
hash.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#include <stdint.h>
#include <stdio.h>
#include <common.h>
#include <message.h>
#include <node.h>
#include <logging/log.h>
#include <logging/log_ctrl.h>
#include <zephyr.h>
LOG_MODULE_REGISTER(hash, GLOBAL_LOG_LEVEL);
#define NUM_BUCKETS (MAX_HASH_COUNT_LIMIT / 2)
struct node
{
uint32_t data;
struct node *next;
};
struct node *buckets[NUM_BUCKETS];
size_t hash_size = 0;
// TODO Find out why this is too small without the constant.
K_HEAP_DEFINE(hash_heap, sizeof(struct node) * MAX_HASH_COUNT_LIMIT * 8);
K_MUTEX_DEFINE(hash_mutex);
uint32_t queue[MAX_HASH_COUNT_LIMIT];
size_t queue_back = MAX_HASH_COUNT_LIMIT - 1;
size_t queue_front = 0;
size_t queue_size = 0;
void enqueue(uint32_t hash_val)
{
if (queue_size == MAX_HASH_COUNT_LIMIT)
{
LOG_ERR("Queue Full!");
return;
}
queue_back = (queue_back + 1) % MAX_HASH_COUNT_LIMIT;
queue[queue_back] = hash_val;
queue_size++;
}
uint32_t dequeue()
{
if (queue_size == 0)
{
LOG_ERR("Nothing to dequeue");
return 0;
}
uint32_t hash_val = queue[queue_front];
queue_front = (queue_front + 1) % MAX_HASH_COUNT_LIMIT;
queue_size--;
return hash_val;
}
/* Based on djb2 */
uint32_t hash_packet(struct message *msg)
{
uint32_t hash = 5381;
for (size_t i = 0; i < MAC_LEN; i++)
{
hash += (hash << 5) + msg->src_mac[i];
}
for (size_t i = 0; i < MAC_LEN; i++)
{
hash += (hash << 5) + msg->dst_mac[i];
}
hash += (hash << 5) + msg->msg_number;
hash += (hash << 5) + msg->payload_len;
for (size_t i = 0; i < msg->payload_len; i++)
{
hash += (hash << 5) + msg->payload[i];
}
return hash;
}
void init_hash()
{
for (size_t i = 0; i < NUM_BUCKETS; i++)
{
buckets[i] = NULL;
}
}
void hash_remove(uint32_t hash_val)
{
uint32_t bucket = hash_val % NUM_BUCKETS;
if (buckets[bucket] == NULL)
return;
if (buckets[bucket]->data == hash_val)
{
buckets[bucket] = buckets[bucket]->next;
return;
}
for (struct node *x = buckets[bucket]; x->next != NULL; x = x->next)
{
if (x->next->data == hash_val)
{
struct node *old_ptr = x->next;
x->next = x->next->next;
k_heap_free(&hash_heap, old_ptr);
hash_size--;
return;
}
}
}
/* Assumes that there isn't already an equal key in the set. This holds for the
* mesh node since every packet is first checked if they're a member of the set.
*/
void hash_add(uint32_t hash_val)
{
k_mutex_lock(&hash_mutex, K_FOREVER);
while (hash_size >= MAX_HASH_COUNT_LIMIT)
{
uint32_t old_hash = dequeue();
hash_remove(old_hash);
}
enqueue(hash_val);
uint32_t bucket = hash_val % NUM_BUCKETS;
void *ptr = k_heap_alloc(&hash_heap, sizeof(struct node), K_NO_WAIT);
if (ptr == NULL)
{
LOG_ERR("Failed to allocate memory in heap.");
return;
}
struct node *new_node = (struct node *)ptr;
new_node->data = hash_val;
new_node->next = buckets[bucket];
buckets[bucket] = new_node;
hash_size++;
k_mutex_unlock(&hash_mutex);
}
bool hash_contains(uint32_t hash_val)
{
uint32_t bucket = hash_val % NUM_BUCKETS;
for (struct node *x = buckets[bucket]; x != NULL; x = x->next)
{
if (x->data == hash_val)
{
return true;
}
}
return false;
}