secgateway/Platform/modules/rpdb/dpi_trie_cache.c

297 lines
5.9 KiB
C
Raw Normal View History

2019-08-28 07:29:18 +00:00
#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");