diff --git a/Platform/modules/rpdb/dpi_trie_cache.c b/Platform/modules/rpdb/dpi_trie_cache.c new file mode 100644 index 000000000..643d61131 --- /dev/null +++ b/Platform/modules/rpdb/dpi_trie_cache.c @@ -0,0 +1,296 @@ + +#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"); + + diff --git a/Platform/user/rpdb/list.h b/Platform/user/rpdb/list.h new file mode 100644 index 000000000..6541971ec --- /dev/null +++ b/Platform/user/rpdb/list.h @@ -0,0 +1,641 @@ +#ifndef _LINUX_LIST_H +#define _LINUX_LIST_H + +#define container_of(ptr,type,member) ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) + + +//#if defined(__KERNEL__) || defined(_LVM_H_INCLUDE) + +//#include + +/* + * Simple doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + */ + +typedef struct list_head { + struct list_head *next, *prev; +} list_t; + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +#define INIT_LIST_HEAD(ptr) do { \ + (ptr)->next = (ptr); (ptr)->prev = (ptr); \ +} while (0) + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ + +static void inline prefetch(void *p){} + +static inline void __list_add(struct list_head *new, + struct list_head *prev, + struct list_head *next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} + +/** + * list_add - add a new entry + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static inline void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + +/** + * list_add_tail - add a new entry + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static inline void list_add_tail(struct list_head *new, struct list_head *head) +{ + __list_add(new, head->prev, head); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_del(struct list_head *prev, struct list_head *next) +{ + next->prev = prev; + prev->next = next; +} + +/** + * list_del - deletes entry from list. + * @entry: the element to delete from the list. + * Note: list_empty on entry does not return true after this, the entry is in an undefined state. + */ +static inline void list_del(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + entry->next = (void *) 0; + entry->prev = (void *) 0; +} + +/** + * list_replace - replace old entry by new one + * @old : the element to be replaced + * @new : the new element to insert + * + * If @old was empty, it will be overwritten. + */ +static inline void list_replace(struct list_head *old, + struct list_head *new) +{ + new->next = old->next; + new->next->prev = new; + new->prev = old->prev; + new->prev->next = new; +} + +static inline void list_replace_init(struct list_head *old, + struct list_head *new) +{ + list_replace(old, new); + INIT_LIST_HEAD(old); +} + +/** + * list_del_init - deletes entry from list and reinitialize it. + * @entry: the element to delete from the list. + */ +static inline void list_del_init(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + INIT_LIST_HEAD(entry); +} + +/** + * list_move - delete from one list and add as another's head + * @list: the entry to move + * @head: the head that will precede our entry + */ +static inline void list_move(struct list_head *list, struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add(list, head); +} + +/** + * list_move_tail - delete from one list and add as another's tail + * @list: the entry to move + * @head: the head that will follow our entry + */ +static inline void list_move_tail(struct list_head *list, + struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add_tail(list, head); +} + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static inline int list_empty(const struct list_head *head) +{ + return head->next == head; +} + +static inline void __list_splice(struct list_head *list, + struct list_head *head) +{ + struct list_head *first = list->next; + struct list_head *last = list->prev; + struct list_head *at = head->next; + + first->prev = head; + head->next = first; + + last->next = at; + at->prev = last; +} + +/** + * list_splice - join two lists + * @list: the new list to add. + * @head: the place to add it in the first list. + */ +static inline void list_splice(struct list_head *list, struct list_head *head) +{ + if (!list_empty(list)) + __list_splice(list, head); +} + +/** + * list_splice_init - join two lists and reinitialise the emptied list. + * @list: the new list to add. + * @head: the place to add it in the first list. + * + * The list at @list is reinitialised + */ +static inline void list_splice_init(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) { + __list_splice(list, head); + INIT_LIST_HEAD(list); + } +} + +/** + * list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_head within the struct. + */ +#define list_entry(ptr, type, member) \ + container_of(ptr, type, member) + +/** + * list_first_entry - get the first element from a list + * @ptr: the list head to take the element from. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_head within the struct. + * + * Note, that list is expected to be not empty. + */ +#define list_first_entry(ptr, type, member) \ + list_entry((ptr)->next, type, member) + +/** + * list_last_entry - get the last element from a list + * @ptr: the list head to take the element from. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_head within the struct. + * + * Note, that list is expected to be not empty. + */ +#define list_last_entry(ptr, type, member) \ + list_entry((ptr)->prev, type, member) + +/** + * list_first_entry_or_null - get the first element from a list + * @ptr: the list head to take the element from. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_head within the struct. + * + * Note that if the list is empty, it returns NULL. + */ +#define list_first_entry_or_null(ptr, type, member) \ + (!list_empty(ptr) ? list_first_entry(ptr, type, member) : NULL) + +/** + * list_next_entry - get the next element in list + * @pos: the type * to cursor + * @member: the name of the list_head within the struct. + */ +#define list_next_entry(pos, member) \ + list_entry((pos)->member.next, typeof(*(pos)), member) + +/** + * list_prev_entry - get the prev element in list + * @pos: the type * to cursor + * @member: the name of the list_head within the struct. + */ +#define list_prev_entry(pos, member) \ + list_entry((pos)->member.prev, typeof(*(pos)), member) + +/** + * list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop cursor. + * @head: the head for your list. + */ +#define list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + +/** + * list_for_each_prev - iterate over a list backwards + * @pos: the &struct list_head to use as a loop cursor. + * @head: the head for your list. + */ +#define list_for_each_prev(pos, head) \ + for (pos = (head)->prev; pos != (head); pos = pos->prev) + +/** + * list_for_each_safe - iterate over a list safe against removal of list entry + * @pos: the &struct list_head to use as a loop cursor. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, n = pos->next) + +/** + * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry + * @pos: the &struct list_head to use as a loop cursor. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_prev_safe(pos, n, head) \ + for (pos = (head)->prev, n = pos->prev; \ + pos != (head); \ + pos = n, n = pos->prev) + +/** + * list_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_head within the struct. + */ +#define list_for_each_entry(pos, head, member) \ + for (pos = list_first_entry(head, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_next_entry(pos, member)) + +/** + * list_for_each_entry_reverse - iterate backwards over list of given type. + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_head within the struct. + */ +#define list_for_each_entry_reverse(pos, head, member) \ + for (pos = list_last_entry(head, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_prev_entry(pos, member)) + +/** + * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue() + * @pos: the type * to use as a start point + * @head: the head of the list + * @member: the name of the list_head within the struct. + * + * Prepares a pos entry for use as a start point in list_for_each_entry_continue(). + */ +#define list_prepare_entry(pos, head, member) \ + ((pos) ? : list_entry(head, typeof(*pos), member)) + +/** + * list_for_each_entry_continue - continue iteration over list of given type + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_head within the struct. + * + * Continue to iterate over list of given type, continuing after + * the current position. + */ +#define list_for_each_entry_continue(pos, head, member) \ + for (pos = list_next_entry(pos, member); \ + &pos->member != (head); \ + pos = list_next_entry(pos, member)) + +/** + * list_for_each_entry_continue_reverse - iterate backwards from the given point + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_head within the struct. + * + * Start to iterate over list of given type backwards, continuing after + * the current position. + */ +#define list_for_each_entry_continue_reverse(pos, head, member) \ + for (pos = list_prev_entry(pos, member); \ + &pos->member != (head); \ + pos = list_prev_entry(pos, member)) + +/** + * list_for_each_entry_from - iterate over list of given type from the current point + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_head within the struct. + * + * Iterate over list of given type, continuing from current position. + */ +#define list_for_each_entry_from(pos, head, member) \ + for (; &pos->member != (head); \ + pos = list_next_entry(pos, member)) + +/** + * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_head within the struct. + */ +#define list_for_each_entry_safe(pos, n, head, member) \ + for (pos = list_first_entry(head, typeof(*pos), member), \ + n = list_next_entry(pos, member); \ + &pos->member != (head); \ + pos = n, n = list_next_entry(n, member)) + +/** + * list_for_each_entry_safe_continue - continue list iteration safe against removal + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_head within the struct. + * + * Iterate over list of given type, continuing after current point, + * safe against removal of list entry. + */ +#define list_for_each_entry_safe_continue(pos, n, head, member) \ + for (pos = list_next_entry(pos, member), \ + n = list_next_entry(pos, member); \ + &pos->member != (head); \ + pos = n, n = list_next_entry(n, member)) + +/** + * list_for_each_entry_safe_from - iterate over list from current point safe against removal + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_head within the struct. + * + * Iterate over list of given type from current point, safe against + * removal of list entry. + */ +#define list_for_each_entry_safe_from(pos, n, head, member) \ + for (n = list_next_entry(pos, member); \ + &pos->member != (head); \ + pos = n, n = list_next_entry(n, member)) + +/** + * list_for_each_entry_safe_reverse - iterate backwards over list safe against removal + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_head within the struct. + * + * Iterate backwards over list of given type, safe against removal + * of list entry. + */ +#define list_for_each_entry_safe_reverse(pos, n, head, member) \ + for (pos = list_last_entry(head, typeof(*pos), member), \ + n = list_prev_entry(pos, member); \ + &pos->member != (head); \ + pos = n, n = list_prev_entry(n, member)) + +/** + * list_safe_reset_next - reset a stale list_for_each_entry_safe loop + * @pos: the loop cursor used in the list_for_each_entry_safe loop + * @n: temporary storage used in list_for_each_entry_safe + * @member: the name of the list_head within the struct. + * + * list_safe_reset_next is not safe to use in general if the list may be + * modified concurrently (eg. the lock is dropped in the loop body). An + * exception to this is if the cursor element (pos) is pinned in the list, + * and list_safe_reset_next is called after re-taking the lock and before + * completing the current iteration of the loop body. + */ +#define list_safe_reset_next(pos, n, member) \ + n = list_next_entry(pos, member) + + +/* + * Double linked lists with a single pointer list head. + * Mostly useful for hash tables where the two pointer list head is + * too wasteful. + * You lose the ability to access the tail in O(1). + */ +#define LIST_POISON1 NULL +#define LIST_POISON2 NULL + +#define READ_ONCE(x) (x) +#define WRITE_ONCE(x, val) x=(val) + + +struct hlist_head { + struct hlist_node *first; +}; + +struct hlist_node { + struct hlist_node *next, **pprev; +}; + +#define HLIST_HEAD_INIT { .first = NULL } +#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL } +#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL) +static inline void INIT_HLIST_NODE(struct hlist_node *h) +{ + h->next = NULL; + h->pprev = NULL; +} + +static inline int hlist_unhashed(const struct hlist_node *h) +{ + return !h->pprev; +} + +static inline int hlist_empty(const struct hlist_head *h) +{ + return !READ_ONCE(h->first); +} + +static inline void __hlist_del(struct hlist_node *n) +{ + struct hlist_node *next = n->next; + struct hlist_node **pprev = n->pprev; + + WRITE_ONCE(*pprev, next); + if (next) + next->pprev = pprev; +} + +static inline void hlist_del(struct hlist_node *n) +{ + __hlist_del(n); + n->next = LIST_POISON1; + n->pprev = LIST_POISON2; +} + +static inline void hlist_del_init(struct hlist_node *n) +{ + if (!hlist_unhashed(n)) { + __hlist_del(n); + INIT_HLIST_NODE(n); + } +} + +static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) +{ + struct hlist_node *first = h->first; + n->next = first; + if (first) + first->pprev = &n->next; + WRITE_ONCE(h->first, n); + n->pprev = &h->first; +} + +/* next must be != NULL */ +static inline void hlist_add_before(struct hlist_node *n, + struct hlist_node *next) +{ + n->pprev = next->pprev; + n->next = next; + next->pprev = &n->next; + WRITE_ONCE(*(n->pprev), n); +} + +static inline void hlist_add_behind(struct hlist_node *n, + struct hlist_node *prev) +{ + n->next = prev->next; + WRITE_ONCE(prev->next, n); + n->pprev = &prev->next; + + if (n->next) + n->next->pprev = &n->next; +} + +/* after that we'll appear to be on some hlist and hlist_del will work */ +static inline void hlist_add_fake(struct hlist_node *n) +{ + n->pprev = &n->next; +} + +static inline int hlist_fake(struct hlist_node *h) +{ + return h->pprev == &h->next; +} + +/* + * Check whether the node is the only node of the head without + * accessing head: + */ +static inline int +hlist_is_singular_node(struct hlist_node *n, struct hlist_head *h) +{ + return !n->next && n->pprev == &h->first; +} + +/* + * Move a list from one list head to another. Fixup the pprev + * reference of the first entry if it exists. + */ +static inline void hlist_move_list(struct hlist_head *old, + struct hlist_head *new) +{ + new->first = old->first; + if (new->first) + new->first->pprev = &new->first; + old->first = NULL; +} + +#define hlist_entry(ptr, type, member) container_of(ptr,type,member) + +#define hlist_for_each(pos, head) \ + for (pos = (head)->first; pos ; pos = pos->next) + +#define hlist_for_each_safe(pos, n, head) \ + for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \ + pos = n) + +#define hlist_entry_safe(ptr, type, member) \ + ({ typeof(ptr) ____ptr = (ptr); \ + ____ptr ? hlist_entry(____ptr, type, member) : NULL; \ + }) + +/** + * hlist_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry(pos, head, member) \ + for (pos = hlist_entry_safe((head)->first, typeof(*(pos)), member);\ + pos; \ + pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member)) + +/** + * hlist_for_each_entry_continue - iterate over a hlist continuing after current point + * @pos: the type * to use as a loop cursor. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry_continue(pos, member) \ + for (pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member);\ + pos; \ + pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member)) + +/** + * hlist_for_each_entry_from - iterate over a hlist continuing from current point + * @pos: the type * to use as a loop cursor. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry_from(pos, member) \ + for (; pos; \ + pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member)) + +/** + * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @pos: the type * to use as a loop cursor. + * @n: another &struct hlist_node to use as temporary storage + * @head: the head for your list. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry_safe(pos, n, head, member) \ + for (pos = hlist_entry_safe((head)->first, typeof(*pos), member);\ + pos && ({ n = pos->member.next; 1; }); \ + pos = hlist_entry_safe(n, typeof(*pos), member)) + + +#endif diff --git a/Platform/user/rpdb/rpdb.c b/Platform/user/rpdb/rpdb.c new file mode 100644 index 000000000..7230b1c03 --- /dev/null +++ b/Platform/user/rpdb/rpdb.c @@ -0,0 +1,468 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "list.h" + + + +struct rpdb_mark { + struct list_head list; + union { + struct in6_addr ip6; + struct in_addr ip4; + + }ip; + + int mark; +}; + + + + +char rt_table[11][128]= { + "# reserved values", + "#", + "255 local", + "254 main", + "253 default", + "0 unspe", + "#", + "# local", + "#", + "#1 inr.ruhep" +}; + + +#define RT_TABLES_PATH ("/etc/iproute2/rt_tables") +#define IPV4_PATTERN "^([0-9]|[1-9][0-9]|1[0-9]{1,2}|2[0-4][0-9]|25[0-5]).([0-9]|[1-9][0-9]|1[0-9]{1,2}|2[0-4][0-9]|25[0-5]).([0-9]|[1-9][0-9]|1[0-9]{1,2}|2[0-4][0-9]|25[0-5]).([0-9]|[1-9][0-9]|1[0-9]{1,2}|2[0-4][0-9]|25[0-5])$" +#define IPV6_PATTERN "^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$" + +#define RPDP_MARK_HASH_DEPTH (1024) +static int gRpdbMark = 0; + +/* + * mark hash list,save mark + */ +struct list_head gRpdbMarkList[RPDP_MARK_HASH_DEPTH] = {0}; + + +/* + popen +*/ + + +void +print_result(FILE *fp) +{ + char buf[100]; + + if(!fp) { + return; + } + printf("\n>>>\n"); + memset(buf, 0, sizeof(buf)); + fgets(buf, sizeof(buf) - 1, fp) ; + + + printf("%s", buf); + + + printf("\n<<<\n"); +} + +int rpdb_popen(char *cmd) +{ + FILE *fp = NULL; + + + fp = NULL; + fp = popen(cmd, "r"); + if(!fp) + { + perror("popen"); + exit(EXIT_FAILURE); + } + print_result(fp); + pclose(fp); + sleep(1); + return 0; +} + +/* + * rpdb 初始化接口 +*/ +bool rpdb_init_route() +{ + FILE *fp = NULL; + int i = 0; + + system("echo > /etc/iproute2/rt_tables"); + fp = fopen(RT_TABLES_PATH,"w"); + if (fp) + { + for (i = 0; i < 11; i++) + { + fprintf(fp,"%s\n",rt_table[i]); + } + } + else + { + return false; + } + + fclose(fp); + + + /* + 初始化链表 + */ + for (i = 0; i < RPDP_MARK_HASH_DEPTH; i++) + { + INIT_LIST_HEAD(&gRpdbMarkList[i]); + } + + return true; +} + + + +static int gRpdbTableIndex = 1; /* 1 - 252 */ +#define RPDB_TABLE_ADD (0) +#define RPDB_TABLE_DEL (1) +bool rpdb_add_delete_table(const char* gateway,const char *tbl_name,int op) +{ + char table_name[128] = {0}; + char line_cnt[1024] = {0}; + FILE *fp = NULL; + FILE *fp_tmp = NULL; + bool ret = false; + int i = 0; + int cn_num = 0; + if (tbl_name == NULL) + { + memset(table_name,0,sizeof(table_name)); + sprintf(table_name,"table_%s",gateway); + } + else + { + if (strlen(tbl_name) < 1) /* 检查name的合法性*/ + { + memset(table_name,0,sizeof(table_name)); + sprintf(table_name,"%s",tbl_name); + } + else + { + return false; + } + } + + fp = fopen(RT_TABLES_PATH,"ra+"); + if (NULL == fp) + { + return false; + } + else + { + while(!feof(fp)) /* 遍历文件每一行,查找 路由表是否存在 */ + { + memset(line_cnt,0,1024); + fgets(line_cnt,1024,fp); + if(strstr(line_cnt,table_name)) + { + if (op == RPDB_TABLE_ADD) + { + fclose(fp); + return true; + } + } + } + } + + /* + 向文件最后一行添加 路由表项 + */ + if (op == RPDB_TABLE_ADD) + { + if (gRpdbTableIndex > 252) + { + return false; + } + + memset(line_cnt,0,1024); + sprintf(line_cnt,"%d %s",gRpdbTableIndex,table_name); + printf("RPDB_TABLE_ADD:%s\n",line_cnt); + fprintf(fp,"%s\n",line_cnt); + fclose(fp); + gRpdbTableIndex++; + return true; + } + + if (op == RPDB_TABLE_DEL) + { + fp = fopen(RT_TABLES_PATH,"r+"); + if (NULL == fp) + { + return false; + } + else + { + fp_tmp = fopen("/tmp/rt_tables","w"); + if (fp_tmp == NULL) return false; + while(!feof(fp)) /* 遍历文件每一行,查找 路由表是否存在 */ + { + memset(line_cnt,0,1024); + fgets(line_cnt,1024,fp); + if(!strstr(line_cnt,table_name)) + { + fprintf(fp_tmp,"%s",line_cnt); + } + + } + + fclose(fp); + fclose(fp_tmp); + system("cp -fr /tmp/rt_tables /etc/iproute2/rt_tables"); + } + + } + return true; +} + +/* + * 判断ip地址是否合法 + */ + +int rpdb_ipaddr_match(char *ip_addr,int flag) +{ + regex_t reg; + regmatch_t match[1]; + int retval = 0; + + if (flag == 1) + { + retval = regcomp(®, IPV4_PATTERN, REG_EXTENDED | REG_NEWLINE); + } + else + { + retval = regcomp(®, IPV6_PATTERN, REG_EXTENDED | REG_NEWLINE); + } + + retval = regexec(®,ip_addr, sizeof match / sizeof match[0], match, 0); + printf("%s is %s\n", ip_addr, retval == 0 ? "legal" : "illegal"); + regfree(®); + return retval; +} + + +int rpdb_ip_hash(struct rpdb_mark node) +{ + int ip_value = 0; + int hash = 0; + int i = 0; + if (node.ip.ip4.s_addr !=0 ) + { + ip_value = node.ip.ip4.s_addr; + } + else + { + for (i = 0; i < 4; ++i) + { + ip_value += node.ip.ip6.s6_addr32[i]; + } + } + hash = (ip_value&0xF) + ((ip_value >> 8)&0xF) + ((ip_value >> 16)&0xF) + ((ip_value >> 24)&0xF); + hash = hash&(1024-1); + return hash; +} + + +/* + * node比较 +*/ + +bool rpdb_mark_node_compare(struct rpdb_mark node1,struct rpdb_mark node2) +{ + if (node1.ip.ip4.s_addr == node2.ip.ip4.s_addr) + { + return true; + } + else + { + return false; + } +} + + +/* + * mark 查找,返回链上的node节点 + */ +struct rpdb_mark * rpdb_mark_search(struct rpdb_mark node) +{ + struct list_head * pList; + struct rpdb_mark *pNode; + int hash = rpdb_ip_hash(node); + + list_for_each(pList,&gRpdbMarkList[hash]) { + pNode = list_entry(pList,struct rpdb_mark,list); + printf("%s,%d,%d,%d\n",__FUNCTION__,__LINE__,pNode->ip.ip4.s_addr,pNode->mark); + if (rpdb_mark_node_compare(node,*pNode)){ + printf("%s,%d,mark = %d\n",__FUNCTION__,__LINE__,pNode->mark); + return pNode; + } + } + + return NULL; +} + +/* + * mark +*/ +int rpdb_mark_hash_add(struct rpdb_mark node) +{ + + struct rpdb_mark *pNode = NULL; + int hash = 0; + + pNode = rpdb_mark_search(node); + if (pNode != NULL) + { + return pNode->mark; + } + + pNode = (struct rpdb_mark*)malloc(sizeof(struct rpdb_mark)); + if (NULL == pNode) + { + return false; + } + + hash = rpdb_ip_hash(node); + node.mark = ++gRpdbMark; + memcpy((char*)pNode,(char*)&node,sizeof(struct rpdb_mark)); + + printf("%s,%d,%d,%d\n",__FUNCTION__,__LINE__,pNode->ip.ip4.s_addr,pNode->mark); + /* + 节点添加到链尾部 + */ + list_add_tail(&pNode->list,&gRpdbMarkList[hash]); + + return gRpdbMark; +} + + +/* + * 根据下一跳地址生成mark +*/ +int rpdb_gen_mark(const char* gateway) +{ + in_addr_t addr; + if (NULL == gateway) + { + return -1; + } + + addr = inet_addr(gateway); + struct rpdb_mark node; + node.ip.ip4.s_addr = addr; + return rpdb_mark_hash_add(node); +} + +/* + * 路由添加接口 +*/ +bool rpdb_add_route(const char* gateway,const char *tbl_name) +{ + char cmd[256] = {0}; + int status = 0; + char table_name[128] = {0}; + int mark = 0; + if (tbl_name == NULL) + { + memset(table_name,0,sizeof(table_name)); + sprintf(table_name,"table_%s",gateway); + } + else + { + if (strlen(tbl_name) < 1) /* 检查name的合法性*/ + { + memset(table_name,0,sizeof(table_name)); + sprintf(table_name,"%s",tbl_name); + } + else + { + return false; + } + } + + if (rpdb_add_delete_table(gateway,tbl_name,RPDB_TABLE_ADD) == false) + { + return false; + } + + if (strstr(":",gateway)) + { + sprintf(cmd,"ip -6 route add default via %s table %s",gateway,table_name); + } + else + { + sprintf(cmd,"ip route add default via %s table %s",gateway,table_name); + } + + printf("%s\n",cmd); + rpdb_popen(cmd); + + mark = rpdb_gen_mark(gateway); + memset(cmd,0,sizeof(cmd)); + sprintf(cmd,"ip rule add fwmark %d table %s",mark,table_name); + printf("%s\n",cmd); + rpdb_popen(cmd); + + return 0; +} + + +int main() +{ + //ipaddr_match("192.168.1.1",1); + + //ipaddr_match("192.168.1.300",1); + + //ipaddr_match("2000:0:0:0:0:0:0:1 ",2); + //ipaddr_match("fe80:0000:0000:0000:0204:61ff:fe9d:ffffff15",2); + struct rpdb_mark mark_value; + struct rpdb_mark mark_value1; + in_addr_t addr; + rpdb_init_route(); + rpdb_add_delete_table("1.1.2.1",NULL,RPDB_TABLE_ADD); + rpdb_add_delete_table("1.1.2.1",NULL,RPDB_TABLE_ADD); + rpdb_add_delete_table("1.2.2.1",NULL,RPDB_TABLE_ADD); + rpdb_add_delete_table("2.1.2.1",NULL,RPDB_TABLE_ADD); + + rpdb_add_delete_table("2.1.2.1",NULL,RPDB_TABLE_DEL); + //rpdb_add_delete_table("2.1.2.1",NULL,RPDB_TABLE_DEL); + //rpdb_add_delete_table("1.1.2.1",NULL,RPDB_TABLE_DEL); + addr = inet_addr("2006.6.6.6"); + mark_value.ip.ip4.s_addr = addr; + rpdb_mark_hash_add(mark_value); + rpdb_mark_hash_add(mark_value); + rpdb_mark_hash_add(mark_value); + rpdb_mark_hash_add(mark_value); + + addr = inet_addr("7.7.7.7"); + mark_value1.ip.ip4.s_addr = addr; + rpdb_mark_hash_add(mark_value1); + rpdb_mark_hash_add(mark_value1); + + + + rpdb_add_route("1.2.3.3",NULL); + rpdb_add_route("2.2.4.3",NULL); + rpdb_add_route("3.2.4.3",NULL); + rpdb_add_route("4.2.4.3",NULL); + + return 0; +}