#include #include #include #include #include #include #include #include /* * 三元组超时时间设置为120s */ int dpi_cache_node_timeout = 120; /* * 三元组数据结构 */ struct dpi_cache_node { struct list_head list; union { struct in6_addr ip6; struct in_addr ip4; }ip; __u16 proto; __u16 port; __u32 appid; uint64_t uptime; }; /* * 初始化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 dport; 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) { int i = 0; int dip = 0; pkt_info_t info; info.dport = node.port; info.sport = 0; info.srcip = 0; info.proto = node.proto; if (node.ip.ip4.s_addr !=0 ) { info.dstip = node.ip.ip4.s_addr; } else { 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) { int i = 0; if (src.port != dst.port){ return false; } if (src.proto != dst.proto){ return false; } if(src.ip.ip4.s_addr != 0){ if(src.ip.ip4.s_addr != dst.ip.ip4.s_addr){ return false; } }else{ for (i = 0; i < 4; i++){ if (src.ip.ip6.s6_addr32[i] != dst.ip.ip6.s6_addr32[i]){ return false; } } } if (update_appid){ 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; struct dpi_cache_node *pNode; int hash = dpi_cache_node_hash(node); list_for_each(pList,&dpi_cache_head[hash]){ 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); pNode->uptime = get_jiffies_64(); pNode->appid = node.appid; list_add_tail(&pNode->list,&dpi_cache_head[hash]); return true; } /* * 释放hash链表上所有node节点 */ void dpi_cache_list_release(void) { struct list_head * pList = NULL; struct dpi_cache_node *pNode = NULL; int i = 0; for (i = 0; i < TRIPLE_CAHCE_HASH_SIZE; i++){ list_for_each(pList,&dpi_cache_head[i]){ pNode = list_entry(pList,struct dpi_cache_node,list); if(pNode){ list_del(&pNode->list); } } } } /* *定时器超时,删除超时的节点 */ void dpi_cache_node_timeout_func(void) { struct list_head * pList = NULL; struct dpi_cache_node *pNode = NULL; int i = 0; for (i = 0; i < TRIPLE_CAHCE_HASH_SIZE; i++){ list_for_each(pList,&dpi_cache_head[i]){ pNode = list_entry(pList,struct dpi_cache_node,list); 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; } void dpi_cache_timer_exit(void) { printk(KERN_INFO"%s jiffies:%ld\n", __func__, jiffies); del_timer(&gTimer); } int dpi_cahce_module_init(void) { dpi_cache_timer_init(); dpi_cache_list_init(); return 1; } int dpi_cache_module_exit(void) { dpi_cache_timer_exit(); dpi_cache_list_release(); return 1; } module_init(dpi_cahce_module_init); module_exit(dpi_cache_timer_exit); MODULE_LICENSE("GPL");