secgateway/Platform/modules/rpdb/dpi_trie_cache.c

297 lines
5.9 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/timer.h>
#include <linux/uaccess.h>
#include <linux/sysctl.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
/*
* 三元组超时时间设置为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");