summaryrefslogtreecommitdiffstats
path: root/hicn-plugin
diff options
context:
space:
mode:
authorLuca Muscariello <muscariello@ieee.org>2023-01-10 16:48:16 +0000
committerGerrit Code Review <gerrit@fd.io>2023-01-10 16:48:16 +0000
commit8adfb21bf73bdb4c77d04a9c8005bd9008dd52ca (patch)
treef3625410471076ae07e0cfb4c8b5209459609918 /hicn-plugin
parentc31c2eab0ef33df0bf1d46238b7509d1429b110e (diff)
parent55d06ad1cd4f64fc7382bcaf14dc57c1f16db8fe (diff)
Merge "feat: upgrade to VPP 22.10"
Diffstat (limited to 'hicn-plugin')
-rw-r--r--hicn-plugin/CMakeLists.txt4
-rw-r--r--hicn-plugin/includes/vpp_plugins/hicn/error.h158
-rw-r--r--hicn-plugin/libvapi-safe/CMakeLists.txt (renamed from hicn-plugin/vapi/CMakeLists.txt)26
-rw-r--r--hicn-plugin/libvapi-safe/includes/vapi/vapi_safe.h (renamed from hicn-plugin/vapi/includes/vapi/vapi_safe.h)2
-rw-r--r--hicn-plugin/libvapi-safe/libsafevapi-config.cmake.in (renamed from hicn-plugin/vapi/libsafevapi-config.cmake.in)0
-rw-r--r--hicn-plugin/libvapi-safe/src/vapi_safe.cc415
-rw-r--r--hicn-plugin/src/faces/app/face_prod.c17
-rw-r--r--hicn-plugin/src/faces/app/face_prod.h7
-rw-r--r--hicn-plugin/src/faces/face.c17
-rw-r--r--hicn-plugin/src/faces/face_cli.c14
-rw-r--r--hicn-plugin/src/route.c17
-rw-r--r--hicn-plugin/src/strategy_dpo_ctx.c5
-rw-r--r--hicn-plugin/src/strategy_dpo_ctx.h5
-rw-r--r--hicn-plugin/vapi/src/vapi_safe.c98
14 files changed, 582 insertions, 203 deletions
diff --git a/hicn-plugin/CMakeLists.txt b/hicn-plugin/CMakeLists.txt
index 965fa5263..2b2600743 100644
--- a/hicn-plugin/CMakeLists.txt
+++ b/hicn-plugin/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2021-2022 Cisco and/or its affiliates.
+# Copyright (c) 2021-2023 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:
@@ -58,4 +58,4 @@ set (CMAKE_C_STANDARD 11)
##############################################################
add_subdirectory(includes/vpp_plugins/hicn)
add_subdirectory(src)
-add_subdirectory(vapi)
+add_subdirectory(libvapi-safe)
diff --git a/hicn-plugin/includes/vpp_plugins/hicn/error.h b/hicn-plugin/includes/vpp_plugins/hicn/error.h
index be4e53c27..717017564 100644
--- a/hicn-plugin/includes/vpp_plugins/hicn/error.h
+++ b/hicn-plugin/includes/vpp_plugins/hicn/error.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Copyright (c) 2021-2023 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:
@@ -22,81 +22,113 @@
* Error codes for the hICN plugin.
*/
+#define PREFIX(x) HICN_ERROR_##x
+#define NEXT(x) PREFIX (x) - 1
+
#define foreach_hicn_error \
_ (NONE, 0, "Ok") \
_ (UNSPECIFIED, -128, "Unspecified Error") \
- _ (FACE_NOT_FOUND, -1000, "Face not found in Face table") \
- _ (FACE_NULL, -1001, "Face null") \
- _ (FACE_IP_ADJ_NOT_FOUND, -1002, "Ip adjacecny for face not found") \
- _ (FACE_HW_INT_NOT_FOUND, -1003, "Hardware interface not found") \
- _ (FACE_NOMEM, -1004, "Face table is full") \
- _ (FACE_NO_GLOBAL_IP, -1005, "No global ip address for face") \
- _ (FACE_NOT_FOUND_IN_ENTRY, -1006, "Face not found in entry") \
- _ (FACE_ALREADY_DELETED, -1007, "Face alredy deleted") \
- _ (FACE_ALREADY_CREATED, -1008, "Face alredy created") \
- _ (FWD_NOT_ENABLED, -2000, "hICN forwarder not enabled") \
- _ (FWD_ALREADY_ENABLED, -2001, "hICN forwarder alredy enabled") \
- _ (PARSER_UNSUPPORTED_PROTO, -3000, "Unsupported protocol") \
- _ (PARSER_PKT_INVAL, -3001, "Packet null") \
- _ (PARSER_MAPME_PACKET, -3002, "Packet is mapme") \
- _ (PIT_CONFIG_MINLT_OOB, -4000, "Min lifetime ouf of bounds") \
- _ (PIT_CONFIG_MAXLT_OOB, -4001, "Max lifetime ouf of bounds") \
- _ (PIT_CONFIG_MINMAXLT, -4002, "Min lifetime grater than max lifetime") \
- _ (PIT_CONFIG_DFTLT_OOB, -4003, "Default lifetime ouf of bounds") \
- _ (PIT_CONFIG_SIZE_OOB, -4004, "Pit size ouf of bounds") \
- _ (CS_CONFIG_SIZE_OOB, -5000, "CS size ouf of bounds") \
- _ (CS_CONFIG_RESERVED_OOB, -5001, \
+ _ (FACE_NOT_FOUND, NEXT (UNSPECIFIED), "Face not found in Face table") \
+ _ (FACE_NULL, NEXT (FACE_NOT_FOUND), "Face null") \
+ _ (FACE_IP_ADJ_NOT_FOUND, NEXT (FACE_NULL), \
+ "Ip adjacecny for face not found") \
+ _ (FACE_HW_INT_NOT_FOUND, NEXT (FACE_IP_ADJ_NOT_FOUND), \
+ "Hardware interface not found") \
+ _ (FACE_NOMEM, NEXT (FACE_HW_INT_NOT_FOUND), "Face table is full") \
+ _ (FACE_NO_GLOBAL_IP, NEXT (FACE_NOMEM), "No global ip address for face") \
+ _ (FACE_NOT_FOUND_IN_ENTRY, NEXT (FACE_NO_GLOBAL_IP), \
+ "Face not found in entry") \
+ _ (FACE_ALREADY_DELETED, NEXT (FACE_NOT_FOUND_IN_ENTRY), \
+ "Face alredy deleted") \
+ _ (FACE_ALREADY_CREATED, NEXT (FACE_ALREADY_DELETED), \
+ "Face alredy created") \
+ _ (FWD_NOT_ENABLED, NEXT (FACE_ALREADY_CREATED), \
+ "hICN forwarder not enabled") \
+ _ (FWD_ALREADY_ENABLED, NEXT (FWD_NOT_ENABLED), \
+ "hICN forwarder alredy enabled") \
+ _ (PARSER_UNSUPPORTED_PROTO, NEXT (FWD_ALREADY_ENABLED), \
+ "Unsupported protocol") \
+ _ (PARSER_PKT_INVAL, NEXT (PARSER_UNSUPPORTED_PROTO), "Packet null") \
+ _ (PARSER_MAPME_PACKET, NEXT (PARSER_PKT_INVAL), "Packet is mapme") \
+ _ (PIT_CONFIG_MINLT_OOB, NEXT (PARSER_MAPME_PACKET), \
+ "Min lifetime ouf of bounds") \
+ _ (PIT_CONFIG_MAXLT_OOB, NEXT (PIT_CONFIG_MINLT_OOB), \
+ "Max lifetime ouf of bounds") \
+ _ (PIT_CONFIG_MINMAXLT, NEXT (PIT_CONFIG_MAXLT_OOB), \
+ "Min lifetime grater than max lifetime") \
+ _ (PIT_CONFIG_DFTLT_OOB, NEXT (PIT_CONFIG_MINMAXLT), \
+ "Default lifetime ouf of bounds") \
+ _ (PIT_CONFIG_SIZE_OOB, NEXT (PIT_CONFIG_DFTLT_OOB), \
+ "Pit size ouf of bounds") \
+ _ (CS_CONFIG_SIZE_OOB, NEXT (PIT_CONFIG_SIZE_OOB), "CS size ouf of bounds") \
+ _ (CS_CONFIG_RESERVED_OOB, NEXT (CS_CONFIG_SIZE_OOB), \
"Reseved CS must be between 0 and 100 (excluded)") \
- _ (DPO_CTX_NHOPS_NS, -6000, "No space for additional next hop") \
- _ (DPO_CTX_NHOPS_EXISTS, -6001, "Next hop already in the route") \
- _ (DPO_CTX_NOT_FOUND, -6002, "Dpo context not found") \
- _ (DPO_MGR_ID_NOT_VALID, -6003, \
+ _ (DPO_CTX_NHOPS_NS, NEXT (CS_CONFIG_RESERVED_OOB), \
+ "No space for additional next hop") \
+ _ (DPO_CTX_NHOPS_EXISTS, NEXT (DPO_CTX_NHOPS_NS), \
+ "Next hop already in the route") \
+ _ (DPO_CTX_NOT_FOUND, NEXT (DPO_CTX_NHOPS_EXISTS), "Dpo context not found") \
+ _ (DPO_MGR_ID_NOT_VALID, NEXT (DPO_CTX_NOT_FOUND), \
"Dpo id for strategy and context not valid") \
- _ (HASHTB_HASH_NOT_FOUND, -7000, "Hash not found in hash table") \
- _ (HASHTB_HASH_INVAL, -7001, "Error while calculating the hash") \
- _ (HASHTB_NOMEM, -7002, "Unable to allocate new buckets or nodes") \
- _ (HASHTB_INVAL, -7003, "Invalid argument") \
- _ (HASHTB_KEY_INVAL, -7004, "Invalid hashtb key") \
- _ (HASHTB_EXIST, -7005, "Hash already in hashtable") \
- _ (ROUTE_INVAL, -8000, "Invalid face id and weight") \
- _ (ROUTE_NO_LD, -8001, "Expected load balance dpo") \
- _ (ROUTE_MLT_LD, -8002, "Unexpected mulitple buckets in load balance dpo") \
- _ (ROUTE_NO_INSERT, -8003, "Unable to insert a new FIB entry") \
- _ (ROUTE_DPO_NO_HICN, -8004, "Dpo is not of type hICN") \
- _ (ROUTE_NOT_FOUND, -8005, "Route not found in FIB") \
- _ (ROUTE_NOT_UPDATED, -8006, "Unable to update route") \
- _ (ROUTE_ALREADY_EXISTS, -8007, "Route already in FIB") \
- _ (CLI_INVAL, -9000, "Invalid input") \
- _ (IPS_ADDR_TYPE_NONUNIFORM, -10000, \
+ _ (HASHTB_HASH_NOT_FOUND, NEXT (DPO_MGR_ID_NOT_VALID), \
+ "Hash not found in hash table") \
+ _ (HASHTB_HASH_INVAL, NEXT (HASHTB_HASH_NOT_FOUND), \
+ "Error while calculating the hash") \
+ _ (HASHTB_NOMEM, NEXT (HASHTB_HASH_INVAL), \
+ "Unable to allocate new buckets or nodes") \
+ _ (HASHTB_INVAL, NEXT (HASHTB_NOMEM), "Invalid argument") \
+ _ (HASHTB_KEY_INVAL, NEXT (HASHTB_INVAL), "Invalid hashtb key") \
+ _ (HASHTB_EXIST, NEXT (HASHTB_KEY_INVAL), "Hash already in hashtable") \
+ _ (ROUTE_INVAL, NEXT (HASHTB_EXIST), "Invalid face id and weight") \
+ _ (ROUTE_NO_LD, NEXT (ROUTE_INVAL), "Expected load balance dpo") \
+ _ (ROUTE_MLT_LD, NEXT (ROUTE_NO_LD), \
+ "Unexpected mulitple buckets in load balance dpo") \
+ _ (ROUTE_NO_INSERT, NEXT (ROUTE_MLT_LD), \
+ "Unable to insert a new FIB entry") \
+ _ (ROUTE_DPO_NO_HICN, NEXT (ROUTE_NO_INSERT), "Dpo is not of type hICN") \
+ _ (ROUTE_NOT_FOUND, NEXT (ROUTE_DPO_NO_HICN), "Route not found in FIB") \
+ _ (ROUTE_NOT_UPDATED, NEXT (ROUTE_NOT_FOUND), "Unable to update route") \
+ _ (ROUTE_ALREADY_EXISTS, NEXT (ROUTE_NOT_UPDATED), "Route already in FIB") \
+ _ (CLI_INVAL, NEXT (ROUTE_ALREADY_EXISTS), "Invalid input") \
+ _ (IPS_ADDR_TYPE_NONUNIFORM, NEXT (CLI_INVAL), \
"Src and dst addr have different ip types") \
- _ (FACE_TYPE_EXISTS, -11000, "Face type already registered") \
- _ (NO_BUFFERS, -12000, "No vlib_buffer available for packet cloning.") \
- _ (NOT_IMPLEMENTED, -13000, "Function not yet implemented") \
- _ (IFACE_IP_ADJ_NOT_FOUND, -14000, \
+ _ (FACE_TYPE_EXISTS, NEXT (IPS_ADDR_TYPE_NONUNIFORM), \
+ "Face type already registered") \
+ _ (NO_BUFFERS, NEXT (FACE_TYPE_EXISTS), \
+ "No vlib_buffer available for packet cloning.") \
+ _ (NOT_IMPLEMENTED, NEXT (NO_BUFFERS), "Function not yet implemented") \
+ _ (IFACE_IP_ADJ_NOT_FOUND, NEXT (NOT_IMPLEMENTED), \
"IP adjacency on incomplete face not available") \
- _ (APPFACE_ALREADY_ENABLED, -15000, \
+ _ (APPFACE_ALREADY_ENABLED, NEXT (IFACE_IP_ADJ_NOT_FOUND), \
"Application face already enabled on interface") \
- _ (APPFACE_FEATURE, -15001, "Error while enabling app face feature") \
- _ (APPFACE_NOT_FOUND, -15002, "Application face not found") \
- _ (APPFACE_PROD_PREFIX_NULL, -15003, \
+ _ (APPFACE_FEATURE, NEXT (APPFACE_ALREADY_ENABLED), \
+ "Error while enabling app face feature") \
+ _ (APPFACE_NOT_FOUND, NEXT (APPFACE_FEATURE), "Application face not found") \
+ _ (APPFACE_PROD_PREFIX_NULL, NEXT (APPFACE_NOT_FOUND), \
"Prefix must not be null for producer face") \
- _ (STRATEGY_NH_NOT_FOUND, -16000, "Next hop not found") \
- _ (MW_STRATEGY_SET, -16001, "Error while setting weight for next hop") \
- _ (STRATEGY_NOT_FOUND, -16002, "Strategy not found") \
- _ (UDP_TUNNEL_NOT_FOUND, -17000, "Udp tunnel not found") \
- _ (UDP_TUNNEL_SRC_DST_TYPE, -17001, \
+ _ (STRATEGY_NH_NOT_FOUND, NEXT (APPFACE_PROD_PREFIX_NULL), \
+ "Next hop not found") \
+ _ (MW_STRATEGY_SET, NEXT (STRATEGY_NH_NOT_FOUND), \
+ "Error while setting weight for next hop") \
+ _ (STRATEGY_NOT_FOUND, NEXT (MW_STRATEGY_SET), "Strategy not found") \
+ _ (UDP_TUNNEL_NOT_FOUND, NEXT (STRATEGY_NOT_FOUND), "Udp tunnel not found") \
+ _ (UDP_TUNNEL_SRC_DST_TYPE, NEXT (UDP_TUNNEL_NOT_FOUND), \
"Src and dst addresses have different type (ipv4 and ipv6)") \
- _ (MAPME_NEXT_HOP_ADDED, -18000, "Next hop added to mapme") \
- _ (MAPME_NEXT_HOP_NOT_ADDED, -18001, "Next hop added to mapme") \
- _ (PCS_NOT_FOUND, -19000, "Hash not found in hash table") \
- _ (PCS_HASH_INVAL, -19001, "Error while calculating the hash") \
- _ (PCS_INVAL, -19002, "Invalid argument") \
- _ (PCS_KEY_INVAL, -19003, "Invalid hashtb key") \
- _ (PCS_EXIST, -19004, "Hash already in hashtable")
+ _ (MAPME_NEXT_HOP_ADDED, NEXT (UDP_TUNNEL_SRC_DST_TYPE), \
+ "Next hop added to mapme") \
+ _ (MAPME_NEXT_HOP_NOT_ADDED, NEXT (MAPME_NEXT_HOP_ADDED), \
+ "Next hop added to mapme") \
+ _ (PCS_NOT_FOUND, NEXT (MAPME_NEXT_HOP_NOT_ADDED), \
+ "Hash not found in hash table") \
+ _ (PCS_HASH_INVAL, NEXT (PCS_NOT_FOUND), \
+ "Error while calculating the hash") \
+ _ (PCS_INVAL, NEXT (PCS_HASH_INVAL), "Invalid argument") \
+ _ (PCS_KEY_INVAL, NEXT (PCS_INVAL), "Invalid hashtb key") \
+ _ (PCS_EXIST, NEXT (PCS_KEY_INVAL), "Hash already in hashtable")
typedef enum
{
-#define _(a, b, c) HICN_ERROR_##a = (b),
+#define _(a, b, c) PREFIX (a) = (b),
foreach_hicn_error
#undef _
HICN_N_ERROR,
diff --git a/hicn-plugin/vapi/CMakeLists.txt b/hicn-plugin/libvapi-safe/CMakeLists.txt
index 2005cdaf7..ba647aa34 100644
--- a/hicn-plugin/vapi/CMakeLists.txt
+++ b/hicn-plugin/libvapi-safe/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2021-2022 Cisco and/or its affiliates.
+# Copyright (c) 2021-2023 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:
@@ -21,9 +21,17 @@ set(SAFE_VAPI_LIBRARIES ${SAFE_VAPI_SHARED} CACHE INTERNAL "" FORCE)
##############################################################
+# C/CXX Standard
+##############################################################
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_C_STANDARD 11)
+
+
+##############################################################
# Dependencies and third party libs
##############################################################
find_package(Vpp ${VPP_DEFAULT_VERSION} EXACT REQUIRED)
+find_package(Asio ${ASIO_DEFAULT_VERSION} REQUIRED)
##############################################################
@@ -34,7 +42,7 @@ if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
find_package(HicnPlugin ${CURRENT_VERSION} EXACT REQUIRED)
else()
list(APPEND DEPENDENCIES
- ${HICNPLUGIN}
+ ${HICNPLUGIN_SHARED}
)
endif()
@@ -47,7 +55,7 @@ list(APPEND HEADER_FILES
)
list(APPEND SOURCE_FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/src/vapi_safe.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/vapi_safe.cc
)
@@ -82,6 +90,14 @@ list (APPEND INCLUDE_DIRS
##############################################################
+# Compiler definitions
+##############################################################
+list(APPEND COMPILER_DEFINITIONS
+ PUBLIC "-DASIO_STANDALONE"
+)
+
+
+##############################################################
# Build library
##############################################################
build_library(${SAFE_VAPI}
@@ -92,8 +108,8 @@ build_library(${SAFE_VAPI}
COMPONENT ${HICN_PLUGIN}
INCLUDE_DIRS ${INCLUDE_DIRS}
HEADER_ROOT_DIR ""
- DEFINITIONS PUBLIC ${COMPILER_DEFINITIONS}
- DEPENDS ${HICNPLUGIN}.shared
+ DEFINITIONS PRIVATE ${COMPILER_DEFINITIONS}
+ DEPENDS ${DEPENDENCIES}
VERSION ${CURRENT_VERSION}
EXPORT_NAME "libsafevapi"
COMPILE_OPTIONS ${COMPILER_OPTIONS}
diff --git a/hicn-plugin/vapi/includes/vapi/vapi_safe.h b/hicn-plugin/libvapi-safe/includes/vapi/vapi_safe.h
index 423034730..e13e73556 100644
--- a/hicn-plugin/vapi/includes/vapi/vapi_safe.h
+++ b/hicn-plugin/libvapi-safe/includes/vapi/vapi_safe.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Copyright (c) 2021-2023 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:
diff --git a/hicn-plugin/vapi/libsafevapi-config.cmake.in b/hicn-plugin/libvapi-safe/libsafevapi-config.cmake.in
index feb278c1f..feb278c1f 100644
--- a/hicn-plugin/vapi/libsafevapi-config.cmake.in
+++ b/hicn-plugin/libvapi-safe/libsafevapi-config.cmake.in
diff --git a/hicn-plugin/libvapi-safe/src/vapi_safe.cc b/hicn-plugin/libvapi-safe/src/vapi_safe.cc
new file mode 100644
index 000000000..8747ca738
--- /dev/null
+++ b/hicn-plugin/libvapi-safe/src/vapi_safe.cc
@@ -0,0 +1,415 @@
+/*
+ * Copyright (c) 2023 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.
+ */
+
+extern "C"
+{
+#include <stdio.h>
+#include <stdlib.h>
+#include <vapi/vapi_safe.h>
+}
+
+#include <thread>
+#include <random>
+#include <asio.hpp>
+#include <iostream>
+
+namespace
+{
+class NonCopyable
+{
+protected:
+ NonCopyable () = default;
+ ~NonCopyable () = default;
+
+ NonCopyable (const NonCopyable &) = delete;
+ NonCopyable &operator= (const NonCopyable &) = delete;
+};
+
+template <typename T> class Singleton : NonCopyable
+{
+public:
+ static T &
+ getInstance ()
+ {
+ static T instance;
+ return instance;
+ }
+
+protected:
+ Singleton () {}
+ ~Singleton () {}
+};
+
+template <typename T> class ThreadLocalSingleton : NonCopyable
+{
+public:
+ static T &
+ getInstance ()
+ {
+ static thread_local T instance;
+ return instance;
+ }
+
+protected:
+ ThreadLocalSingleton () {}
+ ~ThreadLocalSingleton () {}
+};
+
+class EventThread
+{
+public:
+ EventThread (asio::io_service &io_service, bool detached = false)
+ : internal_io_service_ (nullptr), io_service_ (std::ref (io_service)),
+ work_guard_ (asio::make_work_guard (io_service_.get ())),
+ thread_ (nullptr), detached_ (detached)
+ {
+ run ();
+ }
+
+ explicit EventThread (bool detached = false)
+ : internal_io_service_ (std::make_unique<asio::io_service> ()),
+ io_service_ (std::ref (*internal_io_service_)),
+ work_guard_ (asio::make_work_guard (io_service_.get ())),
+ thread_ (nullptr), detached_ (detached)
+ {
+ run ();
+ }
+
+ EventThread (const EventThread &) = delete;
+ EventThread &operator= (const EventThread &) = delete;
+
+ EventThread (EventThread &&other) noexcept
+ : internal_io_service_ (std::move (other.internal_io_service_)),
+ io_service_ (std::move (other.io_service_)),
+ work_guard_ (std::move (other.work_guard_)),
+ thread_ (std::move (other.thread_)),
+ detached_ (other.detached_)
+ {
+ }
+
+ ~EventThread () { stop (); }
+
+ void
+ run ()
+ {
+ if (stopped ())
+ {
+ io_service_.get ().stopped ();
+ }
+
+ thread_ =
+ std::make_unique<std::thread> ([this] () { io_service_.get ().run (); });
+
+ if (detached_)
+ {
+ thread_->detach ();
+ }
+ }
+
+ std::thread::id
+ getThreadId () const
+ {
+ if (thread_)
+ {
+ return thread_->get_id ();
+ }
+ else
+ {
+ throw std::runtime_error ("Event thread is not running.");
+ }
+ }
+
+ template <typename Func>
+ void
+ add (Func &&f)
+ {
+ io_service_.get ().post (std::forward<Func> (f));
+ }
+
+ template <typename Func>
+ void
+ tryRunHandlerNow (Func &&f)
+ {
+ io_service_.get ().dispatch (std::forward<Func> (f));
+ }
+
+ template <typename Func>
+ void
+ addAndWaitForExecution (Func &&f) const
+ {
+ auto promise = std::promise<void> ();
+ auto future = promise.get_future ();
+
+ asio::dispatch (io_service_.get (),
+ [&promise, f = std::forward<Func> (f)] () {
+ f ();
+ promise.set_value ();
+ });
+
+ future.wait ();
+ }
+
+ void
+ stop ()
+ {
+ add ([this] () { work_guard_.reset (); });
+
+ if (thread_ && thread_->joinable ())
+ {
+ thread_->join ();
+ }
+
+ thread_.reset ();
+ }
+
+ bool
+ stopped () const
+ {
+ return io_service_.get ().stopped ();
+ }
+
+ asio::io_service &
+ getIoService ()
+ {
+ return io_service_;
+ }
+
+private:
+ std::unique_ptr<asio::io_service> internal_io_service_;
+ std::reference_wrapper<asio::io_service> io_service_;
+ asio::executor_work_guard<asio::io_context::executor_type> work_guard_;
+ std::unique_ptr<std::thread> thread_;
+ bool detached_;
+};
+
+class UUID : public Singleton<UUID>
+{
+ friend class Singleton<UUID>;
+ static inline unsigned char hex_chars[16] = { '0', '1', '2', '3', '4', '5',
+ '6', '7', '8', '9', 'a', 'b',
+ 'c', 'd', 'e', 'f' };
+
+public:
+ static inline constexpr unsigned int UUID_LEN = 64;
+
+ ~UUID () = default;
+ std::string
+ generate ()
+ {
+ return generate_hex (UUID_LEN);
+ }
+
+ std::string
+ generate_hex (const unsigned int len)
+ {
+ std::string ret (len, 0);
+
+ for (auto &c : ret)
+ {
+ c = random_char ();
+ }
+
+ return ret;
+ }
+
+private:
+ UUID () : rd_ (), gen_ (rd_ ()), dis_ (0, sizeof (hex_chars) - 1) {}
+
+ unsigned char
+ random_char ()
+ {
+ return hex_chars[dis_ (gen_)];
+ }
+
+private:
+ std::random_device rd_;
+ std::mt19937 gen_;
+ std::uniform_int_distribution<> dis_;
+};
+
+} // namespace
+
+DEFINE_VAPI_MSG_IDS_HICN_API_JSON
+DEFINE_VAPI_MSG_IDS_INTERFACE_API_JSON
+DEFINE_VAPI_MSG_IDS_IP_API_JSON
+DEFINE_VAPI_MSG_IDS_UDP_API_JSON
+DEFINE_VAPI_MSG_IDS_MEMIF_API_JSON
+
+class VapiGlobalConnection : public Singleton<VapiGlobalConnection>
+{
+ friend class Singleton<VapiGlobalConnection>;
+
+ static inline char kapp_name[] = "hicn_app";
+ static inline char kapi_prefix[] = "";
+ static inline int kresponse_queue_size = 32;
+ static inline int kmax_outstanding_requests = 32;
+ static inline uint32_t ktimeout_seconds = 1;
+
+public:
+ vapi_error_e
+ vapiConnectSafe (vapi_ctx_t *vapi_ctx_ret)
+ {
+ if (isConnected ())
+ {
+ *vapi_ctx_ret = vapi_ctx_;
+ return VAPI_OK;
+ }
+
+ std::unique_lock<std::mutex> lock (vapi_mtx_);
+
+ auto rv = vapi_ctx_alloc (&vapi_ctx_);
+ if (rv != VAPI_OK)
+ {
+ return rv;
+ }
+
+ rv = vapi_connect (vapi_ctx_, app_name_.c_str (), nullptr,
+ max_outstanding_requests_, response_queue_size_,
+ VAPI_MODE_BLOCKING, 1);
+ connected_ = true;
+
+ vapi_set_generic_event_cb (vapi_ctx_, &VapiGlobalConnection::genericCb,
+ nullptr);
+
+ if (rv == VAPI_OK)
+ {
+ // startDispatcher ();
+ *vapi_ctx_ret = vapi_ctx_;
+ }
+
+ return rv;
+ }
+
+ void
+ vapiLock ()
+ {
+ vapi_mtx_.lock ();
+ }
+
+ void
+ vapiUnLock ()
+ {
+ vapi_mtx_.unlock ();
+ }
+
+ bool
+ isConnected ()
+ {
+ return connected_;
+ }
+
+ ~VapiGlobalConnection ()
+ {
+ std::cout << "\"adios1" << std::endl;
+ if (!isConnected ())
+ {
+ return;
+ }
+ std::cout << "\"adios" << std::endl;
+ std::unique_lock<std::mutex> lock (vapi_mtx_);
+ vapi_disconnect (vapi_ctx_);
+ vapi_ctx_free (vapi_ctx_);
+ timer_.cancel ();
+ }
+
+private:
+ VapiGlobalConnection (
+ const std::string &app_name = std::string (kapp_name) + "_" +
+ UUID::getInstance ().generate_hex (5),
+ const std::string &api_prefix = kapi_prefix,
+ int max_outstanding_requests = kmax_outstanding_requests,
+ int response_queue_size = kresponse_queue_size)
+ : app_name_ (app_name), api_prefix_ (api_prefix),
+ max_outstanding_requests_ (max_outstanding_requests),
+ response_queue_size_ (response_queue_size), vapi_mtx_ (),
+ vapi_ctx_ (nullptr), connected_ (false), thread_ (),
+ timer_ (thread_.getIoService ())
+ {
+ }
+
+ void
+ timerHandler (const std::error_code &ec)
+ {
+ if (ec)
+ {
+ // Timer was canceled
+ return;
+ }
+
+ if (!isConnected ())
+ {
+ return;
+ }
+
+ std::unique_lock<std::mutex> lock (vapi_mtx_);
+ auto err = vapi_dispatch (vapi_ctx_);
+ if (err != VAPI_OK)
+ {
+ return;
+ }
+
+ startDispatcher ();
+ }
+
+ void
+ startDispatcher ()
+ {
+ timer_.expires_after (std::chrono::seconds (ktimeout_seconds));
+ timer_.async_wait (std::bind (&VapiGlobalConnection::timerHandler, this,
+ std::placeholders::_1));
+ }
+
+ static vapi_error_e
+ genericCb (vapi_ctx_t ctx, void *callback_ctx, vapi_msg_id_t id, void *msg)
+ {
+ std::cout << "Called" << std::endl;
+ return VAPI_OK;
+ }
+
+private:
+ std::string app_name_;
+ std::string api_prefix_;
+ int max_outstanding_requests_;
+ int response_queue_size_;
+ std::mutex vapi_mtx_;
+ vapi_ctx_t vapi_ctx_;
+ std::atomic_bool connected_;
+ EventThread thread_;
+ asio::steady_timer timer_;
+};
+
+vapi_error_e
+vapi_connect_safe (vapi_ctx_t *vapi_ctx_ret, int async)
+{
+ return VapiGlobalConnection::getInstance ().vapiConnectSafe (vapi_ctx_ret);
+}
+
+vapi_error_e
+vapi_disconnect_safe ()
+{
+ return VAPI_OK;
+}
+
+void
+vapi_lock ()
+{
+ VapiGlobalConnection::getInstance ().vapiLock ();
+}
+
+void
+vapi_unlock ()
+{
+ VapiGlobalConnection::getInstance ().vapiUnLock ();
+}
diff --git a/hicn-plugin/src/faces/app/face_prod.c b/hicn-plugin/src/faces/app/face_prod.c
index 73e2a1262..54fbd418a 100644
--- a/hicn-plugin/src/faces/app/face_prod.c
+++ b/hicn-plugin/src/faces/app/face_prod.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021-2022 Cisco and/or its affiliates.
+ * Copyright (c) 2021-2023 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:
@@ -17,6 +17,7 @@
#include <vlib/vlib.h>
#include <vnet/vnet.h>
#include <vnet/interface_funcs.h>
+#include <vppinfra/pool.h>
#include "face_prod.h"
#include "address_mgr.h"
@@ -24,6 +25,7 @@
#include "../../route.h"
#include "../../cache_policies/cs_lru.h"
+#define INITIAL_POOL_SIZE 16
hicn_face_prod_state_t *face_state_vec;
/* used to check if an interface is already in the vector */
@@ -32,9 +34,6 @@ u32 *face_state_pool;
static int
hicn_app_state_create (u32 swif, index_t adj_index, fib_prefix_t *prefix)
{
- /* Make sure that the pool is not empty */
- pool_validate_index (face_state_pool, 0);
-
u32 *swif_app;
u8 found = 0;
@@ -74,9 +73,6 @@ hicn_app_state_create (u32 swif, index_t adj_index, fib_prefix_t *prefix)
static int
hicn_app_state_del (u32 swif)
{
- /* Make sure that the pool is not empty */
- pool_validate_index (face_state_pool, 0);
-
u32 *temp;
u32 *swif_app = NULL;
u8 found = 0;
@@ -357,6 +353,13 @@ format_hicn_face_prod (u8 *s, va_list *args)
return s;
}
+void
+hicn_face_prod_init ()
+{
+ /* Make sure that the pool is not empty */
+ pool_alloc (face_state_pool, INITIAL_POOL_SIZE);
+}
+
VNET_FEATURE_INIT (hicn_prod_app_input_ip6, static) = {
.arc_name = "ip6-unicast",
.node_name = "hicn-face-prod-input",
diff --git a/hicn-plugin/src/faces/app/face_prod.h b/hicn-plugin/src/faces/app/face_prod.h
index 51373d541..46bdf7c24 100644
--- a/hicn-plugin/src/faces/app/face_prod.h
+++ b/hicn-plugin/src/faces/app/face_prod.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Copyright (c) 2021-2023 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:
@@ -96,6 +96,11 @@ int hicn_face_prod_set_lru_max (hicn_face_id_t face_id, u32 *requested_size);
*/
u8 *format_hicn_face_prod (u8 *s, va_list *args);
+/**
+ * @brief Init the producer face module
+ */
+void hicn_face_prod_init ();
+
#endif /* _FACE_PROD_H_ */
/*
diff --git a/hicn-plugin/src/faces/face.c b/hicn-plugin/src/faces/face.c
index 58c1c34c8..84fd5e6ee 100644
--- a/hicn-plugin/src/faces/face.c
+++ b/hicn-plugin/src/faces/face.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Copyright (c) 2021-2023 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:
@@ -15,6 +15,7 @@
#include <vnet/fib/fib_entry_track.h>
#include "face.h"
+#include "app/face_prod.h"
#include "../hicn.h"
#include "../params.h"
#include "../error.h"
@@ -60,14 +61,14 @@ face_show (u8 *s, int face_id, u32 indent)
mhash_t hicn_face_hashtb;
const static char *const hicn_face6_nodes[] = {
- "hicn6-face-output", // this is the name you give your node in
- // VLIB_REGISTER_NODE
+ "hicn6-face-output", // this is the name you give your node in
+ // VLIB_REGISTER_NODE
NULL,
};
const static char *const hicn_face4_nodes[] = {
- "hicn4-face-output", // this is the name you give your node in
- // VLIB_REGISTER_NODE
+ "hicn4-face-output", // this is the name you give your node in
+ // VLIB_REGISTER_NODE
NULL,
};
@@ -151,7 +152,6 @@ static const fib_node_vft_t hicn_face_fib_node_vft = {
void
hicn_face_module_init (vlib_main_t *vm)
{
- pool_validate (hicn_dpoi_face_pool);
pool_alloc (hicn_dpoi_face_pool, 1024);
counters = vec_new (vlib_combined_counter_main_t,
HICN_PARAM_FACES_MAX * HICN_N_COUNTER);
@@ -171,6 +171,11 @@ hicn_face_module_init (vlib_main_t *vm)
*/
hicn_face_fib_node_type =
fib_node_register_new_type ("hicn_face_fib_node", &hicn_face_fib_node_vft);
+
+ /*
+ * Init producer face module
+ */
+ hicn_face_prod_init ();
}
u8 *
diff --git a/hicn-plugin/src/faces/face_cli.c b/hicn-plugin/src/faces/face_cli.c
index 20acefc5b..1c1501478 100644
--- a/hicn-plugin/src/faces/face_cli.c
+++ b/hicn-plugin/src/faces/face_cli.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Copyright (c) 2021-2023 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:
@@ -82,12 +82,12 @@ hicn_face_cli_show_command_fn (vlib_main_t *vm, unformat_input_t *main_input,
HICN_FACE_CTRX_STRING[i]);
if (n)
- _vec_len (n) = 0;
+ vec_set_len (n, 0);
n = format (n, "packets");
s = format (s, "%U%-16v%16Ld", format_white_space,
30 - strlen (HICN_FACE_CTRX_STRING[i]), n, v.packets);
- _vec_len (n) = 0;
+ vec_set_len (n, 0);
n = format (n, "bytes");
s = format (s, "\n%U%-16v%16Ld\n", format_white_space, indent + 30,
n, v.bytes);
@@ -120,13 +120,13 @@ hicn_face_cli_show_command_fn (vlib_main_t *vm, unformat_input_t *main_input,
HICN_FACE_CTRX_STRING[i]);
if (n)
- _vec_len (n) = 0;
+ vec_set_len (n, 0);
n = format (n, "packets");
s = format (s, "%U%-16v%16Ld", format_white_space,
30 - strlen (HICN_FACE_CTRX_STRING[i]),
n, v.packets);
- _vec_len (n) = 0;
+ vec_set_len (n, 0);
n = format (n, "bytes");
s =
format (s, "\n%U%-16v%16Ld\n", format_white_space,
@@ -158,13 +158,13 @@ hicn_face_cli_show_command_fn (vlib_main_t *vm, unformat_input_t *main_input,
HICN_FACE_CTRX_STRING[i]);
if (n)
- _vec_len (n) = 0;
+ vec_set_len (n, 0);
n = format (n, "packets");
s = format (s, "%U%-16v%16Ld", format_white_space,
30 - strlen (HICN_FACE_CTRX_STRING[i]), n,
v.packets);
- _vec_len (n) = 0;
+ vec_set_len (n, 0);
n = format (n, "bytes");
s = format (s, "\n%U%-16v%16Ld\n", format_white_space,
indent + 30, n, v.bytes);
diff --git a/hicn-plugin/src/route.c b/hicn-plugin/src/route.c
index 0c96e1412..a2e72b9c1 100644
--- a/hicn-plugin/src/route.c
+++ b/hicn-plugin/src/route.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Copyright (c) 2021-2023 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:
@@ -273,7 +273,7 @@ sync_hicn_fib_entry (hicn_dpo_ctx_t *fib_entry, hicn_face_id_t **pvec_faces)
fib_entry->proto);
ADD_FACE (nh);
HICN_DEBUG ("Added new HICN face: %d because of route prefix %U",
- face_id, format_ip_prefix, &_fib_entry->fe_prefix);
+ face_id, format_fib_prefix, &_fib_entry->fe_prefix);
}
else if (dpo->dpoi_type == dpo_type_udp_ip4 ||
dpo->dpoi_type == dpo_type_udp_ip6)
@@ -405,11 +405,10 @@ hicn_route_enable (fib_prefix_t *prefix, hicn_face_id_t **pvec_faces)
{
HICN_DEBUG (
"No route found for %U. Creating DPO and tracking fib prefix.",
- format_ip_prefix, prefix);
+ format_fib_prefix, prefix);
dpo_id_t dpo = DPO_INVALID;
- index_t dpo_idx;
- default_dpo.hicn_dpo_create (prefix->fp_proto, 0, NEXT_HOP_INVALID,
- &dpo_idx);
+ index_t dpo_idx = ~0;
+ default_dpo.hicn_dpo_create (prefix->fp_proto, 0, 0, &dpo_idx);
HICN_DEBUG ("Created new DPO_MW_CTX_T: %d.", dpo_idx);
/* the value we got when we registered */
@@ -534,8 +533,8 @@ hicn_route_disable (fib_prefix_t *prefix)
if (fib_hicn_entry_index == FIB_NODE_INDEX_INVALID)
{
- HICN_ERROR ("Route %U not found", format_ip_prefix, prefix);
- return HICN_ERROR_ROUTE_NOT_FOUND;
+ HICN_ERROR ("Route %U not found", format_fib_prefix, prefix);
+ ret = HICN_ERROR_ROUTE_NOT_FOUND;
}
else
{
@@ -605,7 +604,7 @@ hicn_route_disable (fib_prefix_t *prefix)
HICN_DEBUG (
"Calling fib_entry_untrack and fib_table_entry_special_remove "
"for route %U.",
- format_ip_prefix, prefix);
+ format_fib_prefix, prefix);
fib_entry_untrack (hicn_fib_entry->fib_entry_index,
hicn_fib_entry->fib_sibling);
diff --git a/hicn-plugin/src/strategy_dpo_ctx.c b/hicn-plugin/src/strategy_dpo_ctx.c
index 2279ecc75..d43b7315b 100644
--- a/hicn-plugin/src/strategy_dpo_ctx.c
+++ b/hicn-plugin/src/strategy_dpo_ctx.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Copyright (c) 2021-2023 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:
@@ -21,7 +21,8 @@ hicn_dpo_ctx_t *hicn_strategy_dpo_ctx_pool;
void
hicn_strategy_init_dpo_ctx_pool ()
{
- // pool_init_fixed (hicn_strategy_dpo_ctx_pool, 256);
+ pool_alloc_aligned (hicn_strategy_dpo_ctx_pool, 256,
+ 2 * CLIB_CACHE_LINE_BYTES);
}
void
diff --git a/hicn-plugin/src/strategy_dpo_ctx.h b/hicn-plugin/src/strategy_dpo_ctx.h
index cb8ca4051..ae642a350 100644
--- a/hicn-plugin/src/strategy_dpo_ctx.h
+++ b/hicn-plugin/src/strategy_dpo_ctx.h
@@ -99,6 +99,7 @@ init_dpo_ctx (hicn_dpo_ctx_t *dpo_ctx, const hicn_face_id_t *next_hop,
int nh_len, dpo_type_t dpo_type, dpo_proto_t proto)
{
hicn_face_id_t invalid = NEXT_HOP_INVALID;
+ int i = 0;
dpo_ctx->entry_count = 0;
dpo_ctx->locks = 0;
@@ -110,13 +111,13 @@ init_dpo_ctx (hicn_dpo_ctx_t *dpo_ctx, const hicn_face_id_t *next_hop,
dpo_ctx->proto = (fib_protocol_t) proto;
- for (int i = 0; i < HICN_PARAM_FIB_ENTRY_NHOPS_MAX && i < nh_len; i++)
+ for (i = 0; i < HICN_PARAM_FIB_ENTRY_NHOPS_MAX && i < nh_len; i++)
{
dpo_ctx->next_hops[i] = next_hop[i];
dpo_ctx->entry_count++;
}
- for (int i = nh_len; i < HICN_PARAM_FIB_ENTRY_NHOPS_MAX; i++)
+ for (; i < HICN_PARAM_FIB_ENTRY_NHOPS_MAX; i++)
{
dpo_ctx->next_hops[i] = invalid;
}
diff --git a/hicn-plugin/vapi/src/vapi_safe.c b/hicn-plugin/vapi/src/vapi_safe.c
deleted file mode 100644
index a91793674..000000000
--- a/hicn-plugin/vapi/src/vapi_safe.c
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (c) 2021 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 <vapi/vapi_safe.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#define APP_NAME "hicn_plugin"
-#define MAX_OUTSTANDING_REQUESTS 4
-#define RESPONSE_QUEUE_SIZE 2
-
-DEFINE_VAPI_MSG_IDS_HICN_API_JSON
-DEFINE_VAPI_MSG_IDS_INTERFACE_API_JSON
-DEFINE_VAPI_MSG_IDS_IP_API_JSON
-DEFINE_VAPI_MSG_IDS_UDP_API_JSON
-DEFINE_VAPI_MSG_IDS_MEMIF_API_JSON
-
-pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
-vapi_ctx_t g_vapi_ctx_instance = NULL;
-u32 count = 0;
-
-vapi_error_e
-vapi_connect_safe (vapi_ctx_t *vapi_ctx_ret, int async)
-{
- vapi_error_e rv = VAPI_OK;
-
- vapi_lock ();
-
- if (!g_vapi_ctx_instance)
- {
- rv = vapi_ctx_alloc (&g_vapi_ctx_instance);
- if (rv != VAPI_OK)
- goto err;
- }
-
- if (!count)
- {
- rv = vapi_connect (g_vapi_ctx_instance, APP_NAME, NULL,
- MAX_OUTSTANDING_REQUESTS, RESPONSE_QUEUE_SIZE,
- async ? VAPI_MODE_NONBLOCKING : VAPI_MODE_BLOCKING,
- true);
-
- if (rv != VAPI_OK)
- goto err;
- }
-
- count++;
- *vapi_ctx_ret = g_vapi_ctx_instance;
-
- vapi_unlock ();
- return rv;
-
-err:
- vapi_unlock ();
- return VAPI_ENOMEM;
-}
-
-vapi_error_e
-vapi_disconnect_safe ()
-{
- vapi_error_e rv = VAPI_OK;
-
- vapi_lock ();
- count--;
- if (count == 0)
- {
- rv = vapi_disconnect (g_vapi_ctx_instance);
- vapi_ctx_free (g_vapi_ctx_instance);
- g_vapi_ctx_instance = NULL;
- }
- vapi_unlock ();
-
- return rv;
-}
-
-void
-vapi_lock ()
-{
- pthread_mutex_lock (&mutex);
-}
-
-void
-vapi_unlock ()
-{
- pthread_mutex_unlock (&mutex);
-}