/* 两个网关四个接口, 四种拓扑模式, 每个网关内有独立线程, 但对于TOPO_ACC_LINK_USER, TOPO_ACC_LINK_FWD应该共用接收/发送线程, 因为内部有NAT转发表, 收发两个方向使用同一个, 如果是多线程, 还要加锁. 所以, 支持TOPO_ACC_LINK_USER, TOPO_ACC_LINK_FWD为不同的捕包模式, 但必须用非阻塞模式在两个网卡之间来回切换获取数据包. */ #include "flowood.h" #include "flowood_fun.h" #include "flwd_net.h" #include "MESA_handle_logger.h" #include "MESA_prof_load.h" #include #include #include #include #include #include typedef struct{ flwd_cap_mode_t cap_mode; char *lib_name; }flwd_io_lib_name_type_t; static const flwd_io_lib_name_type_t g_packet_io_type_name_info[] = { {CAP_MODEL_PAG , (char *)"flwd_io_pag.so" }, {CAP_MODEL_PCAP_ONLINE , (char *)"flwd_io_pcap.so" }, {CAP_MODEL_SOCKET , (char *)"flwd_io_socket.so" }, {CAP_MODEL_PFRING , (char *)"flwd_io_pfring.so" }, {CAP_MODEL_DPDK , (char *)"flwd_io_dpdk.so" }, {CAP_MODEL_PPF , (char *)"flwd_io_ppf.so" }, {CAP_MODEL_NPACKET , (char *)"flwd_io_npacket.so" }, {CAP_MODEL_QNF , (char *)"flwd_io_qnf.so" }, {CAP_MODEL_N95 , (char *)"flwd_io_n95.so" }, {CAP_MODEL_PCAP_DUMPLIST , (char *)"flwd_io_pcap.so"}, {CAP_MODEL_TOPSEC , (char *)"flwd_io_topsec.so"}, {CAP_MODEL_IPFILE , (char *)"flwd_io_ipfile.so"}, {CAP_MODEL_MARSIOV4 , (char *)"flwd_io_marsio.so"}, {CAP_MODEL_AGENT_SMITH , (char *)"flwd_io_agent_smith.so"}, {CAP_MODEL_DPDK_VXLAN , (char *)"flwd_io_dpdk_vxlan.so"}, {CAP_MODEL_MARSIOV4_VXLAN , (char *)"flwd_io_marsio_vxlan.so"}, {CAP_MODEL_PAG_MARSIO , (char *)"flwd_io_pag_marsio.so"}, }; const flwd_packet_io_cfg_para_t g_packet_io_cfg_para[__TOPO_MODE_MAX] = { {TOPO_ACC_LINK_USER, FLWD_MACRO_TO_STRING(TOPO_ACC_LINK_USER), "#todo"}, {TOPO_ACC_LINK_FWD, FLWD_MACRO_TO_STRING(TOPO_ACC_LINK_FWD), "#todo"}, {TOPO_FWD_LINK_ACC, FLWD_MACRO_TO_STRING(TOPO_FWD_LINK_ACC), "#doto"}, {TOPO_FWD_LINK_GDEV, FLWD_MACRO_TO_STRING(TOPO_FWD_LINK_GDEV), "#doto"}, }; static int flwd_packet_io_lib_load(flwd_device_handle_t *global_dev_handle) { char full_lib_path[PATH_MAX]; void *dlopen_handle; switch((int)global_dev_handle->io_para.cap_mode){ case CAP_MODEL_PCAP_ONLINE: case CAP_MODEL_SOCKET: case CAP_MODEL_MARSIOV4: break; default: flwd_log(RLOG_LV_FATAL, "not support cap_mode:%d\n", (int)global_dev_handle->io_para.cap_mode); return -1; break; } snprintf(full_lib_path, PATH_MAX, "%s/%s", "ip_reuse_io_lib", g_packet_io_type_name_info[(int)global_dev_handle->io_para.cap_mode].lib_name); dlopen_handle = dlopen(full_lib_path, RTLD_LAZY | RTLD_LOCAL); if(NULL == dlopen_handle){ flwd_log(RLOG_LV_FATAL, "dlopen %s error, %s", full_lib_path, dlerror()); return -1; } global_dev_handle->low_level_io_init = (int (*)(struct __flwd_device_handle *h))dlsym(dlopen_handle, "low_level_io_init"); global_dev_handle->low_level_io_run = (void (*)(struct __flwd_device_handle *h))dlsym(dlopen_handle, "low_level_io_run"); global_dev_handle->low_level_pkt_recv = (int (*)(struct __flwd_device_handle *h, int tid, void **mbuff))dlsym(dlopen_handle, "low_level_pkt_recv"); global_dev_handle->low_level_pkt_free = (void (*)(struct __flwd_device_handle *h, int tid, void *mbuff))dlsym(dlopen_handle, "low_level_pkt_free"); global_dev_handle->low_level_mbuff_malloc = (void * (* )(struct __flwd_device_handle *h, int tid, int len)) dlsym(dlopen_handle, "low_level_mbuff_malloc"); global_dev_handle->low_level_mbuff_free = (void (* )(struct __flwd_device_handle *h, int, void *mbuff)) dlsym(dlopen_handle, "low_level_mbuff_free"); global_dev_handle->low_level_mbuff_free_after_send = (void (* )(struct __flwd_device_handle *h, int, void *mbuff)) dlsym(dlopen_handle, "low_level_mbuff_free_after_send"); global_dev_handle->low_level_mbuff_mtod = (char * (* )(void *mbuff))dlsym(dlopen_handle, "low_level_mbuff_mtod"); global_dev_handle->low_level_mbuff_data_append = (char * (*)(void *mbuff, const char *user_data, int user_data_len))dlsym(dlopen_handle, "low_level_mbuff_data_append"); global_dev_handle->low_level_mbuff_data_forward = (char * (*)(void *mbuff, int n))dlsym(dlopen_handle, "low_level_mbuff_data_forward"); global_dev_handle->low_level_mbuff_data_rearward = (char * (*)(void *mbuff, int n))dlsym(dlopen_handle, "low_level_mbuff_data_rearward"); global_dev_handle->low_level_mbuff_get_pkt_len = (int (*)(void *mbuff))dlsym(dlopen_handle, "low_level_mbuff_get_pkt_len"); global_dev_handle->low_level_mbuff_set_pkt_len = (void (*)(void *mbuff, int pkt_len)) dlsym(dlopen_handle, "low_level_mbuff_set_pkt_len"); global_dev_handle->low_level_send = (int (*)(struct __flwd_device_handle *h, int tid, void *mbuff))dlsym(dlopen_handle, "low_level_send"); return 0; } static void *flwd_packet_io_run_thread(void *arg) { flwd_device_handle_t *global_io_handle = (flwd_device_handle_t *)arg; global_io_handle->low_level_io_run(global_io_handle); while(1){ pause(); } return NULL; } void flwd_packet_io_run(void) { int i; pthread_t recv_thread_pid[FLWD_MAX_THREAD_NUM]; pthread_t run_thread_pid[FLWD_MAX_THREAD_NUM]; static int thread_seq[FLWD_MAX_THREAD_NUM]; for(i = 0; i < flwd_cfg_val.tot_thread_count; i++){ thread_seq[i] = i; pthread_create(&recv_thread_pid[i], NULL, flwd_packet_io_work_thread, (void *)&thread_seq[i]); } /* NOTE: 受某些底层IO库制约, 可能调用了io_run进入收包流程就再也无法返回了, 如pcap_loop()等函数, 所以需要动态创建收包线程, 但对于marsio等IO库, 是主动收包轮询模式, flwd_packet_io_run_thread线程创建后一直休眠, 实际无意义. */ for(i = 0; i < __TOPO_MODE_MAX; i++){ if(flwd_global_val.global_io_handle[i].low_level_io_handle != NULL){ pthread_create(&run_thread_pid[i], NULL, flwd_packet_io_run_thread, (void *)&flwd_global_val.global_io_handle[i]); } } } /* 每个网关初始化两个设备. */ int flwd_packet_io_init(flwd_topology_t first_top_mode, flwd_topology_t second_top_mode) { char str_tmp[128]; int ret, int_tmp; int i; for(i = 0; i < (int)__TOPO_MODE_MAX; i++){ if((i != first_top_mode) && (i != second_top_mode)){ continue; } /* NOTE: 读取配置文件, 获取物理层相关参数 */ flwd_global_val.global_io_handle[i].io_para.topo_mode = (flwd_topology_t)i; MESA_load_profile_int_def(FLWD_CONFIG_FILE, g_packet_io_cfg_para[i].cfg_file_section, "cap_mode", &int_tmp, 0); if(int_tmp <= 0 || int_tmp > CAP_MODEL_PAG_MARSIO){ flwd_log(RLOG_LV_FATAL, "get config %s->cap_mode error!", g_packet_io_cfg_para[i].cfg_file_section); return -1; } flwd_global_val.global_io_handle[i].io_para.cap_mode = (flwd_cap_mode_t)int_tmp; MESA_load_profile_string_def(FLWD_CONFIG_FILE, g_packet_io_cfg_para[i].cfg_file_section, "device_name", str_tmp, 128, "#"); if('#' == str_tmp[0]){ flwd_log(RLOG_LV_FATAL, "get config %s->device_name error!", g_packet_io_cfg_para[i].cfg_file_section); return -1; } flwd_global_val.global_io_handle[i].io_para.device_name = strdup(str_tmp); MESA_load_profile_string_def(FLWD_CONFIG_FILE, g_packet_io_cfg_para[i].cfg_file_section, "pkt_filter", str_tmp, 128, "#"); if('#' == str_tmp[0]){ flwd_global_val.global_io_handle[i].io_para.pkt_filter = NULL; }else{ flwd_global_val.global_io_handle[i].io_para.pkt_filter = strdup(str_tmp); } /* NOTE: dlopen打开底层IO库句柄, 如io_pcap.so, io_marsio.so等, 获取相关函数指针 */ ret = flwd_packet_io_lib_load(&flwd_global_val.global_io_handle[i]); if(ret < 0){ flwd_log(RLOG_LV_FATAL, "%s, flwd_packet_io_lib_load() error!", g_packet_io_cfg_para[i].cfg_file_section); return -1; } ret = flwd_global_val.global_io_handle[i].low_level_io_init(&flwd_global_val.global_io_handle[i]); if(ret < 0){ flwd_log(RLOG_LV_FATAL, "%s low_level_init() error!", g_packet_io_cfg_para[i].cfg_file_section); return -1; } } flwd_log(RLOG_LV_DEBUG, "flwd_packet_io_init success!"); return 0; }