193 lines
6.5 KiB
C
193 lines
6.5 KiB
C
#include "ip_hashmap.h"
|
|
#include <linux/jhash.h>
|
|
static struct ip_hash_table g_ip_hashtable;
|
|
|
|
void thread_demon_ip_hashmap(void *ctx) {
|
|
struct hlist_head *head;
|
|
struct hlist_node *node, *tmp;
|
|
struct ip_hashmap_node_t *data;
|
|
|
|
while (!kthread_should_stop()) {
|
|
msleep_interruptible(30000); // 每 30 秒执行一次清理操作
|
|
const s64 current_time_sec = ktime_get_real_seconds();
|
|
|
|
spin_lock(&g_ip_hashtable.lock);
|
|
|
|
for (int i = 0; i < g_ip_hashtable.bucket_num; ++i) {
|
|
head = &g_ip_hashtable.heads[i];
|
|
hlist_for_each_safe(node, tmp, head) {
|
|
data = container_of(node, struct ip_hashmap_node_t, node);
|
|
if (data) {
|
|
s64 time_diff =
|
|
(s64)((s64)data->info.ip_meta_info.remove_time -
|
|
(s64)data->info.ip_meta_info.last_attack_time);
|
|
if ((data->info.ip_meta_info.is_attack == false) ||
|
|
(time_diff <= 0)) {
|
|
hlist_del(&data->node);
|
|
kfree(data);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
spin_unlock(&g_ip_hashtable.lock);
|
|
}
|
|
|
|
printk(KERN_INFO "cleanup_iphashmap thread stopped\n");
|
|
}
|
|
// 初始化哈希表对象
|
|
bool init_ip_hashmap(void) {
|
|
int i = 0;
|
|
struct ip_hash_table *table = &g_ip_hashtable;
|
|
table->bucket_num = BUCKET_NUM;
|
|
table->heads = kzalloc(BUCKET_NUM * sizeof(struct hlist_head), GFP_KERNEL);
|
|
if (table->heads) {
|
|
for (i = 0; i < BUCKET_NUM; ++i) {
|
|
INIT_HLIST_HEAD(&table->heads[i]);
|
|
}
|
|
}
|
|
spin_lock_init(&table->lock); // 初始化锁
|
|
|
|
// 新建线程,执行清理操作
|
|
table->cleanup_thread = kthread_run((void *)thread_demon_ip_hashmap, NULL,
|
|
"thread_demon_ip_hashmap");
|
|
if (IS_ERR(table->cleanup_thread)) {
|
|
printk(KERN_ERR "Failed to create cleanup thread\n");
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// 检查是否需要动态调整桶的数量
|
|
void check_resize_table(struct ip_hash_table *table) {
|
|
unsigned int bucket_num = table->bucket_num;
|
|
int count = 0;
|
|
int i = 0;
|
|
for (i = 0; i < bucket_num; ++i) {
|
|
struct hlist_head *head = &table->heads[i];
|
|
if (!hlist_empty(head)) {
|
|
count++;
|
|
}
|
|
}
|
|
|
|
if ((count * 100 / bucket_num) > 70) {
|
|
table->bucket_num = 2 * bucket_num;
|
|
struct hlist_head *new_heads =
|
|
kzalloc(table->bucket_num * sizeof(struct hlist_head), GFP_KERNEL);
|
|
if (new_heads) {
|
|
for (i = 0; i < table->bucket_num / 2; ++i) {
|
|
struct hlist_node *node, *tmp;
|
|
hlist_for_each_safe(node, tmp, &table->heads[i]) {
|
|
struct ip_hashmap_node_t *data =
|
|
container_of(node, struct ip_hashmap_node_t, node);
|
|
hlist_del(&data->node);
|
|
int idx =
|
|
jhash(&data->info.ip_address_key, sizeof(u32), 0) %
|
|
table->bucket_num;
|
|
|
|
// int idx =
|
|
// hash_32(data->info.ip_address_key,
|
|
// table->bucket_num);
|
|
hlist_add_head(&data->node, &new_heads[idx]);
|
|
}
|
|
}
|
|
|
|
kfree(table->heads);
|
|
table->heads = new_heads;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 获取并插入哈希表节点
|
|
void put_ipdata_by_hashmap(u32 ip_address_key, struct ip_hashmap_info *info) {
|
|
struct ip_hash_table *table = &g_ip_hashtable;
|
|
// int idx = hash_32(ip_address_key, table->bucket_num);
|
|
int idx =
|
|
jhash(&ip_address_key, sizeof(ip_address_key), 0) % table->bucket_num;
|
|
|
|
// 新建哈希表节点
|
|
struct ip_hashmap_node_t *data =
|
|
kmalloc(sizeof(struct ip_hashmap_node_t), GFP_KERNEL);
|
|
if (data) {
|
|
memcpy(&data->info, info, sizeof(struct ip_hashmap_info));
|
|
spin_lock(&table->lock);
|
|
hlist_add_head(&data->node, &table->heads[idx]);
|
|
check_resize_table(table);
|
|
spin_unlock(&table->lock);
|
|
}
|
|
}
|
|
|
|
// 通过关键字获取哈希表节点
|
|
struct ip_hashmap_node_t *get_ipdata_by_hashmap(u32 ip_address_key) {
|
|
struct ip_hash_table *table = &g_ip_hashtable;
|
|
// printk(KERN_ERR "ip_address_key %08X table->bucket_num: %d \n",
|
|
// ip_address_key, table->bucket_num);
|
|
spin_lock(&table->lock);
|
|
|
|
// int idx = hash_32(ip_address_key, table->bucket_num);
|
|
int idx =
|
|
jhash(&ip_address_key, sizeof(ip_address_key), 0) % table->bucket_num;
|
|
|
|
struct hlist_head *head = &table->heads[idx];
|
|
struct hlist_node *node = head->first;
|
|
while (node) {
|
|
struct ip_hashmap_node_t *data =
|
|
container_of(node, struct ip_hashmap_node_t, node);
|
|
if (ip_address_key == data->info.ip_address_key) {
|
|
spin_unlock(&table->lock);
|
|
return data;
|
|
}
|
|
node = node->next;
|
|
}
|
|
spin_unlock(&table->lock);
|
|
return NULL;
|
|
}
|
|
|
|
// 从哈希表中删除节点
|
|
void del_ipdata_by_hashmap(u32 ip_address_key) {
|
|
struct ip_hash_table *table = &g_ip_hashtable;
|
|
spin_lock(&table->lock);
|
|
|
|
// int idx = hash_32(ip_address_key, table->bucket_num);
|
|
int idx =
|
|
jhash(&ip_address_key, sizeof(ip_address_key), 0) % table->bucket_num;
|
|
|
|
struct hlist_head *head = &table->heads[idx];
|
|
struct hlist_node *node = head->first;
|
|
while (node) {
|
|
struct ip_hashmap_node_t *data =
|
|
container_of(node, struct ip_hashmap_node_t, node);
|
|
if (ip_address_key == data->info.ip_address_key) {
|
|
hlist_del(&data->node);
|
|
kfree(data);
|
|
break;
|
|
}
|
|
node = node->next;
|
|
}
|
|
// 检查是否需要调整桶的数量
|
|
check_resize_table(table);
|
|
spin_unlock(&table->lock);
|
|
}
|
|
void cleanup_iphashmap(void) {
|
|
int i = 0;
|
|
kthread_stop(g_ip_hashtable.cleanup_thread); // 停止清理线程
|
|
if (g_ip_hashtable.heads) {
|
|
spin_lock(&g_ip_hashtable.lock);
|
|
struct hlist_head *head, *tmp;
|
|
struct hlist_node *node;
|
|
struct ip_hashmap_node_t *data;
|
|
// 释放哈希表节点动态分配的内存
|
|
for (i = 0; i < g_ip_hashtable.bucket_num; ++i) {
|
|
head = &g_ip_hashtable.heads[i];
|
|
hlist_for_each_entry_safe(data, node, head, node) {
|
|
hlist_del(&data->node);
|
|
kfree(data);
|
|
}
|
|
}
|
|
kfree(g_ip_hashtable.heads);
|
|
spin_unlock(&g_ip_hashtable.lock);
|
|
}
|
|
|
|
printk(KERN_INFO "clean up iphashmap\n");
|
|
}
|