diff options
| -rw-r--r-- | service/CMakeLists.txt | 8 | ||||
| -rw-r--r-- | service/include/olp_dev.h | 106 | ||||
| -rw-r--r-- | service/src/core.c | 14 | ||||
| -rw-r--r-- | service/src/olp.c | 108 | ||||
| -rw-r--r-- | service/src/olp_6500.c | 1052 | ||||
| -rw-r--r-- | service/test/TestOLP.cc | 246 |
6 files changed, 1443 insertions, 91 deletions
diff --git a/service/CMakeLists.txt b/service/CMakeLists.txt index 2d2c3b2..ee8a1bf 100644 --- a/service/CMakeLists.txt +++ b/service/CMakeLists.txt @@ -9,7 +9,7 @@ add_executable(mrzcpd src/core.c src/devmgr.c src/mrb.c src/hwinfo.c src/vdev.c src/vdata.c src/app.c src/monit.c src/node.c src/node_shmdev.c src/node_phydev.c src/node_lb.c src/node_classifier.c src/node_etherfabric.c src/node_eth_ingress.c src/node_eth_egress.c src/node_bfd.c src/node_vwire.c - src/node_health_check.c src/node_forwarder.c src/node_bridge.c src/pdump.c src/olp.c src/http_serv.c src/classifier_rule_parser.c) + src/node_health_check.c src/node_forwarder.c src/node_bridge.c src/pdump.c src/olp.c src/olp_6500.c src/http_serv.c src/classifier_rule_parser.c) target_link_libraries(mrzcpd MESA_prof_load_static msgpack-c-static ${DPDK_LIBRARY} ${SYSTEMD_LIBRARIES}) target_link_libraries(mrzcpd rt pthread dl infra z elf) @@ -17,3 +17,9 @@ target_include_directories(mrzcpd INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/include target_include_directories(mrzcpd INTERFACE ${SYSTEMD_INCLUDE_DIRS}) install(TARGETS mrzcpd RUNTIME DESTINATION ${MR_INSTALL_BINDIR_RELATIVE_PATH} COMPONENT Program) + +add_executable(TestOLP test/TestOLP.cc src/olp_6500.c ) +target_link_libraries(TestOLP gtest_main MESA_prof_load_static ${SYSTEMD_LIBRARIES} ${DPDK_LIBRARY}) +target_link_libraries(TestOLP rt pthread dl infra z elf) +target_include_directories(TestOLP PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include/") +target_include_directories(TestOLP PRIVATE ${SYSTEMD_INCLUDE_DIRS}) diff --git a/service/include/olp_dev.h b/service/include/olp_dev.h new file mode 100644 index 0000000..8205242 --- /dev/null +++ b/service/include/olp_dev.h @@ -0,0 +1,106 @@ +#pragma once +#include <netinet/in.h> + +#include <common.h> + +#define NR_OLP_DEVICE_MAX 8 +#define NR_OLP_CHANNEL_PER_DEVICE_MAX 16 + +typedef int (*olp_status_query_cb)(void); + +enum olp_connect_type +{ + OLP_CONNECT_TYPE_UNKNOW, + OLP_CONNECT_TYPE_COM, + OLP_CONNECT_TYPE_USB, + OLP_CONNECT_TYPE_NETWORK, +}; + +enum olp_device_type +{ + OLP_DEVICE_TYPE_UNKNOWN, + OLP_DEVICE_TYPE_NIAGARA_3296, + OLP_DEVICE_TYPE_OLP_6500, +}; + +enum olp_channel_used +{ + OLP_CHANNEL_STATE_UNUSED, + OLP_CHANNEL_STATE_USED, +}; + +enum olp_channel_state +{ + OLP_CHANNEL_STATE_FORCE_ACTIVE, + OLP_CHANNEL_STATE_FORCE_BYPASS, + OLP_CHANNEL_STATE_REGULAR, +}; + +enum olp_channel_heartbeat +{ + OLP_CHANNEL_HEARTBEAT_DISABLE, + OLP_CHANNEL_HEARTBEAT_ENABLE, +}; + +enum olp_channel_nonrevertive_mode +{ + OLP_CHANNEL_NONREVERTIVE_DISABLE, + OLP_CHANNEL_NONREVERTIVE_ENABLE, +}; + +struct olp_channel_timer +{ + int enable; + pthread_mutex_t timer_lock; +}; + +struct olp_channel +{ + uint32_t olp_channel_id; + enum olp_channel_used used; + enum olp_channel_state state; + + uint32_t en_heartbeat; + uint32_t heartbeat_send_interval_in_ms; + uint32_t heartbeat_timeout_interval_in_ms; + uint32_t heartbeat_lost_threshold; + uint32_t nonrevertive_mode; + + struct olp_channel_timer timer; + struct olp_dev_desc * dev_desc; +}; + +struct olp_network_s +{ + struct sockaddr_in addr; +}; + +struct olp_dev_desc +{ + char devsym[MR_SYMBOL_MAX]; + enum olp_device_type type; + enum olp_connect_type conn_type; + union { + struct olp_network_s network; + }; + + struct olp_channel * channels; + + olp_status_query_cb status_query; +}; + +struct olp_manager_main +{ + struct olp_dev_desc * olp_dev_descs[NR_OLP_DEVICE_MAX]; + uint32_t nr_olp_dev_descs; +}; + +struct olp_dev_register +{ + char devsym[MR_SYMBOL_MAX]; + enum olp_device_type type; + + olp_status_query_cb status_query; +}; + +struct olp6500_packet; diff --git a/service/src/core.c b/service/src/core.c index cd74760..6549969 100644 --- a/service/src/core.c +++ b/service/src/core.c @@ -893,6 +893,11 @@ __rte_unused static void signal_handler(int signum) g_keep_running = 0; } +__rte_unused static void config_reload_handler(int signum) +{ + return; +} + extern int hwinfo_init(struct sc_main * sc); extern int phydev_init(struct sc_main * sc); extern int devmgr_early_init(struct sc_main * sc); @@ -917,6 +922,7 @@ extern int health_check_init(struct sc_main * sc); extern int bridge_init(struct sc_main * sc); extern int mr_pdump_init(struct sc_main * sc); extern int http_serv_init(struct sc_main * sc_main); +extern int olp_manager_init(struct sc_main * sc_main); int main(int argc, char * argv[]) { @@ -996,6 +1002,7 @@ int main(int argc, char * argv[]) /* Exegesis the singnal for fast stop */ // signal(SIGINT, signal_handler); // signal(SIGTERM, signal_handler); + // signal(SIGHUP, config_reload_handler); if (devmgr_early_init(sc) != RT_SUCCESS) { @@ -1165,6 +1172,13 @@ int main(int argc, char * argv[]) goto quit; } + if (olp_manager_init(sc) != RT_SUCCESS) + { + MR_ERROR("olp manager initialization failed. "); + ret = EXIT_FAILURE; + goto quit; + } + sc_config_dump(sc); vdev_dump(sc); diff --git a/service/src/olp.c b/service/src/olp.c index 8615b24..08a2d6c 100644 --- a/service/src/olp.c +++ b/service/src/olp.c @@ -5,6 +5,8 @@ #include <sys/queue.h> #include <unistd.h> #include <sched.h> +#include <signal.h> +#include <time.h> #include <rte_bus_pci.h> #include <rte_config.h> @@ -26,103 +28,29 @@ #include <sc_devmgr.h> #include <sc_mrb.h> #include <sc_vdev.h> +#include <olp_dev.h> -#define NR_OLP_DEVICE_MAX 8 -#define NR_OLP_CHANNEL_PER_DEVICE_MAX 8 +struct olp_manager_main * g_olp_mgr_main; -enum olp_device_type -{ - OLP_DEVICE_TYPE_UNKNOWN, - OLP_DEVICE_TYPE_NIAGARA_3296, -}; - -enum olp_channel_state -{ - OLP_CHANNEL_STATE_FORCE_ACTIVE, - OLP_CHANNEL_STATE_FORCE_BYPASS, - OLP_CHANNEL_STATE_REGULAR, -}; - -struct olp_manager_main -{ - struct olp_dev_desc * olp_dev_descs[NR_OLP_DEVICE_MAX]; - unsigned int nr_olp_dev_descs; -}; - -struct olp_dev_desc -{ - char devsym[MR_SYMBOL_MAX]; - enum olp_device_type type; - struct olp_channel * channels[NR_OLP_CHANNEL_PER_DEVICE_MAX]; -}; +int olp6500_init(struct sc_main * sc_main); -struct olp_channel +int olp_manager_init(struct sc_main * sc_main) { - unsigned int olp_channel_id; - enum olp_channel_state state; - - struct olp_dev_desc * dev_desc; - unsigned int en_watchdog; - unsigned int watchdog_kick_time_in_ms; - unsigned int watchdog_timeout_in_ms; -}; + int ret = 0; -/* config example: - * [olp_device:0] - * name = olp0 - * type = niagara_3296 - * serial_number = 12345678abcdefgh - * - * [olp_channel:0] - * device = olp0 - * state = 3 - * watchdog = 1 - * watchdog_kick_time_in_ms = 300 - * watchdog_timeout_in_ms = 600 - */ + struct olp_manager_main * olp_mgr_main = ZMALLOC(sizeof(struct olp_manager_main)); + MR_VERIFY_MALLOC(olp_mgr_main); + g_olp_mgr_main = olp_mgr_main; + sc_main->olp_mgr_main = olp_mgr_main; -int olp_manager_config(struct olp_manager_main * olp_mgr, const char * cfgfile) -{ - for (unsigned int i = 0; i < NR_OLP_DEVICE_MAX; i++) + ret = olp6500_init(sc_main); + if (ret != RT_SUCCESS) { - char str_section_header[MR_SYMBOL_MAX]; - snprintf(str_section_header, MR_SYMBOL_MAX, "olp_device:%u", i); - - char olp_dev_sym[MR_SYMBOL_MAX]; - int ret = MESA_load_profile_string_nodef(cfgfile, str_section_header, "name", olp_dev_sym, MR_SYMBOL_MAX); - if (ret < 0) - { - continue; - } - - unsigned int olp_dev_type = 0; - MESA_load_profile_uint_def(cfgfile, str_section_header, "type", &olp_dev_type, OLP_DEVICE_TYPE_UNKNOWN); - switch (olp_dev_type) - { - case OLP_DEVICE_TYPE_NIAGARA_3296: - case OLP_DEVICE_TYPE_UNKNOWN: - default: - MR_ERROR("olp device %s is not supported (type = %d) \n", olp_dev_sym, olp_dev_type); - continue; - } - - struct olp_dev_desc * dev_desc = ZMALLOC(sizeof(struct olp_dev_desc)); - MR_VERIFY_MALLOC(dev_desc); - snprintf(dev_desc->devsym, MR_SYMBOL_MAX, "%s", olp_dev_sym); - dev_desc->type = olp_dev_type; - - /* add the olp device to the list */ - olp_mgr->olp_dev_descs[olp_mgr->nr_olp_dev_descs++] = dev_desc; + MR_ERROR("OLP_6500 initialization failed. "); + goto errout; } - return 0; + return RT_SUCCESS; +errout: + return RT_ERR; } - -int olp_manager_init(struct sc_main * sc_main) -{ - struct olp_manager_main * olp_mgr_main = ZMALLOC(sizeof(struct olp_manager_main)); - MR_VERIFY_MALLOC(olp_mgr_main); - sc_main->olp_mgr_main = olp_mgr_main; - - return 0; -}
\ No newline at end of file diff --git a/service/src/olp_6500.c b/service/src/olp_6500.c new file mode 100644 index 0000000..4e6d7a4 --- /dev/null +++ b/service/src/olp_6500.c @@ -0,0 +1,1052 @@ +#include <assert.h> +#include <net/if.h> +#include <stdio.h> +#include <sys/ioctl.h> +#include <sys/queue.h> +#include <unistd.h> +#include <sched.h> +#include <signal.h> +#include <time.h> + +#include <rte_bus_pci.h> +#include <rte_config.h> +#include <rte_debug.h> +#include <rte_eth_bond.h> +#include <rte_ethdev.h> +#include <rte_ether.h> +#include <rte_flow.h> +#include <rte_graph.h> +#include <rte_malloc.h> +#include <rte_node_eth_api.h> +#include <rte_pci.h> +#include <rte_string_fns.h> + +#include <MESA_prof_load.h> +#include <cJSON.h> +#include <common.h> +#include <rpc.h> +#include <sc_common.h> +#include <sc_devmgr.h> +#include <sc_mrb.h> +#include <sc_vdev.h> +#include <olp_dev.h> + +#define BUFF_MAX 256 +#define NR_OLP6500_CHANNEL_PER_DEVICE_MAX (17) + +#define OLP6500_HEARTBEAT_SWITCH_OBJECT (0x0600) +#define OLP6500_HEARTBEAT_PACKET_OBJECT (0x0601) +#define OLP6500_WORK_MODE_OBJECT (0x1010) +#define OLP6500_WORK_LINE_OBJECT (0x1070) +#define OLP6500_SWITCHBACK_OBJECT (0x1020) + +#define LINE_STATUS_INLINE (0x30) +#define LINE_STATUS_BYPASS (0xc0) + +#define OLP6500_TIMER_ONE_CYCLE 5000 + +#define MR_OLP6500_TOPIC_FULL_UPDATE "OLP6500FullUpdate" +#define OLP6500_CJSON_KEY_ARRAY "OPBArray" +#define OLP6500_CJSON_KEY_DEV_NAME "name" +#define OLP6500_CJSON_KEY_TYPE "type" +#define OLP6500_CJSON_KEY_CONNECT "connect" +#define OLP6500_CJSON_KEY_ADDR "addr" +#define OLP6500_CJSON_KEY_PORT "port" +#define OLP6500_CJSON_KEY_SEGMENT "segment" +#define OLP6500_CJSON_KEY_SEGMENT_ID "segment_id" +#define OLP6500_CJSON_KEY_WORKLINE "workline" +#define OLP6500_CJSON_KEY_HEARTBEAT "heartbeat" +#define OLP6500_CJSON_KEY_HEARTBEAT_SEND_INTERVAL_IN_MS "heartbeat_send_interval_in_ms" +#define OLP6500_CJSON_KEY_HEARTBEAT_TIMEOUT_INTERVAL_IN_MS "heartbeat_timeout_interval_in_ms" +#define OLP6500_CJSON_KEY_HEARTBEAT_LOST_THRESHOLD "heartbeat_lost_threshold" +#define OLP6500_CJSON_KEY_NONREVERTIVE_MODE "nonrevertive_mode" + +/* Dynamic classifier rule result */ +#define OLP6500_RPC_RESULT "Result" +#define OLP6500_RPC_ERR_REASON "ErrReason" + +enum +{ + OLP_TIMER_DISABLE, + OLP_TIMER_ENABLE, +}; + +enum +{ + OLP_CONFIG_GET, + OLP_CONFIG_SET, +}; + +enum +{ + OLP_SET_HEARTBEAT_SWITCH = 0, + OLP_SET_WORK_MODE = 1, + OLP_SET_WORK_LINE = 2, + OLP_SET_SWITCHBACK_MODE = 3, + + OLP_HEARTBEAT_PACKET = 4, + + OLP_OBJECT_MAX +}; + +/* + * Heartbeat Switch Data Format + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Alive | Idle | Interval | Count + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * Alive : enable:1 disable:0. + * Idle : idle time before the initial detection (seconds). + * Interval : heartbeat detection interval, in 20 milliseconds. + * Count : number of detection failures for determination + */ + +struct heartbeat_switch_data +{ + uint8_t enable; + uint8_t idle; + uint8_t interval; + uint8_t count; +}__attribute__((packed)); + +/* + * Work Mode Data Format + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Mode | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * Mode : manual:1 auto:2. + */ + +struct work_mode_data +{ + uint8_t mode; +}__attribute__((packed)); + +/* + * Work Line Data Format + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Line | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * Line : inline:0x30 bypass:0xC0. + */ + +struct work_line_data +{ + uint8_t line_status; +}__attribute__((packed)); + +/* + * Switch Back Data Format + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Enable | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * Enable : enable:0x01 disable:0x02. + */ + +struct switch_back_data +{ + uint8_t enable; +}__attribute__((packed)); + +/* + * OLP6500 Format + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Action | Slot | Object + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Port | Len | Data + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * Action : SET/GET 0x00:get 0x01:set 8 bits + * Slot : Channal ID 8 bits + * Object : Object 16 bits + * Port : 0 represents the card, + * 1~8 represent the SFP module port numbers. 8 bits + * Len : Data length 8 bits + * Data + */ + +struct olp6500_packet +{ + uint8_t action; + uint8_t slot; + uint16_t object; + uint8_t port; + uint8_t len; + union { + struct heartbeat_switch_data hb_sw; + struct work_mode_data work_mode; + struct work_line_data work_line; + struct switch_back_data sw_back; + char data[0]; + }; +}__attribute__((packed)); + +uint16_t olp6500_object_map[OLP_OBJECT_MAX] = { + [OLP_SET_HEARTBEAT_SWITCH] = OLP6500_HEARTBEAT_SWITCH_OBJECT, + [OLP_SET_WORK_MODE] = OLP6500_WORK_MODE_OBJECT, + [OLP_SET_WORK_LINE] = OLP6500_WORK_LINE_OBJECT, + [OLP_SET_SWITCHBACK_MODE] = OLP6500_SWITCHBACK_OBJECT, + [OLP_HEARTBEAT_PACKET] = OLP6500_HEARTBEAT_PACKET_OBJECT, +}; + +int olp6500_construct_packet(struct olp_channel * channel, int object, char *buff); +int olp6500_dev_deinit(struct olp_dev_desc * dev_desc); + +// void * heartbeat_recv_thread(void * args) +// { +// return NULL; +// } + +#if 0 +/* + * [olp0:0] + * state = 0 + * heartbeat = 1 + * heartbeat_send_interval_in_ms = 300 + * heartbeat_timeout_interval_in_ms = 300 + * heartbeat_lost_threshold = 3 + * nonrevertive_mode = 1 + */ +static int olp6500_channel_config_load(struct olp_dev_desc * olp_dev_desc, char *cfgfile, char *devsym) +{ + int ret = 0; + struct olp_channel * channel; + olp_dev_desc->channels = ZMALLOC(sizeof(struct olp_channel) * NR_OLP6500_CHANNEL_PER_DEVICE_MAX); + MR_VERIFY_MALLOC(olp_dev_desc->channels); + + for (uint32_t i = 0; i < NR_OLP6500_CHANNEL_PER_DEVICE_MAX; i++) + { + char chann_section[MR_SYMBOL_MAX] = {0}; + snprintf(chann_section, sizeof(chann_section) - 1, "%s:%u", devsym, i); + + uint32_t olp_channel_state = 0; + ret = MESA_load_profile_uint_nodef(cfgfile, chann_section, "state", &olp_channel_state); + if (ret < 0) + { + MR_DEBUG("state is not existed in section %s, ignore this section", chann_section); + continue; + } + + uint32_t olp_channel_heartbeat = 0; + ret = MESA_load_profile_uint_nodef(cfgfile, chann_section, "heartbeat", &olp_channel_heartbeat); + if (ret < 0) + { + MR_DEBUG("heartbeat is not existed in section %s, ignore this section", chann_section); + continue; + } + + channel = &olp_dev_desc->channels[i]; + channel->olp_channel_id = i; + channel->used = OLP_CHANNEL_STATE_USED; + channel->state = olp_channel_state; + channel->dev_desc = olp_dev_desc; + channel->en_heartbeat = olp_channel_heartbeat; + + MESA_load_profile_uint_nodef(cfgfile, chann_section, "heartbeat_timeout_interval_in_ms", &channel->heartbeat_timeout_interval_in_ms); + MESA_load_profile_uint_nodef(cfgfile, chann_section, "heartbeat_send_interval_in_ms", &channel->heartbeat_send_interval_in_ms); + MESA_load_profile_uint_nodef(cfgfile, chann_section, "heartbeat_lost_threshold", &channel->heartbeat_lost_threshold); + MESA_load_profile_uint_nodef(cfgfile, chann_section, "nonrevertive_mode", &channel->nonrevertive_mode); + } + return RT_SUCCESS; +} + +/* config example: + * [olp_device:0] + * name = olp0 + * type = 2 + * connect = 3 + * in_addr = 1.1.1.1 + * port = 6800 + */ +int olp6500_config_load(struct olp_manager_main * olp_mgr_main, char *cfgfile) +{ + int ret = 0; + + for (uint32_t i = 0; i < NR_OLP_DEVICE_MAX; i++) + { + char dev_symbol[MR_SYMBOL_MAX] = {0}; + snprintf(dev_symbol, sizeof(dev_symbol) - 1, "olp_device:%u", i); + + uint32_t olp_dev_type = 0; + MESA_load_profile_uint_def(cfgfile, dev_symbol, "type", &olp_dev_type, OLP_DEVICE_TYPE_UNKNOWN); + + if (olp_dev_type != OLP_DEVICE_TYPE_OLP_6500) + { + MR_DEBUG("type is not OLP_6500 in section %s, ignore this section", dev_symbol); + continue; + } + + if (olp_mgr_main->nr_olp_dev_descs == NR_OLP_DEVICE_MAX) + { + MR_WARNING("failed to add OLP_6500 config, Configured quantity has reached its maximum limit."); + continue; + } + + struct olp_dev_desc * olp_dev_desc = ZMALLOC(sizeof(struct olp_dev_desc)); + MR_VERIFY_MALLOC(olp_dev_desc); + + MESA_load_profile_string_nodef(cfgfile, dev_symbol, "name", olp_dev_desc->devsym, + sizeof(olp_dev_desc->devsym) - 1); + olp_dev_desc->type = OLP_DEVICE_TYPE_OLP_6500; + + uint32_t olp_conn_type = 0; + MESA_load_profile_uint_def(cfgfile, dev_symbol, "connect", &olp_conn_type, OLP_CONNECT_TYPE_UNKNOW); + olp_dev_desc->conn_type = olp_conn_type; + + if (olp_dev_desc->conn_type == OLP_CONNECT_TYPE_NETWORK) + { + char str_in_addr[INET_ADDRSTRLEN] = {0}; + MESA_load_profile_string_nodef(cfgfile, dev_symbol, "in_addr", str_in_addr, sizeof(str_in_addr)); + ret = inet_pton(AF_INET, str_in_addr, &olp_dev_desc->network.addr.sin_addr); + if (ret <= 0) + { + MR_CFGERR_INVALID_FORMAT(cfgfile, dev_symbol, "in_addr"); + return RT_ERR; + } + + uint32_t port = 0; + ret = MESA_load_profile_uint_nodef(cfgfile, dev_symbol, "port", &port); + if (ret < 0) + { + MR_CFGERR_INVALID_FORMAT(cfgfile, dev_symbol, "port"); + return RT_ERR; + } + + olp_dev_desc->network.addr.sin_family = AF_INET; + olp_dev_desc->network.addr.sin_port = htons(port); + } + olp6500_channel_config_load(olp_dev_desc, cfgfile, olp_dev_desc->devsym); + + olp_mgr_main->olp_dev_descs[olp_mgr_main->nr_olp_dev_descs++] = olp_dev_desc; + } + + return RT_SUCCESS; +} + +int olp6500_enable_dev(struct olp_manager_main * olp_mgr_main, char *cfgfile) +{ + int ret = 0; + uint32_t g_vwire_max_entry = 256; + + for (uint32_t i = 0; i < g_vwire_max_entry; i++) + { + char sec_symbol[MR_SYMBOL_MAX] = {0}; + snprintf(sec_symbol, sizeof(sec_symbol) - 1, "vwire:%u", i); + + char str_opb_dev[MR_SYMBOL_MAX] = {0}; + ret = MESA_load_profile_string_nodef(cfgfile, sec_symbol, "opb-device", str_opb_dev, + sizeof(str_opb_dev) - 1); + if (ret > 0) + { + int channel_id = -1; + ret = MESA_load_profile_int_nodef(cfgfile, sec_symbol, "opb-segment", &channel_id); + if (ret >= 0) + { + struct olp_dev_desc *dev_desc = NULL; + dev_desc = olp6500_find_device_by_symbol(olp_mgr_main, str_opb_dev); + if (dev_desc == NULL) + { + continue; + } + olp6500_apply_control_command_to_peer(dev_desc, channel_id); + } + } + } + return RT_SUCCESS; +} +#endif + +void olp6500_dump(struct olp_manager_main *olp_mgr_main) +{ + struct olp_dev_desc * olp_dev_desc = NULL; + struct olp_channel * channel = NULL; + char str_ip_addr[INET_ADDRSTRLEN] = {0}; + uint16_t port; + + for (uint32_t i = 0; i < olp_mgr_main->nr_olp_dev_descs; i++) + { + olp_dev_desc = olp_mgr_main->olp_dev_descs[i]; + inet_ntop(AF_INET, &(olp_dev_desc->network.addr.sin_addr), str_ip_addr, INET_ADDRSTRLEN); + port = ntohs(olp_dev_desc->network.addr.sin_port); + MR_INFO("olp 6500 name:%s, type:%d, conn_type:%d, ipaddr:%s, port:%u", + olp_dev_desc->devsym, + olp_dev_desc->type, + olp_dev_desc->conn_type, + str_ip_addr, + port); + for (uint32_t j = 0; j < NR_OLP6500_CHANNEL_PER_DEVICE_MAX; j++) + { + channel = &olp_dev_desc->channels[j]; + if (channel->used == OLP_CHANNEL_STATE_UNUSED) + { + continue; + } + MR_INFO("channel: channel_id:%u, used:%d, state:%d, en_heartbeat:%u, heartbeat_send_interval_in_ms:%u, heartbeat_timeout_interval_in_ms:%u, heartbeat_lost_threshold:%u, nonrevertive_mode:%u", + channel->olp_channel_id, + channel->used, + channel->state, + channel->en_heartbeat, + channel->heartbeat_send_interval_in_ms, + channel->heartbeat_timeout_interval_in_ms, + channel->heartbeat_lost_threshold, + channel->nonrevertive_mode); + } + } +} + +void olp6500_wait_timer_close() +{ + usleep(OLP6500_TIMER_ONE_CYCLE); +} + +int olp_6500_get_channel_timer_enable(struct olp_channel *channel) +{ + int enable = 0; + if (channel->used == OLP_CHANNEL_STATE_UNUSED) + { + return enable; + } + + pthread_mutex_lock(&channel->timer.timer_lock); + enable = channel->timer.enable; + pthread_mutex_unlock(&channel->timer.timer_lock); + return enable; +} + +int olp_6500_set_channel_timer_enable(struct olp_channel *channel, int enable) +{ + if (channel->used == OLP_CHANNEL_STATE_UNUSED) + { + return RT_ERR; + } + + pthread_mutex_lock(&channel->timer.timer_lock); + channel->timer.enable = enable; + pthread_mutex_unlock(&channel->timer.timer_lock); + return RT_SUCCESS; +} + +void olp6500_send_heartbeat_handler(int socket, struct olp_channel *channel) +{ + int ret = 0; + int pkt_len = 0; + char buff[BUFF_MAX] = {0}; + struct olp_dev_desc *dev_desc = channel->dev_desc; + struct sockaddr_in *addr = &dev_desc->network.addr; + + pkt_len = olp6500_construct_packet(channel, OLP_HEARTBEAT_PACKET, buff); + if (pkt_len <= 0) + { + return; + } + + switch (dev_desc->conn_type) + { + case OLP_CONNECT_TYPE_NETWORK: + do { + ret = sendto(socket, buff, pkt_len, 0, (struct sockaddr*)addr, sizeof(*addr)); + } while(ret == -1 && errno == EINTR); + + break; + default: + break; + } + return; +} + +void * olp6500_cycle_send_heartbeat(void * args) +{ + struct olp_channel *channel = (struct olp_channel *)args; + int timer_enable = 1; + struct timespec current_time; + struct timespec send_pkt_last_time; + struct timespec interval_time; + struct timeval timeout; + timeout.tv_sec = 5; + timeout.tv_usec = 0; + + clock_gettime(CLOCK_MONOTONIC, ¤t_time); + send_pkt_last_time = current_time; + + int sock = socket(AF_INET, SOCK_DGRAM, 0); + if (sock < 0) + { + return NULL; + } + + setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)); + setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); + + olp6500_send_heartbeat_handler(sock, channel); + while(timer_enable) + { + usleep(OLP6500_TIMER_ONE_CYCLE); + clock_gettime(CLOCK_MONOTONIC, ¤t_time); + timespec_diff(&send_pkt_last_time, ¤t_time, &interval_time); + if ((interval_time.tv_sec * 1000 + interval_time.tv_nsec/1000/1000) >= channel->heartbeat_send_interval_in_ms) + { + send_pkt_last_time = current_time; + olp6500_send_heartbeat_handler(sock, channel); + } + timer_enable = olp_6500_get_channel_timer_enable(channel); + } + close(sock); + return NULL; +} + +int olp6500_create_thread_for_heartbeat(struct olp_channel *channel) +{ + int ret = 0; + pthread_t tid; + pthread_mutex_init(&channel->timer.timer_lock, NULL); + olp_6500_set_channel_timer_enable(channel, OLP_TIMER_ENABLE); + ret = pthread_create(&tid, NULL, olp6500_cycle_send_heartbeat, (void *)channel); + if (ret < 0) + { + MR_ERROR("OLP_6500 create send heartbeat packet thread failed : %s", strerror(errno)); + return RT_ERR; + } + return RT_SUCCESS; +} + +char *olp6500_str_object(uint16_t object) +{ + switch(object) + { + case OLP_SET_HEARTBEAT_SWITCH: + return "OLP_HEARTBEAT_SWITCH"; + case OLP_SET_WORK_MODE: + return "OLP_WORK_MODE"; + case OLP_SET_WORK_LINE: + return "OLP_WORK_LINE"; + case OLP_SET_SWITCHBACK_MODE: + return "OLP_SWITCHBACK_MODE"; + default: + break; + } + return NULL; +} + +int olp6500_check_recv_data(char *buff, uint16_t object) +{ + struct olp6500_packet *pkt = (struct olp6500_packet*)buff; + if (ntohs(pkt->object) != olp6500_object_map[object]) + { + MR_ERROR("Object [%s] failed! receive data: 0xFF 0xEE", olp6500_str_object(object)); + return RT_ERR; + } + + if (pkt->len == 2 && pkt->data[0] == 0xFF && pkt->data[1] == 0xEE) + { + MR_ERROR("Object [%s] failed! receive data: 0xFF 0xEE", olp6500_str_object(object)); + return RT_ERR; + } + return RT_SUCCESS; +} + +int olp6500_send_command_over_network_sync(struct olp_dev_desc *dev_desc, char *send_buff, int send_len, char *recv_buff, int recv_len) +{ + int ret = 0; + int length = 0; + char str_ip_addr[INET_ADDRSTRLEN] = {0}; + struct sockaddr_in addr = dev_desc->network.addr; + + struct timeval timeout; + timeout.tv_sec = 5; + timeout.tv_usec = 0; + int sock = socket(AF_INET, SOCK_DGRAM, 0); + if (sock < 0) + { + MR_ERROR("unable to get a socket %s", strerror(errno)); + return RT_ERR; + } + + setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)); + setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); + + do { + ret = sendto(sock, send_buff, send_len, 0, (struct sockaddr*)&addr, sizeof(addr)); + } while(ret == -1 && errno == EINTR); + + if (ret == -1) + { + inet_ntop(AF_INET, &(addr.sin_addr), str_ip_addr, INET_ADDRSTRLEN); + MR_ERROR("send request to [%s] fail: %s", str_ip_addr, strerror(errno)); + goto error; + } + + do { + length = recvfrom (sock, recv_buff, recv_len, 0, NULL, 0); + } while(length == -1 && errno == EINTR); + + if (length <= 0) + { + inet_ntop(AF_INET, &(addr.sin_addr), str_ip_addr, INET_ADDRSTRLEN); + MR_ERROR("recv from [%s] fail : %s", str_ip_addr, strerror(errno)); + goto error; + } + close(sock); + return length; +error: + close(sock); + return RT_ERR; +} + +int olp6500_send_command_sync(struct olp_dev_desc *dev_desc, uint16_t object, char *send_buff, int send_len) +{ + int length = 0; + char recv_buff[BUFF_MAX] = {0}; + + switch (dev_desc->conn_type) + { + case OLP_CONNECT_TYPE_NETWORK: + length = olp6500_send_command_over_network_sync(dev_desc, send_buff, send_len, recv_buff, BUFF_MAX); + if (length <= 0) + { + return RT_ERR; + } + + case OLP_CONNECT_TYPE_COM: + case OLP_CONNECT_TYPE_USB: + break; + default: + break; + } + + return olp6500_check_recv_data(recv_buff, object); +} + +int olp6500_construct_packet(struct olp_channel * channel, int object, char *buff) +{ + int length = 0; + struct olp6500_packet *pkt = (struct olp6500_packet *)buff; + + switch(object) + { + case OLP_SET_HEARTBEAT_SWITCH: + pkt->action = OLP_CONFIG_SET; + pkt->slot = channel->olp_channel_id; + pkt->object = htons(olp6500_object_map[object]); + pkt->port = 0; + pkt->len = 4; + + if (channel->en_heartbeat == OLP_CHANNEL_HEARTBEAT_DISABLE) + { + pkt->hb_sw.enable = 0; + pkt->hb_sw.idle = 0; + pkt->hb_sw.interval = 0; + pkt->hb_sw.count = 0; + } + else + { + pkt->hb_sw.enable = channel->en_heartbeat; + pkt->hb_sw.idle = 1; + pkt->hb_sw.interval = channel->heartbeat_timeout_interval_in_ms/20; + pkt->hb_sw.count = channel->heartbeat_lost_threshold; + } + length = 10; + break; + case OLP_SET_WORK_MODE: + pkt->action = OLP_CONFIG_SET; + pkt->slot = channel->olp_channel_id; + pkt->object = htons(olp6500_object_map[object]); + pkt->port = 0; + pkt->len = 1; + + if (channel->en_heartbeat == OLP_CHANNEL_HEARTBEAT_DISABLE) + { + pkt->work_mode.mode = 1; + } + else + { + pkt->work_mode.mode = 2; + } + length = 7; + break; + case OLP_SET_WORK_LINE: + if (channel->en_heartbeat == OLP_CHANNEL_HEARTBEAT_DISABLE) + { + pkt->action = OLP_CONFIG_SET; + pkt->slot = channel->olp_channel_id; + pkt->object = htons(olp6500_object_map[object]); + pkt->port = 0; + pkt->len = 1; + + if (channel->state == OLP_CHANNEL_STATE_FORCE_ACTIVE) + { + pkt->work_line.line_status = LINE_STATUS_INLINE; + } + else if (channel->state == OLP_CHANNEL_STATE_FORCE_BYPASS) + { + pkt->work_line.line_status = LINE_STATUS_BYPASS; + } + else + { + goto out; + } + length = 7; + } + break; + case OLP_SET_SWITCHBACK_MODE: + pkt->action = OLP_CONFIG_SET; + pkt->slot = channel->olp_channel_id; + pkt->object = htons(olp6500_object_map[object]); + pkt->port = 0; + pkt->len = 1; + + pkt->sw_back.enable = channel->nonrevertive_mode==OLP_CHANNEL_NONREVERTIVE_ENABLE?0x02:0x01; + length = 7; + break; + case OLP_HEARTBEAT_PACKET: + pkt->action = OLP_CONFIG_GET; + pkt->slot = channel->olp_channel_id; + pkt->object = htons(olp6500_object_map[object]); + pkt->port = 0; + pkt->len = 0; + + length = 6; + default: + break; + } +out: + return length; +} + +struct olp_dev_desc *olp6500_find_device_by_symbol(struct olp_manager_main * olp_mgr_main, char *olp_dev_sym) +{ + struct olp_dev_desc *dev_desc = NULL; + + for (uint32_t i = 0; i < olp_mgr_main->nr_olp_dev_descs; i++) + { + dev_desc = olp_mgr_main->olp_dev_descs[i]; + if (dev_desc->type == OLP_DEVICE_TYPE_OLP_6500 && + strncmp(olp_dev_sym, dev_desc->devsym, MR_SYMBOL_MAX) == 0) + { + return dev_desc; + } + } + return NULL; +} + +int olp6500_apply_control_command_to_peer(struct olp_dev_desc *dev_desc, uint32_t channel_id) +{ + int ret = 0; + int pkt_len = 0; + char buff[BUFF_MAX] = {0}; + struct olp_channel *channel = NULL; + + channel = &dev_desc->channels[channel_id]; + if (channel->used == OLP_CHANNEL_STATE_UNUSED) + { + return RT_ERR; + } + + pkt_len = olp6500_construct_packet(channel, OLP_SET_HEARTBEAT_SWITCH, buff); + if (pkt_len > 0) + { + ret = olp6500_send_command_sync(dev_desc, OLP_SET_HEARTBEAT_SWITCH, buff, pkt_len); + if (ret != RT_SUCCESS) + { + return RT_ERR; + } + } + pkt_len = olp6500_construct_packet(channel, OLP_SET_WORK_MODE, buff); + if (pkt_len > 0) + { + ret = olp6500_send_command_sync(dev_desc, OLP_SET_WORK_MODE, buff, pkt_len); + if (ret != RT_SUCCESS) + { + return RT_ERR; + } + } + pkt_len = olp6500_construct_packet(channel, OLP_SET_WORK_LINE, buff); + if (pkt_len > 0) + { + ret = olp6500_send_command_sync(dev_desc, OLP_SET_WORK_LINE, buff, pkt_len); + if (ret != RT_SUCCESS) + { + return RT_ERR; + } + } + pkt_len = olp6500_construct_packet(channel, OLP_SET_SWITCHBACK_MODE, buff); + if (pkt_len > 0) + { + ret = olp6500_send_command_sync(dev_desc, OLP_SET_SWITCHBACK_MODE, buff, pkt_len); + if (ret != RT_SUCCESS) + { + return RT_ERR; + } + } + + olp6500_create_thread_for_heartbeat(channel); + return RT_SUCCESS; +} + +/* +{ + "OPBArray": [ + { + "name": "opb1", + "type": 2, + "connect": 3, + "addr": "192.168.40.76", + "port": "6800", + "segment": [ + { + "segment_id": 7, + "workline": 1, + "heartbeat": 1, + "heartbeat_send_interval_in_ms": 60, + "heartbeat_timeout_interval_in_ms": 60, + "heartbeat_lost_threshold": 5, + "nonrevertive_mode": 1 + } + ] + } + ] +} + */ +int olp6500_cjson_parser(cJSON * req, struct olp_manager_main *olp_mgr_main, char *err_reason, uint32_t sz_err_reason) +{ + struct olp_channel * channel = NULL; + cJSON * olp_array = cJSON_GetObjectItem(req, OLP6500_CJSON_KEY_ARRAY); + if (olp_array == NULL) + { + snprintf(err_reason, sz_err_reason, "OLP6500Array parser cjson error, array is null ."); + MR_ERROR("%s", err_reason); + return RT_ERR; + } + + int olp_array_num = cJSON_GetArraySize(olp_array); + if (olp_array_num > NR_OLP_DEVICE_MAX) + { + snprintf(err_reason, sz_err_reason, "OLP6500Array num over max [%d] .", NR_OLP_DEVICE_MAX); + MR_ERROR("%s", err_reason); + return RT_ERR; + } + + for (int i = 0; i < olp_array_num; i++) + { + cJSON * olp_array_item = cJSON_GetArrayItem(olp_array, i); + + cJSON * cj_dev_name = cJSON_GetObjectItem(olp_array_item, OLP6500_CJSON_KEY_DEV_NAME); + cJSON * cj_type = cJSON_GetObjectItem(olp_array_item, OLP6500_CJSON_KEY_TYPE); + cJSON * cj_connect = cJSON_GetObjectItem(olp_array_item, OLP6500_CJSON_KEY_CONNECT); + cJSON * cj_addr = cJSON_GetObjectItem(olp_array_item, OLP6500_CJSON_KEY_ADDR); + cJSON * cj_port = cJSON_GetObjectItem(olp_array_item, OLP6500_CJSON_KEY_PORT); + cJSON * segment_array = cJSON_GetObjectItem(olp_array_item, OLP6500_CJSON_KEY_SEGMENT); + + if (cj_type->valueint != OLP_DEVICE_TYPE_OLP_6500) + { + continue; + } + + struct olp_dev_desc * olp_dev_desc = ZMALLOC(sizeof(struct olp_dev_desc)); + MR_VERIFY_MALLOC(olp_dev_desc); + + snprintf(olp_dev_desc->devsym, MR_SYMBOL_MAX, "%s", cj_dev_name->valuestring); + olp_dev_desc->type = OLP_DEVICE_TYPE_OLP_6500; + olp_dev_desc->conn_type = cj_connect->valueint; + if (cj_addr) + { + olp_dev_desc->network.addr.sin_family = AF_INET; + inet_pton(AF_INET, cj_addr->valuestring, &olp_dev_desc->network.addr.sin_addr); + } + if (cj_port) + { + int port = 0; + sscanf(cj_port->valuestring, "%d", &port); + olp_dev_desc->network.addr.sin_port = htons(port); + } + + olp_dev_desc->channels = ZMALLOC(sizeof(struct olp_channel) * NR_OLP6500_CHANNEL_PER_DEVICE_MAX); + MR_VERIFY_MALLOC(olp_dev_desc->channels); + int segment_array_num = cJSON_GetArraySize(segment_array); + for (int j = 0; j < segment_array_num; j++) + { + cJSON * segment_array_item = cJSON_GetArrayItem(segment_array, j); + cJSON * cj_segment_id = cJSON_GetObjectItem(segment_array_item, OLP6500_CJSON_KEY_SEGMENT_ID); + cJSON * cj_segment_workline = cJSON_GetObjectItem(segment_array_item, OLP6500_CJSON_KEY_WORKLINE); + cJSON * cj_segment_heartbeat = cJSON_GetObjectItem(segment_array_item, OLP6500_CJSON_KEY_HEARTBEAT); + cJSON * cj_segment_hb_send_interval = cJSON_GetObjectItem(segment_array_item, OLP6500_CJSON_KEY_HEARTBEAT_SEND_INTERVAL_IN_MS); + cJSON * cj_segment_hb_timeout_interval = cJSON_GetObjectItem(segment_array_item, OLP6500_CJSON_KEY_HEARTBEAT_TIMEOUT_INTERVAL_IN_MS); + cJSON * cj_segment_lost_threshold = cJSON_GetObjectItem(segment_array_item, OLP6500_CJSON_KEY_HEARTBEAT_LOST_THRESHOLD); + cJSON * cj_segment_nonrevertive_mode = cJSON_GetObjectItem(segment_array_item, OLP6500_CJSON_KEY_NONREVERTIVE_MODE); + + channel = &olp_dev_desc->channels[cj_segment_id->valueint]; + channel->olp_channel_id = cj_segment_id->valueint; + channel->used = OLP_CHANNEL_STATE_USED; + channel->dev_desc = olp_dev_desc; + channel->state = cj_segment_workline->valueint; + channel->en_heartbeat = cj_segment_heartbeat->valueint; + if (cj_segment_hb_send_interval) + { + channel->heartbeat_send_interval_in_ms = cj_segment_hb_send_interval->valueint; + } + if (cj_segment_hb_timeout_interval) + { + channel->heartbeat_timeout_interval_in_ms = cj_segment_hb_timeout_interval->valueint; + } + if (cj_segment_lost_threshold) + { + channel->heartbeat_lost_threshold = cj_segment_lost_threshold->valueint; + } + channel->nonrevertive_mode = cj_segment_nonrevertive_mode->valueint; + } + olp_mgr_main->olp_dev_descs[olp_mgr_main->nr_olp_dev_descs++] = olp_dev_desc; + } + return RT_SUCCESS; +} + +int olp6500_apply_new_config(struct olp_manager_main *olp_mgr_old, struct olp_manager_main *olp_mgr_new) +{ + int ret = 0; + struct olp_channel *channel_old = NULL; + struct olp_channel *channel_new = NULL; + struct olp_dev_desc *olp_dev_old = NULL; + struct olp_dev_desc *olp_dev_new = NULL; + + for (uint32_t i = 0; i < olp_mgr_new->nr_olp_dev_descs; i++) + { + olp_dev_new = olp_mgr_new->olp_dev_descs[i]; + if (olp_dev_new->type != OLP_DEVICE_TYPE_OLP_6500) + { + continue; + } + + for (uint32_t j = 0; j < NR_OLP6500_CHANNEL_PER_DEVICE_MAX; j++) + { + channel_new = &olp_dev_new->channels[j]; + if (channel_new->used == OLP_CHANNEL_STATE_UNUSED) + { + continue; + } + ret = olp6500_apply_control_command_to_peer(olp_dev_new, channel_new->olp_channel_id); + if (ret != RT_SUCCESS) + { + return ret; + } + } + } + + for (uint32_t i = 0; i < olp_mgr_old->nr_olp_dev_descs; i++) + { + olp_dev_old = olp_mgr_old->olp_dev_descs[i]; + if (olp_dev_old->type != OLP_DEVICE_TYPE_OLP_6500) + { + continue; + } + + for (uint32_t j = 0; j < NR_OLP6500_CHANNEL_PER_DEVICE_MAX; j++) + { + channel_old = &olp_dev_old->channels[j]; + if (channel_old->used == OLP_CHANNEL_STATE_UNUSED) + { + continue; + } + olp_6500_set_channel_timer_enable(channel_old, OLP_TIMER_DISABLE); + } + } + + return RT_SUCCESS; +} + +int olp6500_dev_deinit(struct olp_dev_desc * dev_desc) +{ + struct olp_channel * channel = NULL; + + if (dev_desc->channels) + { + for (uint32_t i = 0; i < NR_OLP6500_CHANNEL_PER_DEVICE_MAX; i++) + { + channel = &dev_desc->channels[i]; + if (channel->used == OLP_CHANNEL_STATE_UNUSED) + { + continue; + } + pthread_mutex_destroy(&channel->timer.timer_lock); + } + FREE(dev_desc->channels); + } + FREE(dev_desc); + return RT_SUCCESS; +} + +int olp6500_manager_deinit(struct olp_manager_main *olp_mgr_main) +{ + struct olp_dev_desc * dev_desc = NULL; + + for (uint32_t i = 0; i < olp_mgr_main->nr_olp_dev_descs; i++) + { + dev_desc = olp_mgr_main->olp_dev_descs[i]; + olp6500_dev_deinit(dev_desc); + } + FREE(olp_mgr_main); + return RT_SUCCESS; +} + +int olp6500_full_update_handler(cJSON * req, cJSON ** rsp, void * arg) +{ + int ret = 0; + char str_error_reason[MR_STRING_MAX] = {}; + struct sc_main * sc = (struct sc_main *)arg; + cJSON * response = cJSON_CreateObject(); + + struct olp_manager_main * olp_mgr_new = ZMALLOC(sizeof(struct olp_manager_main)); + MR_VERIFY_MALLOC(olp_mgr_new); + + ret = olp6500_cjson_parser(req, olp_mgr_new, str_error_reason, MR_STRING_MAX); + if (ret != RT_SUCCESS) + { + goto end; + } + + ret = olp6500_apply_new_config(sc->olp_mgr_main, olp_mgr_new); + if (ret != RT_SUCCESS) + { + snprintf(str_error_reason, MR_STRING_MAX, "Set OPB device failed! communication with the OPB Device failed"); + goto end; + } + + olp6500_wait_timer_close(sc->olp_mgr_main); + olp6500_manager_deinit(sc->olp_mgr_main); + sc->olp_mgr_main = olp_mgr_new; + olp6500_dump(sc->olp_mgr_main); + +end: + cJSON_AddNumberToObject(response, OLP6500_RPC_RESULT, ret); + if (ret != 0) + { + cJSON_AddStringToObject(response, OLP6500_RPC_ERR_REASON, str_error_reason); + } + *rsp = response; + return RT_SUCCESS; +} + +int olp6500_init(struct sc_main * sc_main) +{ + struct olp_manager_main *olp_mgr_main = sc_main->olp_mgr_main; + if (olp_mgr_main->nr_olp_dev_descs >= NR_OLP_DEVICE_MAX) { + MR_ERROR("create OLP_6500 device failed: too many devices. "); + goto errout; + } + + if (rpc_server_recv_request_register(sc_main->rpc_srv_handler, MR_OLP6500_TOPIC_FULL_UPDATE, + olp6500_full_update_handler, sc_main) != 0) + { + MR_ERROR("The '%s' Request Register Failed . ", MR_OLP6500_TOPIC_FULL_UPDATE); + return RT_ERR; + } + + return RT_SUCCESS; +errout: + return RT_ERR; +} diff --git a/service/test/TestOLP.cc b/service/test/TestOLP.cc new file mode 100644 index 0000000..65a0021 --- /dev/null +++ b/service/test/TestOLP.cc @@ -0,0 +1,246 @@ +#include <gtest/gtest.h> + +#include <olp_dev.h> + + +enum +{ + OLP_SET_HEARTBEAT_SWITCH = 0, + OLP_SET_WORK_MODE = 1, + OLP_SET_WORK_LINE = 2, + OLP_SET_SWITCHBACK_MODE = 3, + + OLP_HEARTBEAT_PACKET = 4, + + OLP_TYPES_MAX +}; + +unsigned int g_logger_to_stdout = 1; +unsigned int g_logger_level = LOG_DEBUG; +unsigned int g_keep_running = 1; +uint8_t g_ctrlzone_id = 0; + +#define BUFF_MAX 256 + +extern "C" +{ +extern int olp6500_construct_packet(struct olp_channel * channel, int type, char *buff); +extern int olp6500_check_recv_data(char *buff, int type); +} + +void olp_dev_desc_init(struct olp_dev_desc *dev_desc, struct olp_channel *channel) +{ + snprintf(dev_desc->devsym, sizeof(dev_desc->devsym), "olp0"); + dev_desc->type = OLP_DEVICE_TYPE_OLP_6500; + + channel->olp_channel_id = 0; + channel->state = OLP_CHANNEL_STATE_FORCE_ACTIVE; + channel->en_heartbeat = 1; + channel->heartbeat_timeout_interval_in_ms = 5; + channel->heartbeat_send_interval_in_ms = 30; + channel->heartbeat_lost_threshold = 3; + channel->nonrevertive_mode = 1; + channel->dev_desc = dev_desc; + + dev_desc->channels = channel; +} + +TEST(OLP_PACKET, OLP_SET_HEARTBEAT_SWITCH) +{ + int pkt_len = 0; + char buff[BUFF_MAX] = {0}; + struct olp_dev_desc dev_desc; + struct olp_channel dev_channel; + + memset(&dev_desc, 0, sizeof(dev_desc)); + memset(&dev_channel, 0, sizeof(dev_channel)); + + olp_dev_desc_init(&dev_desc, &dev_channel); + + pkt_len = olp6500_construct_packet(&dev_desc.channels[0], OLP_SET_HEARTBEAT_SWITCH, buff); + EXPECT_TRUE(pkt_len == 10); + EXPECT_TRUE(buff[0] == 0x01); + EXPECT_TRUE(buff[1] == 0x00); + EXPECT_TRUE(buff[2] == 0x06); + EXPECT_TRUE(buff[3] == 0x00); + EXPECT_TRUE(buff[4] == 0x00); + EXPECT_TRUE(buff[5] == 0x04); + EXPECT_TRUE(buff[6] == 0x01); + EXPECT_TRUE(buff[7] == 0x01); + EXPECT_TRUE(buff[8] == 0x05); + EXPECT_TRUE(buff[9] == 0x03); +} + +TEST(OLP_PACKET, OLP_HEARTBEAT_PACKET) +{ + int pkt_len = 0; + char buff[256] = {0}; + struct olp_dev_desc dev_desc; + struct olp_channel dev_channel; + + memset(&dev_desc, 0, sizeof(dev_desc)); + memset(&dev_channel, 0, sizeof(dev_channel)); + + olp_dev_desc_init(&dev_desc, &dev_channel); + + pkt_len = olp6500_construct_packet(&dev_desc.channels[0], OLP_HEARTBEAT_PACKET, buff); + EXPECT_TRUE(pkt_len == 10); + EXPECT_TRUE(buff[0] == 0x00); + EXPECT_TRUE(buff[1] == 0x00); + EXPECT_TRUE(buff[2] == 0x06); + EXPECT_TRUE(buff[3] == 0x01); + EXPECT_TRUE(buff[4] == 0x00); + EXPECT_TRUE(buff[5] == 0x04); + EXPECT_TRUE(buff[6] == 0x00); + EXPECT_TRUE(buff[7] == 0x00); + EXPECT_TRUE(buff[8] == 0x00); + EXPECT_TRUE(buff[9] == 0x00); +} + +TEST(OLP_PACKET, OLP_SET_WORK_MODE) +{ + int pkt_len = 0; + char buff[256] = {0}; + struct olp_dev_desc dev_desc; + struct olp_channel dev_channel; + + memset(&dev_desc, 0, sizeof(dev_desc)); + memset(&dev_channel, 0, sizeof(dev_channel)); + + olp_dev_desc_init(&dev_desc, &dev_channel); + + pkt_len = olp6500_construct_packet(&dev_desc.channels[0], OLP_SET_WORK_MODE, buff); + EXPECT_TRUE(pkt_len == 7); + EXPECT_TRUE(buff[0] == 0x01); + EXPECT_TRUE(buff[1] == 0x00); + EXPECT_TRUE(buff[2] == 0x10); + EXPECT_TRUE(buff[3] == 0x10); + EXPECT_TRUE(buff[4] == 0x00); + EXPECT_TRUE(buff[5] == 0x01); + EXPECT_TRUE(buff[6] == 0x02); +} + +TEST(OLP_PACKET, OLP_SET_WORK_LINE) +{ + int pkt_len = 0; + char buff[256] = {0}; + struct olp_dev_desc dev_desc; + struct olp_channel dev_channel; + + memset(&dev_desc, 0, sizeof(dev_desc)); + memset(&dev_channel, 0, sizeof(dev_channel)); + + olp_dev_desc_init(&dev_desc, &dev_channel); + + pkt_len = olp6500_construct_packet(&dev_desc.channels[0], OLP_SET_WORK_LINE, buff); + EXPECT_TRUE(pkt_len == 0); +} + +TEST(OLP_PACKET, OLP_SET_SWITCHBACK_MODE) +{ + int pkt_len = 0; + char buff[256] = {0}; + struct olp_dev_desc dev_desc; + struct olp_channel dev_channel; + + memset(&dev_desc, 0, sizeof(dev_desc)); + memset(&dev_channel, 0, sizeof(dev_channel)); + + olp_dev_desc_init(&dev_desc, &dev_channel); + + pkt_len = olp6500_construct_packet(&dev_desc.channels[0], OLP_SET_SWITCHBACK_MODE, buff); + EXPECT_TRUE(pkt_len == 7); + EXPECT_TRUE(buff[0] == 0x01); + EXPECT_TRUE(buff[1] == 0x00); + EXPECT_TRUE(buff[2] == 0x10); + EXPECT_TRUE(buff[3] == 0x20); + EXPECT_TRUE(buff[4] == 0x00); + EXPECT_TRUE(buff[5] == 0x01); + EXPECT_TRUE(buff[6] == 0x02); +} + +TEST(OLP_RECV_PACKET, OLP_SET_HEARTBEAT_SWITCH) +{ + int ret = 0; + unsigned char data_succ[] = { + 0x01, 0x00, 0x06, 0x00, 0x00, 0x04, 0x01, 0x01, 0x05, 0x03 + }; + unsigned char data_fail[] = { + 0x01, 0x00, 0x86, 0x00, 0x00, 0x02, 0xFF, 0xEE + }; + + ret = olp6500_check_recv_data((char *)data_succ, OLP_SET_HEARTBEAT_SWITCH); + EXPECT_TRUE(ret == 0); + ret = olp6500_check_recv_data((char *)data_fail, OLP_SET_HEARTBEAT_SWITCH); + EXPECT_TRUE(ret == -1); +} + +TEST(OLP_RECV_PACKET, OLP_HEARTBEAT_PACKET) +{ + int ret = 0; + unsigned char data_succ[] = { + 0x00, 0x00, 0x06, 0x01, 0x00, 0x04, 0x30, 0x00, 0x00, 0x00 + }; + unsigned char data_fail[] = { + 0x00, 0x00, 0x86, 0x01, 0x00, 0x02, 0xFF, 0xEE + }; + + ret = olp6500_check_recv_data((char *)data_succ, OLP_HEARTBEAT_PACKET); + EXPECT_TRUE(ret == 0); + ret = olp6500_check_recv_data((char *)data_fail, OLP_HEARTBEAT_PACKET); + EXPECT_TRUE(ret == -1); +} + +TEST(OLP_RECV_PACKET, OLP_SET_WORK_MODE) +{ + int ret = 0; + unsigned char data_succ[] = { + 0x01, 0x00, 0x10, 0x10, 0x00, 0x01, 0x02 + }; + unsigned char data_fail[] = { + 0x01, 0x00, 0x90, 0x10, 0x00, 0x02, 0xFF, 0xEE + }; + + ret = olp6500_check_recv_data((char *)data_succ, OLP_SET_WORK_MODE); + EXPECT_TRUE(ret == 0); + ret = olp6500_check_recv_data((char *)data_fail, OLP_SET_WORK_MODE); + EXPECT_TRUE(ret == -1); +} + +TEST(OLP_RECV_PACKET, OLP_SET_WORK_LINE) +{ + int ret = 0; + unsigned char data_succ[] = { + 0x01, 0x00, 0x10, 0x70, 0x00, 0x01, 0x30 + }; + unsigned char data_fail[] = { + 0x01, 0x00, 0x90, 0x70, 0x00, 0x02, 0xFF, 0xEE + }; + + ret = olp6500_check_recv_data((char *)data_succ, OLP_SET_WORK_LINE); + EXPECT_TRUE(ret == 0); + ret = olp6500_check_recv_data((char *)data_fail, OLP_SET_WORK_LINE); + EXPECT_TRUE(ret == -1); +} + +TEST(OLP_RECV_PACKET, OLP_SET_SWITCHBACK_MODE) +{ + int ret = 0; + unsigned char data_succ[] = { + 0x01, 0x00, 0x10, 0x20, 0x00, 0x01, 0x02 + }; + unsigned char data_fail[] = { + 0x01, 0x00, 0x90, 0x20, 0x00, 0x02, 0xFF, 0xEE + }; + + ret = olp6500_check_recv_data((char *)data_succ, OLP_SET_SWITCHBACK_MODE); + EXPECT_TRUE(ret == 0); + ret = olp6500_check_recv_data((char *)data_fail, OLP_SET_SWITCHBACK_MODE); + EXPECT_TRUE(ret == -1); +} + +int main(int argc, char * argv[]) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} |
