/* Includes ------------------------------------------------------------------*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef CFG_DEV_TYPE_LAND_PD /* 标准C库头文件. */ #include #include #include #include #include #include #include #include #include #include #include #include #include /* 用户代码头文件. */ #include "main.h" #include "cmd.h" #include "fifo.h" #include "pd_dau.h" #include "pd_hf.h" #include "pd_csg.h" /* Define --------------------------------------------------------------------*/ #define DUA_UDP_PORT 23760 #define DUA_SEND_FIFO_NUM (8) /* Private typedef -----------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ dau_t daus[PD_SLOTS_MAX]; const char *pd_sync_str[PD_SYNC_MAX] = { "", "pt", "inside", "outside" }; const char *pd_pps_str[PD_PPS_MAX] = { "auto", "master", "slave" }; const char *pd_protocol_str[PD_PROTOCOL_MAX] = { "land", "csg" }; /* DAU 端口类型分类 */ const char *dau_port_type_str[PD_PORT_TYPE_COUNT] = { "", "uhf", "ae", "tev", "hf" }; /* DAU 端口降噪类型分类. */ const char *pd_noise_type_str[PD_DENOISE_TYPE_COUNT] = { "none", "auto", "manual", "variance" }; /* Private function prototypes -----------------------------------------------*/ /* Internal functions --------------------------------------------------------*/ /* 显示 DAU */ void _dau_show_slot(uint8_t slot) { struct sockaddr_in server; dau_contact_t *dau = &daus[slot].info; char buf[128] = {0}; time_t temp = 0; printh("APP version %s (%08x)\r\n", dau->app_version, dau->dev_id); printh("APP Compile date: %s\r\n", dau->app_compile_time); printh("FPGA version %s\r\n", dau->FPGA_version); printh("HW version %s\r\n", dau->hardware_version); printh("Id: %03d.%03d\r\n", dau->type_m, dau->type_s); printh("Mac: %02x:%02x:%02x:%02x:%02x:%02x\r\n",dau->mac[0], dau->mac[1], dau->mac[2], dau->mac[3], dau->mac[4], dau->mac[5]); server.sin_addr.s_addr = dau->ip; printh("ip: %s\r\n", inet_ntoa(server.sin_addr)); server.sin_addr.s_addr = dau->mask; printh("%s\r\n", inet_ntoa(server.sin_addr)); server.sin_addr.s_addr = dau->gw; printh("route: %s\r\n", inet_ntoa(server.sin_addr)); temp = dau->factory_date; strftime(buf, 128, "%Y-%m-%d %H:%M:%S", localtime(&temp)); printh("factory date: %s\r\n", buf); temp = dau->deployment_date; strftime(buf, 128, "%Y-%m-%d %H:%M:%S", localtime(&temp)); printh("deployment date: %s\r\n\n", buf); return; } /* 显示 DAU 状态 */ void _dau_show_state(void) { uint8_t i = 0; dau_state_t *state = NULL; printh("SL IN CO PS TO\r\n"); for(i = 0; i < PD_SLOTS_MAX; i++) { state = &daus[i].state; printh("%-02d %-02d %-02d %-02d %-05d\r\n", i + 1, state->is_insert, state->is_connect, state->port_sum, state->beat_cnt); } printh("\n"); return; } /* 连接超时时间 */ CMD(dau_connect_timeout, dau_connect_timeout_cmd, "connect-timeout <1-1440>", "Connect timeout\n" "Timeout time: min\n") { uint8_t slot = pd_slot_node.param_num; pd_config.config_slot[slot].timeout = strtol(argv[0], NULL, 10); return CMD_SUCCESS; } /* Slot 状态显示 */ CMD(dau_slot_show, dau_slot_show_cmd, "show slot <1-8>", "Show\n" "Slot\n" "Slot id\n") { uint8_t slot = strtol(argv[0], NULL, 10); _dau_show_slot(slot - 1); return CMD_SUCCESS; } /* Slot 状态显示 */ CMD(dau_state_show, dau_state_show_cmd, "show slot state", "Show\n" "Slot\n" "State\n") { _dau_show_state(); return CMD_SUCCESS; } /* Slot 全局配置显示 */ CMD(dau_cfg_show, dau_cfg_show_cmd, "show slot cfg <1-8>", "Show\n" "Slot\n" "Config\n" "Slot id\n") { uint8_t slot = strtol(argv[0], NULL, 10); dau_t *dau = &daus[slot - 1]; if (dau->show_cfg_cb) { dau->show_cfg_cb(dau->slot); } return CMD_SUCCESS; } /* Slot 端口配置显示 */ CMD(dau_port_show, dau_port_show_cmd, "show slot <1-8> port <1-8> ", "Show\n" "Slot\n" "Slot id\n" "Port\n" "Port id\n") { uint8_t slot = strtol(argv[0], NULL, 10); uint8_t port = strtol(argv[1], NULL, 10); dau_t *dau = &daus[slot - 1]; if (port > dau->state.port_sum) { return CMD_ERR_NO_MATCH; } if (dau->show_port_cb) { dau->show_port_cb(dau->slot, port - 1); } return CMD_SUCCESS; } /* 包头填充 */ void _dau_head_init(dau_t *dau, dau_head_init_t *head_data) { dau_pkt_head_t *head = (dau_pkt_head_t*)head_data->pkt; /* 封装报文头. */ head->len = head_data->len; head->dev_type_m = dau->info.type_m; head->dev_type_s= dau->info.type_s; head->dev_id = dau->info.dev_id; head->cmd_type = head_data->cmd_type; head->cmd = head_data->cmd; head->version = 1; head->pkt_id = head_data->pkt_id; } /* dau 接入处理 */ int _dau_insert(dau_t *dau) { if (3 == dau->info.type_m && 1 == dau->info.type_s) { /* 申请和释放放在一起, 避免地址失效 */ if (dau->private_data && dau->free_cb) { dau->free_cb(dau->slot); } dau->private_data = hf_data_malloc(); dau->recv_cb = hf_recv_process; dau->send_cb = hf_send_process; dau->free_cb = hf_data_free; dau->show_cfg_cb = hf_show_cfg; dau->show_port_cb = hf_show_port; } else { return E_NOT_FOUND; } dau->state.beat_cnt = 0; dau->state.is_connect = TRUE; return E_NONE; } /* dau 移除处理 */ int _dau_remove(dau_t *dau) { dau->recv_cb = NULL; dau->send_cb = NULL; dau->show_cfg_cb = NULL; dau->show_port_cb = NULL; dau->state.is_connect = FALSE; return E_NONE; } /* 初始化UDP服务器 */ int32_t _dau_udp_server_init(dau_t *dau) { struct sockaddr_in server = {0}; int fd = -1; fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { log_err(LOG_DAU, "ERROR at socket creating return %s!", safe_strerror(errno)); return E_SYS_CALL; } /* 绑定端口 */ bzero(&server, sizeof(server)); server.sin_family = AF_INET; server.sin_addr.s_addr = htonl(INADDR_ANY); server.sin_port = htons(DUA_UDP_PORT + dau->slot); if (bind(fd, (struct sockaddr*)&server, sizeof(server)) < 0) { log_err(LOG_DAU, "ERROR at socket bind return %s!", safe_strerror(errno)); close(fd); return E_SYS_CALL; } dau->fd = fd; return E_NONE; } /* dau 开机联络处理函数 */ void _dau_recv_connect(dau_t *dau, uint16_t recv_len) { dau_head_init_t head_data; dau_pkt_head_t *head = (dau_pkt_head_t*)dau->buf_recv; dau_contact_t *pnet = (dau_contact_t*)(dau->buf_recv + sizeof(dau_pkt_head_t)); dau_ack_t *ack = (dau_ack_t*)(dau->buf_recv + sizeof(dau_pkt_head_t)); dau_contact_t *info = NULL; uint8_t i = 0; /* 如果当前状态还是连接状态先释放内存 */ if (dau->state.is_connect) { LD_N_RETURN_N(_dau_remove(dau)); } /* 复制设备信息 */ memcpy(&dau->info, pnet, sizeof(dau_contact_t)); dau->state.port_sum = 0; for(i = 0; i < PD_DAU_PORT_SUM; i++) { if (pnet->port[i]) { dau->state.port_sum++; } } /* 回复报文 */ ack->result = 0; head_data.cmd_type = DAU_REQUEST; head_data.cmd = DAU_C_CONTACT; head_data.pkt_id = head->pkt_id; head_data.pkt = dau->buf_recv; head_data.len = sizeof(dau_pkt_head_t) + sizeof(dau_ack_t); dau_data_send(dau, &head_data); /* 添加 dau */ LD_N_RETURN_N(_dau_insert(dau)); /* 给后台发送添加信息 */ /* 申请内存 */ info = XMALLOC(MTYPE_CSG, sizeof(dau_contact_t)); if (!info) { DBG(DBG_M_PD_DAU_ERR, "XMALLOC ERROR!\r\n"); return; } /* 复制设备信息 */ memcpy(info, &dau->info, sizeof(dau_contact_t)); /* 发送给后台 */ if (dau_msg_send_cmd(DAU_SEND_ADD, dau->slot, info) != E_NONE) { XFREE(MTYPE_CSG, info); } return; } /* dau 数据包处理函数 */ void _dau_recv_data_process(dau_t *dau, uint16_t recv_len, struct sockaddr_in *server) { dau_pkt_head_t *head = (dau_pkt_head_t*)dau->buf_recv; if (DAU_REPLY == head->cmd_type && DAU_C_CONTACT == head->cmd) { /* 响应连接报文 */ if (head->len > DAU_BUF_SIZE) { DBG(DBG_M_PD_DAU_ERR, "Recvfrom len %d ERROR!\r\n", head->len); return; } memcpy(&dau->server, server, sizeof(struct sockaddr_in)); _dau_recv_connect(dau, recv_len); } else { /* 响应其他报文 */ if (dau->recv_cb) { dau->recv_cb(dau->slot, dau->buf_recv, recv_len); } } return; } /* dau 收包线程 */ void *_dau_recv_handle(void *arg) { dau_t *dau = (dau_t*)arg; struct sockaddr_in server; socklen_t server_len = sizeof(struct sockaddr_in); uint16_t data_len = 0; /* 初始化 socket */ if (_dau_udp_server_init(dau) != E_NONE) { return NULL; } /* 等待初始化完成 */ while(!is_system_init) { sleep(1); } while(1) { /* 读取数据. */ data_len = recvfrom(dau->fd, dau->buf_recv, DAU_BUF_SIZE, 0, (struct sockaddr*)&server, &server_len); if (data_len <= 0) { DBG(DBG_M_PD_DAU_ERR, "Recvfrom return ERROR %s!\r\n", safe_strerror(errno)); continue; } _dau_recv_data_process(dau, data_len, &server); } return NULL; } /* dau 收包线程 */ void *_dau_send_handle(void *arg) { dau_t *dau = (dau_t*)arg; dau_send_msg_t *recv_msg = NULL; /* 等待初始化完成 */ while(!is_system_init) { sleep(1); } while(1) { if (fifo_read(dau->fifo_send, (void**)&recv_msg) != 0) { DBG(DBG_M_PD_DAU_ERR, "ERROR at fifo %d read!\r\n", dau->fifo_send); continue; } /* 响应其他报文 */ if (dau->send_cb) { dau->send_cb(dau->slot, recv_msg->type, recv_msg->data); } /* 释放数据内存, 注意一定要在 fifo_push 之前调用, 因为 fifo_push 后 recv_msg 已被释放. */ XFREE(MTYPE_CSG, recv_msg->data); fifo_push(dau->fifo_send); } return NULL; } /* dau 收包线程 */ void *_dau_state_handle(void *arg) { dau_state_t *state = NULL; uint8_t i = 0; /* 等待初始化完成 */ while(!is_system_init) { sleep(1); } while(1) { sleep(1); for(i = 0; i < PD_SLOTS_MAX; i++) { state = &daus[i].state; if (state->is_connect) { state->beat_cnt++; if (state->beat_cnt > pd_config.config_slot[i].timeout * 60) { log_warn(LOG_DAU, "Slot %d remove!", i); _dau_remove(&daus[i]); } } } } return NULL; } /* config模式配置保存函数: vty -- 相应的终端 */ int _dau_port_config_save(vty_t *vty, uint8_t slot) { vty_out(vty, " connect-timeout %d%s", pd_config.config_slot[slot].timeout, VTY_NEWLINE); return E_NONE; } /* Interface functions -------------------------------------------------------*/ /* dau 预初始化 */ int32_t dau_handle_init(void) { uint8_t i = 0; int32_t rv = E_ERROR; memset(&daus, 0, sizeof(dau_t) * PD_SLOTS_MAX); for (i = 0; i < PD_SLOTS_MAX; i++) { daus[i].slot = i; } cmd_install_element(PORT_NODE, &dau_connect_timeout_cmd); cmd_install_element(COMMON_NODE, &dau_slot_show_cmd); cmd_install_element(COMMON_NODE, &dau_state_show_cmd); cmd_install_element(COMMON_NODE, &dau_cfg_show_cmd); cmd_install_element(COMMON_NODE, &dau_port_show_cmd); rv = pd_slot_cmd_config_register(PD_PORT_CMD_PRI_DAU, _dau_port_config_save); if (rv != E_NONE) { log_err(LOG_DAU, "DAU port command save register ERROR %d!", rv); return rv; } return E_NONE; } /* dau 初始化 */ int32_t dau_handle_init_after(void) { thread_param_t param = {0}; char fifo_name[THREAD_NAME_LEN]; uint8_t i = 0; /* 初始收包线程 */ for (i = 0; i < DAU_ETH_SLOTS_SUM; i++) { snprintf(fifo_name, THREAD_NAME_LEN, "DAU_SEND_%d", i); daus[i].fifo_send = fifo_create(fifo_name, DUA_SEND_FIFO_NUM); param.arg = (void*)(&daus[i]); param.priority = 80; param.log_module = LOG_DAU; snprintf(param.thread_name, THREAD_NAME_LEN, "DAU_RECV_%d", i); create_thread(_dau_recv_handle, ¶m); param.arg = (void*)(&daus[i]); param.priority = 50; param.log_module = LOG_DAU; snprintf(param.thread_name, THREAD_NAME_LEN, "DAU_SEND_%d", i); create_thread(_dau_send_handle, ¶m); } /* 监控 dau 状态 */ param.arg = NULL; param.priority = 20; param.log_module = LOG_DAU; snprintf(param.thread_name, THREAD_NAME_LEN, "DAU_STATE"); create_thread(_dau_state_handle, ¶m); return E_NONE; } /* 数据发送 */ void dau_data_send(dau_t *dau, dau_head_init_t *head_data) { int32_t rv = 0; /* 封装报文头. */ _dau_head_init(dau, head_data); rv = sendto(dau->fd, head_data->pkt, head_data->len, 0, (struct sockaddr*)&dau->server, sizeof(dau->server)); if (rv < 0) { DBG(DBG_M_PD_DAU_ERR, "Sendto return %s!\r\n", safe_strerror(errno)); } } /* 发送数据到后台通讯进程. */ int32_t dau_msg_send(uint32_t type, uint8_t slot, void *data) { uint32_t fifo = 0; dau_send_msg_t msg; if (DAU_SEND_PRPS == type) { fifo = csg.fifo_prps_id; } else { DBG(DBG_M_PD_DAU_ERR, "DAU write ERROR! type=%d\r\n", type); return E_BAD_PARAM; } /* 封装消息. */ msg.type = type; msg.slot = slot; msg.data = data; /* 发送消息 */ if (fifo_write(fifo, (void*)(&msg), sizeof(dau_send_msg_t)) != sizeof(dau_send_msg_t)) { return E_ERROR; } return E_NONE; } /* 发送数据到后台通讯进程. */ int32_t dau_msg_send_cmd(uint32_t type, uint8_t slot, void *data) { dau_send_msg_t msg; /* 封装消息. */ msg.type = type; msg.slot = slot; msg.data = data; /* 发送消息 */ if (fifo_write(csg.fifo_cmd_id, (void*)(&msg), sizeof(dau_send_msg_t)) != sizeof(dau_send_msg_t)) { return E_ERROR; } return E_NONE; } #endif