summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--service/CMakeLists.txt8
-rw-r--r--service/include/olp_dev.h106
-rw-r--r--service/src/core.c14
-rw-r--r--service/src/olp.c108
-rw-r--r--service/src/olp_6500.c1052
-rw-r--r--service/test/TestOLP.cc246
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, &current_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, &current_time);
+ timespec_diff(&send_pkt_last_time, &current_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();
+}