diff --git a/Platform/common/rpc/list.h b/Platform/common/rpc/list.h new file mode 100644 index 000000000..5dc2503bf --- /dev/null +++ b/Platform/common/rpc/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/common/rpc/rpc_common.h b/Platform/common/rpc/rpc_common.h index d62f73afe..eff27ba7d 100755 --- a/Platform/common/rpc/rpc_common.h +++ b/Platform/common/rpc/rpc_common.h @@ -36,6 +36,8 @@ typedef enum { RET_NOTSUPPORT = 11, RET_INPUTERR = 12, RET_IPINVALID = 13, + RET_BR_INVALID = 14, + RET_EXIST = 15, } ret_code; #define RET_ERROR_DISC \ @@ -53,7 +55,9 @@ typedef enum { { RET_SOCKERR, "SockError"},\ { RET_NOTSUPPORT, "NotSupport"},\ { RET_INPUTERR, "InputError"},\ - { RET_IPINVALID, "IpInvalid"}\ + { RET_IPINVALID, "IpInvalid"},\ + { RET_BR_INVALID, "BrNameInvalid"}, + { RET_EXIST, "AlreadyExist"}\ } #define RET_BUFF_SIZE 256; diff --git a/Platform/common/rpc/rpc_util.h b/Platform/common/rpc/rpc_util.h index bb9027841..51ec9b874 100755 --- a/Platform/common/rpc/rpc_util.h +++ b/Platform/common/rpc/rpc_util.h @@ -75,6 +75,16 @@ do { \ }\ } while (0) +#define ASSERT_PTR_RET(ptr) \ +do { \ + if (ptr == NULL) \ + {\ + rpc_log_error("ret error: %s\n", rpc_code_format(RET_NULLP));\ + return RET_NULLP;\ + }\ +} while (0) + + #define ASSERT_RET_VOID(ret) \ do { \ if (ret != RET_OK) \ diff --git a/Platform/user/configm/config-server/include/brconfig.h b/Platform/user/configm/config-server/include/brconfig.h new file mode 100644 index 000000000..3b8c4dd00 --- /dev/null +++ b/Platform/user/configm/config-server/include/brconfig.h @@ -0,0 +1,162 @@ +#ifndef BRCONFIG_H_ +#define BRCONFIG_H_ + +#define BR_NAMSIZ INTERFACE_NAMSIZ +#define MAC_STRSIZ 32 +#define LOCAL_STRSIZ 16 +#define TIME_STRSIZ 16 +#define MAC_MAXIZS 1024 +#define FDB_CHUNK 128 + +typedef enum { + BR_CREATE_EVENT = 1, + BR_DELETE_EVENT, + BR_IF_JOIN_EVENT, + BR_IF_LEAVE_EVENT, + BR_EVENT_INVALID +} BR_EVENT_TYPE; + +typedef int (*BR_EVENT_FUNC)(BR_EVENT_TYPE event_type, br_event_t event_arg); + +/************************************************************/ +/* 结构体 */ +/************************************************************/ +/* 事件通知数据结构 */ +struct _br_event { + char *br_name; + char *if_name; +}; +typedef struct _br_event br_event_t; + +struct _br_event_node { + struct hlist_node list; + BR_EVENT_TYPE br_event; + BR_EVENT_FUNC event_func; +}; +typedef struct _br_event_node br_event_node_t; + +struct _br_event_head { + struct hlist_head head; + pthread_mutex_t lock; + boolean init; +}; +typedef struct _br_event_head br_event_head_t; + + +/* 临时数据结构 */ +struct _brif_temp { + int index; + char *if_list; +}; +typedef struct _brif_temp br_if_temp_t; + +struct _br_temp { + char *br_name; + boolean result; +}; +typedef struct _br_temp br_temp_t; + +/* 配置消息数据结构 */ +struct _br_config { + char br_name[BR_NAMSIZ]; + int port_num; + char *ports; +}; +typedef struct _br_config br_config_t; + +struct _br_fdb_config { + char br_name[BR_NAMSIZ]; +}; +typedef struct _br_fdb_config br_fdb_config_t; + +/* json解析数据结构 */ +struct _br_config_string { + int config_type; + char br_name[BR_NAMSIZ]; +}; +typedef struct _br_config_string br_config_string_t; + +struct _br_if_config_string { + int config_type; + char br_name[BR_NAMSIZ]; + char *ports; +}; +typedef struct _br_if_config_string br_if_config_string_t; + +struct _br_fdb_string{ + int config_type; + char br_name[BR_NAMSIZ]; +}; +typedef struct _br_fdb_string br_fdb_string_t; + +/* 状态数据结构 */ +struct _br_fdb_info{ + char mac_addr[MAC_STRSIZ]; + char port[INTERFACE_NAMSIZ]; + char local[LOCAL_STRSIZ]; + char time[TIME_STRSIZ]; +}; +typedef struct _br_fdb_info fdb_info_t; + +struct _br_fdb_status{ + char br_name[BR_NAMSIZ]; + int fdb_num; + fdb_info_t fdb_info[MAC_MAXIZS]; +}; +typedef struct _br_fdb_status br_fdb_status_t; + +/* **********************************************************/ +/* 提供给其他模块调用的函数 */ +/************************************************************/ + +/* 通过接口名获取所在桥名 */ +int br_if_bridge_get(char *port_name , char *br_name); + +/* 向桥中添加接口 */ +ret_code br_if_bridge_add(char *br_name, char *port_list, + int cnt, int *sys_err); + +/* 删除桥中的接口 */ +ret_code br_if_bridge_del(char *br_name, char *port_list, + int cnt, int *sys_err); + +/* 获取桥中接口数量 */ +int br_if_bridge_num(char *br_name); + +/* **********************************************************/ +/* 配置管理注册函数 */ +/************************************************************/ + +/* 桥配置 */ +ret_code br_config_chk(uint source,uint *config_type, + pointer input, int *input_len, + pointer output, int *output_len); + +ret_code br_config_proc(uint source, uint config_type, + pointer input, int input_len, + pointer output, int *output_len); +/* 桥接口配置 */ +ret_code br_if_config_chk(uint source,uint *config_type, + pointer input, int *input_len, + pointer output, int *output_len); + +ret_code br_if_config_proc(uint source, uint config_type, + pointer input, int input_len, + pointer output, int *output_len); + +ret_code br_if_config_get(uint source, + pointer input, int input_len, + pointer output, int *output_len); + +ret_code br_if_config_get_all(uint source, + pointer output, int *output_len); +/* 桥fdb配置 */ +ret_code br_fdb_config_chk(uint source,uint *config_type, + pointer input, int *input_len, + pointer output, int *output_len); + +ret_code br_fdb_config_get(uint source, + pointer input, int input_len, + pointer output, int *output_len); + +#endif diff --git a/Platform/user/configm/config-server/netconfig/bridge/brconfig.c b/Platform/user/configm/config-server/netconfig/bridge/brconfig.c new file mode 100644 index 000000000..5bc534f0b --- /dev/null +++ b/Platform/user/configm/config-server/netconfig/bridge/brconfig.c @@ -0,0 +1,925 @@ + +#include +#include +#include +#include +#include + +#include "configm.h" +#include "brconfig.h" +#include "rpc.h" +#include "parsefile.h" +#include "libbridge.h" +#include "brnetlink.h" +#include "list.h" + +#ifndef DESC("事件通知函数") +struct br_event_head_t br_event_tbl = {.lock = 0, .init = false}; + +int br_invoke_event(BR_EVENT_TYPE event_type, br_event_t event_arg) +{ + br_event_node_t *hnode; + + pthread_mutex_lock(&(br_event_tbl.lock)); + hlist_for_each_entry(hnode, &(br_event_tbl.head), list) + { + if(hnode->br_event == event_type) + { + hnode->event_func(event_type, event_arg); + } + } + pthread_mutex_unlock(&(br_event_tbl.lock)); +} + + +int br_event_register(BR_EVENT_TYPE event_type, BR_EVENT_FUNC event_func) +{ + br_event_node_t *hnode = NULL; + + if(br_event_tbl.init == false) + { INIT_HLIST_HEAD(&(br_event_tbl.head); + pthread_mutex_init(&(br_event_tbl.lock), NULL); + br_event_tbl.init = true; + } + + hnode = (br_event_node_t *)rpc_new0(br_event_node_t, 1); + if(!hnode) + { + rpc_log_error("br_event_register failed\n"); + return -1; + } + + INIT_HLIST_NODE(&hnode->list); + hnode->br_event = event_type; + hnode->event_func = event_func; + + pthread_mutex_lock(&(br_event_tbl.lock)); + hlist_add_head(&hnode->list, &(br_event_tbl.head)); + pthread_mutex_unlock(&(br_event_tbl.lock)); + + return 0; +} + +int br_event_unregister(BR_EVENT_TYPE event_type, BR_EVENT_FUNC event_func) +{ + br_event_node_t *hnode = NULL; + struct hlist_node *n; + + if(br_event_tbl.init == false) + { + return 0; + } + + pthread_mutex_lock(&(br_event_tbl.lock)); + hlist_for_each_entry_safe(hnode, n, &(br_event_tbl.head), list) + { + if(event_type == hnode->br_event && + event_func == hnode->event_func) + { + hlist_del(&hnode->list); + rpc_free(hnode); + break; + } + } + pthread_mutex_unlock(&(br_event_tbl.lock)); + + return 0; +} + +#endif +#ifndef DESC("桥配置辅助函数") +int br_copy_port_name(const char *b, const char *p, void *arg) +{ + br_if_temp_t *br_if = (br_if_temp_t *)arg; + char *dst_ptr = NULL; + + br_if->if_list = realloc(br_if->if_list, INTERFACE_NAMSIZ); + ASSERT_PTR_RET(br_if->if_list); + + dst_ptr = br_if->if_list + br_if->index * INTERFACE_NAMSIZ + strncpy(dst_ptr, p, INTERFACE_NAMSIZ - 1); + + br_if->index++; + return 0; +} + +ret_code br_name_chk(char *br_name) +{ + if(strlen(br_name) == 0 + || strlen(br_name) > BR_NAMSIZ - 1 + || strstr(br_name, "br-vl") != NULL) + { + return RET_BR_INVALID; + } + + return RET_OK; +} + +int br_name_cmp(char *br_name, void *args) +{ + br_temp_t *cmp_args = (br_temp_t *)args; + + if(strcmp(br_name, cmp_args->br_name) == 0) + { + cmp_args->result = true; + return 1; + } + + return 0; +} + +boolean br_is_exist(char *br_name) +{ + br_temp_t cmp_args = {br_name, false}; + + br_foreach_bridge(br_name_cmp, &cmp_args); + + return cmp_args.result; +} + + +ret_code br_if_bridge_get(char *port_name, char* br_name) +{ + char bridge_name[BR_NAMSIZ] = {0}; + + if(get_br_from_port(port_name, bridge_name) == RET_OK) + { + if(br_name) + { + strncpy(br_name, bridge_name, BR_NAMSIZ - 1); + } + + return RET_OK; + } + + return RET_NOTFOUND; +} + +ret_code br_if_bridge_check(char *port_list, int cnt, uint config_type) +{ + char *ptr_name = NULL; + int i; + + for(i = 0; i< cnt; i++) + { + ptr_name = port_list + INTERFACE_NAMSIZ * i; + if (if_nametoindex(ptr_name) == 0) + { + return RET_NOTFOUND; + } + + if(br_if_bridge_get(ptr_name, NULL) == RET_OK) + { + if(config_type == CM_CONFIG_ADD) + { + return RET_EXIST; + } + } + else if(config_type == CM_CONFIG_DEL) + { + return RET_NOTFOUND; + } + } + + return RET_OK; +} + +ret_code br_if_bridge_add(char * br_name, char *port_list, int cnt, int *sys_err) +{ + ret_code ret = RET_OK; + char *port_name; + int err = 0; + int i; + + for(i = 0; i < cnt) + { + port_name = port_list + INTERFACE_NAMSIZ * i; + err = br_add_interface(br_name, port_name); + if(err != 0) + { + sys_err = err; + ret = RET_SYSERR; + continue; + } + + br_event_t event_arg = {br_name, port_name}; + br_invoke_event(BR_IF_JOIN_EVENT, event_arg); + } + + return ret; +} + +ret_code br_if_bridge_del(char * br_name, char *port_list, int cnt, int *sys_err) +{ + ret_code ret = RET_OK; + char *port_name; + int err = 0; + int i; + + for(i = 0; i < cnt) + { + port_name = port_list + INTERFACE_NAMSIZ * i; + err = br_del_interface(br_name, port_name); + if(err != 0) + { + sys_err = err; + ret = RET_SYSERR; + continue; + } + + br_event_t event_arg = {br_name, port_name}; + br_invoke_event(BR_IF_LEAVE_EVENT, event_arg); + } + + return ret; +} + +int br_if_bridge_num(char *br_name) +{ + int cnt = 0; + + err = br_for_port_num(br_name, &cnt); + cnt = (err != 0) ? 0 : cnt; + + return cnt; +} + +#endif + + +#ifndef DESC("桥配置json格式转换函数") + +ret_code br_config_json_parse(pointer input, uint *conf_type, char *br_name) +{ + cJSON *json_obj; + + json_obj = cJSON_Parse(input); + ASSERT_PTR_RET(json_obj); + + rpc_log_info("json input:\n %s\n", cJSON_Print(json_obj)); + + s2j_create_struct_obj(br_config, br_config_string_t); + + if(br_config == NULL) + { + cJSON_Delete(json_obj); + return RET_NOMEM; + } + + s2j_struct_get_basic_element(br_config, json_obj, int, config_type); + s2j_struct_get_string_element(br_config, json_obj, br_name, BR_NAMSIZ); + + strncpy(br_name, br_config->br_name, BR_NAMSIZ - 1); + *conf_type = br_config->config_type; + + s2j_delete_struct_obj(br_config); + cJSON_Delete(json_obj); + + return RET_OK; +} + +int br_json_to_string( cJSON *json_obj, pointer output) +{ + char *json_str; + int output_len = 0; + + if(json_obj == NULL) + { + return 0; + } + + json_str = cJSON_PrintUnformatted(json_array); + output_len = strlen(json_str) + 1; + + if(output_len > CM_BUFF_SIZE) + { + rpc_log_warn("output len is too long %d, cut off!", output_len); + json_str[CM_BUFF_SIZE - 1] = '\0'; + output_len = CM_BUFF_SIZE; + } + + memcpy(output, json_str, output_len); + + rpc_free(json_str); + s2j_delete_json_obj(json_obj); + + return output_len; +} + +cJSON *br_config_format_json(br_config_t *br_config) +{ + cJSON *json_obj; + + s2j_create_json_obj(json_obj); + if(json_obj == NULL) + { + return NULL; + } + + s2j_json_set_basic_element(json_obj, br_config, string, br_name); + s2j_json_set_array_element(json_obj, br_config, string, + ports, br_config->port_num); + + return json_obj; +} + +ret_code br_bridge_info( char *br_name, cJSON *json_obj, int *err) +{ + ret_code ret = RET_OK; + br_if_temp_t br_if = {0}; + br_config_t br_config = {0}; + + br_if.index = 0; + br_if.if_list = NULL; + + *err = br_foreach_port(br_name, br_copy_port_name, &br_if) + if (*err >= 0) + { + strncpy(br_config.br_name, br_name, BR_NAMSIZ - 1); + br_config.ports = br_if.if_list; + br_config.port_num = br_if.index; + json_obj = br_config_format_json(&br_config); + } + else + { + ret = RET_SYSERR; + } + + if(br_if.if_list) + { + rpc_free(br_if.if_list); + } + + return ret; +} + +int br_bridge_info_each(const char *br_name, void *args) +{ + cJSON *json_array = (cJSON *)args; + cJSON *json_obj = NULL; + ret_code ret = RET_OK; + int err = 0; + + ret = br_bridge_info(br_name, json_obj, &err); + + if(json_obj) + { + cJSON_AddItemToArray(json_array, json_obj); + } + + return 0; +} + +ret_code br_if_config_json_parse(pointer input, uint *conf_type, br_config_t *br_if) +{ + cJSON *json_obj; + int port_num = 0; + + json_obj = cJSON_Parse(input); + ASSERT_PTR_RET(json_obj); + + rpc_log_info("json input:\n %s\n", cJSON_Print(json_obj)); + + s2j_create_struct_obj(br_if_conf, br_if_config_string_t); + + if(br_if_conf == NULL) + { + cJSON_Delete(json_obj); + return RET_NOMEM; + } + + s2j_struct_get_basic_element(br_if_conf, json_obj, int, config_type); + *conf_type = br_if_conf->config_type; + + if(br_if_conf->config_type != CM_CONFIG_GET_ALL) + { + s2j_struct_get_string_element(br_if_conf, json_obj, string, br_name, BR_NAMSIZ); + strncpy(br_if->br_name, br_if_conf->br_name, BR_NAMSIZ - 1); + } + + if(br_if_conf->config_type == CM_CONFIG_ADD + || br_if_conf->config_type == CM_CONFIG_DEL) + { + s2j_struct_get_array_string_n(br_if_conf, json_obj, string, + ports, port_num, INTERFACE_NAMSIZ); + br_if->port_num = port_num; + br_if->ports = br_if_conf->ports; /*指针赋值,后续需要对该指针进行内存释放*/ + br_if_conf->ports = NULL; + } + + s2j_delete_struct_obj(br_if_conf); + cJSON_Delete(json_obj); + + return RET_OK; +} + +#endif + +#ifndef DESC("桥配置钩子函数") +ret_code br_config_chk(uint source,uint *config_type, + pointer input, int *input_len, + pointer output, int *output_len) +{ + int config_len = 0; + uint conf_type = CM_CONFIG_GET; + char br_name[BR_NAMSIZ] = {0}; + ret_code ret = RET_OK; + int code = 0; + + br_config_json_parse(input, &conf_type, br_name); + config_len = strlen(br_name) + 1; + + switch (conf_type) + { + case CM_CONFIG_ADD: + case CM_CONFIG_DEL: + case CM_CONFIG_GET: + ret = br_name_chk(br_name); + break; + case CM_CONFIG_GET_ALL: + break; + default: + ret = RET_NOTSUPPORT; + } + + /* 将传入的json数据转换成结构体,便于后续处理 */ + if(config_len <= CM_BUFF_SIZE) + { + memset(input, 0, *input_len); + memcpy(input, br_name, config_len); + *config_type = conf_type; + *input_len = config_len; + } + else + { + ret = RET_NOMEM; + } + + RET_ERR_FORMART(ret, code, output, *output_len); + + return ret; +} + +ret_code br_config_proc(uint source, uint config_type, + pointer input, int input_len, + pointer output, int *output_len) +{ + BR_EVENT_TYPE event_type = BR_EVENT_INVALID; + ret_code ret = RET_OK; + int sys_ret = 0; + char *br_name; + + br_name = (char *)input; + + if(config_type == CM_CONFIG_ADD) + { + sys_ret = br_add_bridge(br_name); + event_type = BR_CREATE_EVENT; + } + else if(config_type == CM_CONFIG_DEL) + { + sys_ret = br_del_bridge(br_name); + event_type = BR_DELETE_EVENT; + } + + if(sys_ret != 0) + { + ret = RET_SYSERR; + RET_ERR_FORMART(ret, sys_ret, output, *output_len); + return ret; + } + + if(event_type != BR_EVENT_INVALID) + { + br_event_t event_arg = {br_name, NULL}; + br_invoke_event(event_type, event_arg); + } + + return ret; +} + +#endif + + +#ifndef DESC("桥接口配置钩子函数") +ret_code br_if_config_chk(uint source,uint *config_type, + pointer input, int *input_len, + pointer output, int *output_len) +{ + ret_code ret = RET_OK; + br_config_t br_config = {0}; + br_config_t *temp_conf = NULL; + int cfg_len = 0; + + br_if_config_json_parse(input, config_type, &br_config); + + cfg_len = BR_NAMSIZ + sizeof(br_config.port_num) + + br_config.port_num * INTERFACE_NAMSIZ; + + if(cfg_len > CM_BUFF_SIZE) + { + ret = RET_NOMEM; + goto exit; + } + + ret = br_name_chk(br_config.br_name); + if(ret != RET_OK) + { + goto exit; + } + + if(br_is_exist(br_config.br_name) == false) + { + ret = RET_NOTFOUND; + goto exit; + } + + if(*config_type != CM_CONFIG_ADD && *config_type != CM_CONFIG_DEL) + { + ret = RET_INPUTERR; + goto exit; + } + + ret = br_if_bridge_check(br_config.ports, br_config.port_num, *config_type); + if(ret != RET_OK) + { + goto exit; + } + + memset(input, 0, *input_len); + temp_conf = (br_config_t *)input; + + strncpy(temp_conf->br_name, br_config.br_name, BR_NAMSIZ - 1); + temp_conf->port_num = br_config.port_num; + memcpy(temp_conf->ports, br_config.ports, br_config.port_num * INTERFACE_NAMSIZ); + + *input_len = cfg_len; + +exit: + RET_ERR_FORMART(ret, 0, output, *output_len); + rpc_free(br_config.ports); + return ret; +} + +ret_code br_if_config_proc(uint source, uint config_type, + pointer input, int input_len, + pointer output, int *output_len) +{ + br_config_t *br_conf = (br_config_t *)input; + ret_code ret = RET_OK; + int err = 0; + + if(config_type == CM_CONFIG_ADD) + { + ret = br_if_bridge_add(br_conf->br_name, br_conf->ports, + br_conf->port_num, &err); + } + else if(config_type == CM_CONFIG_DEL) + { + ret = br_if_bridge_del(br_conf->br_name, br_conf->ports, + br_conf->port_num, &err); + } + + RET_ERR_FORMART(ret, err, output, *output_len); + return ret; +} + +ret_code br_if_config_get(uint source, + pointer input, int input_len, + pointer output, int *output_len) +{ + ret_code ret = RET_OK; + cJSON *json_obj = NULL; + int err = 0; + + ret = br_bridge_info((char *)input, json_obj, &err); + + if(ret != RET_OK) + { + RET_ERR_FORMART(ret, err, output, *output_len); + } + else + { + *output_len = br_json_to_string(json_obj, output); + } + + return ret; +} + +ret_code br_if_config_get_all(uint source, + pointer output, int *output_len) +{ + cJSON *json_obj = NULL; + ret_code ret = RET_OK; + int err = 0; + + json_obj = cJSON_CreateArray(); + if(json_obj == NULL) + { + ret = RET_NOMEM; + RET_ERR_FORMART(RET_NOMEM, err, output, *output_len); + return ret; + } + + if(br_foreach_bridge(br_bridge_info_each, json_obj) > 0) + { + *output_len = br_json_to_string(json_obj, output); + } + + return ret; +} + + +#endif + +#ifndef DESC("桥FDB配置辅助函数") + +void br_format_time(const struct timeval *tv, char *str, int len) +{ + snprintf(str, len, "%4i.%.2i", (int)tv->tv_sec, (int)tv->tv_usec/10000); +} + + +int br_compare_fdbs(const void *_f0, const void *_f1) +{ + const struct fdb_entry *f0 = _f0; + const struct fdb_entry *f1 = _f1; + + return memcmp(f0->mac_addr, f1->mac_addr, 6); +} + +int br_get_if_from_portno(const char *brname, int port_no, char *ifname) +{ + int ifindices[MAX_PORTS]; + unsigned long args[4] = { BRCTL_GET_PORT_LIST, + (unsigned long)ifindices, MAX_PORTS, 0 }; + struct ifreq ifr; + + if (port_no >= MAX_PORTS) + return -1; + + memset(ifindices, 0, sizeof(ifindices)); + strncpy(ifr.ifr_name, brname, IFNAMSIZ); + ifr.ifr_data = (char *) &args; + + if (ioctl(br_socket_fd, SIOCDEVPRIVATE, &ifr) < 0) { + dprintf("get_portno: get ports of %s failed: %s\n", + brname, strerror(errno)); + return -1; + } + + if(if_indextoname(ifindices[port_no], ifname) == NULL) + { + return -1; + } + + return 0; +} + + +int br_fdb_get(char *brname, struct fdb_entry **br_fdb) +{ + struct fdb_entry *fdb; + int i = 0, n = 0; + int offset = 0; + + fdb = NULL; + *br_fdb = NULL; + + for(;;) { + fdb = realloc(fdb, (offset + FDB_CHUNK) * sizeof(struct fdb_entry)); + if (!fdb) { + rpc_log_error("Out of memory\n"); + return offset; + } + + *br_fdb = fdb; + + n = br_read_fdb(brname, fdb+offset, offset, FDB_CHUNK); + if (n == 0) + break; + + if (n < 0) { + rpc_log_error( "read of forward table failed: %s\n", strerror(errno)); + return offset; + } + + offset += n; + } + + qsort(fdb, offset, sizeof(struct fdb_entry), br_compare_fdbs); + + #if 0 + printf("port no\tmac addr\t\tis local?\tageing timer\n"); + for (i = 0; i < offset; i++) { + const struct fdb_entry *f = fdb + i; + printf("%3i\t", f->port_no); + printf("%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\t", + f->mac_addr[0], f->mac_addr[1], f->mac_addr[2], + f->mac_addr[3], f->mac_addr[4], f->mac_addr[5]); + printf("%s\t\t", f->is_local?"yes":"no"); + br_show_timer(&f->ageing_timer_value); + printf("\n"); + } + #endif + return offset; +} + +int br_fdb_cpy(br_fdb_status_t *fdb_status, struct fdb_entry *fdb) +{ + struct fdb_entry *temp_fdb; + char if_name[INTERFACE_NAMSIZ]; + int i = 0; + + for(i = 0; i < fdb_status->fdb_num && i < MAC_MAXIZS; i++) + { + temp_fdb = fdb + i; + + memset(if_name, 0, INTERFACE_NAMSIZ); + if(br_get_if_from_portno(fdb_status->br_name, + temp_fdb->port_no, + if_name) != 0) + { + rpc_log_error("port no %d can not get ifname\n", temp_fdb->port_no); + continue; + } + + snprintf(fdb_status->fdb_info[i].mac_addr, MAC_STRSIZ, + "%02x:%02x:%02x:%02x:%02x:%02x", + temp_fdb->mac_addr[0], temp_fdb->mac_addr[1], temp_fdb->mac_addr[2], + temp_fdb->mac_addr[3], temp_fdb->mac_addr[4], temp_fdb->mac_addr[5]); + + strncpy(fdb_status->fdb_info[i].port, if_name, INTERFACE_NAMSIZ - 1); + + if(temp_fdb->is_local) + { + strncpy(fdb_status->fdb_info[i].local, "true", LOCAL_STRSIZ - 1); + } + else + { + strncpy(fdb_status->fdb_info[i].local, "false", LOCAL_STRSIZ - 1); + } + + br_format_time(&temp_fdb->ageing_timer_value, + fdb_status->fdb_info[i].time, TIME_STRSIZ); + } + + return i; +} + +#endif + +#ifndef DESC("桥FDB配置json格式转换") +ret_code br_fdb_config_json_parse(pointer input, uint *conf_type, br_fdb_config_t *br_fdb) +{ + cJSON *json_obj; + int port_num = 0; + + json_obj = cJSON_Parse(input); + if(!json_obj) + { + return RET_INPUTERR; + } + + rpc_log_info("json input:\n %s\n", cJSON_Print(json_obj)); + + s2j_create_struct_obj(br_fdb_conf, br_fdb_string_t); + + if(br_fdb_conf == NULL) + { + cJSON_Delete(json_obj); + return RET_NOMEM; + } + + s2j_struct_get_string_element(br_fdb_conf, json_obj, string, br_name, BR_NAMSIZ); + + *conf_type = br_fdb_conf->config_type; + strncpy(br_fdb->br_name, br_fdb_conf->br_name, BR_NAMSIZ - 1); + + s2j_delete_struct_obj(br_fdb_conf); + cJSON_Delete(json_obj); + + return RET_OK; +} + +ret_code br_each_fdb_to_json_string(cJSON *json_array, fdb_info_t *fdb_info) +{ + cJSON *fdb_obj; + + s2j_create_json_obj(fdb_obj); + if(fdb_obj == NULL) + { + return RET_NOMEM; + } + + s2j_json_set_basic_element(fdb_obj, fdb_info, string, mac_addr); + s2j_json_set_basic_element(fdb_obj, fdb_info, string, port); + s2j_json_set_basic_element(fdb_obj, fdb_info, string, local); + s2j_json_set_basic_element(fdb_obj, fdb_info, string, time); + + cJSON_AddItemToArray(json_array, fdb_obj); + + return RET_OK +} + +int br_fdb_to_json_string(br_fdb_status_t *fdb_status, char *output) +{ + cJSON *br_obj; + cJSON *fdb_array; + char *json_str; + int i; + + s2j_create_json_obj(br_obj); + fdb_array = cJSON_CreateArray(); + + if(br_obj == NULL || fdb_array) + { + return 0; + } + + s2j_json_set_basic_element(br_obj, fdb_status, string, br_name); + s2j_json_set_basic_element(br_obj, fdb_status, int, fdb_num); + + for(i = 0; i < fdb_status->fdb_num; i++) + { + br_each_fdb_to_json_string(fdb_array, &(fdb_status->fdb_info[i])); + } + + cJSON_AddItemToObject(br_obj, "fdb", fdb_array); + + br_json_to_string(br_obj, output); + + return (strlen(output) + 1); +} + +#endif + + +#ifndef DESC("桥FDB表配置钩子函数") +ret_code br_fdb_config_chk(uint source,uint *config_type, + pointer input, int *input_len, + pointer output, int *output_len) +{ + ret_code ret = RET_OK; + br_fdb_config_t br_fdb = {0}; + br_fdb_config_t *temp_conf; + int cfg_len = 0; + + ret = br_fdb_config_json_parse(input, config_type, &br_fdb); + if(ret != RET_OK) + { + RET_ERR_FORMART(ret, 0, output, *output_len); + return ret; + } + + if(*config_type != CM_CONFIG_GET) + { + ret = RET_INPUTERR; + RET_ERR_FORMART(ret, 0, output, *output_len); + return ret; + } + + + /* 回填解析过的数据 */ + memset(input, 0, *input_len); + temp_conf = (br_fdb_config_t *)input; + + strncpy(temp_conf->br_name, br_fdb.br_name, BR_NAMSIZ - 1); + *input_len = cfg_len; + + return ret; +} + +ret_code br_fdb_config_get(uint source, + pointer input, int input_len, + pointer output, int *output_len) +{ + br_fdb_status_t *fdb_status; + br_fdb_config_t *br_fdb; + struct fdb_entry *fdb; + ret_code ret = RET_OK; + int err = 0; + + br_fdb = (br_fdb_config_t *)input; + + fdb_status = (br_fdb_status_t *)rpc_new0(br_fdb_status_t, 1); + if(fdb_status == NULL) + { + ret = RET_NOMEM; + RET_ERR_FORMART(ret, 0, output, *output_len); + return ret; + } + + strncpy(fdb_status->br_name, br_fdb->br_name, BR_NAMSIZ - 1); + fdb_status->fdb_num = br_fdb_get(br_fdb->br_name, &fdb); + fdb_status->fdb_num = br_fdb_cpy(fdb_status, fdb); + + *output_len = br_fdb_to_json_string(fdb_status, output); + + rpc_free(fdb); + rpc_free(fdb_status); + + return ret; +} + +#endif diff --git a/Platform/user/configm/config-server/netconfig/bridge/brnetlink.c b/Platform/user/configm/config-server/netconfig/bridge/brnetlink.c new file mode 100644 index 000000000..eeea5c1d3 --- /dev/null +++ b/Platform/user/configm/config-server/netconfig/bridge/brnetlink.c @@ -0,0 +1,282 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "brnetlink.h" + +#define BR_NLMSG_TAIL(nmsg) \ + ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) +#define BR_MIN(a, b) ((a) < (b) ? (a) : (b)) + +int br_seq = 0; +int br_fd = -1; + +int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,int alen) +{ + int len = RTA_LENGTH(alen); + struct rtattr *rta; + + if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) { + printf("addattr_l ERROR: message exceeded bound of %d\n",maxlen); + return -1; + } + rta = BR_NLMSG_TAIL(n); + rta->rta_type = type; + rta->rta_len = len; + memcpy(RTA_DATA(rta), data, alen); + n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len); + return 0; +} + +int netlink_socket(unsigned long groups) +{ + socklen_t addr_len; + struct sockaddr_nl snl; + int fd = -1; + int ret; + + + fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); + if (fd < 0) { + rpc_log_error("Netlink: Cannot open netlink socket : (%s)",strerror(errno)); + return -1; + } + + ret = fcntl(fd, F_SETFL, O_NONBLOCK); + if (ret < 0) { + rpc_log_error("Netlink: Cannot set netlink socket flags : (%s)",strerror(errno)); + close(fd); + return -1; + } + + memset(&snl, 0, sizeof (snl)); + snl.nl_family = AF_NETLINK; + snl.nl_groups = groups; /*设为0 表示不用多播,其他情况按照设置的组来进行多播,就是会多播到这些组*/ + + ret = bind(fd, (struct sockaddr *) &snl, sizeof (snl)); + if (ret < 0) { + rpc_log_error("Netlink: Cannot bind netlink socket : (%s)", + strerror(errno)); + close(fd); + return -1; + } + + addr_len = sizeof (snl); + ret = getsockname(fd, (struct sockaddr *) &snl, &addr_len); + if (ret < 0 || addr_len != sizeof (snl)) { + printf("Netlink: Cannot getsockname : (%s)",strerror(errno)); + close(fd); + return -1; + } + + if (snl.nl_family != AF_NETLINK) { + printf("Netlink: Wrong address family %d",snl.nl_family); + close(fd); + return -1; + } + + br_seq = time(NULL); + return fd; +} + +int rtnl_talk(int fd , struct nlmsghdr *n, + struct nlmsghdr *answer, size_t maxlen) +{ + int status; + struct nlmsghdr *h; + struct sockaddr_nl nladdr = { .nl_family = AF_NETLINK }; + struct iovec iov = { + .iov_base = n, + .iov_len = n->nlmsg_len + }; + struct msghdr msg = { + .msg_name = &nladdr, + .msg_namelen = sizeof(nladdr), + .msg_iov = &iov, + .msg_iovlen = 1, + }; + char buf[32768] = {}; + + n->nlmsg_seq = ++br_seq; + + if (answer == NULL) + n->nlmsg_flags |= NLM_F_ACK; + + status = sendmsg(fd, &msg, 0); + if (status < 0) { + perror("Cannot talk to rtnetlink"); + return -1; + } + + iov.iov_base = buf; + while (1) { + iov.iov_len = sizeof(buf); + status = recvmsg(fd, &msg, 0); + + if (status < 0) { + if (errno == EINTR || errno == EAGAIN) + continue; + printf("netlink receive error %s (%d)\n",strerror(errno), errno); + return -1; + } + if (status == 0) { + printf("EOF on netlink\n"); + return -1; + } + if (msg.msg_namelen != sizeof(nladdr)) { + printf("sender address length == %d\n",msg.msg_namelen); + exit(1); + } + for (h = (struct nlmsghdr *)buf; status >= sizeof(*h); ) { + int len = h->nlmsg_len; + int l = len - sizeof(*h); + + if (l < 0 || len > status) { + if (msg.msg_flags & MSG_TRUNC) { + printf("Truncated message\n"); + return -1; + } + printf("!!!malformed message: len=%d\n",len); + exit(1); + } + + if (nladdr.nl_pid != 0 || + h->nlmsg_seq != br_seq) { + /* Don't forget to skip that message. */ + status -= NLMSG_ALIGN(len); + h = (struct nlmsghdr *)((char *)h + NLMSG_ALIGN(len)); + continue; + } + + if (h->nlmsg_type == NLMSG_ERROR) { + struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(h); + + if (l < sizeof(struct nlmsgerr)) { + fprintf(stderr, "ERROR truncated\n"); + } else if (!err->error) { + if (answer) + memcpy(answer, h, + BR_MIN(maxlen, h->nlmsg_len)); + return 0; + } + + errno = -err->error; + return -1; + } + + if (answer) { + memcpy(answer, h, + BR_MIN(maxlen, h->nlmsg_len)); + return 0; + } + + printf("Unexpected reply!!!\n"); + + status -= NLMSG_ALIGN(len); + h = (struct nlmsghdr *)((char *)h + NLMSG_ALIGN(len)); + } + + if (msg.msg_flags & MSG_TRUNC) { + printf("Message truncated\n"); + continue; + } + + if (status) { + fprintf(stderr, "!!!Remnant of size %d\n", status); + exit(1); + } + } +} + +void parse_rtattr(struct rtattr **tb, int max, struct rtattr *rta, int len) +{ + while (RTA_OK(rta, len)) { + if (rta->rta_type <= max) + tb[rta->rta_type] = rta; + rta = RTA_NEXT(rta, len); + } +} + +int get_br_from_port(char *port_name , char *br_name) +{ + struct { + struct nlmsghdr n; + struct ifinfomsg i; + char buf[1024]; + }req; + + if(if_nametoindex(port_name) == 0) + { + return RET_NOTFOUND; + } + + memset(&req,0,sizeof(req)); + + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); + req.n.nlmsg_flags = NLM_F_REQUEST ; + req.n.nlmsg_type = RTM_GETLINK; /*消息类型*/ + req.i.ifi_family = PF_BRIDGE; + struct { + struct nlmsghdr n; + char buf[16384]; + }answer; + + memset(&answer,0,sizeof(answer)); + + if(br_fd < 0){ + br_fd = netlink_socket(0); + } + + if(br_fd <0){ + printf("netlink_socket failed\n"); + return RET_SYSERR; + } + + addattr_l(&req.n, sizeof(req), IFLA_IFNAME, port_name, strlen(port_name)+1); + if (rtnl_talk(br_fd, &req.n, &answer.n, sizeof(answer)) < 0) + return RET_SYSERR; + + struct ifinfomsg *ifi = NLMSG_DATA(&answer.n); + struct rtattr *tb[IFLA_MAX+1]; + + printf("struct ifinfomsg: ifi_family=%u,ifi_index=%d\n", + ifi->ifi_family,ifi->ifi_index); + + + int len = answer.n.nlmsg_len - NLMSG_LENGTH(sizeof (struct ifinfomsg)); + parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len); + + printf("enum : IFLA_IFNAME=%s,IFLA_MTU=%d,IFLA_TXQLEN=%d\n", + (char *)RTA_DATA(tb[IFLA_IFNAME]), + *(int *)RTA_DATA(tb[IFLA_MTU]), + *(int *)RTA_DATA(tb[IFLA_TXQLEN])); + + printf("if_nametoindex:%d\n",if_nametoindex((char *)RTA_DATA(tb[IFLA_IFNAME]))); + + if (tb[IFLA_MASTER]) { + int master = rta_getattr_u32(tb[IFLA_MASTER]); + char if_name[INTERFACE_NAMSIZ] = {0}; + + if_indextoname(master, if_name); + printf("master:%s\n", if_name); + + if(br_get_bridge_info(if_name, NULL) == 0) + { + strncpy(br_name, if_name, BR_NAMSIZ - 1); + br_name[BR_NAMSIZ - 1] = 0; + return RET_OK; + } + } + + return RET_NOTFOUND; +} + diff --git a/Platform/user/configm/config-server/netconfig/bridge/brnetlink.h b/Platform/user/configm/config-server/netconfig/bridge/brnetlink.h new file mode 100644 index 000000000..784a248cb --- /dev/null +++ b/Platform/user/configm/config-server/netconfig/bridge/brnetlink.h @@ -0,0 +1,7 @@ +#ifndef BRNETLINK_H_ +#define BRNETLINK_H_ + +int get_br_from_port(char *port_name , char *br_name); + +#endif + diff --git a/Platform/user/configm/config-server/netconfig/bridge/libbridge/libbridge.h b/Platform/user/configm/config-server/netconfig/bridge/libbridge/libbridge.h index ff047f933..6ae82151a 100644 --- a/Platform/user/configm/config-server/netconfig/bridge/libbridge/libbridge.h +++ b/Platform/user/configm/config-server/netconfig/bridge/libbridge/libbridge.h @@ -118,4 +118,5 @@ extern int br_read_fdb(const char *br, struct fdb_entry *fdbs, unsigned long skip, int num); extern int br_set_hairpin_mode(const char *bridge, const char *dev, int hairpin_mode); +extern int br_for_port_num(const char *brname, int *cnt); #endif diff --git a/Platform/user/configm/config-server/netconfig/bridge/libbridge/libbridge_devif.c b/Platform/user/configm/config-server/netconfig/bridge/libbridge/libbridge_devif.c index 2cf78f6db..ee7ac000b 100644 --- a/Platform/user/configm/config-server/netconfig/bridge/libbridge/libbridge_devif.c +++ b/Platform/user/configm/config-server/netconfig/bridge/libbridge/libbridge_devif.c @@ -118,7 +118,6 @@ static int old_get_bridge_info(const char *bridge, struct bridge_info *info) unsigned long args[4] = { BRCTL_GET_BRIDGE_INFO, (unsigned long) &i, 0, 0 }; - memset(info, 0, sizeof(*info)); strncpy(ifr.ifr_name, bridge, IFNAMSIZ); ifr.ifr_data = (char *) &args; @@ -128,25 +127,31 @@ static int old_get_bridge_info(const char *bridge, struct bridge_info *info) return errno; } - memcpy(&info->designated_root, &i.designated_root, 8); - memcpy(&info->bridge_id, &i.bridge_id, 8); - info->root_path_cost = i.root_path_cost; - info->root_port = i.root_port; - info->topology_change = i.topology_change; - info->topology_change_detected = i.topology_change_detected; - info->stp_enabled = i.stp_enabled; - __jiffies_to_tv(&info->max_age, i.max_age); - __jiffies_to_tv(&info->hello_time, i.hello_time); - __jiffies_to_tv(&info->forward_delay, i.forward_delay); - __jiffies_to_tv(&info->bridge_max_age, i.bridge_max_age); - __jiffies_to_tv(&info->bridge_hello_time, i.bridge_hello_time); - __jiffies_to_tv(&info->bridge_forward_delay, i.bridge_forward_delay); - __jiffies_to_tv(&info->ageing_time, i.ageing_time); - __jiffies_to_tv(&info->hello_timer_value, i.hello_timer_value); - __jiffies_to_tv(&info->tcn_timer_value, i.tcn_timer_value); - __jiffies_to_tv(&info->topology_change_timer_value, - i.topology_change_timer_value); - __jiffies_to_tv(&info->gc_timer_value, i.gc_timer_value); + if(info) + { + memset(info, 0, sizeof(*info)); + + memcpy(&info->designated_root, &i.designated_root, 8); + memcpy(&info->bridge_id, &i.bridge_id, 8); + info->root_path_cost = i.root_path_cost; + info->root_port = i.root_port; + info->topology_change = i.topology_change; + info->topology_change_detected = i.topology_change_detected; + info->stp_enabled = i.stp_enabled; + __jiffies_to_tv(&info->max_age, i.max_age); + __jiffies_to_tv(&info->hello_time, i.hello_time); + __jiffies_to_tv(&info->forward_delay, i.forward_delay); + __jiffies_to_tv(&info->bridge_max_age, i.bridge_max_age); + __jiffies_to_tv(&info->bridge_hello_time, i.bridge_hello_time); + __jiffies_to_tv(&info->bridge_forward_delay, i.bridge_forward_delay); + __jiffies_to_tv(&info->ageing_time, i.ageing_time); + __jiffies_to_tv(&info->hello_timer_value, i.hello_timer_value); + __jiffies_to_tv(&info->tcn_timer_value, i.tcn_timer_value); + __jiffies_to_tv(&info->topology_change_timer_value, + i.topology_change_timer_value); + __jiffies_to_tv(&info->gc_timer_value, i.gc_timer_value); + } + return 0; } @@ -167,27 +172,31 @@ int br_get_bridge_info(const char *bridge, struct bridge_info *info) goto fallback; } - memset(info, 0, sizeof(*info)); - fetch_id(path, "root_id", &info->designated_root); - fetch_id(path, "bridge_id", &info->bridge_id); - info->root_path_cost = fetch_int(path, "root_path_cost"); - fetch_tv(path, "max_age", &info->max_age); - fetch_tv(path, "hello_time", &info->hello_time); - fetch_tv(path, "forward_delay", &info->forward_delay); - fetch_tv(path, "max_age", &info->bridge_max_age); - fetch_tv(path, "hello_time", &info->bridge_hello_time); - fetch_tv(path, "forward_delay", &info->bridge_forward_delay); - fetch_tv(path, "ageing_time", &info->ageing_time); - fetch_tv(path, "hello_timer", &info->hello_timer_value); - fetch_tv(path, "tcn_timer", &info->tcn_timer_value); - fetch_tv(path, "topology_change_timer", - &info->topology_change_timer_value);; - fetch_tv(path, "gc_timer", &info->gc_timer_value); - - info->root_port = fetch_int(path, "root_port"); - info->stp_enabled = fetch_int(path, "stp_state"); - info->topology_change = fetch_int(path, "topology_change"); - info->topology_change_detected = fetch_int(path, "topology_change_detected"); + if(info) + { + memset(info, 0, sizeof(*info)); + fetch_id(path, "root_id", &info->designated_root); + fetch_id(path, "bridge_id", &info->bridge_id); + info->root_path_cost = fetch_int(path, "root_path_cost"); + fetch_tv(path, "max_age", &info->max_age); + fetch_tv(path, "hello_time", &info->hello_time); + fetch_tv(path, "forward_delay", &info->forward_delay); + fetch_tv(path, "max_age", &info->bridge_max_age); + fetch_tv(path, "hello_time", &info->bridge_hello_time); + fetch_tv(path, "forward_delay", &info->bridge_forward_delay); + fetch_tv(path, "ageing_time", &info->ageing_time); + fetch_tv(path, "hello_timer", &info->hello_timer_value); + fetch_tv(path, "tcn_timer", &info->tcn_timer_value); + fetch_tv(path, "topology_change_timer", + &info->topology_change_timer_value);; + fetch_tv(path, "gc_timer", &info->gc_timer_value); + + info->root_port = fetch_int(path, "root_port"); + info->stp_enabled = fetch_int(path, "stp_state"); + info->topology_change = fetch_int(path, "topology_change"); + info->topology_change_detected = fetch_int(path, "topology_change_detected"); + } + closedir(dir); return 0; diff --git a/Platform/user/configm/config-server/netconfig/bridge/libbridge/libbridge_init.c b/Platform/user/configm/config-server/netconfig/bridge/libbridge/libbridge_init.c index f3a551e68..764a60faf 100644 --- a/Platform/user/configm/config-server/netconfig/bridge/libbridge/libbridge_init.c +++ b/Platform/user/configm/config-server/netconfig/bridge/libbridge/libbridge_init.c @@ -145,6 +145,23 @@ int br_foreach_bridge(int (*iterator)(const char *, void *), return ret; } +int br_cnt_num(const char *name, void *arg) +{ + int *cnt = arg; + + (*cnt)++; + + return 0 +} + + int br_for_bridge_num(int *cnt) + { + *cnt = 0; + br_foreach_bridge(br_cnt_num, cnt); + + return 0; + } + /* * Only used if sysfs is not available. */ @@ -222,3 +239,75 @@ int br_foreach_port(const char *brname, return count; } + +/* + * Only used if sysfs is not available. + */ +static int old_for_port_num(const char *brname, int *cnt) +{ + int i, err, count; + struct ifreq ifr; + char ifname[IFNAMSIZ]; + int ifindices[MAX_PORTS]; + unsigned long args[4] = { BRCTL_GET_PORT_LIST, + (unsigned long)ifindices, MAX_PORTS, 0 }; + + memset(ifindices, 0, sizeof(ifindices)); + strncpy(ifr.ifr_name, brname, IFNAMSIZ); + ifr.ifr_data = (char *) &args; + + err = ioctl(br_socket_fd, SIOCDEVPRIVATE, &ifr); + if (err < 0) { + dprintf("list ports for bridge:'%s' failed: %s\n", + brname, strerror(errno)); + return -errno; + } + + count = 0; + for (i = 0; i < MAX_PORTS; i++) { + if (!ifindices[i]) + continue; + + if (!if_indextoname(ifindices[i], ifname)) { + dprintf("can't find name for ifindex:%d\n", + ifindices[i]); + continue; + } + + ++count; + } + + *cnt = count; + + return 0; +} + +int br_for_port_num(const char *brname, int *cnt) +{ + int i, count; + struct dirent **namelist; + char path[SYSFS_PATH_MAX]; + + *cnt = 0; + + snprintf(path, SYSFS_PATH_MAX, SYSFS_CLASS_NET "%s/brif", brname); + count = scandir(path, &namelist, 0, alphasort); + if (count < 0) + return old_for_port_num(brname, cnt); + + for (i = 0; i < count; i++) { + if (namelist[i]->d_name[0] == '.' + && (namelist[i]->d_name[1] == '\0' + || (namelist[i]->d_name[1] == '.' + && namelist[i]->d_name[2] == '\0'))) + continue; + + (*cnt)++; + } + for (i = 0; i < count; i++) + free(namelist[i]); + free(namelist); + + return 0; +} + diff --git a/Platform/user/configm/config-server/netconfig/parsefile.c b/Platform/user/configm/config-server/netconfig/parsefile.c index 42549879f..16278c445 100644 --- a/Platform/user/configm/config-server/netconfig/parsefile.c +++ b/Platform/user/configm/config-server/netconfig/parsefile.c @@ -236,6 +236,92 @@ int conf_value_in_block_del(char *conf_path, char *start_str, return conf_file_write(conf_path, sum_buf); } +int conf_value_block_del(char *conf_path, char *start_str, char *end_str) +{ + char config_linebuf[IF_BUFF_LEN]; + int configbuf_lenth = strlen(conf_buff) + 5; + long congig_lenth = 0; + + boolean next_flag = FALSE; + char *start_line = NULL; + FILE *f = fopen(conf_path, "r+"); + + if(f == NULL) + { + printf("OPEN CONFIG FALID\n"); + return RET_ERR; + } + + fseek(f, 0, SEEK_END); + + congig_lenth = ftell(f); + + char sum_buf[congig_lenth + configbuf_lenth]; + + memset(sum_buf, 0, sizeof(sum_buf)); + + fseek(f, 0, SEEK_SET); + + memset(config_linebuf, 0, sizeof(config_linebuf)); + + while(fgets(config_linebuf, IF_BUFF_LEN,f) != NULL) + { + /* 该做的事情已经做完 */ + if(next_flag == TRUE) + { + strcat(sum_buf, config_linebuf); + goto next_while; + } + + /* 判断是否是空行 */ + if(strlen(config_linebuf) < 3) + { + strcat(sum_buf, config_linebuf); + goto next_while; + } + + /* 没有找到接口配置块,则继续循环 */ + if(start_line == NULL) + { + start_line = strstr(config_linebuf, start_str); + if(start_line == NULL) + { + strcat(sum_buf, config_linebuf); + } + goto next_while; + } + + /* 已经到了end, 删除结束*/ + if(strstr(config_linebuf, end_str)) + { + strcat(sum_buf, config_linebuf); + next_flag = TRUE; + goto next_while; + } + + if(next_flag == TRUE) + { + strcat(sum_buf, config_linebuf); + } + + next_while: + + if(fgetc(f)==EOF) + { + break; + } + fseek(f,-1,SEEK_CUR); + + memset(config_linebuf, 0, sizeof(config_linebuf)); + } + + remove(conf_path); + fclose(f); + + rpc_log_dbg("---sum_buf---->%s<----------\n",sum_buf); + + return conf_file_write(conf_path, sum_buf); +} /* *添加修改文件(当配置文件中存在标记字段,则进行修改,若不存在则进行添加)