diff options
Diffstat (limited to 'src/srvpp')
-rw-r--r-- | src/srvpp/CMakeLists.txt | 40 | ||||
-rw-r--r-- | src/srvpp/libsrvpp.pc.in | 10 | ||||
-rw-r--r-- | src/srvpp/src/CMakeLists.txt | 44 | ||||
-rw-r--r-- | src/srvpp/src/srvpp.c | 823 | ||||
-rw-r--r-- | src/srvpp/src/srvpp.h | 185 | ||||
-rw-r--r-- | src/srvpp/src/srvpp_logger.c | 83 | ||||
-rw-r--r-- | src/srvpp/src/srvpp_logger.h | 89 | ||||
-rw-r--r-- | src/srvpp/tests/CMakeLists.txt | 40 | ||||
-rw-r--r-- | src/srvpp/tests/srvpp_test.c | 160 |
9 files changed, 0 insertions, 1474 deletions
diff --git a/src/srvpp/CMakeLists.txt b/src/srvpp/CMakeLists.txt deleted file mode 100644 index 539675d..0000000 --- a/src/srvpp/CMakeLists.txt +++ /dev/null @@ -1,40 +0,0 @@ -# -# Copyright (c) 2018 Cisco and/or its affiliates. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -cmake_minimum_required(VERSION 2.8) -project(srvpp) - -# add subdirectories -add_subdirectory(src) - -# enable testing if requested and possible -SET(ENABLE_TESTS 1 CACHE BOOL "Enable unit tests.") -if(ENABLE_TESTS) - find_package(CMOCKA) - if(CMOCKA_FOUND) - MESSAGE(STATUS "CMocka found, tests are enabled.") - enable_testing() - add_subdirectory(tests) - else(CMOCKA_FOUND) - MESSAGE(WARNING "CMocka not found, tests are disabled.") - endif(CMOCKA_FOUND) -endif(ENABLE_TESTS) - -find_package(PkgConfig QUIET) -if(PKG_CONFIG_FOUND) - # generate and install pkg-config file - configure_file("libsrvpp.pc.in" "libsrvpp.pc" @ONLY) - install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libsrvpp.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") -endif() diff --git a/src/srvpp/libsrvpp.pc.in b/src/srvpp/libsrvpp.pc.in deleted file mode 100644 index c57c267..0000000 --- a/src/srvpp/libsrvpp.pc.in +++ /dev/null @@ -1,10 +0,0 @@ -prefix=@CMAKE_INSTALL_PREFIX@ -includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@ -libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@ - -Name: srvpp -Description: VPP-Sysrepo integration library -Version: 0.0.1 -Libs: -L${libdir} -lsrvpp -Cflags: -I${includedir} - diff --git a/src/srvpp/src/CMakeLists.txt b/src/srvpp/src/CMakeLists.txt deleted file mode 100644 index 8cc0a04..0000000 --- a/src/srvpp/src/CMakeLists.txt +++ /dev/null @@ -1,44 +0,0 @@ -# -# Copyright (c) 2018 Cisco and/or its affiliates. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -include(GNUInstallDirs) - -# srvpp sources -set(SRVPP_SOURCES - srvpp_logger.c - srvpp.c -) - -# srvpp public headers -set(SRVPP_HEADERS - srvpp.h -) - -set(CMAKE_C_FLAGS " -g -O0 -fpic -fPIC -std=gnu99 -Wl,-rpath-link=/usr/lib") - -# libraries to link with -set(LINK_LIBRARIES sysrepo vlibmemoryclient vapiclient vppapiclient svm vppinfra pthread rt dl) - -# build instructions -add_library(srvpp SHARED ${SRVPP_SOURCES}) -add_library(srvpp_a ${SRVPP_SOURCES}) - -# linker instructions -target_link_libraries(srvpp ${LINK_LIBRARIES}) -target_link_libraries(srvpp_a ${LINK_LIBRARIES}) - -# install rules -install(TARGETS srvpp DESTINATION ${CMAKE_INSTALL_LIBDIR}) -install(FILES ${SRVPP_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) diff --git a/src/srvpp/src/srvpp.c b/src/srvpp/src/srvpp.c deleted file mode 100644 index 9b3467b..0000000 --- a/src/srvpp/src/srvpp.c +++ /dev/null @@ -1,823 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <stdlib.h> -#include <stdint.h> -#include <stdbool.h> -#include <pthread.h> - -#include "srvpp.h" -#include "srvpp_logger.h" - -#undef vl_api_version -#define vl_api_version(n,v) static u32 vpe_api_version = v; -#include <vpp/api/vpe.api.h> -#undef vl_api_version - - -#define SRVPP_RESPONSE_TIMEOUT 2 /**< Maximum time (in seconds) that a client waits for the response(s) to a request or dumprequest. */ - -#define CHECK_NULL(ARG) \ - if (NULL == ARG) { \ - SRVPP_LOG_ERR("NULL value detected for %s argument of %s", #ARG, __func__); \ - return -1; \ - } \ - -#define CHECK_NULL_RET(ARG, RET) \ - if (NULL == ARG) { \ - SRVPP_LOG_ERR("NULL value detected for %s argument of %s", #ARG, __func__); \ - return RET; \ - } \ - -/** - * @brief Type of the response expected from VPP. - */ -typedef enum srvpp_response_type_e { - SRVPP_REPLY, /**< A reply message (single message). */ - SRVPP_DETAILS, /**< Multiple details messages. */ -} srvpp_response_type_t; - -/** - * @brief srvpp request context structure. - */ -typedef struct srvpp_request_ctx_s { - struct srvpp_request_ctx_s *_next; /**< Pointer to the next request context in the linked-list. */ - u32 ctx_id; /**< Context ID used to map responses with requests. */ - srvpp_response_type_t resp_type; /**< Type of the response expected from VPP. */ - - i32 resp_retval; /**< Return value of the last response (0 = success). */ - bool resp_data_copy; /**< Controls whether data of the responses shall be copied (returned) or ignored. */ - void **resp_msg_arr; /**< Array of the pointers to response messages. */ - size_t *resp_msg_sizes; /**< Array of sizes of messages in the ::resp_msg_arr. */ - size_t resp_msg_arr_size; /**< Size of the ::resp_msg_arr array. */ - size_t resp_msg_cnt; /**< Count of the messages currently stored in ::resp_msg_arr array. */ - - bool resp_ready; /**< Signals that the expected response has arrived and is ready to be returned. */ - pthread_cond_t resp_cv; /**< Condition variable for ::resp_ready. */ - pthread_mutex_t lock; /**< Mutex to protect shared access to the context. */ -} srvpp_request_ctx_t; - -/** - * @brief srvpp interface info context structure. - */ -typedef struct srvpp_if_info_s { - struct srvpp_if_info_s *_next; - const char *if_name; - u32 if_index; -} srvpp_if_info_t; - -/** - * @brief srvpp context structure. - */ -typedef struct srvpp_ctx_s { - size_t ref_cnt; /**< Context reference counter. */ - unix_shared_memory_queue_t *vlib_input_queue; /**< VPP Library input queue. */ - u32 vlib_client_index; /**< VPP Library client index. */ - srvpp_request_ctx_t *request_ctx_list; /**< Linked-list of request contexts. */ - srvpp_if_info_t *if_info_list; /**< Linked-list of VPP interfaces information. */ - pthread_key_t request_key; /**< Key to the thread-specific request context. */ -} srvpp_ctx_t; - -/** - * @brief Generic VPP request structure. - */ -typedef struct __attribute__ ((packed)) vl_generic_request_s { - unsigned short _vl_msg_id; - unsigned int client_index; - unsigned int context; -} vl_generic_request_t; - -/** - * @brief Generic VPP response structure. - */ -typedef struct __attribute__ ((packed)) vl_generic_response_s { - u16 _vl_msg_id; - u32 context; -} vl_generic_response_t; - -/** - * @brief Generic VPP reply structure (response with a single message). - */ -typedef struct __attribute__ ((packed)) vl_generic_reply_s { - u16 _vl_msg_id; - u32 context; - i32 retval; -} vl_generic_reply_t; - -/** - * @brief Global srvpp context. - */ -static srvpp_ctx_t *srvpp_ctx = NULL; - -/** - * @brief Mutex for the global context. - */ -static pthread_mutex_t srvpp_ctx_lock = PTHREAD_MUTEX_INITIALIZER; - -/** - * @brief Not used, just to satisfy external references when -lvlib is not available. - */ -void -vlib_cli_output(struct vlib_main_t *vm, char *fmt, ...) -{ - SRVPP_LOG_WRN_MSG("vlib_cli_output callled!"); -} - -/** - * @brief Sets correct VPP API version. - */ -void -vl_client_add_api_signatures(vl_api_memclnt_create_t *mp) -{ - /* - * Send the main API signature in slot 0. This bit of code must - * match the checks in ../vpe/api/api.c: vl_msg_api_version_check(). - */ - mp->api_versions[0] = clib_host_to_net_u32(vpe_api_version); -} - -/** - * @brief Returns the request context assigned to the active thread. - * If no request context exists for the thread, it will be automatically created. - */ -static srvpp_request_ctx_t * -srvpp_get_thread_request_ctx(srvpp_ctx_t *ctx) -{ - srvpp_request_ctx_t *req_ctx = NULL; - - CHECK_NULL_RET(ctx, NULL); - - if (NULL == (req_ctx = pthread_getspecific(ctx->request_key))) { - /* allocate a new request context */ - req_ctx = calloc(1, sizeof(*req_ctx)); - if (NULL != req_ctx) { - /* initialize the new context */ - req_ctx->ctx_id = (u32)(((uintptr_t)req_ctx) & 0xFFFFFFFF) << 16; - SRVPP_LOG_DBG("Creating new request ctx with id=%u", req_ctx->ctx_id); - - pthread_mutex_init(&req_ctx->lock, NULL); - pthread_cond_init (&req_ctx->resp_cv, NULL); - - /* save the request ctx in the srvpp context */ - pthread_mutex_lock(&srvpp_ctx_lock); - req_ctx->_next = ctx->request_ctx_list; - ctx->request_ctx_list = req_ctx; - pthread_mutex_unlock(&srvpp_ctx_lock); - - /* save the request ctx in the thread-local memory */ - pthread_setspecific(ctx->request_key, req_ctx); - } else { - SRVPP_LOG_ERR_MSG("Unable to allocate new request context."); - } - } - - return req_ctx; -} - -/** - * @brief Returns the request context matching with the provided context id. - */ -static srvpp_request_ctx_t * -srvpp_get_request_ctx(srvpp_ctx_t *ctx, u32 req_ctx_id) -{ - srvpp_request_ctx_t *req_ctx = NULL, *match = NULL; - - CHECK_NULL_RET(ctx, NULL); - - pthread_mutex_lock(&srvpp_ctx_lock); - - req_ctx = ctx->request_ctx_list; - - while (NULL != req_ctx) { - if (req_ctx->ctx_id == req_ctx_id) { - match = req_ctx; - break; - } - req_ctx = req_ctx->_next; - } - - pthread_mutex_unlock(&srvpp_ctx_lock); - - return match; -} - -/** - * @brief Copy data of the message into the provided request context. - */ -static int -srvpp_msg_data_copy(srvpp_request_ctx_t *req_ctx, void *msg, size_t msg_size) -{ - void **msg_arr = NULL; - size_t *sizes_arr = NULL; - void *msg_space = NULL; - - CHECK_NULL(req_ctx); - - if (req_ctx->resp_msg_arr_size < (req_ctx->resp_msg_cnt + 1)) { - /* reallocate arrays to fit one new message */ - msg_arr = realloc(req_ctx->resp_msg_arr, (req_ctx->resp_msg_cnt + 1) * sizeof(*req_ctx->resp_msg_arr)); - if (NULL == msg_arr) { - SRVPP_LOG_ERR_MSG("Unable to reallocate message array."); - return -1; - } - sizes_arr = realloc(req_ctx->resp_msg_sizes, (req_ctx->resp_msg_cnt + 1) * sizeof(*req_ctx->resp_msg_sizes)); - if (NULL == sizes_arr) { - SRVPP_LOG_ERR_MSG("Unable to reallocate message sizes array."); - return -1; - } - req_ctx->resp_msg_arr = msg_arr; - req_ctx->resp_msg_sizes = sizes_arr; - req_ctx->resp_msg_arr_size = req_ctx->resp_msg_cnt + 1; - - req_ctx->resp_msg_arr[req_ctx->resp_msg_cnt] = NULL; - req_ctx->resp_msg_sizes[req_ctx->resp_msg_cnt] = 0; - } - - if (req_ctx->resp_msg_sizes[req_ctx->resp_msg_cnt] < msg_size) { - /* reallocate space for the message */ - msg_space = realloc(req_ctx->resp_msg_arr[req_ctx->resp_msg_cnt], msg_size); - if (NULL == msg_space) { - SRVPP_LOG_ERR_MSG("Unable to reallocate message space."); - return -1; - } - req_ctx->resp_msg_arr[req_ctx->resp_msg_cnt] = msg_space; - req_ctx->resp_msg_sizes[req_ctx->resp_msg_cnt] = msg_size; - } - - /* copy the message content */ - memcpy(req_ctx->resp_msg_arr[req_ctx->resp_msg_cnt], msg, msg_size); - - req_ctx->resp_msg_cnt++; - - return 0; -} - -/** - * @brief Processes a reply to a single VPP request. - */ -static int -srvpp_process_reply_msg(srvpp_request_ctx_t *req_ctx, u16 msg_id, void *msg, size_t msg_size) -{ - vl_generic_reply_t *reply = NULL; - int rc = 0; - - CHECK_NULL(req_ctx); - - reply = (vl_generic_reply_t *) msg; - - if (req_ctx->ctx_id != reply->context) { - SRVPP_LOG_ERR_MSG("Invalid request context for provided message, ignoring the message."); - return -1; - } - - if (req_ctx->resp_data_copy) { - /* copy msg data into req_ctx */ - rc = srvpp_msg_data_copy(req_ctx, msg, msg_size); - } - - if (0 == rc) { - req_ctx->resp_retval = reply->retval; - } else { - req_ctx->resp_retval = rc; - } - - /* signal the requesting thread */ - req_ctx->resp_ready = true; - pthread_cond_signal(&req_ctx->resp_cv); - - return rc; -} - -/** - * @brief Processes a reply to a dump request to VPP (response consisting of multiple messages). - */ -static int -srvpp_process_details_msg(srvpp_request_ctx_t *req_ctx, u16 msg_id, void *msg, size_t msg_size) -{ - vl_generic_response_t *response = NULL; - int rc = 0; - - CHECK_NULL(req_ctx); - - response = (vl_generic_response_t *) msg; - - if (req_ctx->ctx_id != response->context) { - SRVPP_LOG_ERR_MSG("Invalid request context for provided message, ignoring the message."); - return -1; - } - - if (VL_API_CONTROL_PING_REPLY != msg_id) { - /* details message - copy message data into req contex*/ - rc = srvpp_msg_data_copy(req_ctx, msg, msg_size); - if (0 != rc && 0 == req_ctx->resp_retval) { - /* in case of error, propagate it to the req context */ - req_ctx->resp_retval = rc; - } - } else { - /* control ping reply, signal the requesting thread */ - req_ctx->resp_ready = true; - pthread_cond_signal(&req_ctx->resp_cv); - } - - return req_ctx->resp_retval; -} - -/** - * @brief Internal callback automatically called by VPP library when a message - * from VPP is received. - */ -void -_srvpp_receive_msg_handler(void *msg) -{ - srvpp_request_ctx_t *req_ctx = NULL; - vl_generic_response_t *response = NULL; - msgbuf_t *msg_header = NULL; - size_t msg_size = 0; - u16 msg_id = 0; - - if (NULL == msg) { - SRVPP_LOG_WRN_MSG("NULL message received, ignoring."); - return; - } - - response = (vl_generic_response_t *) msg; - - /* get message details */ - msg_header = (msgbuf_t *) (((u8 *) msg) - offsetof(msgbuf_t, data)); - msg_size = ntohl(msg_header->data_len); - msg_id = ntohs(*((u16 *)msg)); - - SRVPP_LOG_DBG("New message received from VPP (id=%d, size=%zu).", msg_id, msg_size); - - /* get request context matching with context id */ - req_ctx = srvpp_get_request_ctx(srvpp_ctx, response->context); - if (NULL == req_ctx) { - SRVPP_LOG_WRN("Unexpected context id=%d within the received message, ignoring.", response->context); - return; - } - - pthread_mutex_lock(&req_ctx->lock); - - if (SRVPP_REPLY == req_ctx->resp_type) { - srvpp_process_reply_msg(req_ctx, msg_id, msg, msg_size); - } else { - srvpp_process_details_msg(req_ctx, msg_id, msg, msg_size); - } - - pthread_mutex_unlock(&req_ctx->lock); -} - -/** - * @brief Blocks the thread until a response from VPP comes or until a timeout expires. - */ -static int -srvpp_wait_response(srvpp_request_ctx_t *req_ctx) -{ - struct timespec ts = { 0, }; - int retval = 0, rc = 0; - - CHECK_NULL(req_ctx); - - pthread_mutex_lock(&req_ctx->lock); - - clock_gettime(CLOCK_REALTIME, &ts); - ts.tv_sec += SRVPP_RESPONSE_TIMEOUT; - - while (!req_ctx->resp_ready && (0 == rc)) { - rc = pthread_cond_timedwait(&req_ctx->resp_cv, &req_ctx->lock, &ts); - } - if (0 == rc) { - SRVPP_LOG_DBG("Received the response from VPP, retval=%d", req_ctx->resp_retval); - retval = req_ctx->resp_retval; - } else { - SRVPP_LOG_ERR("Response not received from VPP within the timeout period (%d sec).", SRVPP_RESPONSE_TIMEOUT); - retval = -1; - } - - /* invalidate previous context id */ - ++req_ctx->ctx_id; - - pthread_mutex_unlock(&req_ctx->lock); - - return retval; -} - -/** - * @brief Connects to VPP. - */ -static int -srvpp_vlib_connect(srvpp_ctx_t *ctx) -{ - api_main_t *am = &api_main; - int rc = 0; - - CHECK_NULL(ctx); - - SRVPP_LOG_DBG_MSG("Connecting to VPP..."); - - rc = vl_client_connect_to_vlib("/vpe-api", "srvpp", 32); - - if (rc < 0) { - SRVPP_LOG_ERR("Unable to connect to VPP, rc=%d.", rc); - } else { - SRVPP_LOG_DBG("Connection to VPP established, client index=%d.", am->my_client_index); - ctx->vlib_client_index = am->my_client_index; - ctx->vlib_input_queue = am->shmem_hdr->vl_input_queue; - } - - return rc; -} - -/** - * @brief Disconnects from VPP. - */ -static void -srvpp_vlib_disconnect() -{ - vl_client_disconnect_from_vlib(); -} - -/** - * @brief Adds a new interface into interfaces list. - */ -static int -srvpp_if_info_add(srvpp_ctx_t *ctx, const char *if_name, u32 if_index) -{ - srvpp_if_info_t *tmp = NULL, *if_info = NULL; - - SRVPP_LOG_DBG("Adding interface '%s', id=%d", if_name, if_index); - - if_info = calloc(1, sizeof(*if_info)); - if (NULL == if_info) { - return 1; - } - - if_info->if_name = strdup(if_name); - if (NULL == if_info->if_name) { - return 1; - } - - if_info->if_index = if_index; - - if (NULL == ctx->if_info_list) { - ctx->if_info_list = if_info; - } else { - tmp = ctx->if_info_list; - while (NULL != tmp->_next) { - tmp = tmp->_next; - } - tmp->_next = if_info; - } - - return 0; -} - -/** - * @brief Loads VPP interfaces information. - */ -static int -srvpp_if_info_load(srvpp_ctx_t *ctx) -{ - vl_api_sw_interface_dump_t *if_dump_req = NULL; - vl_api_sw_interface_details_t *if_details = NULL; - void **details = NULL; - size_t details_cnt = 0; - int ret = 0; - - SRVPP_LOG_DBG_MSG("Loading VPP interfaces information"); - - /* dump interfaces */ - if_dump_req = srvpp_alloc_msg(VL_API_SW_INTERFACE_DUMP, sizeof(*if_dump_req)); - - ret = srvpp_send_dumprequest(ctx, if_dump_req, &details, &details_cnt); - if (0 != ret) { - return ret; - } - - pthread_mutex_lock(&srvpp_ctx_lock); - - for (size_t i = 0; i < details_cnt; i++) { - if_details = (vl_api_sw_interface_details_t *) details[i]; - ret = srvpp_if_info_add(ctx, (char*)if_details->interface_name, ntohl(if_details->sw_if_index)); - } - - pthread_mutex_unlock(&srvpp_ctx_lock); - - return 0; -} - -/** - * @brief Cleans up VPP interfaces information. - */ -static void -srvpp_if_info_cleanup(srvpp_ctx_t *ctx) -{ - srvpp_if_info_t *tmp = NULL, *if_info = NULL; - - if (NULL != ctx) { - if_info = ctx->if_info_list; - - while (NULL != if_info) { - tmp = if_info; - if_info = if_info->_next; - free((void*)tmp->if_name); - free(tmp); - } - } -} - -/** - * @brief Initializes the srvpp context. - */ -srvpp_ctx_t * -srvpp_ctx_init() -{ - srvpp_ctx_t *ctx = NULL; - int rc = 0; - - srvpp_logger_init(); - - ctx = calloc(1, sizeof(*ctx)); - if (NULL == ctx) { - SRVPP_LOG_ERR_MSG("Unable to allocate srvpp context."); - return NULL; - } - - rc = srvpp_vlib_connect(ctx); - if (0 != rc) { - SRVPP_LOG_ERR_MSG("Unable to initialize srvpp context."); - free(ctx); - return NULL; - } - - while (pthread_key_create(&ctx->request_key, NULL) == EAGAIN); - pthread_setspecific(ctx->request_key, NULL); - - ctx->ref_cnt = 1; - - SRVPP_LOG_INF_MSG("srvpp context initialized successfully."); - - return ctx; -} - -/** - * @brief Cleans up the srvpp context. - */ -static void -srvpp_ctx_cleanup(srvpp_ctx_t *ctx) -{ - srvpp_request_ctx_t *tmp = NULL, *req_ctx = NULL; - - if (NULL != ctx) { - srvpp_vlib_disconnect(); - - srvpp_if_info_cleanup(ctx); - - req_ctx = ctx->request_ctx_list; - while (NULL != req_ctx) { - tmp = req_ctx; - req_ctx = req_ctx->_next; - - pthread_mutex_destroy(&tmp->lock); - pthread_cond_destroy(&tmp->resp_cv); - - for (size_t i = 0; i < tmp->resp_msg_arr_size; i++) { - free(tmp->resp_msg_arr[i]); - } - free(tmp->resp_msg_arr); - free(tmp->resp_msg_sizes); - - free(tmp); - } - free(ctx); - - srvpp_logger_cleanup(); - - SRVPP_LOG_INF_MSG("srvpp context cleaned up successfully."); - } -} - -srvpp_ctx_t * -srvpp_get_ctx() -{ - bool setup_handlers = false; - - pthread_mutex_lock(&srvpp_ctx_lock); - - if (NULL == srvpp_ctx) { - /* initialize a new context */ - SRVPP_LOG_DBG_MSG("Initializing a new srvpp context."); - srvpp_ctx = srvpp_ctx_init(); - setup_handlers = true; - } else { - /* increment ref. count */ - srvpp_ctx->ref_cnt++; - SRVPP_LOG_DBG("Reusing existing srvpp context, new refcount=%zu.", srvpp_ctx->ref_cnt); - } - - pthread_mutex_unlock(&srvpp_ctx_lock); - - if (setup_handlers) { - /* setup required handlers */ - srvpp_setup_handler(CONTROL_PING_REPLY, control_ping_reply); - srvpp_setup_handler(SW_INTERFACE_DETAILS, sw_interface_details); - - /* load VPP interfaces information */ - srvpp_if_info_load(srvpp_ctx); - } - - return srvpp_ctx; -} - -void -srvpp_release_ctx(srvpp_ctx_t *ctx) -{ - pthread_mutex_lock(&srvpp_ctx_lock); - - if (ctx != srvpp_ctx) { - SRVPP_LOG_ERR_MSG("Invalid srvpp context passed in, unable to release."); - pthread_mutex_unlock(&srvpp_ctx_lock); - return; - } - - if (srvpp_ctx->ref_cnt > 1) { - /* there are still some other references */ - srvpp_ctx->ref_cnt--; - SRVPP_LOG_DBG("Releasing a reference to srvpp context, new refcount=%zu.", srvpp_ctx->ref_cnt); - } else { - /* last reference - cleanup */ - SRVPP_LOG_DBG_MSG("Releasing srvpp context (last ctx reference)."); - srvpp_ctx_cleanup(srvpp_ctx); - srvpp_ctx = NULL; - } - - pthread_mutex_unlock(&srvpp_ctx_lock); -} - -void * -srvpp_alloc_msg(uint16_t msg_id, size_t msg_size) -{ - vl_generic_request_t *req = NULL; - - req = vl_msg_api_alloc(msg_size); - if (NULL != req) { - memset(req, 0, msg_size); - req->_vl_msg_id = ntohs(msg_id); - } - - return req; -} - -int -srvpp_send_request(srvpp_ctx_t *ctx, void *request, void **response) -{ - vl_generic_request_t *req = NULL; - srvpp_request_ctx_t *req_ctx = NULL; - int retval = 0; - - CHECK_NULL(ctx); - CHECK_NULL(request); - - req_ctx = srvpp_get_thread_request_ctx(ctx); - if (NULL == req_ctx) { - SRVPP_LOG_ERR_MSG("Unable to obtain a request context."); - return -1; - } - - req = (vl_generic_request_t *) request; - req->client_index = ctx->vlib_client_index; - - pthread_mutex_lock(&req_ctx->lock); - - if (NULL != response) { - /* response data is requested */ - req_ctx->resp_data_copy = true; - req_ctx->resp_msg_cnt = 0; - } else { - /* not interested in response data */ - req_ctx->resp_data_copy = false; - } - - req_ctx->resp_type = SRVPP_REPLY; - req_ctx->resp_ready = false; - req_ctx->resp_retval = 0; - req->context = ++req_ctx->ctx_id; - - pthread_mutex_unlock(&req_ctx->lock); - - SRVPP_LOG_DBG_MSG("Sending a request to VPP."); - - vl_msg_api_send_shmem(ctx->vlib_input_queue, (u8*)&req); - - /* wait for expected response */ - retval = srvpp_wait_response(req_ctx); - - if (0 == retval) { - if (NULL != response && req_ctx->resp_msg_cnt > 0) { - *response = req_ctx->resp_msg_arr[0]; - } - SRVPP_LOG_DBG_MSG("VPP request successfully processed."); - } else { - SRVPP_LOG_ERR_MSG("Error by handling of a VPP request."); - } - - return retval; -} - -int -srvpp_send_dumprequest(srvpp_ctx_t *ctx, void *request, void ***response_arr, size_t *response_cnt) -{ - vl_generic_request_t *req = NULL; - srvpp_request_ctx_t *req_ctx = NULL; - vl_api_control_ping_t *ping = NULL; - int retval = 0; - - CHECK_NULL(ctx); - CHECK_NULL(request); - CHECK_NULL(response_arr); - CHECK_NULL(response_cnt); - - req_ctx = srvpp_get_thread_request_ctx(ctx); - if (NULL == req_ctx) { - SRVPP_LOG_ERR_MSG("Unable to obtain a request context."); - return -1; - } - - req = (vl_generic_request_t *) request; - req->client_index = ctx->vlib_client_index; - - /* allocate control ping request */ - ping = srvpp_alloc_msg(VL_API_CONTROL_PING, sizeof(*ping)); - if (NULL == ping) { - SRVPP_LOG_ERR_MSG("Unable to allocate control ping message."); - return -1; - } - ping->client_index = ctx->vlib_client_index; - - pthread_mutex_lock(&req_ctx->lock); - - req_ctx->resp_data_copy = true; - req_ctx->resp_msg_cnt = 0; - - req_ctx->resp_type = SRVPP_DETAILS; - req_ctx->resp_ready = false; - req_ctx->resp_retval = 0; - - req_ctx->ctx_id++; - req->context = req_ctx->ctx_id; - ping->context = req_ctx->ctx_id; - - pthread_mutex_unlock(&req_ctx->lock); - - SRVPP_LOG_DBG_MSG("Sending a dumprequest to VPP."); - - vl_msg_api_send_shmem(ctx->vlib_input_queue, (u8*)&req); - - vl_msg_api_send_shmem(ctx->vlib_input_queue, (u8*)&ping); - - /* wait for expected response */ - retval = srvpp_wait_response(req_ctx); - - if (0 == retval) { - *response_arr = req_ctx->resp_msg_arr; - *response_cnt = req_ctx->resp_msg_cnt; - SRVPP_LOG_DBG_MSG("VPP dumprequest successfully processed."); - } else { - SRVPP_LOG_ERR_MSG("Error by handling of a VPP dumprequest."); - } - - return retval; -} - -int -srvpp_get_if_index(srvpp_ctx_t *ctx, const char *if_name, uint32_t *if_index) -{ - CHECK_NULL(if_name); - CHECK_NULL(if_index); - - srvpp_if_info_t *if_info = NULL; - - if_info = ctx->if_info_list; - - while ((NULL != if_info) && (NULL != if_info->if_name)) { - if (0 == strcmp(if_info->if_name, if_name)) { - *if_index = if_info->if_index; - return 0; - } - if_info = if_info->_next; - } - - return 1; -} diff --git a/src/srvpp/src/srvpp.h b/src/srvpp/src/srvpp.h deleted file mode 100644 index 4830d7b..0000000 --- a/src/srvpp/src/srvpp.h +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef INC_SRVPP_H_ -#define INC_SRVPP_H_ - -/** - * @defgroup srvpp Sysrepo-VPP Integration Library - * @{ - * - * @brief Provides synchronous interface to VPP binary API aimed primarily for - * the integration of VPP with Sysrepo datastore. - * - * The library is thread-safe - can be used to communicate with VPP from multiple - * threads simultaneously. - */ - -#include <stddef.h> - -#include <vlibapi/api.h> -#include <vlibmemory/api.h> -#include <vapi/vpe.api.vapi.h> - -#include <vpp/api/vpe_msg_enum.h> - -#define vl_typedefs /* define message structures */ -#include <vpp/api/vpe_all_api_h.h> -#undef vl_typedefs - -#define vl_endianfun -#include <vpp/api/vpe_all_api_h.h> -#undef vl_endianfun - -/* instantiate all the print functions we know about */ -#define vl_print(handle, ...) -#define vl_printfun -#include <vpp/api/vpe_all_api_h.h> -#undef vl_printfun - -/** - * @brief Sysrepo - VPP interface context. - */ -typedef struct srvpp_ctx_s srvpp_ctx_t; - -/** - * @brief srvpp logger severity levels. - */ -typedef enum srvpp_log_level_e { - SRVPP_NONE, /**< Do not print any messages. */ - SRVPP_ERR, /**< Print only error messages. */ - SRVPP_WRN, /**< Print error and warning messages. */ - SRVPP_INF, /**< Besides errors and warnings, print some other informational messages. */ - SRVPP_DBG, /**< Print all messages including some development debug messages. */ -} srvpp_log_level_t; - -/** - * @brief Sets callback that will be called when a log entry would be populated. - * - * @param[in] level Severity level of the log entry. - * @param[in] message Message of the log entry. - */ -typedef void (*srvpp_log_cb)(srvpp_log_level_t level, const char *message); - -/** - * @brief Returns a reference to the global srvpp context. If the global context - * does not exists yet, it will be automatically created (a connection to VPP - * will be established). - * - * @note The caller is supposed to call ::srvpp_release_ctx after it finishes - * the work with VPP. - * - * @return srvpp context to be used for subsequent API calls. - */ -srvpp_ctx_t* srvpp_get_ctx(); - -/** - * @brief Releases a reference to the global srvpp context. If this is the last - * reference, the context will be released (the connection to the VPP will be closed). - * - * @param[in] ctx srvpp context acquired using ::srvpp_get_ctx call. - */ -void srvpp_release_ctx(srvpp_ctx_t *ctx); - -/** - * @brief Allocates a VPP API message of specified type and size. - * - * @param[in] msg_id Message ID. - * @param[in] msg_size Size of the message. - * - * @return Space allocated for the message. - */ -void* srvpp_alloc_msg(uint16_t msg_id, size_t msg_size); - -/** - * @brief Sends a simple request to VPP and receive the response. - * - * @note Subsequent ::srvpp_send_request or ::srvpp_send_dumprequest calls from the same - * thread may overwrite the content of ::response, therefore it is not safe to call - * them until the response is fully consumed / processed by the caller. - * - * @param[in] ctx srvpp context acquired using ::srvpp_get_ctx call. - * @param[in] request Message with the request to be sent to VPP. - * @param[out] response (optional) Response to the request received from VPP. - * Caller must not free it - to save memory allocations, response is always - * placed into the same thread-local buffer owned by the library. - * - * @return 0 on success, non-zero in case of error. - */ -int srvpp_send_request(srvpp_ctx_t *ctx, void *request, void **response); - -/** - * @brief Sends a dump request to VPP and receives all responses with details. - * - * @note Subsequent ::srvpp_send_request or ::srvpp_send_dumprequest calls from the same - * thread may overwrite the content of ::response_arr, therefore it is not safe to call - * them until the response array is fully consumed / processed by the caller. - * - * @param[in] ctx srvpp context acquired using ::srvpp_get_ctx call. - * @param[in] request Message with the request to be sent to VPP. - * @param[out] response_arr Array of responses to the request received from VPP. - * Caller must not free it - to save memory allocations, response_arr is always - * placed into the same thread-local buffer owned by the library. - * @param[out] response_cnt Count of the response messages in the response_arr array. - * - * @return 0 on success, non-zero in case of error. - */ -int srvpp_send_dumprequest(srvpp_ctx_t *ctx, void *request, void ***response_arr, size_t *response_cnt); - -/** - * @brief Get interface index for provided interface name. - * - * @param[in] ctx srvpp context acquired using ::srvpp_get_ctx call. - * @param[in] if_name Name of an existing VPP interface. - * @param[out] if_index Index of the interface. - * - * @return 0 on success, non-zero in case of error. - */ -int srvpp_get_if_index(srvpp_ctx_t *ctx, const char *if_name, uint32_t *if_index); - -/** - * @brief Sets callback that will be called when a log entry would be populated. - * Callback will be called for each message with any log level. - * - * @param[in] log_callback Callback to be called when a log entry would populated. - */ -void srvpp_set_log_cb(srvpp_log_cb log_callback); - -/** - * @brief Setups message handler to provided VPP API call. Needs to be called - * for each VPP API function that can arrive as response from VPP. - * - * @param[in] ID VPP API function ID. - * @param[in] NAME VPP API function name. - */ -#define srvpp_setup_handler(ID, NAME) \ - do { \ - vl_msg_api_set_handlers(VL_API_##ID, #NAME, \ - (void*)_srvpp_receive_msg_handler, \ - (void*)vl_noop_handler, \ - (void*)vl_api_##NAME##_t_endian, \ - (void*)vl_api_##NAME##_t_print, \ - sizeof(vl_api_##NAME##_t), 1); \ - } while(0) - -/** - * @brief Internal callback automatically called by VPP library when a message - * from VPP is received. - */ -void _srvpp_receive_msg_handler(void *message); - -/**@} srvpp */ - -#endif /* INC_SRVPP_H_ */ diff --git a/src/srvpp/src/srvpp_logger.c b/src/srvpp/src/srvpp_logger.c deleted file mode 100644 index ee03a4b..0000000 --- a/src/srvpp/src/srvpp_logger.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <stdlib.h> -#include <pthread.h> - -#include "srvpp_logger.h" - -#define MAX_LOG_MSG_SIZE 2048 /**< Maximum size of one log entry. */ - -volatile srvpp_log_cb srvpp_log_callback = NULL; /**< Global variable used to store logging callback, if set. */ - -static pthread_once_t srvpp_log_buff_create_key_once = PTHREAD_ONCE_INIT; /** Used to control that ::srvpp_log_buff_create_key is called only once per thread. */ -static pthread_key_t srvpp_log_buff_key; /**< Key for thread-specific buffer data. */ - -/** - * @brief Create key for thread-specific buffer data. Should be called only once per thread. - */ -static void -srvpp_log_buff_create_key(void) -{ - while (pthread_key_create(&srvpp_log_buff_key, free) == EAGAIN); - pthread_setspecific(srvpp_log_buff_key, NULL); -} - -void -srvpp_logger_init() -{ - /* no init needed */ -} - -void -srvpp_logger_cleanup() -{ - /* since the thread-specific data for the main thread seems to be not auto-freed, - * (at least on Linux), we explicitly release it here for the thread from which - * sr_logger_cleanup has been called (which should be always the main thread). */ - pthread_once(&srvpp_log_buff_create_key_once, srvpp_log_buff_create_key); - char *msg_buff = pthread_getspecific(srvpp_log_buff_key); - if (NULL != msg_buff) { - free(msg_buff); - pthread_setspecific(srvpp_log_buff_key, NULL); - } -} - -void -srvpp_log_to_cb(srvpp_log_level_t level, const char *format, ...) -{ - char *msg_buff = NULL; - va_list arg_list; - - if (NULL != srvpp_log_callback) { - /* get thread-local message buffer */ - pthread_once(&srvpp_log_buff_create_key_once, srvpp_log_buff_create_key); - msg_buff = pthread_getspecific(srvpp_log_buff_key); - if (NULL == msg_buff) { - msg_buff = calloc(MAX_LOG_MSG_SIZE, sizeof(*msg_buff)); - pthread_setspecific(srvpp_log_buff_key, msg_buff); - } - /* print the message into buffer and call callback */ - if (NULL != msg_buff) { - va_start(arg_list, format); - vsnprintf(msg_buff, MAX_LOG_MSG_SIZE - 1, format, arg_list); - va_end(arg_list); - msg_buff[MAX_LOG_MSG_SIZE - 1] = '\0'; - /* call the callback */ - srvpp_log_callback(level, msg_buff); - } - } -} - diff --git a/src/srvpp/src/srvpp_logger.h b/src/srvpp/src/srvpp_logger.h deleted file mode 100644 index 3a1c947..0000000 --- a/src/srvpp/src/srvpp_logger.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef SRC_SRVPP_LOGGER_H_ -#define SRC_SRVPP_LOGGER_H_ - -#include "srvpp.h" - -/** - * @brief Pointer to logging callback, if set. - */ -extern volatile srvpp_log_cb srvpp_log_callback; - -/** - * @brief Returns the string representing the specified log level. - */ -#define _SRVPP_LL_STR(LL) \ - ((SRVPP_ERR == LL) ? "ERR" : \ - (SRVPP_WRN == LL) ? "WRN" : \ - (SRVPP_INF == LL) ? "INF" : \ - (SRVPP_DBG == LL) ? "DBG" : \ - "") - -/** - * @brief Internal logging macro for formatted messages. - */ -#ifdef NDEBUG -#define _SRVPP_LOG_FMT(LL, MSG, ...) \ - do { \ - if (NULL != srvpp_log_callback) { \ - srvpp_log_to_cb(LL, MSG, __VA_ARGS__); \ - } else { \ - fprintf(stderr, "[%s] " MSG "\n", _SRVPP_LL_STR(LL), __VA_ARGS__); \ - } \ -} while(0) -#else -#define _SRVPP_LOG_FMT(LL, MSG, ...) \ - do { \ - if (NULL != srvpp_log_callback) { \ - srvpp_log_to_cb(LL, "(%s:%d) " MSG, __func__, __LINE__, __VA_ARGS__); \ - } else { \ - fprintf(stderr, "[%s] (%s:%d) " MSG "\n", _SRVPP_LL_STR(LL), __func__, __LINE__, __VA_ARGS__); \ - } \ -} while(0) -#endif - -/* Logging macros for formatted messages. */ -#define SRVPP_LOG_ERR(MSG, ...) _SRVPP_LOG_FMT(SRVPP_ERR, MSG, __VA_ARGS__); -#define SRVPP_LOG_WRN(MSG, ...) _SRVPP_LOG_FMT(SRVPP_WRN, MSG, __VA_ARGS__); -#define SRVPP_LOG_INF(MSG, ...) _SRVPP_LOG_FMT(SRVPP_INF, MSG, __VA_ARGS__); -#define SRVPP_LOG_DBG(MSG, ...) _SRVPP_LOG_FMT(SRVPP_DBG, MSG, __VA_ARGS__); - -/* Logging macros for unformatted messages. */ -#define SRVPP_LOG_ERR_MSG(MSG) _SRVPP_LOG_FMT(SRVPP_ERR, MSG "%s", ""); -#define SRVPP_LOG_WRN_MSG(MSG) _SRVPP_LOG_FMT(SRVPP_WRN, MSG "%s", ""); -#define SRVPP_LOG_INF_MSG(MSG) _SRVPP_LOG_FMT(SRVPP_INF, MSG "%s", ""); -#define SRVPP_LOG_DBG_MSG(MSG) _SRVPP_LOG_FMT(SRVPP_DBG, MSG "%s", ""); - -/** - * @brief Initializes logger. - */ -void srvpp_logger_init(); - -/** - * @brief Cleans up resources used by he logger. - */ -void srvpp_logger_cleanup(); - -/** - * @brief Logs into the callback pre-specified by ::srvpp_set_log_cb. - * - * @param[in] level Log level. - * @param[in] format Format message. - */ -void srvpp_log_to_cb(srvpp_log_level_t level, const char *format, ...); - -#endif /* SRC_SRVPP_LOGGER_H_ */ diff --git a/src/srvpp/tests/CMakeLists.txt b/src/srvpp/tests/CMakeLists.txt deleted file mode 100644 index dc14ffb..0000000 --- a/src/srvpp/tests/CMakeLists.txt +++ /dev/null @@ -1,40 +0,0 @@ -# -# Copyright (c) 2018 Cisco and/or its affiliates. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -include_directories ("${PROJECT_SOURCE_DIR}/src") - -# check whether valgrind is installed -find_program(valgrind_FOUND valgrind) - -# macro for adding of an unit test -macro(ADD_UNIT_TEST TEST_NAME) - set(TEST_SRC - ${TEST_NAME}.c - ) - add_executable(${TEST_NAME} ${TEST_SRC}) - target_link_libraries(${TEST_NAME} ${CMOCKA_LIBRARIES} srvpp_a) - add_test(${TEST_NAME} ${TEST_NAME}) - - if(valgrind_FOUND) - add_test(${TEST_NAME}_valgrind valgrind - --error-exitcode=1 --read-var-info=yes - --leak-check=full --show-leak-kinds=all - ./${TEST_NAME} - ) - endif(valgrind_FOUND) -endmacro(ADD_UNIT_TEST) - -# add individual unit-tests -ADD_UNIT_TEST(srvpp_test)
\ No newline at end of file diff --git a/src/srvpp/tests/srvpp_test.c b/src/srvpp/tests/srvpp_test.c deleted file mode 100644 index 89e56db..0000000 --- a/src/srvpp/tests/srvpp_test.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <stdlib.h> -#include <stdio.h> -#include <unistd.h> -#include <setjmp.h> -#include <cmocka.h> - -#include "srvpp.h" - -#include <vpp/api/vpe_msg_enum.h> - -#define vl_typedefs /* define message structures */ -#include <vpp/api/vpe_all_api_h.h> -#undef vl_typedefs - -#define vl_endianfun -#include <vpp/api/vpe_all_api_h.h> -#undef vl_endianfun - -/* instantiate all the print functions we know about */ -#define vl_print(handle, ...) -#define vl_printfun -#include <vpp/api/vpe_all_api_h.h> -#undef vl_printfun - -static int -srvpp_test_setup(void **state) -{ - srvpp_ctx_t *ctx = NULL; - - ctx = srvpp_get_ctx(); - assert_non_null(ctx); - - srvpp_setup_handler(CONTROL_PING_REPLY, control_ping_reply); - srvpp_setup_handler(CREATE_LOOPBACK_REPLY, create_loopback_reply); - srvpp_setup_handler(DELETE_LOOPBACK_REPLY, delete_loopback_reply); - srvpp_setup_handler(SW_INTERFACE_DETAILS, sw_interface_details); - - *state = ctx; - return 0; -} - -static int -srvpp_test_teardown(void **state) -{ - srvpp_ctx_t *ctx = *state; - - srvpp_release_ctx(ctx); - - return 0; -} - -static void -srvpp_ctx_test(void **state) -{ - srvpp_ctx_t *ctx = *state; - assert_non_null(ctx); - - srvpp_ctx_t *ctx1 = NULL, *ctx2 = NULL; - vl_api_control_ping_t *msg = NULL; - int ret = 0; - - /* try to get additional contexts */ - ctx1 = srvpp_get_ctx(); - assert_non_null(ctx1); - - ctx2 = srvpp_get_ctx(); - assert_non_null(ctx2); - - assert_true(ctx == ctx1); - assert_true(ctx1 == ctx2); - - /* send a control ping */ - msg = srvpp_alloc_msg(VL_API_CONTROL_PING, sizeof(*msg)); - assert_non_null(msg); - - ret = srvpp_send_request(ctx1, msg, NULL); - assert_int_equal(ret, 0); - - /* release not needed contexts */ - srvpp_release_ctx(ctx1); - srvpp_release_ctx(ctx2); -} - -static void -srvpp_msg_test(void **state) -{ - srvpp_ctx_t *ctx = *state; - assert_non_null(ctx); - - vl_api_create_loopback_t *create_loop_req = NULL; - vl_api_create_loopback_reply_t *create_loop_reply = NULL; - vl_api_delete_loopback_t *del_loop_req = NULL; - vl_api_sw_interface_dump_t *if_dump_req = NULL; - vl_api_sw_interface_details_t *if_details = NULL; - void **details = NULL; - size_t details_cnt = 0; - u8 mac[6] = { 0, 10, 11, 12, 13, 14}; - int if_index = -1; - int ret = 0; - - /* create a loopback interface */ - create_loop_req = srvpp_alloc_msg(VL_API_CREATE_LOOPBACK, sizeof(*create_loop_req)); - assert_non_null(create_loop_req); - - memcpy(create_loop_req->mac_address, mac, sizeof(mac)); - - ret = srvpp_send_request(ctx, create_loop_req, (void**)&create_loop_reply); - assert_int_equal(ret, 0); - assert_non_null(create_loop_reply); - if_index = ntohl(create_loop_reply->sw_if_index); - - printf("connected loopback interface, ifindex=%d\n", if_index); - - /* dump interfaces */ - if_dump_req = srvpp_alloc_msg(VL_API_SW_INTERFACE_DUMP, sizeof(*if_dump_req)); - assert_non_null(if_dump_req); - - ret = srvpp_send_dumprequest(ctx, if_dump_req, &details, &details_cnt); - assert_int_equal(ret, 0); - - for (size_t i = 0; i < details_cnt; i++) { - if_details = (vl_api_sw_interface_details_t *) details[i]; - printf("interface %s id=%d %s\n", if_details->interface_name, ntohl(if_details->sw_if_index), if_details->admin_up_down ? "up" : "down"); - } - - /* delete a loopback interface */ - del_loop_req = srvpp_alloc_msg(VL_API_DELETE_LOOPBACK, sizeof(*del_loop_req)); - assert_non_null(del_loop_req); - - del_loop_req->sw_if_index = htonl(if_index); - - ret = srvpp_send_request(ctx, del_loop_req, NULL); - assert_int_equal(ret, 0); -} - -int -main() -{ - const struct CMUnitTest tests[] = { - cmocka_unit_test_setup_teardown(srvpp_ctx_test, srvpp_test_setup, srvpp_test_teardown), - cmocka_unit_test_setup_teardown(srvpp_msg_test, srvpp_test_setup, srvpp_test_teardown), - }; - - return cmocka_run_group_tests(tests, NULL, NULL); -} |