#include "vlan_config.h" /* 定义全局接口vlan信息变量 */ interface_vlan_info g_if_vlan_info[MAX_INTERFACES] = {0}; /* 存放全局error data信息 */ char g_err_data[ERR_DATA_LEN] = {0}; /************************************************************ * 函数功能:设置vlan bitmap某位 * 输入: * 输出: * 返回值: ************************************************************/ void vlan_bitmap_set(int *v, int i) { if(!v || i < 0){ printf("[vlan]vlan_bitmap_set: input error.\n"); return; } v[i >> SHIFT] |= (1 << (i & MASK)); } /************************************************************ * 函数功能:清除vlan bitmap某位 * 输入: * 输出: * 返回值: ************************************************************/ void vlan_bitmap_clear(int *v, int i) { if(!v || i < 0){ printf("[vlan]vlan_bitmap_clear: input error.\n"); return; } v[i >> SHIFT] &= ~(1 << (i & MASK)); } /************************************************************ * 函数功能:查询vlan bitmap某位是否被设置 * 输入: * 输出: * 返回值: ************************************************************/ int vlan_bitmap_check(int *v, int i) { if(!v || i < 0){ printf("[vlan]vlan_bitmap_check: input error.\n"); return -1; } return v[i >> SHIFT] & (1 << (i & MASK)); } /************************************************************ * 函数功能:根据if_name查找attr在g_if_vlan_info[]中遍历 * if_name,求得其attr * 输入: * 输出: * 返回值: ************************************************************/ interface_link_attr get_attr_from_ifname(char *if_name) { if(!if_name){ return LINK_TYPE_UNKNOWN; } int ifnode; ifnode = get_ifnode_from_global(if_name); if(ifnode == -1){ printf("[vlan]get_attr_from_ifname: ifnode is -1.\n"); return LINK_TYPE_UNKNOWN; } return g_if_vlan_info[ifnode].attr; } /************************************************************ * 函数功能:根据物理接口名称和vid生成子接口名称 * 输入:if_name、vid * 输出:subif * 返回值: ************************************************************/ int if_vlan2subif(char *if_name, int vid, char *subif) { if(!if_name || !subif){ printf("[vlan]if_vlan2subif: input error.\n"); return -1; } sprintf(subif, "%s.%d", if_name, vid); return 0; } int br_if_num_stub(char *br_name, operation_type op_type) { int ret; if(op_type == OP_ADD){ ret = 0; } else if(op_type == OP_MOD){ ret = 1; } else if(op_type == OP_DEL){ ret = 0; } return ret; } /************************************************************ * 函数功能:返回br上的接口数目 * 输入: * 输出: * 返回值: ************************************************************/ int br_if_num(char *br_name) { return br_if_num_stub(br_name, OP_ADD); } int create_br_stub(char *br_vlname) { char buf[SYSCALL_BUF_LEN] = {0}; sprintf(buf, "brctl addbr %s", br_vlname); system(buf); return 0; } /************************************************************ * 函数功能:创建br * 输入: * 输出: * 返回值: ************************************************************/ int create_br(char *br_vlname) { return create_br_stub(br_vlname); } int br_addif_stub(char *br_name, char *if_name) { char buf[SYSCALL_BUF_LEN] = {0}; sprintf(buf, "brctl addif %s %s", br_name, if_name); system(buf); return 0; } /************************************************************ * 函数功能:将接口加入br * 输入: * 输出: * 返回值: ************************************************************/ int br_addif(char *br_name, char *if_name) { return br_addif_stub(br_name, if_name); } int interface_br_stub(char *if_name, char *br_name) { return 0; } /************************************************************ * 函数功能:判断某个接口是否在br上,在哪个br上 * 输入: * 输出:br_name * 返回值: ************************************************************/ int interface_br(char *if_name, char *br_name) { /* 先打桩处理 */ return interface_br_stub(if_name, br_name); } int del_br_stub(char *br_name) { char buf[SYSCALL_BUF_LEN] = {0}; sprintf(buf, "brctl delbr %s", br_name); system(buf); return 0; } /************************************************************ * 函数功能:删除br * 输入: * 输出: * 返回值: ************************************************************/ int del_br(char *br_name) { return del_br_stub(br_name); } /************************************************************ * 函数功能:判断接口属于何种模型:路由桥接 or 桥接 * 目前只支持路由桥接 * 输入: * 输出: * 返回值: ************************************************************/ interface_model which_interface_model(char *if_name) { return INTERFACE_MODEL_ROUTE_FORWARD; } /************************************************************ * 函数功能:初始化init,这个应该放在配置管理的init, * 而不是配置触发阶段的这里,后面再调整 * 输入: * 输出: * 返回值: ************************************************************/ void vlan_config_init(void) { ret_code ret = RET_OK; int sys_ret = 0; system("modprobe 8021q"); ret = br_event_register(BR_IF_LEAVE_EVENT_PRE, del_interface_vlan_cb); #if 0 /* 创建br0 */ ret = br_bridge_add("br0", &sys_ret); if(ret != RET_OK){ printf("[vlan]vlan_config_init: br0_bridge_add failed(%d)\n", sys_ret); return; } /* 将子接口添加进br0 */ br_if_bridge_add("br0", "ens38", 1, &sys_ret); if(sys_ret != 0){ printf("[vlan]vlan_config_init: br0_if_bridge_add failed(%d)(%s)\n", sys_ret, strerror(sys_ret)); return; } /* 创建br1 */ ret = br_bridge_add("br1", &sys_ret); if(ret != RET_OK){ printf("[vlan]vlan_config_init: br1_bridge_add failed(%d)\n", sys_ret); return; } /* 将子接口添加进br1 */ br_if_bridge_add("br1", "ens39", 1, &sys_ret); if(sys_ret != 0){ printf("[vlan]vlan_config_init: br1_if_bridge_add failed(%d)(%s)\n", sys_ret, strerror(sys_ret)); return; } #endif return; } /************************************************************ * 函数功能:添加桥接模式的access vlan * 目前只支持路由桥接,涉及桥接的暂不实现 * 输入: * 输出: * 返回值: ************************************************************/ int add_bridge_vlan_access(char *if_name, int vid) { //系统调用("bridge vlan add vid %d dev %s pvid untagged", vid, if_name); //调用张亮的iproute2接口,创建bridge vlan return 0; } /************************************************************ * 函数功能:校验:之前是否添加过该接口 * 输入: * 输出: * 返回值: 0:未配置过 * 1:配置过 ************************************************************/ int check_config(char *if_name) { int i; for(i = 0; i < MAX_INTERFACES; i++){ if(!strcmp(g_if_vlan_info[i].if_name, if_name)){ printf("[vlan]check_config:already exists, return 1\n"); return 1; } } return 0; } /************************************************************ * 函数功能:添加access vlan * 目前只支持路由桥接,涉及桥接的暂不实现 * 输入: * 输出: * 返回值: ************************************************************/ int add_interface_vlan_access(char *if_name, int *vlan_bitmap, interface_model if_model) { int i; /* 检查接口属于何种模型 */ if(INTERFACE_MODEL_FORWARD != if_model){ printf("access必须属于桥接模型,否则报错\n"); return -1; } for(i = VID_MIN; i <= VID_MAX; i++){ if(vlan_bitmap_check(vlan_bitmap, i)){ return add_bridge_vlan_access(if_name, i); } } return -1; } /************************************************************ * 函数功能:添加trunk vlan * 目前只支持路由桥接,涉及桥接的暂不实现 * vids[i]如果为1,表示配置了vlan的vid为i * 输入: * 输出: * 返回值: ************************************************************/ int add_bridge_vlan_trunk(char *if_name, int *vlan_bitmap) { int i; char buf[SYSCALL_BUF_LEN] = {0}; if(!if_name || !vlan_bitmap){ return -1; } for(i = VID_MIN; i <= VID_MAX; i++){ if(vlan_bitmap_check(vlan_bitmap, i)){ sprintf(buf,"bridge vlan add vid %d dev %s", i, if_name);//after change to snprintf system(buf);//after change to execv return 0; } } return -1; } /************************************************************ * 函数功能:创建vlan子接口 * vids[i]如果为1,表示配置了vlan的vid为i * 遍历vid从2开始 * 输入: * 输出: * 返回值: ************************************************************/ ret_code add_vlan_sub_interface(char *if_name, int *vlan_bitmap) { if(!if_name || !vlan_bitmap){ printf("[vlan]add_vlan_sub_interface: input is null.\n"); return RET_NULLP; } printf("[vlan]add_vlan_sub_interface: begin.\n"); int vid; char subif[IF_NAME_LEN] = {0}; char buf[SYSCALL_BUF_LEN] = {0}; char br_vlname[BR_VLAN_NAME_LEN] = {0}; char tmp_brname[BR_VLAN_NAME_LEN] = {0}; int sys_ret = 0, status = 0; ret_code ret = RET_OK; for(vid = VID_MIN; vid <= VID_MAX; vid++){ if(vlan_bitmap_check(vlan_bitmap, vid)){ /* vconfig创建子接口 */ sprintf(buf, "vconfig add %s %d", if_name, vid); printf("[vlan]add_vlan_sub_interface: vconfig buf=%s\n", buf); status = system(buf); if(status != 0){ printf("[vlan]add_vlan_sub_if: subif status error. (%s)\n", strerror(errno)); return RET_SYSERR; } memset(buf, 0, SYSCALL_BUF_LEN); /* 生成子接口 */ (void)if_vlan2subif(if_name, vid, subif); sprintf(buf, "ifconfig %s up", subif); printf("[vlan]add_vlan_sub_interface: ifconfig sub buf=%s\n", buf); status = system(buf); if(status != 0){ printf("[vlan]add_vlan_sub_if: ifconfig subif status error. (%s)\n", strerror(errno)); return RET_SYSERR; } memset(buf, 0, SYSCALL_BUF_LEN); /* WAN口不需要建桥 */ /* 如果返回不是RET_OK,则说明是WAN口,不需要做后面的建vlan桥,继续下一个循环 */ if(RET_OK != br_if_bridge_get(if_name, tmp_brname)){ printf("[vlan]add_vlan_sub_interface: port is WAN, don't creat br-vl and addif, continue\n"); memset(subif, 0, IF_NAME_LEN); memset(tmp_brname, 0, BR_VLAN_NAME_LEN); continue; } /* 生成br-vl桥 */ sprintf(br_vlname, "br-vl%d", vid); printf("[vlan]add_vlan_sub_interface: br_vlname=%s\n", br_vlname); /* 查询生成的br-vl是否存在,不存在则创建br-vl */ if(br_is_exist(br_vlname) == FALSE){ ret = br_bridge_add(br_vlname, &sys_ret); if(ret != RET_OK){ printf("[vlan]add_vlan_sub_interface: br_bridge_add failed(%d)(%s)\n", sys_ret, strerror(sys_ret)); return ret; } } /* 将子接口添加进br */ br_if_bridge_add(br_vlname, subif, 1, &sys_ret); if(ret != RET_OK){ printf("[vlan]add_vlan_sub_interface: br_if_bridge_add failed(%d)(%s)\n", sys_ret, strerror(sys_ret)); return ret; } memset(subif, 0, IF_NAME_LEN); memset(br_vlname, 0, BR_VLAN_NAME_LEN); } } return RET_OK; } /************************************************************ * 函数功能:创建vlan trunk * 输入: * 输出: * 返回值: ************************************************************/ ret_code add_interface_vlan_trunk(char *if_name, int *vlan_bitmap, interface_model if_model) { ret_code ret = RET_OK; /* 桥接 */ if(INTERFACE_MODEL_FORWARD == if_model){ ret = add_bridge_vlan_trunk(if_name, vlan_bitmap); } /* 路由桥接,需创建子接口和br-vlan */ else if(INTERFACE_MODEL_ROUTE_FORWARD == if_model){ ret = add_vlan_sub_interface(if_name, vlan_bitmap); } return ret; } /************************************************************ * 函数功能:添加接口vlan * 输入: * 输出: * 返回值: ************************************************************/ ret_code add_interface_vlan(interface_vlan_info *if_vlan_info) { interface_link_attr new_attr = if_vlan_info->attr; ret_code ret = RET_OK; /* 配置校验 */ //ret = check_config(if_vlan_info->if_name); //if(0 != ret){ //return -1; //} /* 接口模型赋值 */ if_vlan_info->if_model = which_interface_model(if_vlan_info->if_name); /* 判断链路类型 */ if(new_attr == LINK_TYPE_TRUNK){ ret = add_interface_vlan_trunk(if_vlan_info->if_name, if_vlan_info->vlan_bitmap, if_vlan_info->if_model); if(ret != RET_OK){ printf("[vlan]add_interface_vlan: add trunk failed.\n"); return ret; } } else if(new_attr == LINK_TYPE_ACCESS){ ret = add_interface_vlan_access(if_vlan_info->if_name, if_vlan_info->vlan_bitmap, if_vlan_info->if_model); if(ret != RET_OK){ printf("[vlan]add_interface_vlan: add access failed.\n"); return ret; } } else{ printf("[vlan]add_interface_vlan: LINK-TYPE attr(%d) input error.\n", new_attr); return RET_INPUTERR; } /* 更新全局接口vlan数据结构 */ ret = refresh_if_vlan_info(if_vlan_info); return ret; } /************************************************************ * 函数功能:删除bridge vlan * 目前用不到,目前不支持桥接 * 输入: * 输出: * 返回值: ************************************************************/ int del_bridge_vlan_access(char *if_name) { int vid; char buf[SYSCALL_BUF_LEN] = {0}; int ifnode; ifnode = get_ifnode_from_global(if_name); /* 在这个节点i上再遍历VLAN,找到该节点所有的vlan j,j有多个 找到一个j,拼接成一个子接口,删除这个子接口*/ for(vid = VID_MIN; vid <= VID_MAX; vid++){ if(vlan_bitmap_check(g_if_vlan_info[ifnode].vlan_bitmap, vid)){ sprintf(buf, "bridge vlan del vid %d dev %s pvid untagged", vid, if_name); system(buf); memset(buf, 0, SYSCALL_BUF_LEN); sprintf(buf, "bridge vlan add vid %d dev %s pvid untagged", 1, if_name); system(buf); memset(buf, 0, SYSCALL_BUF_LEN); } } return 0; } /************************************************************ * 函数功能:删除access vlan * 目前用不到,目前不支持桥接 * 输入: * 输出: * 返回值: ************************************************************/ int del_interface_vlan_access(char *if_name, interface_model if_model) { int ret; /* 检查接口属于何种模型 */ if(INTERFACE_MODEL_FORWARD != if_model){ printf("access必须属于桥接模型,否则报错\n"); return -1; } ret = del_bridge_vlan_access(if_name); return ret; } /************************************************************ * 函数功能:删除trunk vlan * 输入: * 输出: * 返回值: ************************************************************/ int del_bridge_vlan_trunk(char *if_name) { int ifnode, vid; char buf[SYSCALL_BUF_LEN] = {0}; /* 根据ifname遍历全局结构中在哪个节点i上,i只有一个 */ for(ifnode = 0; ifnode < MAX_INTERFACES; ifnode++){ if(!strcmp(g_if_vlan_info[ifnode].if_name, if_name)){ break; } } /* 没找到 */ if(ifnode >= MAX_INTERFACES){ return -1; } /* 在这个节点i上再遍历VLAN,找到该节点所有的vlan j,j有多个 */ for(vid = 1; vid < MAX_VLAN; vid++){ //if(g_if_vlan_info[i].vid[j]){ if(vlan_bitmap_check(g_if_vlan_info[ifnode].vlan_bitmap, vid)){ sprintf(buf, "bridge vlan del vid %d dev %s", vid, if_name); system(buf); memset(buf, 0, SYSCALL_BUF_LEN); } } /* 恢复vlan 1 pvid untagged */ sprintf(buf, "bridge vlan add vid %d dev %s pvid untagged", 1, if_name); system(buf); return 0; } interface_network_type lan_or_wan_stub(char *if_name) { return IF_TYPE_LAN; } /************************************************************ * 函数功能:读配置文件区分LAN还是WAN * 输入: * 输出: * 返回值: ************************************************************/ interface_network_type lan_or_wan(char *if_name) { return lan_or_wan_stub(if_name); } /************************************************************ * 函数功能:删除vlan子接口 * 这里不用做校验了,前面chk校验过了 * 输入: * 输出: * 返回值: ************************************************************/ ret_code del_vlan_sub_interface(char *if_name, int *vlan_bitmap) { int ifnode, vid; char br_vlname[BR_VLAN_NAME_LEN] = {0}; char tmp_brname[BR_VLAN_NAME_LEN] = {0}; char subif[IF_NAME_LEN]= {0}; char buf[SYSCALL_BUF_LEN] = {0}; int sys_ret = 0, status = 0, num = 0; ret_code ret = RET_OK; if(!if_name || !vlan_bitmap){ return -1; } printf("[vlan]del_vlan_sub_interface: begin.\n"); /* 在这个节点i上再遍历VLAN,找到该节点所有的vlan j,j有多个 找到一个j,拼接成一个子接口,删除这个子接口*/ for(vid = VID_MIN; vid <= VID_MAX; vid++){ if(vlan_bitmap_check(vlan_bitmap, vid)){//这里就不做校验了,下发哪个vid,就删除哪个 /* 生成子接口 */ (void)if_vlan2subif(if_name, vid, subif); /* 查询物理口是否挂桥上 */ ret = br_if_bridge_get(if_name, tmp_brname); /* 没找到桥,是WAN,只删除VLAN子接口 */ if(RET_NOTFOUND == ret){ printf("[vlan]del_vlan_sub_interface: %s is WAN,only del vlansubif\n", if_name); /* 删除vlan子接口 */ sprintf(buf, "vconfig rem %s", subif); printf("[vlan]del_vlan_sub_interface: buf=%s\n", buf); status = system(buf); if(status != 0){ printf("[vlan]del_vlan_sub_if:status error. (%s)\n", strerror(errno)); return RET_ERR; } memset(buf, 0, SYSCALL_BUF_LEN); memset(tmp_brname, 0, BR_VLAN_NAME_LEN); memset(subif, 0, IF_NAME_LEN); } /* 找到桥了,是LAN */ else if(RET_OK == ret){ sprintf(br_vlname, "br-vl%d", vid); printf("[vlan]del_vlan_sub_interface: br_vlname=%s\n", br_vlname); /* 如果br-vlxx不存在,报错返回 */ if(br_is_exist(br_vlname) == FALSE){ printf("[vlan]del_vlan_sub_interface: %s is not exist, error,return.\n", br_vlname); return RET_ERR; } /* brctl delif删除br-vl上的vlan子接口 */ printf("[vlan]del_vlan_sub_interface: br-vl%d delif %s\n", vid, subif); ret = br_if_bridge_del(br_vlname, subif, 1, &sys_ret); if(ret != RET_OK){ printf("[vlan]del_vlan_sub_interface: br_if_bridge_del error(%d).\n", sys_ret); return ret; } /* 删除vlan子接口 */ sprintf(buf, "vconfig rem %s", subif); printf("[vlan]del_vlan_sub_interface: buf=%s\n", buf); status = system(buf); if(status != 0){ printf("[vlan]del_vlan_sub_if:status error. (%s)\n",strerror(errno)); return RET_ERR; } memset(buf, 0, SYSCALL_BUF_LEN); /* br-vlan上的接口数为0,则删除br-vlan */ num = br_if_bridge_num(br_vlname); printf("[vlan]del_vlan_sub_interface: num=%d\n", num); if(num == 0){ printf("[vlan]del_vlan_sub_interface: br's port is zero.\n"); ret = br_bridge_del(br_vlname, &sys_ret); if(ret != RET_OK){ printf("[vlan]del_vlan_sub_interface: del br failed(%d)(%s).\n", sys_ret, strerror(sys_ret)); return ret; } } memset(br_vlname, 0, BR_VLAN_NAME_LEN); memset(subif, 0, IF_NAME_LEN); memset(buf, 0, SYSCALL_BUF_LEN); } } } return RET_OK; } /************************************************************ * 函数功能:删除vlan trunk * 输入: * 输出: * 返回值: ************************************************************/ ret_code del_interface_vlan_trunk(char *if_name, int *vlan_bitmap, interface_model if_model) { ret_code ret = RET_OK; /* 桥接 */ if(INTERFACE_MODEL_FORWARD == if_model){ ret = del_bridge_vlan_trunk(if_name); } /* 路由桥接,需创建子接口和br-vlan */ else if(INTERFACE_MODEL_ROUTE_FORWARD == if_model){ ret = del_vlan_sub_interface(if_name, vlan_bitmap); } return ret; } /************************************************************ * 函数功能:在全局if_vlan结构中查找之前配置过的节点或者 * 空节点,以便插入 * 存在两种情况,一种是当前配置的接口,在之前已经配置过,匹配 * 出来在次节点更新就行,如果之前没配置过,那找到新节点插入 * 输入: * 输出: * 返回值: -1:没有空位置了 ifnode:第ifnode个位置 ************************************************************/ int find_insert_ifnode_from_global(char *if_name) { int ifnode; if(!if_name){ return -1; } /* 找到之前已经配置过的节点位置 */ for(ifnode = 0; ifnode < MAX_INTERFACES; ifnode++){ if(!strcmp(g_if_vlan_info[ifnode].if_name, if_name)){ printf("[vlan]find_empty_ifnode_from_global: find exist gnode[%d].%s\n", ifnode, if_name); return ifnode; } } /* 找到一个空的,插入 */ for(ifnode = 0; ifnode < MAX_INTERFACES; ifnode++){ if(!strcmp(g_if_vlan_info[ifnode].if_name, "")){ printf("[vlan]find_empty_ifnode_from_global: find empty gnode[%d]\n", ifnode); return ifnode; } } /* 说明满了,没有空的可插入信息的节点了 */ return -1; } /************************************************************ * 函数功能:ADD操作更新全局结构 * 输入: * 输出: * 返回值: ************************************************************/ ret_code refresh_if_vlan_info_op_add(interface_vlan_info *if_vlan_info) { int ifnode; int vid; if(!if_vlan_info){ return -1; } ifnode = find_insert_ifnode_from_global(if_vlan_info->if_name); /* 没找到空白可插入信息的节点,add出错 */ if(-1 == ifnode){ printf("[vlan]refresh_if_vlan_info_op_add: donot find empty node.\n"); return -1; } printf("[vlan]refresh_if_vlan_info_op_add: find node[%d].ifname=%s\n", ifnode, if_vlan_info->if_name); /* 更新ifname, attr, op_type, if_model */ memcpy(g_if_vlan_info[ifnode].if_name, if_vlan_info->if_name, strlen(if_vlan_info->if_name)); g_if_vlan_info[ifnode].attr = if_vlan_info->attr; g_if_vlan_info[ifnode].op_type = if_vlan_info->op_type; g_if_vlan_info[ifnode].if_model = if_vlan_info->if_model; printf("[vlan]refresh_op_add: node[%d]'s info::\nif_name=%s, attr=%d, op_type=%d, if_model=%d\n", ifnode, if_vlan_info->if_name, if_vlan_info->attr, if_vlan_info->op_type, if_vlan_info->if_model); /* 更新vlanbitmap */ printf("[vlan]refresh_op_add: vlan_info:\n<"); for(vid = VID_MIN; vid <= VID_MAX; vid++){ /* 如果找到了vid存在,则在全局结构的vlan_bitmap中设置vid bitmap */ if(vlan_bitmap_check(if_vlan_info->vlan_bitmap, vid)){ vlan_bitmap_set(g_if_vlan_info[ifnode].vlan_bitmap, vid); g_if_vlan_info[ifnode].vidcnt++; printf("%d, ", vid); } } printf(">\n"); return 0; } /************************************************************ * 函数功能:DEL操作更新全局结构 * 输入: * 输出: * 返回值: ************************************************************/ ret_code refresh_if_vlan_info_op_del(interface_vlan_info *if_vlan_info) { int ifnode; int vid = 0; int vcnt = 0; if(!if_vlan_info){ return -1; } ifnode = get_ifnode_from_global(if_vlan_info->if_name); /* 如果==-1说明没找到,就不是del了 */ if(-1 == ifnode){ return -1; } /* 没找到对应的节点 */ if(ifnode >= MAX_INTERFACES){ return -1; } #if 0 /* 清除第ifnode节点的信息 */ memset(&g_if_vlan_info[ifnode], 0, sizeof(g_if_vlan_info[ifnode])); printf("\n\n\n\n\n[vlan]refresh_op_del: g.ifname=%s, g.attr=%d, g.op_type=%d, g.ifmodel=%d\n", g_if_vlan_info[ifnode].if_name, g_if_vlan_info[ifnode].attr, g_if_vlan_info[ifnode].op_type, g_if_vlan_info[ifnode].if_model); printf("[vlan]refresh_op_del: if_vlan_info vid:\n"); for(vid = 2; vid < MAX_VLAN; vid++){ if(vlan_bitmap_check(if_vlan_info->vlan_bitmap, vid)){ printf("%d\n", vid); } } printf("[vlan]refresh_op_del: g_if_vlan_info vid:\n"); for(vid = 2; vid < MAX_VLAN; vid++){ if(vlan_bitmap_check(g_if_vlan_info[ifnode].vlan_bitmap, vid)){ printf("%d\n", vid); } } #endif /* 打印之前全局g结构信息 */ printf("[vlan]refresh_if_vlan_info_op_del: Before Gloabl node information:::::\n"); printf("[vlan]refresh_if_vlan_info_op_del: nodeid=%d, if_name=%s, op_type=%d, attr=%d, vid=[" , ifnode, g_if_vlan_info[ifnode].if_name, g_if_vlan_info[ifnode].op_type , g_if_vlan_info[ifnode].attr); for(vid = VID_MIN; vid <= VID_MAX; vid++){ if(vlan_bitmap_check(g_if_vlan_info[ifnode].vlan_bitmap, vid)){ printf("%d, ", vid); } } printf("]\n"); /* 打印新下发结构信息 */ printf("[vlan]refresh_if_vlan_info_op_del: config if_vlan_info node information:::::\n"); printf("[vlan]refresh_if_vlan_info_op_del: if_name=%s, op_type=%d, attr=%d, vid=[" , if_vlan_info->if_name, if_vlan_info->op_type , if_vlan_info->attr); for(vid = VID_MIN; vid <= VID_MAX; vid++){ if(vlan_bitmap_check(if_vlan_info->vlan_bitmap, vid)){ printf("%d, ", vid); } } printf("]\n"); printf("[vlan]refresh_if_vlan_info_op_del: if_vlan_info delete vid:["); for(vid = VID_MIN; vid <= VID_MAX; vid++){ /* 去新下发结构if_vlan_info取配置的vid, 在旧的结构全局g_if_vlan_info中清除这些vid */ if(vlan_bitmap_check(if_vlan_info->vlan_bitmap, vid)){ printf("%d, ", vid); vlan_bitmap_clear(g_if_vlan_info[ifnode].vlan_bitmap, vid); g_if_vlan_info[ifnode].vidcnt--; } } printf("]\n"); printf("[vlan]refresh_if_vlan_info_op_del: g_[%d].vidcnt=%d\n", ifnode, g_if_vlan_info[ifnode].vidcnt); /* 如果本接口上还有vid,则不处理,如果没有,则清除接口信息 */ /* 如果vcnt == 0 说明idnode下已经没有vid了,清除ifnode信息 */ if(g_if_vlan_info[ifnode].vidcnt == 0){ printf("[vlan]refresh_if_vlan_info_op_del: clean g_if_vlan_info[%d] info.\n", ifnode); memset(&g_if_vlan_info[ifnode], 0, sizeof(interface_vlan_info)); } #if 0 printf("[vlan]refresh_if_vlan_info_op_del: g_vlan_info[%d],vid left:[", ifnode); for(vid = VID_MIN; vid <= VID_MAX; vid++){ if(vlan_bitmap_check(g_if_vlan_info[ifnode].vlan_bitmap, vid)){ printf("%d, ", vid); vcnt++; } } printf("]\n"); /* 如果vcnt == 0 说明idnode下已经没有vid了,清除ifnode信息 */ if(vcnt == 0){ printf("[vlan]refresh_if_vlan_info_op_del: clean g_if_vlan_info[%d] info.\n", ifnode); memset(&g_if_vlan_info[ifnode], 0, sizeof(interface_vlan_info)); } #endif return 0; } /************************************************************ * 函数功能:根据ifname获取全局结构中所在节点编号 * 输入: * 输出: * 返回值: -1:没找到 ifnode: 第ifnode个节点 ************************************************************/ int get_ifnode_from_global(char *if_name) { int ifnode; if(!if_name){ return -1; } if(!strcmp(if_name, "")){ printf("[vlan]get_ifnode_from_global: if_name is empty.\n"); return -1; } for(ifnode = 0; ifnode < MAX_INTERFACES; ifnode++){ if(!strcmp(g_if_vlan_info[ifnode].if_name, if_name)){ printf("[vlan]get_ifnode_from_global: find gnode[%d], ifname=%s\n", ifnode, if_name); return ifnode; } } return -1; } /************************************************************ * 函数功能:ADD操作存配置文件 * 输入: * 输出: * 返回值: ************************************************************/ ret_code vlan_save_conf_file_add(interface_vlan_info *if_vlan_info) { int vid; char subif[IF_NAME_LEN] = {0}; char *addr_name = "address"; char addr_buff[IF_BUFF_LEN] = {0}; if(!if_vlan_info){ return RET_NULLP; } printf("[vlan]save_conf_file_add: begin.\n"); sprintf(addr_buff, "address %d\n", 0); for(vid = VID_MIN; vid <= VID_MAX; vid++){ if(vlan_bitmap_check(if_vlan_info->vlan_bitmap, vid)){ (void)if_vlan2subif(if_vlan_info->if_name, vid, subif); ip_conf_file_set(subif, addr_name, addr_buff); } } return RET_OK; } ret_code vlan_conf_file_del(char *if_name, char *address) { if(!if_name || !address){ return RET_NULLP; } char buf[100] = {0}; int status = 0; //sprintf(buf, "sed -r -i ':a;N;$!ba;s/auto[ \\t]+%s\\n[ \\t]*iface[ \\t]+%s[ \\t]+inet[ \\t]+static\\n[ \\t]*address[ \\t]+%s\\n//g' %s", if_name, if_name, address, ETC_NETWORK_IFS); sprintf(buf, "sed -r -i '/^auto[ \\t]+%s*$/d' %s", if_name, ETC_NETWORK_IFS); status = system(buf); if(status != 0){ printf("[vlan]vlan_conf_file_del1: status error. (%s)\n", strerror(errno)); return RET_SYSERR; } memset(buf, 0, 100); sprintf(buf, "sed -r -i '/^iface[ \\t]+%s[ \\t]+inet[ \\t]+static*$/,+1d' %s", if_name, ETC_NETWORK_IFS); status = system(buf); if(status != 0){ printf("[vlan]vlan_conf_file_del2: status error. (%s)\n", strerror(errno)); return RET_SYSERR; } memset(buf, 0, 100); //sprintf(buf, "sed -r -i '/^address[ \\t]+%s*$/d' %s", address, ETC_NETWORK_IFS); //system(buf); return RET_OK; } /************************************************************ * 函数功能:DEL操作存配置文件 * 输入: * 输出: * 返回值: ************************************************************/ ret_code vlan_save_conf_file_del(interface_vlan_info *if_vlan_info) { //int ifnode; int vid; char subif[IF_NAME_LEN] = {0}; char *del_address = "0"; ret_code ret = RET_OK; if(!if_vlan_info){ return RET_NULLP; } //ifnode = get_ifnode_from_global(if_vlan_info->if_name); for(vid = VID_MIN; vid <= VID_MAX; vid++){ if(vlan_bitmap_check(if_vlan_info->vlan_bitmap, vid)){ (void)if_vlan2subif(if_vlan_info->if_name, vid, subif); printf("[vlan]vlan_save_conf_file_del: vid=%d, subif=%s\n", vid, subif); ret = vlan_conf_file_del(subif, del_address); if(ret != RET_OK){ printf("[vlan]vlan_save_conf_file_del: vlan-conffile del failed(%d).\n", ret); return ret; } } } return RET_OK; } /************************************************************ * 函数功能:存配置文件 * 输入: * 输出: * 返回值: ************************************************************/ ret_code vlan_save_conf_file(interface_vlan_info *if_vlan_info) { ret_code ret = RET_OK; if(!if_vlan_info){ return RET_NULLP; } if(if_vlan_info->op_type == OP_ADD){ ret = vlan_save_conf_file_add(if_vlan_info); } else if(if_vlan_info->op_type == OP_DEL){ ret = vlan_save_conf_file_del(if_vlan_info); } else{ printf("[vlan]vlan_save_conf_file: OP_TYPE ERROR.return\n"); ret = RET_UNKNOWN; } return ret; } /************************************************************ * 函数功能:更新全局结构 * 输入: * 输出: * 返回值: ************************************************************/ ret_code refresh_if_vlan_info(interface_vlan_info *if_vlan_info) { ret_code ret = RET_OK; if(!if_vlan_info){ return RET_NULLP; } /* 路由桥接模型才会用到子接口,才需要保存配置文件 */ if(INTERFACE_MODEL_ROUTE_FORWARD == if_vlan_info->if_model){ ret = vlan_save_conf_file(if_vlan_info); if(ret != RET_OK){ printf("[vlan]refresh_if_vlan_info: save conf file failed.return.(%d)\n", ret); return ret; } } if(OP_ADD == if_vlan_info->op_type){ ret = refresh_if_vlan_info_op_add(if_vlan_info); } else if(OP_DEL == if_vlan_info->op_type){ ret = refresh_if_vlan_info_op_del(if_vlan_info); } else { printf("[vlan]refresh_if_vlan_info: OP_TYPE ERROR.return\n"); ret = RET_UNKNOWN; } return ret; } /************************************************************ * 函数功能:删除接口vlan * 此函数肯定是指定端口删除,默认删除端口下所有vlan信息 * 或者删除原接口下某个vlan,但是这种删除原接口下某个vlan可以 * 通过mod来做,没必要通过del来做 * 输入: * 输出: * 返回值: ************************************************************/ ret_code del_interface_vlan(interface_vlan_info *if_vlan_info) { ret_code ret = RET_OK; if(!if_vlan_info){ return RET_NULLP; } /* 配置校验 */ //ret = check_config(if_vlan_info->if_name); //if(0 == ret){//为0表示之前没有配置,返回错误。这种情况相当于ADD //return -1; //} /* 接口模型赋值 */ if_vlan_info->if_model = which_interface_model(if_vlan_info->if_name); /* 查询当前全局结构中此port的attr */ interface_link_attr old_attr = get_attr_from_ifname(if_vlan_info->if_name); /* trunk */ if(old_attr == LINK_TYPE_TRUNK){ ret = del_interface_vlan_trunk(if_vlan_info->if_name, if_vlan_info->vlan_bitmap, if_vlan_info->if_model); if(ret != RET_OK){ printf("[vlan]del_interface_vlan: del trunk failed(%d).\n", ret); return ret; } } else if(old_attr == LINK_TYPE_ACCESS){ ret = del_interface_vlan_access(if_vlan_info->if_name, if_vlan_info->if_model); if(ret != RET_OK){ printf("[vlan]del_interface_vlan: del access failed(%d).\n", ret); return ret; } } else { printf("[vlan]del_interface_vlan: LINK-TYPE attr(%d) input error.\n", old_attr); return RET_UNKNOWN; } /* 更新全局接口vlan数据结构 */ ret = refresh_if_vlan_info(if_vlan_info); return ret; } /************************************************************ * 函数功能:从全局gloabl结构中获取old的接口model * 输入: * 输出: * 返回值: ************************************************************/ interface_model get_old_interface_model(char *if_name, interface_model *if_model) { int ifnode; if(!if_name || !if_model){ printf("[vlan]get_old_interface_model: input or output para error.\n"); return -1; } ifnode = get_ifnode_from_global(if_name); if(-1 == ifnode){ return -1; } *if_model = g_if_vlan_info[ifnode].if_model; return 0; } /************************************************************ * 函数功能:判断新旧接口模型是否一致 * 输入: * 输出: * 返回值: 0: 一致,没变更 -1: 不一致,变更了 ************************************************************/ int if_model_is_change(interface_model old, interface_model new) { if(old == new){ return 0; } else{ return -1; } } int get_old_interface_attr(char *if_name, interface_link_attr *attr) { int ifnode; if(!if_name || !attr){ printf("[vlan]get_old_interface_attr: input or output para error.\n"); return -1; } ifnode = get_ifnode_from_global(if_name); if(-1 == ifnode){ return -1; } *attr = g_if_vlan_info[ifnode].attr; return 0; } /************************************************************ * 函数功能:接口vlan设置 * 根据操作类型来分别处理add、mod、del * 如果是add,则直接加 * 如果是del,则直接删 * 输入: * 输出: * 返回值: ************************************************************/ ret_code interface_vlan_set(interface_vlan_info *if_vlan_info) { operation_type op_type; ret_code ret = RET_OK; op_type = if_vlan_info->op_type; if(!if_vlan_info){ return RET_NULLP; } /* ADD只管现在 */ if(op_type == OP_ADD){ ret = add_interface_vlan(if_vlan_info); } /* 只管以前 */ else if(op_type == OP_DEL){ ret = del_interface_vlan(if_vlan_info); } else{ printf("[vlan]interface_vlan_set: op_type error.\n"); ret = RET_INPUTERR; } return ret; } /************************************************************ * 函数功能: 循环解析json串,将分段的值填加进port_vlan_info[] * 结构体数组中 * 只有ADD、DEL需要做chk校验,get和getall不需要,直接返回 * 每一个proc是一个operate操作 * { * "operate" : "add", * "conf-ifvlan": [ * { * "if-name" : "eth0", * "vid" : [ * 100, * 200, * ], * "if-attr" : "trunk" * }, * { * "if-name" : "eth1", * "vid" : [ * 300, * 400, * ], * "if-attr" : "trunk" * }, * ] * } * 输入: * 输出: if_vlnum、if_vlan_info * 返回值: ************************************************************/ ret_code vlan_config_json_parse(pointer input, interface_vlan_info *if_vlan_info, int *if_vlnum) { ret_code ret = RET_OK; int i, if_num = 0, vl_num = 0, j; cJSON *root = NULL, *operate = NULL, *conf_ifvlan = NULL; if(!if_vlan_info || !input){ ret = RET_NULLP; goto out; } if(!(root = cJSON_Parse(input))){ printf("[vlan-test]vlan_config_json_parse: json parse error, return error.\n"); ret = RET_INPUTERR; goto out; } if(!(operate = cJSON_GetObjectItem(root, "operate"))){ printf("[vlan]vlan_config_json_parse: No operate node.\n"); ret = RET_INPUTERR; goto out; } if(!(conf_ifvlan = cJSON_GetObjectItem(root, "conf-ifvlan"))){ ret = RET_INPUTERR; goto out; } /* 解析最外层interface数组 */ if_num = cJSON_GetArraySize(conf_ifvlan); if(if_num == 0){ printf("[vlan]vlan_config_json_parse: json array has no interface.\n"); ret = RET_INPUTERR; goto out; } cJSON *node; for(i = 0; i < if_num; i++){ /* 给每个接口的op_type赋值 */ if(NULL == operate->valuestring){ printf("[vlan]vlan_config_json_parse: operate->valuestring is null.\n"); ret = RET_INPUTERR; goto out; } if(!strcmp(operate->valuestring, "add")){ if_vlan_info[i].op_type = OP_ADD; } else if(!strcmp(operate->valuestring, "del")){ if_vlan_info[i].op_type = OP_DEL; } else if(!strcmp(operate->valuestring, "mod")){ if_vlan_info[i].op_type = OP_MOD; } node = cJSON_GetArrayItem(conf_ifvlan, i); if(!node){ continue; } cJSON *ifName = cJSON_GetObjectItem(node, "if-name"); if(!ifName){ continue; } if(NULL == ifName->valuestring){ printf("[vlan]vlan_config_json_parse: ifName->valuestring is null.\n"); ret = RET_INPUTERR; goto out; } memcpy(if_vlan_info[i].if_name, ifName->valuestring, strlen(ifName->valuestring)); printf("[vlan]if_vlan_info[%d].if_name=%s\n", i, if_vlan_info[i].if_name); cJSON *ifAttr = cJSON_GetObjectItem(node, "if-attr"); if(!ifAttr){ continue; } if(NULL == ifAttr->valuestring){ printf("[vlan]vlan_config_json_parse: ifAttr->valuestring is null.\n"); ret = RET_INPUTERR; goto out; } if(!strcmp(ifAttr->valuestring, "trunk")){ if_vlan_info[i].attr = LINK_TYPE_TRUNK; } else if(!strcmp(ifAttr->valuestring, "access")){ if_vlan_info[i].attr = LINK_TYPE_ACCESS; } cJSON *vId = cJSON_GetObjectItem(node, "vid"); if(!vId){ continue; } /* 解析内层vid数组 */ vl_num = cJSON_GetArraySize(vId); if(vl_num == 0){ printf("[vlan]vlan_config_json_parse: json array has no vid.\n"); ret = RET_INPUTERR; goto out; } /* 校验vid个数,如果超过边界,报错 */ ret = vid_num_chk(if_vlan_info[i].if_name, if_vlan_info[i].op_type, vl_num); if(ret != RET_OK){ printf("[vlan]vlan_config_json_parse: vid-num-chk error.\n"); goto out; } cJSON *item = NULL; for(j = 0; j < vl_num; j++){ item = cJSON_GetArrayItem(vId, j); printf("i=%d, vid=%d\n", i, item->valueint); /* vid数值及范围校验 */ ret = vid_value_chk(item->valueint); if(ret != RET_OK){ printf("[vlan]vlan_config_json_parse: vid check failed.\n"); ret = RET_INPUTERR; goto out; } vlan_bitmap_set(if_vlan_info[i].vlan_bitmap, item->valueint); } } if(if_vlnum){ *if_vlnum = if_num; } out: if(root){ cJSON_Delete(root); } return ret; } /************************************************************ * 函数功能:vlan模块配置管理入口 * 输入: * 输出: * 返回值: ************************************************************/ ret_code vlan_config_proc(uint source, uint config_type, pointer input, int input_len, pointer output, int *output_len) { operation_type op_type; int if_vl_num = 0, i; ret_code ret = RET_OK; interface_vlan_info if_vlan_info[MAX_INTERFACES] = {0}; printf("[vlan]===config-proc begin.===\n"); /* 配置下发 */ if(source == CONFIG_FROM_WEB){ ret = vlan_config_json_parse(input, if_vlan_info, &if_vl_num); if(ret != RET_OK){ printf("[vlan]vlan_config_proc: source:%d, json parse failed(%d).\n", source, ret); return ret; } for(i = 0; i < if_vl_num; i++){ ret = interface_vlan_set(&if_vlan_info[i]); if(ret != RET_OK){ printf("[vlan]vlan_config_proc: source:%d, vlan set failed(%d).\n", source, ret); return ret; } } } /* 配置恢复 */ else if(source == CONFIG_FROM_RECOVER1){ ret = vlan_config_json_parse(input, if_vlan_info, &if_vl_num); if(ret != RET_OK){ printf("[vlan]vlan_config_proc: source:%d, json parse failed(%d).\n", source, ret); return ret; } for(i = 0; i < if_vl_num; i++){ ret = interface_vlan_set(&if_vlan_info[i]); if(ret != RET_OK){ printf("[vlan]vlan_config_proc: source:%d, vlan set failed(%d).\n", source, ret); return ret; } } } return RET_OK; } /************************************************************ * 函数功能:从下发的get的json解析 * 根据ifname去全局结构中查询,如果节点存在,则将所在节点下标 * 放入interface结构,以便后续使用 * get格式 * { * "get-ifvlan": [ * { * "if-name" : "eth0", * }, * { * "if-name" : "eth1", * }, * } * * 返回数据格式 * { * "if-vlan": [ * { * "if-name" : "eth0", * "vid" : [ * 100, * 200, * ], * "if-attr" : "trunk" * }, * { * "if-name" : "eth1", * "vid" : [ * 300, * 400, * ], * "if-attr" : "trunk" * }, * } * 输入: * 输出: * 返回值: ************************************************************/ ret_code vlan_get_json_parse(int *interface, pointer input) { ret_code ret = RET_OK; int i, if_num, vl_num, j, ifnode; cJSON *root = NULL, *operate = NULL, *get_ifvlan = NULL; if(!interface){ printf("[vlan]vlan_get_json_parse: interface is null.\n"); ret = RET_NULLP; goto out; } if(!(root = cJSON_Parse(input))){ printf("[vlan]vlan_get_json_parse: root failed.\n"); ret = RET_INPUTERR; goto out; } if(!(operate = cJSON_GetObjectItem(root, "operate"))){ printf("[vlan]vlan_get_json_parse: No operate node.\n"); ret = RET_INPUTERR; goto out; } //if(operate->valuestring == NULL || strcmp(operate->valuestring, "get") != 0){ //printf("[vlan]vlan_get_json_parse: error: operate-val is %s.\n", operate->valuestring); //ret = RET_INPUTERR; //goto out; //} if(!(get_ifvlan = cJSON_GetObjectItem(root, "get-ifvlan"))){ printf("[vlan]vlan_get_json_parse: No get-ifvlan node.\n"); ret = RET_INPUTERR; goto out; } /* 解析最外层interface数组 */ if_num = cJSON_GetArraySize(get_ifvlan); if(if_num == 0){ printf("[vlan]vlan_get_json_parse: json array has no interface.\n"); ret = RET_INPUTERR; goto out; } cJSON *node = NULL; for(i = 0; i < if_num; i++){ node = cJSON_GetArrayItem(get_ifvlan, i); if(!node){//??? continue; } cJSON *ifName = cJSON_GetObjectItem(node, "if-name"); if(!ifName){ continue; } //if_vlan_info[i].if_name= ifName->valuestring;//memcpy /* 如果找到了对应的ifnode,则对应下标置1 */ ifnode = get_ifnode_from_global(ifName->valuestring); if(ifnode != -1){ interface[ifnode] = 1; } } out: if(root){ cJSON_Delete(root); } return ret; } /************************************************************ * 函数功能:将所传interface中数据为1则将此下标作为全局结构 * 下标,取出对应节点封装成json传出 * 输入: * 输出: * 返回值: ************************************************************/ ret_code vlan_config_format_json(int *interface, pointer output, int *output_len) { cJSON *root = NULL, *arr = NULL, *js_list = NULL, *js_vid = NULL; char *out = NULL; int i, j, vid; root = cJSON_CreateObject(); if(!root){ printf("[vlan]cJSON_CreateObject1 error.\n"); return RET_ERR; } cJSON_AddItemToObject(root, "if-vlan", arr = cJSON_CreateArray()); for(i = 0; i < MAX_INTERFACES; i++){ //ifnode = get_ifnode_from_global(if_vlan_info[i].if_name) if(!(interface[i])){ continue; } js_list = cJSON_CreateObject(); if(!js_list){ printf("[vlan]cJSON_CreateObject2 error.\n"); cJSON_Delete(root); return RET_ERR; } cJSON_AddStringToObject(js_list , "if-name", g_if_vlan_info[i].if_name); cJSON_AddNumberToObject(js_list , "if-attr", g_if_vlan_info[i].attr); cJSON_AddItemToObject(js_list, "vid", js_vid = cJSON_CreateArray()); for(vid = 0; vid < MAX_VLAN;vid++){ if(vlan_bitmap_check(g_if_vlan_info[i].vlan_bitmap, vid)){ cJSON_AddItemToArray(js_vid, cJSON_CreateNumber(vid)); } } cJSON_AddItemToArray(arr, js_list); } out = cJSON_PrintUnformatted(root); if(!out){ printf("[vlan]vlan_config_format_json: cJSON_PrintUnformatted failed.\n"); cJSON_Delete(root); return RET_ERR; } *output_len = strlen(out) + 1; memcpy(output, out, *output_len); xfree(out); cJSON_Delete(root); return RET_OK; } /************************************************************ * 函数功能:vlan配置get总入口 * 输入: * 输出: * 返回值: ************************************************************/ ret_code vlan_config_get(uint source, pointer input, int input_len, pointer output, int *output_len) { //interface_vlan_info if_vlan_info[MAX_INTERFACES] = {0}; int if_vlnum = 0; ret_code ret = RET_OK; int interface[MAX_INTERFACES] = {0}; if(!input){ printf("[vlan]vlan_config_get: input is null.\n"); return RET_INPUTERR; } printf("[vlan]===config-get begin.===\n"); /* 将存匹配的节点下标传入interface中对应下标 */ ret = vlan_get_json_parse(interface, input); if(ret != RET_OK){ printf("[vlan]vlan_config_get: get json parse failed.\n"); return ret; } /* 根据对应interface下标,去获取全局g_if_vlan_info信息 */ ret = vlan_config_format_json(interface, output, output_len); if(ret != RET_OK){ printf("[vlan]vlan_config_get: format json failed.\n"); return ret; } return RET_OK; } /************************************************************ * 函数功能:从配置文件中读取子接口信息 * "/etc/network/interfaces" * 解析物理口名字和vlan id * auto ens38.100 * | | | * pauto pifname ppoint * * 输入: * 输出: * 返回值: ************************************************************/ ret_code vlan_get_from_conf_file(int *interface) { if(!interface){ printf("[vlan]vlan_get_from_conf_file: para is null.\n"); return RET_NULLP; } FILE *fp = NULL; char line[FILE_BUF_LINE] = {0}; if(!(fp = fopen(ETC_NETWORK_IFS, "r"))){ printf("[vlan]vlan_get_from_conf_file: file open failed.\n"); return RET_ERR; } //fseek(fp,0,SEEK_END); //rewind(fp); int vid; int node_num = 0; char *pauto = NULL;//"auto"指针位置 char *point = NULL;//'.'指针位置 char *ifname = NULL;//"ens38"指针位置 char tmp_name[IF_NAME_LEN] = {0};// int i; while(fgets(line, FILE_BUF_LINE, fp)){ /* 找到"auto" */ pauto = strstr(line, "auto"); if(!pauto){ continue; } /* 找到'.' */ point = strchr(pauto, '.'); if(!point){ continue; } /* auto后第一个字符 */ ifname = pauto + strlen("auto"); /* 过滤空格或TAB */ while(ifname && (*ifname == ' ' || *ifname == '\t')){ ifname++; } /* 找到ens38 */ if(ifname){ char *p; printf("[vlan]vlan_get_from_conf_file: ifname="); for(p = ifname; p < point && p; p++){ printf("%c", *p); } memcpy(tmp_name, ifname, point - ifname); /* 在已经添加进g的node里的结构中的if-name做比较 如果发现重名的,说明该节点当时赋值过了,只需再设置 当前行解析出的vid即可*/ for(i = 0; i < node_num; i++){ if(!strcmp(g_if_vlan_info[i].if_name, tmp_name)){ vid = atoi(point+1); printf("\n[vlan]vlan_get_from_conf_file: find same node, vid = %d\n", vid); vlan_bitmap_set(g_if_vlan_info[i].vlan_bitmap, vid); break; } } /* i==node_num说明前面没找到,这是个全新的 */ if(i == node_num){ memcpy(g_if_vlan_info[node_num].if_name, ifname, point - ifname); g_if_vlan_info[node_num].attr = LINK_TYPE_TRUNK; g_if_vlan_info[node_num].op_type = OP_ADD; g_if_vlan_info[node_num].if_model = INTERFACE_MODEL_ROUTE_FORWARD; vid = atoi(point+1); printf("\n[vlan]vlan_get_from_conf_file: vid = %d\n", vid); vlan_bitmap_set(g_if_vlan_info[node_num].vlan_bitmap, vid); interface[node_num] = 1; node_num++; } } } fclose(fp); return RET_OK; } /************************************************************ * 函数功能:vlan配置get all总入口 * 输入: * 输出: * 返回值: ************************************************************/ ret_code vlan_config_get_all(uint source, pointer output, int *output_len) { int interface[MAX_INTERFACES] = {0}; int i; ret_code ret= RET_OK; printf("[vlan]===config-get-all begin.===\n"); /* WEB下发,g_if_vlan_info对应的node是有数据的 只需将有数据的节点node返回到interface里即可*/ printf("[vlan]vlan_config_get_all: source=%d.\n", source); if(source == CONFIG_FROM_WEB){ for(i = 0; i < MAX_INTERFACES; i++){ //if(get_ifnode_from_global(g_if_vlan_info[i].if_name) != -1) /* 不为空串才给interface置1 */ if(strcmp(g_if_vlan_info[i].if_name, "")){ interface[i] = 1; printf("[vlan]vlan_config_get_all: interface[%d].\n", i); } } } /* 配置恢复g_if_vlan_info里是空的,需要先从 配置文件将数据恢复到内存g_if_vlan_info[]中 然后再将有数据的节点node放入interface*/ else if(source == CONFIG_FROM_RECOVER1){ ret = vlan_get_from_conf_file(interface); if(ret != RET_OK){ printf("[vlan]vlan_config_get_all: source %d, get from cfg file failed(%d).\n", source, ret); return ret; } } ret = vlan_config_format_json(interface, output, output_len); if(ret != RET_OK){ printf("[vlan]vlan_config_get_all: source %d, get from cfg file failed(%d).\n", source, ret); return ret; } return RET_OK; } /************************************************************ * 函数功能:对外提供的接口 * 组装删除vlan的信息 * 输入: * 输出: * 返回值: ************************************************************/ ret_code del_compose_if_vlan_info(char *if_name, interface_vlan_info *if_vlan_info) { int ifnode = -1, vid; if(!if_name || !if_vlan_info){ printf("[vlan]del_compose_if_vlan_info: input pointer is null.\n"); return RET_NULLP; } /* 根据ifname查找到当前if节点,并将vlan赋值给if_vlan_info */ ifnode = get_ifnode_from_global(if_name); if(ifnode == -1){ printf("[vlan]del_compose_if_vlan_info: find empty ifnode.\n"); return RET_NOTFOUND; } if_vlan_info->attr = g_if_vlan_info[ifnode].attr; if_vlan_info->if_model = g_if_vlan_info[ifnode].if_model; if_vlan_info->op_type = OP_DEL; if_vlan_info->vidcnt = g_if_vlan_info[ifnode].vidcnt; memcpy(if_vlan_info->if_name, g_if_vlan_info[ifnode].if_name, strlen(g_if_vlan_info[ifnode].if_name)); printf("[vlan]del_compose_if_vlan_info: attr=%d, op_type=%d, ifname=%s\n", if_vlan_info->attr, if_vlan_info->op_type, if_vlan_info->if_name); /* 提取vlanbitmap */ printf("[vlan]del_compose_if_vlan_info: vlan_info:\n("); for(vid = VID_MIN; vid <= VID_MAX; vid++){ /* 如果找到了vid存在,则在新结构的vlan_bitmap中设置vid bitmap */ if(vlan_bitmap_check(g_if_vlan_info[ifnode].vlan_bitmap, vid)){ vlan_bitmap_set(if_vlan_info->vlan_bitmap, vid); printf("%d, ", vid); } } printf(")\n"); return RET_OK; } /************************************************************ * 函数功能:对外提供的接口 * 删除指定物理口上的vlan的回调函数 * 输入: * 输出: * 返回值: ************************************************************/ int del_interface_vlan_cb(BR_EVENT_TYPE event_type, br_event_t event_arg) { interface_vlan_info if_vlan_info = {0}; ret_code ret = RET_OK; ret = del_compose_if_vlan_info(event_arg.if_name, &if_vlan_info); if(ret != RET_OK){ printf("[vlan]del_interface_vlan_cb: compose-if-vlan-info failed(%d).\n", ret); return ret; } ret = del_interface_vlan(&if_vlan_info); if(ret != RET_OK){ printf("[vlan]del_interface_vlan_cb: del-if-vlan failed(%d).\n", ret); return ret; } return RET_OK; } /************************************************************ * 函数功能:vlan vid值校验 * 输入: * 输出: * 返回值: ************************************************************/ ret_code vid_value_chk(int vid) { if(!(vid >= VID_MIN && vid <= VID_MAX)){ printf("[vlan]vid_value_chk: vid value error,return error\n"); return RET_INPUTERR; } return RET_OK; } /************************************************************ * 函数功能:vlan数目校验 * 输入: * 输出: * 返回值: ************************************************************/ ret_code vid_num_chk(char *if_name, operation_type op_type, int num) { int ifnode = -1; if(!if_name){ printf("[vlan]vid_num_chk: if_name is null.\n"); return RET_NULLP; } printf("[vlan]vid_num_chk: if_name=%s, op_type=%d, num=%d\n", if_name, op_type, num); ifnode = get_ifnode_from_global(if_name); if(ifnode == -1){ printf("[vlan]vid_num_chk: get ifnode empty, return\n"); return RET_OK; } if(op_type == OP_ADD && g_if_vlan_info[ifnode].vidcnt + num > EACH_PORT_MAX_VLAN_NUM){ printf("[vlan]vid_num_chk: ADD operation's vid num(%d+%d=%d) > EACH_PORT_MAX_VLAN_NUM\n", g_if_vlan_info[ifnode].vidcnt, num, g_if_vlan_info[ifnode].vidcnt + num); return RET_INPUTERR; } return RET_OK; } /************************************************************ * 函数功能:vlan属性校验 * 目前只支持trunk,非trunk报错 * 输入: * 输出: * 返回值: ************************************************************/ ret_code if_attr_chk(interface_vlan_info *if_vlan_info) { if(if_vlan_info->attr != LINK_TYPE_TRUNK){ printf("[vlan]if_attr_chk: now we only support link-type trunk.\n"); return RET_INPUTERR; } return RET_OK; } /************************************************************ * 函数功能:vlan配置操作类型ADD校验 * 新下发的vlan id如果全局中有,则报错 * 输入: * 输出: * 返回值: ************************************************************/ ret_code op_type_add_chk(interface_vlan_info *if_vlan_info) { int ifnode, vid; ifnode = get_ifnode_from_global(if_vlan_info->if_name); if(ifnode == -1){ printf("[vlan]op_type_add_chk: This if_name has no node, return OK.\n"); return RET_OK; } /* 新下发的vid如果全局g中有,则报错返回 */ for(vid = VID_MIN; vid <= VID_MAX; vid++){ if(vlan_bitmap_check(if_vlan_info->vlan_bitmap, vid) && vlan_bitmap_check(g_if_vlan_info[ifnode].vlan_bitmap, vid)){ printf("[vlan]op_type_add_chk: Already have vid[%d], now return\n", vid); return RET_INPUTERR; } } return RET_OK; } /************************************************************ * 函数功能:vlan配置操作类型DEL校验 * 新下发的vid如果全局中没有,则报错 * 输入: * 输出: * 返回值: ************************************************************/ ret_code op_type_del_chk(interface_vlan_info *if_vlan_info) { int ifnode, vid; ret_code ret = RET_OK; ifnode = get_ifnode_from_global(if_vlan_info->if_name); if(ifnode == -1){ printf("[vlan]op_type_del_chk: get_ifnode failed.\n"); ret = RET_INPUTERR; goto out; } /* 新下发的vid如果全局g中没有,则报错返回 */ for(vid = VID_MIN; vid <= VID_MAX; vid++){ if(vlan_bitmap_check(if_vlan_info->vlan_bitmap, vid) && !vlan_bitmap_check(g_if_vlan_info[ifnode].vlan_bitmap, vid)){ printf("[vlan]op_type_del_chk: node[%d] do not have vid[%d], now return\n", ifnode, vid); ret = RET_INPUTERR; goto out; } } out: return ret; } /************************************************************ * 函数功能:vlan配置操作类型校验 * 只支持ADD、DEL,其他类型报错 * 输入: * 输出: * 返回值: ************************************************************/ ret_code op_type_chk(interface_vlan_info *if_vlan_info) { int ifnode, vid, i; ret_code ret = RET_OK; /* ADD操作校验 */ if(if_vlan_info->op_type == OP_ADD){ ret = op_type_add_chk(if_vlan_info); } /* DEL操作校验 */ else if(if_vlan_info->op_type == OP_DEL){ ret = op_type_del_chk(if_vlan_info); } else { printf("[vlan]op_type_chk: op_type error.\n"); ret = RET_INPUTERR; } return ret; } /************************************************************ * 函数功能:接口名校验 * 如果下发的接口名为空,报错 * 输入: * 输出: * 返回值: ************************************************************/ ret_code if_name_chk(interface_vlan_info *if_vlan_info) { if(!(strcmp(if_vlan_info->if_name, ""))){ printf("[vlan]if_name_chk: if-name is emptyp, return error.\n"); return RET_ERR; } return RET_OK; } /************************************************************ * 函数功能:vlan配置校验 * 接口名、属性、操作类型校验;vid放在json解析时校验 * 输入: * 输出: * 返回值: ************************************************************/ ret_code interface_vlan_check(interface_vlan_info *if_vlan_info) { ret_code ret = RET_OK; if(!if_vlan_info){ return RET_NULLP; } printf("[vlan]interface_vlan_check: ifname=%s, op_type=%d, attr=%d\n", if_vlan_info->if_name, if_vlan_info->op_type, if_vlan_info->attr); /* if_name校验 */ ret = if_name_chk(if_vlan_info); if(ret != RET_OK){ printf("[vlan-chk]interface_vlan_check: if-name-chk failed.\n"); goto out; } /* if_attr校验 */ ret = if_attr_chk(if_vlan_info); if(ret != RET_OK){ printf("[vlan-chk]interface_vlan_check: if-attr-chk failed.\n"); goto out; } /* 操作校验 */ ret = op_type_chk(if_vlan_info); if(ret != RET_OK){ printf("[vlan-chk]interface_vlan_check: op-type-chk failed.\n"); goto out; } out: return ret; } /************************************************************ * 函数功能:vlan配置操作类型校验 * 先json解析出来放入临时结构if_vlan_info[],然后调用校验函数 * 输入: * 输出: * 返回值: ************************************************************/ ret_code vlan_config_set_chk(uint source, pointer input) { int if_vl_num = 0, i; ret_code ret = RET_OK; interface_vlan_info if_vlan_info[MAX_INTERFACES] = {0}; ret = vlan_config_json_parse(input, if_vlan_info, &if_vl_num); if(ret != RET_OK){ printf("[vlan]vlan_config_set_chk: json-parse failed(%d).\n", ret); goto out; } for(i = 0; i < if_vl_num; i++){ ret = interface_vlan_check(&if_vlan_info[i]); if(ret != RET_OK){ printf("[vlan]vlan_config_set_chk: if-node[%d] vlan chk failed(%d).\n", i, ret); goto out; } } out: return ret; } /************************************************************ * 函数功能:解析操作类型 * 输入: * 输出: * 返回值: ************************************************************/ ret_code vlan_operate_parse(pointer input, int *oper_type) { ret_code ret = RET_OK; int i, if_num, vl_num, j; cJSON *root = NULL, *operate = NULL, *conf_ifvlan = NULL; if(!input || !oper_type){ printf("[vlan]vlan_operate_chk: input or oper_type para is null.\n"); ret = RET_INPUTERR; goto out; } if(!(root = cJSON_Parse(input))){ printf("[vlan]vlan_operate_chk: json parse error, return error.\n"); ret = RET_INPUTERR; goto out; } if(!(operate = cJSON_GetObjectItem(root, "operate"))){ printf("[vlan]vlan_operate_chk: No operate node.\n"); ret = RET_INPUTERR; goto out; } if(operate->valuestring != NULL && !strcmp(operate->valuestring, "add") || operate->valuestring != NULL && !strcmp(operate->valuestring, "del")){ printf("[vlan]vlan_operate_chk: operate-val is SET.\n"); *oper_type = CM_CONFIG_SET; ret = RET_OK; goto out; } else if(operate->valuestring != NULL && !strcmp(operate->valuestring, "get")){ printf("[vlan]vlan_operate_chk: operate-val is GET.\n"); *oper_type = CM_CONFIG_GET; ret = RET_OK; goto out; } else if(operate->valuestring != NULL && !strcmp(operate->valuestring, "getall")){ printf("[vlan]vlan_operate_chk: operate-val is GETALL.\n"); *oper_type = CM_CONFIG_GET_ALL; ret = RET_OK; goto out; } out: if(root){ cJSON_Delete(root); } return ret; } /************************************************************ * 函数功能:vlan get操作类型校验 * 根据operate类型分别进set、get、getall校验 * 目前只有set校验 * 输入: * 输出: * 返回值: ************************************************************/ ret_code vlan_config_get_chk(uint source, pointer input) { int ret = RET_OK; int i; int interface[MAX_INTERFACES] = {0}; if(!input){ printf("[vlan]vlan_config_get_chk: input null.\n"); return RET_NULLP; } ret = vlan_get_json_parse(interface, input); if(ret != RET_OK){ printf("[vlan]vlan_config_get_chk: get json parse failed(%d).\n", ret); return ret; } for(i = 0; i < MAX_INTERFACES; i++){ if(interface[i] == 1){ return RET_OK; } } return RET_INPUTERR; } /************************************************************ * 函数功能:vlan getall操作类型校验 * 根据operate类型分别进set、get、getall校验 * 目前只有set校验 * 输入: * 输出: * 返回值: ************************************************************/ ret_code vlan_config_get_all_chk(uint source, pointer input) { return RET_OK; } /************************************************************ * 函数功能:vlan配置操作类型校验 * 根据operate类型分别进set、get、getall校验 * 目前只有set校验 * 输入: * 输出: * 返回值: ************************************************************/ ret_code vlan_config_chk(uint source,uint *config_type, pointer input, int *input_len, pointer output, int *output_len) { printf("[vlan]===config-chk begin.===\n"); int if_vl_num = 0, i, ret = RET_OK; interface_vlan_info if_vlan_info[MAX_INTERFACES] = {0}; int oper_type; ret = vlan_operate_parse(input, &oper_type); if(ret != RET_OK){ goto out; } *config_type = oper_type; printf("[vlan]vlan_config_chk: operate_type=%d\n", oper_type); if(oper_type == CM_CONFIG_SET){ printf("[vlan]vlan_config_chk: SET chk\n"); ret = vlan_config_set_chk(source, input); } else if(oper_type == CM_CONFIG_GET){ printf("[vlan]vlan_config_chk: GET chk\n"); ret = vlan_config_get_chk(source, input); } else if(oper_type == CM_CONFIG_GET_ALL){ printf("[vlan]vlan_config_chk: GET-ALL chk\n"); ret = vlan_config_get_all_chk(source, input); } else { printf("[vlan]vlan_config_chk: oper_type is unknown(%d).\n", oper_type); ret = RET_UNKNOWN; } out: printf("[vlan]vlan_config_chk: return ret=%d\n", ret); return ret; } void vlan_set_struct_stub(interface_vlan_info *if_vlan_info, operation_type op_type, int *if_vlnum) { int vid, i; *if_vlnum = 0; int cnt = 0; if(op_type == OP_ADD){ /* 设置ens38.100 */ memcpy(if_vlan_info[cnt].if_name, "ens38", strlen("ens38")); if_vlan_info[cnt].op_type = op_type; if_vlan_info[cnt].attr = LINK_TYPE_TRUNK; if_vlan_info[cnt].if_model = INTERFACE_MODEL_ROUTE_FORWARD; vid = 100; vlan_bitmap_set(if_vlan_info[cnt].vlan_bitmap, vid); cnt++; /* 设置ens39.200, ens39.300 */ memcpy(if_vlan_info[cnt].if_name, "ens39", strlen("ens39")); if_vlan_info[cnt].op_type = op_type; if_vlan_info[cnt].attr = LINK_TYPE_TRUNK; if_vlan_info[cnt].if_model = INTERFACE_MODEL_ROUTE_FORWARD; vid = 200; vlan_bitmap_set(if_vlan_info[cnt].vlan_bitmap, vid); vid = 300; vlan_bitmap_set(if_vlan_info[cnt].vlan_bitmap, vid); cnt++; for(i = 0; i < cnt; i++){ printf("[vlan-stub]vlan_set_struct_stub: ADD-->if_vlan_info[%d].if_name=%s\n", i, if_vlan_info[i].if_name); } } else if(op_type == OP_DEL){ /* 删除ens39.200 */ memcpy(if_vlan_info[cnt].if_name, "ens39", strlen("ens39")); if_vlan_info[cnt].op_type = op_type; if_vlan_info[cnt].attr = LINK_TYPE_TRUNK; if_vlan_info[cnt].if_model = INTERFACE_MODEL_ROUTE_FORWARD; vid = 200; vlan_bitmap_set(if_vlan_info[cnt].vlan_bitmap, vid); cnt++; } else if(op_type == OP_MOD){ /* 修改ens39.300-->ens39.400 */ memcpy(if_vlan_info[cnt].if_name, "ens39", strlen("ens39")); if_vlan_info[cnt].op_type = op_type; if_vlan_info[cnt].attr = LINK_TYPE_TRUNK; if_vlan_info[cnt].if_model = INTERFACE_MODEL_ROUTE_FORWARD; vid = 400; vlan_bitmap_set(if_vlan_info[cnt].vlan_bitmap, vid); cnt++; for(i = 0; i < cnt; i++){ printf("[vlan-stub]vlan_set_struct_stub: MOD-->if_vlan_info[%d].if_name=%s\n", i, if_vlan_info[i].if_name); } } *if_vlnum = cnt; return; } void vlan_config_stub1(void) { int if_vlnum, i; interface_vlan_info if_vlan_info_add[MAX_INTERFACES] = {0}; interface_vlan_info if_vlan_info_del[MAX_INTERFACES] = {0}; interface_vlan_info if_vlan_info_mod[MAX_INTERFACES] = {0}; /* ADD */ vlan_set_struct_stub(if_vlan_info_add, OP_ADD, &if_vlnum); for(i = 0; i < if_vlnum; i++){ interface_vlan_set(&if_vlan_info_add[i]); } /* DEL */ //vlan_set_struct_stub(if_vlan_info_del, OP_DEL, &if_vlnum); //for(i = 0; i < if_vlnum; i++){ //interface_vlan_set(&if_vlan_info_del[i]); //} /* MOD */ vlan_set_struct_stub(if_vlan_info_add, OP_MOD, &if_vlnum); for(i = 0; i < if_vlnum; i++){ interface_vlan_set(&if_vlan_info_mod[i]); } return; } void vlan_config_stub(operation_type op_type) { int if_vlnum, i; interface_vlan_info if_vlan_info[MAX_INTERFACES] = {0}; vlan_set_struct_stub(if_vlan_info, op_type, &if_vlnum); for(i = 0; i < if_vlnum; i++){ interface_vlan_set(&if_vlan_info[i]); } return; } void vlan_config_format_json_stub(int *interface) { int i, j, vid; for(i = 0; i < MAX_INTERFACES; i++){ if(!(interface[i])){ continue; } printf("[vlan]vlan_config_format_json_stub: g_if_vlan_info[%d].if_name=%s, attr=%d, if_model=%d, op_type=%d, vlan=\n", i, g_if_vlan_info[i].if_name, g_if_vlan_info[i].attr, g_if_vlan_info[i].if_model, g_if_vlan_info[i].op_type); for(vid = 0; vid < MAX_VLAN;vid++){ if(vlan_bitmap_check(g_if_vlan_info[i].vlan_bitmap, vid)){ printf("%d,", vid); } } printf("\n"); } return; } void vlan_config_get_stub(void) { int if_vlnum; int interface[MAX_INTERFACES] = {0}; interface[1] = 1; printf("[vlan]vlan_config_get_stub:start.\n"); /* 根据对应interface下标,去获取全局g_if_vlan_info信息 */ vlan_config_format_json_stub(interface); return; } void vlan_config_get_all_stub(uint source) { int interface[MAX_INTERFACES] = {0}; int i; /* WEB下发,g_if_vlan_info对应的node是有数据的 只需将有数据的节点node返回到interface里即可*/ if(source == CONFIG_FROM_WEB){ printf("[vlan]vlan_config_get_all: CONFIG_FROM_WEB.\n"); for(i = 0; i < MAX_INTERFACES; i++){ //if(get_ifnode_from_global(g_if_vlan_info[i].if_name) != -1) /* 不为空串才给interface置1 */ if(strcmp(g_if_vlan_info[i].if_name, "")){ interface[i] = 1; printf("[vlan]get_all_stub: interface[%d].\n", i); } } } /* 配置恢复g_if_vlan_info里是空的,需要先从 配置文件将数据恢复到内存g_if_vlan_info[]中 然后再将有数据的节点node放入interface*/ else if(source == CONFIG_FROM_RECOVER1){ printf("[vlan]vlan_config_get_all: CONFIG_FROM_RECOVER1.\n"); vlan_get_from_conf_file(interface); } vlan_config_format_json_stub(interface); return; }