#include #include #include #include #include #include #include #include #include #include "dpi_trie_cache.h" /* * 三元组超时时间设置为300s */ int dpi_cache_node_timeout = 300; #define IPV4_ADDR (1) #define IPV6_ADDR (2) /* * 初始化cache链表 */ #define TRIPLE_CAHCE_HASH_SIZE (2048) struct list_head dpi_cache_head[TRIPLE_CAHCE_HASH_SIZE] = {0}; typedef struct pkt_info{ unsigned int srcip; unsigned short sport; unsigned int dstip; unsigned short port; unsigned short proto; }pkt_info_t; #define POLY 0x01101 // CRC20生成多项式x^20+x^12+x^8+1即:01101 CRC32:04C11DB7L static unsigned int crc_table[256] = {0}; unsigned int get_sum_poly(unsigned char data) { unsigned int sum_poly = data; int j; sum_poly <<= 24; for(j = 0; j < 8; j++) { int hi = sum_poly&0x80000000; // 取得reg的最高位 sum_poly <<= 1; if(hi) sum_poly = sum_poly^POLY; } return sum_poly; } void create_crc_table(void) //在使用CRC20_key函数应该先建立crc表 { int i; for(i = 0; i < 256; i++) { crc_table[i] = get_sum_poly(i&0xFF); } } unsigned int CRC20_key(unsigned char* data, int len) { int i; unsigned int reg = 0xFFFFFFFF;// 0xFFFFFFFF,见后面解释 for(i = 0; i < len; i++) { reg = (reg<<8) ^ crc_table[((reg>>24)&0xFF) ^ data[i]]; } return (reg&0XFFFFF);//得到的reg取后20作为key值 } /* * 初始化dpi三元组hash链表 */ void dpi_cache_list_init(void) { int i = 0; for (i = 0; i < TRIPLE_CAHCE_HASH_SIZE; i++){ INIT_LIST_HEAD(&dpi_cache_head[i]); } return; } /* * 三元组hash值计算 */ int dpi_cache_node_hash(struct dpi_cache_node node) { pkt_info_t info; info.port = node.port; info.sport = 0; info.srcip = 0; info.proto = node.proto; if (node.ipv4 == true ) { info.dstip = node.ip.ip4.s_addr; } else { int i = 0; int dip = 0; for (i = 0; i < 4; ++i) { dip ^= node.ip.ip6.s6_addr32[i]; } info.dstip = dip; } return CRC20_key((unsigned char *)&info, sizeof(pkt_info_t))&(TRIPLE_CAHCE_HASH_SIZE - 1); } /* * src 和dst比较,并更新dst的appid,update_appid=true,update */ bool dpi_cache_node_compare(struct dpi_cache_node src,struct dpi_cache_node dst,bool update_appid) { if (src.port != dst.port){ return false; } if (src.proto != dst.proto){ return false; } if(src.ipv4 == true){ if(src.ip.ip4.s_addr != dst.ip.ip4.s_addr){ return false; } }else{ int i = 0; for (i = 0; i < 4; i++){ if (src.ip.ip6.s6_addr32[i] != dst.ip.ip6.s6_addr32[i]){ return false; } } } if (update_appid){ if(src.appid != -1) dst.appid = src.appid; dst.uptime = get_jiffies_64(); } return true; } /* *遍历hash链表,查找node */ bool dpi_cache_node_search(struct dpi_cache_node node,int flag) { struct list_head * pList = NULL; int hash = dpi_cache_node_hash(node); list_for_each(pList,&dpi_cache_head[hash]){ struct dpi_cache_node *pNode = list_entry(pList,struct dpi_cache_node,list); if (dpi_cache_node_compare(node,*pNode,flag)){ return true; } } return false; } /* * DPI 信息记录,外部接口调用 */ bool dpi_cache_node_add(struct dpi_cache_node node) { int hash = 0; struct dpi_cache_node *pNode =NULL; if (dpi_cache_node_search(node,true)) { return true; } pNode = kmalloc(sizeof(struct dpi_cache_node), GFP_KERNEL); if (NULL == pNode) { return false; } hash = dpi_cache_node_hash(node); memcpy((char*)pNode,(char*)&node,sizeof(node)); pNode->uptime = get_jiffies_64(); //printk("%s,%d,%d,%d,%d\n",__FUNCTION__,__LINE__,pNode->proto,pNode->port,pNode->ipv4); list_add_tail(&pNode->list,&dpi_cache_head[hash]); return true; } /* * 释放hash链表上所有node节点 */ void dpi_cache_list_release(void) { int i = 0; for (i = 0; i < TRIPLE_CAHCE_HASH_SIZE; i++){ while(!list_empty(&dpi_cache_head[i])) { list_del(dpi_cache_head[i].next); } } } /* *定时器超时,删除超时的节点 */ void dpi_cache_node_timeout_func(void) { struct list_head * pList = NULL; struct list_head * n = NULL; struct dpi_cache_node *pNode = NULL; int i = 0; for (i = 0; i < TRIPLE_CAHCE_HASH_SIZE; i++){ list_for_each_safe(pList,(n),&dpi_cache_head[i]){ pNode = list_entry(pList,struct dpi_cache_node,list); //printk("%s,%d,%d\n",__FUNCTION__,__LINE__,pNode->port); if(pNode&& (get_jiffies_64() - pNode->uptime >= dpi_cache_node_timeout)){ list_del(&pNode->list); } } } } /* * 定时器操作 */ struct timer_list gTimer; void dpi_cache_timer_handler(unsigned long data) { //printk(KERN_INFO"timer pending:%d\n", timer_pending(&gTimer)); dpi_cache_node_timeout_func(); mod_timer(&gTimer, jiffies+msecs_to_jiffies(dpi_cache_node_timeout*1000)); } int dpi_cache_timer_init(void) { printk(KERN_INFO"%s jiffies:%ld\n", __func__, jiffies); printk(KERN_INFO"ji:%d,HZ:%d\n", jiffies_to_msecs(250), HZ); init_timer(&gTimer); gTimer.expires = jiffies + dpi_cache_node_timeout*HZ; gTimer.function = dpi_cache_timer_handler; add_timer(&gTimer); printk(KERN_INFO"timer pending:%d\n", timer_pending(&gTimer)); return 0; } #if 0 void test_func(void) { struct dpi_cache_node node1,node2,node3; node1.proto = 17; in4_pton("192.168.1.1", strlen("192.168.1.1"), (u8*)&node1.ip.ip4, -1, NULL); node1.port = 200; node1.ipv4 = true; dpi_cache_node_add(node1); node2.proto = 17; in4_pton("192.168.2.1", strlen("192.168.1.1"), (u8*)&node2.ip.ip4, -1, NULL); node2.port = 200; node2.ipv4 = true; dpi_cache_node_add(node2); node3.proto = 17; in6_pton("2a01:198:603:0:396e:4789:8e99:890f", strlen("2a01:198:603:0:396e:4789:8e99:890f"), (u8*)&node3.ip.ip6, -1, NULL); node3.port = 200; node3.ipv4 = false; dpi_cache_node_add(node3); return; } #endif void dpi_cache_timer_exit(void) { printk(KERN_INFO"%s jiffies:%ld\n", __func__, jiffies); del_timer(&gTimer); } EXPORT_SYMBOL_GPL(dpi_cache_node_add); static int __init dpi_cahce_module_init(void) { create_crc_table(); dpi_cache_list_init(); dpi_cache_timer_init(); //test_func(); return 0; } static void __exit dpi_cache_module_exit(void) { dpi_cache_timer_exit(); dpi_cache_list_release(); } module_init(dpi_cahce_module_init); module_exit(dpi_cache_module_exit); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("rpdb process module"); MODULE_AUTHOR("wuhuanzheng");