aboutsummaryrefslogtreecommitdiffstats
path: root/libtransport/src/io_modules/memif
diff options
context:
space:
mode:
Diffstat (limited to 'libtransport/src/io_modules/memif')
-rw-r--r--libtransport/src/io_modules/memif/CMakeLists.txt38
-rw-r--r--libtransport/src/io_modules/memif/hicn_vapi.c49
-rw-r--r--libtransport/src/io_modules/memif/hicn_vapi.h14
-rw-r--r--libtransport/src/io_modules/memif/memif_connector.cc492
-rw-r--r--libtransport/src/io_modules/memif/memif_connector.h130
-rw-r--r--libtransport/src/io_modules/memif/memif_vapi.c7
-rw-r--r--libtransport/src/io_modules/memif/memif_vapi.h6
-rw-r--r--libtransport/src/io_modules/memif/vpp_forwarder_module.cc50
-rw-r--r--libtransport/src/io_modules/memif/vpp_forwarder_module.h13
9 files changed, 99 insertions, 700 deletions
diff --git a/libtransport/src/io_modules/memif/CMakeLists.txt b/libtransport/src/io_modules/memif/CMakeLists.txt
index fc1c1f135..134ac1db6 100644
--- a/libtransport/src/io_modules/memif/CMakeLists.txt
+++ b/libtransport/src/io_modules/memif/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2021 Cisco and/or its affiliates.
+# Copyright (c) 2021-2022 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:
@@ -11,18 +11,28 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-find_package(Vpp REQUIRED)
-find_package(Libmemif REQUIRED)
+
+##############################################################
+# Dependencies and third party libs
+##############################################################
+find_package(Vpp ${VPP_DEFAULT_VERSION} EXACT REQUIRED)
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
- find_package(HicnPlugin REQUIRED)
- find_package(SafeVapi REQUIRED)
+ find_package(HicnPlugin ${CURRENT_VERSION} REQUIRED)
+ find_package(SafeVapi ${CURRENT_VERSION} REQUIRED)
else()
list(APPEND DEPENDENCIES
${SAFE_VAPI_SHARED}
)
endif()
+list(APPEND DEPENDENCIES
+ ${MEMIF_THIRD_PARTY_DEPENDENCIES}
+)
+
+##############################################################
+# Sources
+##############################################################
list(APPEND MODULE_HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/hicn_vapi.h
${CMAKE_CURRENT_SOURCE_DIR}/memif_connector.h
@@ -32,23 +42,23 @@ list(APPEND MODULE_HEADER_FILES
list(APPEND MODULE_SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/hicn_vapi.c
- ${CMAKE_CURRENT_SOURCE_DIR}/memif_connector.cc
${CMAKE_CURRENT_SOURCE_DIR}/memif_vapi.c
${CMAKE_CURRENT_SOURCE_DIR}/vpp_forwarder_module.cc
)
build_module(memif_module
- SHARED
SOURCES ${MODULE_SOURCE_FILES}
DEPENDS ${DEPENDENCIES}
COMPONENT ${LIBTRANSPORT_COMPONENT}-io-modules
- LINK_LIBRARIES ${LIBMEMIF_LIBRARIES} ${SAFE_VAPI_LIBRARIES}
+ OBJECT_LIBRARIES ${MEMIF_THIRD_PARTY_OBJECT_LIBRARIES}
+ LINK_LIBRARIES PRIVATE ${HICN_LIBRARIES} ${SAFE_VAPI_LIBRARIES}
INCLUDE_DIRS
- ${LIBTRANSPORT_INCLUDE_DIRS}
- ${LIBTRANSPORT_INTERNAL_INCLUDE_DIRS}
- ${VPP_INCLUDE_DIRS}
- ${LIBMEMIF_INCLUDE_DIRS}
- ${SAFE_VAPI_INCLUDE_DIRS}
+ PUBLIC
+ ${MEMIF_THIRD_PARTY_INCLUDE_DIRS}
+ ${LIBTRANSPORT_INTERNAL_INCLUDE_DIRS}
+ ${VPP_INCLUDE_DIRS}
+ ${LIBMEMIF_INCLUDE_DIRS}
+ ${SAFE_VAPI_INCLUDE_DIRS}
DEFINITIONS ${COMPILER_DEFINITIONS}
- COMPILE_OPTIONS ${COMPILE_FLAGS}
+ COMPILE_OPTIONS ${COMPILER_OPTIONS} ${MARCH_COMPILER_OPTIONS}
)
diff --git a/libtransport/src/io_modules/memif/hicn_vapi.c b/libtransport/src/io_modules/memif/hicn_vapi.c
index 6d78026ab..9fc64f720 100644
--- a/libtransport/src/io_modules/memif/hicn_vapi.c
+++ b/libtransport/src/io_modules/memif/hicn_vapi.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
@@ -27,8 +27,6 @@
#include <vlibapi/api.h>
#include <vlibmemory/api.h>
#include <vnet/ip/format.h>
-#include <vnet/ip/ip4_packet.h>
-#include <vnet/ip/ip6_packet.h>
#include <vpp_plugins/hicn/error.h>
#include <vppinfra/error.h>
@@ -46,9 +44,6 @@ u8 *format_vl_api_address_union(u8 *s, va_list *args) { return NULL; }
/*********************************************************************************/
-DEFINE_VAPI_MSG_IDS_HICN_API_JSON
-DEFINE_VAPI_MSG_IDS_IP_API_JSON
-
static vapi_error_e register_prod_app_cb(
vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last,
vapi_payload_hicn_api_register_prod_app_reply *reply) {
@@ -58,14 +53,15 @@ static vapi_error_e register_prod_app_cb(
if (reply == NULL) return rv;
output_params->cs_reserved = reply->cs_reserved;
- output_params->prod_addr = (ip_address_t *)malloc(sizeof(ip_address_t));
- memset(output_params->prod_addr, 0, sizeof(ip_address_t));
+ output_params->prod_addr =
+ (hicn_ip_address_t *)malloc(sizeof(hicn_ip_address_t));
+ memset(output_params->prod_addr, 0, sizeof(hicn_ip_address_t));
if (reply->prod_addr.af == ADDRESS_IP6)
memcpy(&output_params->prod_addr->v6, reply->prod_addr.un.ip6,
- sizeof(ip6_address_t));
+ sizeof(ipv6_address_t));
else
memcpy(&output_params->prod_addr->v4, reply->prod_addr.un.ip4,
- sizeof(ip4_address_t));
+ sizeof(ipv4_address_t));
output_params->face_id = reply->faceid;
return reply->retval;
@@ -78,13 +74,14 @@ int hicn_vapi_register_prod_app(vapi_ctx_t ctx,
vapi_msg_hicn_api_register_prod_app *msg =
vapi_alloc_hicn_api_register_prod_app(ctx);
- if (ip46_address_is_ip4((ip46_address_t *)&input_params->prefix->address)) {
+ if (hicn_ip_address_is_v4(
+ (hicn_ip_address_t *)&input_params->prefix->address)) {
memcpy(&msg->payload.prefix.address.un.ip4, &input_params->prefix->address,
- sizeof(ip4_address_t));
+ sizeof(ipv4_address_t));
msg->payload.prefix.address.af = ADDRESS_IP4;
} else {
memcpy(&msg->payload.prefix.address.un.ip6, &input_params->prefix->address,
- sizeof(ip6_address_t));
+ sizeof(ipv6_address_t));
msg->payload.prefix.address.af = ADDRESS_IP6;
}
msg->payload.prefix.len = input_params->prefix->len;
@@ -126,14 +123,14 @@ static vapi_error_e register_cons_app_cb(
if (reply == NULL) return rv;
- output_params->src6 = (ip_address_t *)malloc(sizeof(ip_address_t));
- output_params->src4 = (ip_address_t *)malloc(sizeof(ip_address_t));
- memset(output_params->src6, 0, sizeof(ip_address_t));
- memset(output_params->src4, 0, sizeof(ip_address_t));
+ output_params->src6 = (hicn_ip_address_t *)malloc(sizeof(hicn_ip_address_t));
+ output_params->src4 = (hicn_ip_address_t *)malloc(sizeof(hicn_ip_address_t));
+ memset(output_params->src6, 0, sizeof(hicn_ip_address_t));
+ memset(output_params->src4, 0, sizeof(hicn_ip_address_t));
memcpy(&output_params->src6->v6, &reply->src_addr6.un.ip6,
- sizeof(ip6_address_t));
+ sizeof(ipv6_address_t));
memcpy(&output_params->src4->v4, &reply->src_addr4.un.ip4,
- sizeof(ip4_address_t));
+ sizeof(ipv4_address_t));
output_params->face_id1 = reply->faceid1;
output_params->face_id2 = reply->faceid2;
@@ -190,31 +187,31 @@ int hicn_vapi_register_route(vapi_ctx_t ctx,
vapi_msg_ip_route_add_del *msg = vapi_alloc_ip_route_add_del(ctx, 1);
msg->payload.is_add = 1;
- if (ip46_address_is_ip4((ip46_address_t *)(input_params->prod_addr))) {
+ if (hicn_ip_address_is_v4((hicn_ip_address_t *)(input_params->prod_addr))) {
memcpy(&msg->payload.route.prefix.address.un.ip4,
- &input_params->prefix->address.v4, sizeof(ip4_address_t));
+ &input_params->prefix->address.v4, sizeof(ipv4_address_t));
msg->payload.route.prefix.address.af = ADDRESS_IP4;
msg->payload.route.prefix.len = input_params->prefix->len;
} else {
memcpy(&msg->payload.route.prefix.address.un.ip6,
- &input_params->prefix->address.v6, sizeof(ip6_address_t));
+ &input_params->prefix->address.v6, sizeof(ipv6_address_t));
msg->payload.route.prefix.address.af = ADDRESS_IP6;
msg->payload.route.prefix.len = input_params->prefix->len;
}
msg->payload.route.paths[0].sw_if_index = ~0;
msg->payload.route.paths[0].table_id = 0;
- if (ip46_address_is_ip4((ip46_address_t *)(input_params->prod_addr))) {
+ if (hicn_ip_address_is_v4((hicn_ip_address_t *)(input_params->prod_addr))) {
memcpy(&(msg->payload.route.paths[0].nh.address.ip4),
- input_params->prod_addr->v4.as_u8, sizeof(ip4_address_t));
+ input_params->prod_addr->v4.as_u8, sizeof(ipv4_address_t));
msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP4;
} else {
memcpy(&(msg->payload.route.paths[0].nh.address.ip6),
- input_params->prod_addr->v6.as_u8, sizeof(ip6_address_t));
+ input_params->prod_addr->v6.as_u8, sizeof(ipv6_address_t));
msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP6;
}
- msg->payload.route.paths[0].type = FIB_API_PATH_FLAG_NONE;
+ msg->payload.route.paths[0].type = FIB_API_PATH_TYPE_NORMAL;
msg->payload.route.paths[0].flags = FIB_API_PATH_FLAG_NONE;
int ret = vapi_ip_route_add_del(ctx, msg, reigster_route_cb, NULL);
diff --git a/libtransport/src/io_modules/memif/hicn_vapi.h b/libtransport/src/io_modules/memif/hicn_vapi.h
index e94c97749..cfdc93fe3 100644
--- a/libtransport/src/io_modules/memif/hicn_vapi.h
+++ b/libtransport/src/io_modules/memif/hicn_vapi.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2020 Cisco and/or its affiliates.
+ * 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:
@@ -27,7 +27,7 @@ extern "C" {
#include "stdint.h"
typedef struct {
- ip_prefix_t* prefix;
+ hicn_ip_prefix_t* prefix;
uint32_t swif;
uint32_t cs_reserved;
} hicn_producer_input_params;
@@ -42,20 +42,20 @@ typedef struct {
typedef struct {
uint32_t cs_reserved;
- ip_address_t* prod_addr;
+ hicn_ip_address_t* prod_addr;
uint32_t face_id;
} hicn_producer_output_params;
typedef struct {
- ip_address_t* src4;
- ip_address_t* src6;
+ hicn_ip_address_t* src4;
+ hicn_ip_address_t* src6;
uint32_t face_id1;
uint32_t face_id2;
} hicn_consumer_output_params;
typedef struct {
- ip_prefix_t* prefix;
- ip_address_t* prod_addr;
+ hicn_ip_prefix_t* prefix;
+ hicn_ip_address_t* prod_addr;
} hicn_producer_set_route_params;
int hicn_vapi_register_prod_app(vapi_ctx_t ctx,
diff --git a/libtransport/src/io_modules/memif/memif_connector.cc b/libtransport/src/io_modules/memif/memif_connector.cc
deleted file mode 100644
index 68ad52b63..000000000
--- a/libtransport/src/io_modules/memif/memif_connector.cc
+++ /dev/null
@@ -1,492 +0,0 @@
-/*
- * Copyright (c) 2017-2019 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 <glog/logging.h>
-#include <hicn/transport/errors/not_implemented_exception.h>
-#include <io_modules/memif/memif_connector.h>
-#include <sys/epoll.h>
-
-#include <cstdlib>
-
-extern "C" {
-#include <memif/libmemif.h>
-};
-
-#define CANCEL_TIMER 1
-
-namespace transport {
-
-namespace core {
-
-struct memif_connection {
- uint16_t index;
- /* memif conenction handle */
- memif_conn_handle_t conn;
- /* transmit queue id */
- uint16_t tx_qid;
- /* tx buffers */
- memif_buffer_t *tx_bufs;
- /* allocated tx buffers counter */
- /* number of tx buffers pointing to shared memory */
- uint16_t tx_buf_num;
- /* rx buffers */
- memif_buffer_t *rx_bufs;
- /* allcoated rx buffers counter */
- /* number of rx buffers pointing to shared memory */
- uint16_t rx_buf_num;
- /* interface ip address */
- uint8_t ip_addr[4];
-};
-
-std::once_flag MemifConnector::flag_;
-utils::EpollEventReactor MemifConnector::main_event_reactor_;
-
-MemifConnector::MemifConnector(PacketReceivedCallback &&receive_callback,
- PacketSentCallback &&packet_sent,
- OnCloseCallback &&close_callback,
- OnReconnectCallback &&on_reconnect,
- asio::io_service &io_service,
- std::string app_name)
- : Connector(std::move(receive_callback), std::move(packet_sent),
- std::move(close_callback), std::move(on_reconnect)),
- memif_worker_(nullptr),
- timer_set_(false),
- send_timer_(std::make_unique<utils::FdDeadlineTimer>(event_reactor_)),
- disconnect_timer_(
- std::make_unique<utils::FdDeadlineTimer>(event_reactor_)),
- io_service_(io_service),
- work_(asio::make_work_guard(io_service_)),
- memif_connection_(std::make_unique<memif_connection_t>()),
- tx_buf_counter_(0),
- is_reconnection_(false),
- data_available_(false),
- app_name_(app_name),
- socket_filename_("") {
- std::call_once(MemifConnector::flag_, &MemifConnector::init, this);
-}
-
-MemifConnector::~MemifConnector() { close(); }
-
-void MemifConnector::init() {
- /* initialize memory interface */
- int err = memif_init(controlFdUpdate, const_cast<char *>(app_name_.c_str()),
- nullptr, nullptr, nullptr);
-
- if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
- LOG(ERROR) << "memif_init: " << memif_strerror(err);
- }
-}
-
-void MemifConnector::connect(uint32_t memif_id, long memif_mode) {
- state_ = State::CONNECTING;
-
- memif_id_ = memif_id;
- socket_filename_ = "/run/vpp/memif.sock";
-
- createMemif(memif_id, memif_mode, nullptr);
-
- while (state_ != State::CONNECTED) {
- MemifConnector::main_event_reactor_.runOneEvent();
- }
-
- int err;
-
- /* get interrupt queue id */
- int fd = -1;
- err = memif_get_queue_efd(memif_connection_->conn, 0, &fd);
- if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
- LOG(ERROR) << "memif_get_queue_efd: " << memif_strerror(err);
- return;
- }
-
- // Remove fd from main epoll
- main_event_reactor_.delFileDescriptor(fd);
-
- // Add fd to epoll of instance
- event_reactor_.addFileDescriptor(
- fd, EPOLLIN, [this](const utils::Event &evt) -> int {
- return onInterrupt(memif_connection_->conn, this, 0);
- });
-
- memif_worker_ = std::make_unique<std::thread>(
- std::bind(&MemifConnector::threadMain, this));
-}
-
-int MemifConnector::createMemif(uint32_t index, uint8_t mode, char *s) {
- memif_connection_t *c = memif_connection_.get();
-
- /* setting memif connection arguments */
- memif_conn_args_t args;
- memset(&args, 0, sizeof(args));
-
- args.is_master = mode;
- args.log2_ring_size = MEMIF_LOG2_RING_SIZE;
- args.buffer_size = MEMIF_BUF_SIZE;
- args.num_s2m_rings = 1;
- args.num_m2s_rings = 1;
- strncpy((char *)args.interface_name, IF_NAME, strlen(IF_NAME) + 1);
- args.mode = memif_interface_mode_t::MEMIF_INTERFACE_MODE_IP;
-
- int err;
-
- err = memif_create_socket(&args.socket, socket_filename_.c_str(), nullptr);
-
- if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
- throw errors::RuntimeException(memif_strerror(err));
- }
-
- args.interface_id = index;
- /* last argument for memif_create (void * private_ctx) is used by user
- to identify connection. this context is returned with callbacks */
-
- /* default interrupt */
- if (s == nullptr) {
- err = memif_create(&c->conn, &args, onConnect, onDisconnect, onInterrupt,
- this);
-
- if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
- throw errors::RuntimeException(memif_strerror(err));
- }
- }
-
- c->index = (uint16_t)index;
- c->tx_qid = 0;
- /* alloc memif buffers */
- c->rx_buf_num = 0;
- c->rx_bufs = static_cast<memif_buffer_t *>(
- malloc(sizeof(memif_buffer_t) * MAX_MEMIF_BUFS));
- c->tx_buf_num = 0;
- c->tx_bufs = static_cast<memif_buffer_t *>(
- malloc(sizeof(memif_buffer_t) * MAX_MEMIF_BUFS));
-
- // memif_set_rx_mode (c->conn, MEMIF_RX_MODE_POLLING, 0);
-
- return 0;
-}
-
-int MemifConnector::deleteMemif() {
- memif_connection_t *c = memif_connection_.get();
-
- if (c->rx_bufs) {
- free(c->rx_bufs);
- }
-
- c->rx_bufs = nullptr;
- c->rx_buf_num = 0;
-
- if (c->tx_bufs) {
- free(c->tx_bufs);
- }
-
- c->tx_bufs = nullptr;
- c->tx_buf_num = 0;
-
- int err;
- /* disconenct then delete memif connection */
- err = memif_delete(&c->conn);
-
- if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
- LOG(ERROR) << "memif_delete: " << memif_strerror(err);
- }
-
- if (TRANSPORT_EXPECT_FALSE(c->conn != nullptr)) {
- LOG(ERROR) << "memif delete fail";
- }
-
- return 0;
-}
-
-int MemifConnector::controlFdUpdate(int fd, uint8_t events, void *private_ctx) {
- /* convert memif event definitions to epoll events */
- if (events & MEMIF_FD_EVENT_DEL) {
- return MemifConnector::main_event_reactor_.delFileDescriptor(fd);
- }
-
- uint32_t evt = 0;
-
- if (events & MEMIF_FD_EVENT_READ) {
- evt |= EPOLLIN;
- }
-
- if (events & MEMIF_FD_EVENT_WRITE) {
- evt |= EPOLLOUT;
- }
-
- if (events & MEMIF_FD_EVENT_MOD) {
- return MemifConnector::main_event_reactor_.modFileDescriptor(fd, evt);
- }
-
- return MemifConnector::main_event_reactor_.addFileDescriptor(
- fd, evt, [](const utils::Event &evt) -> int {
- uint32_t event = 0;
- int memif_err = 0;
-
- if (evt.events & EPOLLIN) {
- event |= MEMIF_FD_EVENT_READ;
- }
-
- if (evt.events & EPOLLOUT) {
- event |= MEMIF_FD_EVENT_WRITE;
- }
-
- if (evt.events & EPOLLERR) {
- event |= MEMIF_FD_EVENT_ERROR;
- }
-
- memif_err = memif_control_fd_handler(evt.data.fd, event);
-
- if (TRANSPORT_EXPECT_FALSE(memif_err != MEMIF_ERR_SUCCESS)) {
- LOG(ERROR) << "memif_control_fd_handler: "
- << memif_strerror(memif_err);
- }
-
- return 0;
- });
-}
-
-int MemifConnector::bufferAlloc(long n, uint16_t qid) {
- memif_connection_t *c = memif_connection_.get();
- int err;
- uint16_t r;
- /* set data pointer to shared memory and set buffer_len to shared mmeory
- * buffer len */
- err = memif_buffer_alloc(c->conn, qid, c->tx_bufs, n, &r, 2000);
-
- if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
- LOG(ERROR) << "memif_buffer_alloc: " << memif_strerror(err);
- return -1;
- }
-
- c->tx_buf_num += r;
- return r;
-}
-
-int MemifConnector::txBurst(uint16_t qid) {
- memif_connection_t *c = memif_connection_.get();
- int err;
- uint16_t r;
- /* inform peer memif interface about data in shared memory buffers */
- /* mark memif buffers as free */
- err = memif_tx_burst(c->conn, qid, c->tx_bufs, c->tx_buf_num, &r);
-
- if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
- LOG(ERROR) << "memif_tx_burst: " << memif_strerror(err);
- }
-
- // err = memif_refill_queue(c->conn, qid, r, 0);
-
- if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
- LOG(ERROR) << "memif_tx_burst: " << memif_strerror(err);
- c->tx_buf_num -= r;
- return -1;
- }
-
- c->tx_buf_num -= r;
- return 0;
-}
-
-void MemifConnector::sendCallback(const std::error_code &ec) {
- timer_set_ = false;
-
- if (TRANSPORT_EXPECT_TRUE(!ec && state_ == State::CONNECTED)) {
- doSend();
- }
-}
-
-void MemifConnector::processInputBuffer(std::uint16_t total_packets) {
- utils::MemBuf::Ptr ptr;
-
- for (; total_packets > 0; total_packets--) {
- if (input_buffer_.pop(ptr)) {
- receive_callback_(this, *ptr, std::make_error_code(std::errc(0)));
- }
- }
-}
-
-/* informs user about connected status. private_ctx is used by user to identify
- connection (multiple connections WIP) */
-int MemifConnector::onConnect(memif_conn_handle_t conn, void *private_ctx) {
- MemifConnector *connector = (MemifConnector *)private_ctx;
- connector->state_ = State::CONNECTED;
- memif_refill_queue(conn, 0, -1, 0);
-
- return 0;
-}
-
-/* informs user about disconnected status. private_ctx is used by user to
- identify connection (multiple connections WIP) */
-int MemifConnector::onDisconnect(memif_conn_handle_t conn, void *private_ctx) {
- MemifConnector *connector = (MemifConnector *)private_ctx;
- connector->state_ = State::CLOSED;
- return 0;
-}
-
-void MemifConnector::threadMain() { event_reactor_.runEventLoop(1000); }
-
-int MemifConnector::onInterrupt(memif_conn_handle_t conn, void *private_ctx,
- uint16_t qid) {
- MemifConnector *connector = (MemifConnector *)private_ctx;
-
- memif_connection_t *c = connector->memif_connection_.get();
- int err = MEMIF_ERR_SUCCESS, ret_val;
- uint16_t total_packets = 0;
- uint16_t rx;
-
- do {
- err = memif_rx_burst(conn, qid, c->rx_bufs, MAX_MEMIF_BUFS, &rx);
- ret_val = err;
-
- if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS &&
- err != MEMIF_ERR_NOBUF)) {
- LOG(ERROR) << "memif_rx_burst: " << memif_strerror(err);
- goto error;
- }
-
- c->rx_buf_num += rx;
-
- if (TRANSPORT_EXPECT_FALSE(connector->io_service_.stopped())) {
- LOG(ERROR) << "socket stopped: ignoring " << rx << " packets";
- goto error;
- }
-
- std::size_t packet_length;
- for (int i = 0; i < rx; i++) {
- auto buffer = connector->getRawBuffer();
- packet_length = (c->rx_bufs + i)->len;
- std::memcpy(buffer.first, (c->rx_bufs + i)->data, packet_length);
- auto packet = connector->getPacketFromBuffer(buffer.first, packet_length);
-
- if (!connector->input_buffer_.push(std::move(packet))) {
- LOG(ERROR) << "Error pushing packet. Ring buffer full.";
-
- // TODO Here we should consider the possibility to signal the congestion
- // to the application, that would react properly (e.g. slow down
- // message)
- }
- }
-
- /* mark memif buffers and shared memory buffers as free */
- /* free processed buffers */
-
- err = memif_refill_queue(conn, qid, rx, 0);
-
- if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
- LOG(ERROR) << "memif_buffer_free: " << memif_strerror(err);
- }
-
- c->rx_buf_num -= rx;
- total_packets += rx;
-
- } while (ret_val == MEMIF_ERR_NOBUF);
-
- connector->io_service_.post(
- std::bind(&MemifConnector::processInputBuffer, connector, total_packets));
-
- return 0;
-
-error:
- err = memif_refill_queue(c->conn, qid, rx, 0);
-
- if (TRANSPORT_EXPECT_FALSE(err != MEMIF_ERR_SUCCESS)) {
- LOG(ERROR) << "memif_buffer_free: " << memif_strerror(err);
- }
- c->rx_buf_num -= rx;
-
- return 0;
-}
-
-void MemifConnector::close() {
- if (state_ != State::CLOSED) {
- disconnect_timer_->expiresFromNow(std::chrono::microseconds(50));
- disconnect_timer_->asyncWait([this](const std::error_code &ec) {
- deleteMemif();
- event_reactor_.stop();
- });
-
- if (memif_worker_ && memif_worker_->joinable()) {
- memif_worker_->join();
- }
- }
-}
-
-void MemifConnector::send(Packet &packet) {
- {
- utils::SpinLock::Acquire locked(write_msgs_lock_);
- output_buffer_.push_back(packet.shared_from_this());
- }
-#if CANCEL_TIMER
- if (!timer_set_) {
- timer_set_ = true;
- send_timer_->expiresFromNow(std::chrono::microseconds(50));
- send_timer_->asyncWait(
- std::bind(&MemifConnector::sendCallback, this, std::placeholders::_1));
- }
-#endif
-}
-
-int MemifConnector::doSend() {
- std::size_t max = 0;
- int32_t n = 0;
- std::size_t size = 0;
-
- {
- utils::SpinLock::Acquire locked(write_msgs_lock_);
- size = output_buffer_.size();
- }
-
- do {
- max = size < MAX_MEMIF_BUFS ? size : MAX_MEMIF_BUFS;
- n = bufferAlloc(max, memif_connection_->tx_qid);
-
- if (TRANSPORT_EXPECT_FALSE(n < 0)) {
- LOG(ERROR) << "Error allocating buffers.";
- return -1;
- }
-
- for (uint16_t i = 0; i < n; i++) {
- utils::SpinLock::Acquire locked(write_msgs_lock_);
-
- auto packet = output_buffer_.front().get();
- const utils::MemBuf *current = packet;
- std::size_t offset = 0;
- uint8_t *shared_buffer =
- reinterpret_cast<uint8_t *>(memif_connection_->tx_bufs[i].data);
- do {
- std::memcpy(shared_buffer + offset, current->data(), current->length());
- offset += current->length();
- current = current->next();
- } while (current != packet);
-
- memif_connection_->tx_bufs[i].len = uint32_t(offset);
-
- output_buffer_.pop_front();
- }
-
- txBurst(memif_connection_->tx_qid);
-
- utils::SpinLock::Acquire locked(write_msgs_lock_);
- size = output_buffer_.size();
- } while (size > 0);
-
- return 0;
-}
-
-void MemifConnector::send(const uint8_t *packet, std::size_t len) {
- throw errors::NotImplementedException();
-}
-
-} // end namespace core
-
-} // end namespace transport
diff --git a/libtransport/src/io_modules/memif/memif_connector.h b/libtransport/src/io_modules/memif/memif_connector.h
deleted file mode 100644
index 0a189f893..000000000
--- a/libtransport/src/io_modules/memif/memif_connector.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (c) 2017-2019 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.
- */
-
-#pragma once
-
-#include <hicn/transport/config.h>
-#include <hicn/transport/core/connector.h>
-#include <hicn/transport/portability/portability.h>
-#include <hicn/transport/utils/ring_buffer.h>
-//#include <hicn/transport/core/hicn_vapi.h>
-#include <hicn/transport/core/asio_wrapper.h>
-#include <utils/epoll_event_reactor.h>
-#include <utils/fd_deadline_timer.h>
-
-#include <deque>
-#include <mutex>
-#include <thread>
-
-#define _Static_assert static_assert
-
-namespace transport {
-
-namespace core {
-
-typedef struct memif_connection memif_connection_t;
-
-#define APP_NAME "libtransport"
-#define IF_NAME "vpp_connection"
-
-#define MEMIF_BUF_SIZE 2048
-#define MEMIF_LOG2_RING_SIZE 13
-#define MAX_MEMIF_BUFS (1 << MEMIF_LOG2_RING_SIZE)
-
-class MemifConnector : public Connector {
- using memif_conn_handle_t = void *;
- using PacketRing = utils::CircularFifo<utils::MemBuf::Ptr, queue_size>;
-
- public:
- MemifConnector(PacketReceivedCallback &&receive_callback,
- PacketSentCallback &&packet_sent,
- OnCloseCallback &&close_callback,
- OnReconnectCallback &&on_reconnect,
- asio::io_service &io_service,
- std::string app_name = "Libtransport");
-
- ~MemifConnector() override;
-
- void send(Packet &packet) override;
-
- void send(const uint8_t *packet, std::size_t len) override;
-
- void close() override;
-
- void connect(uint32_t memif_id, long memif_mode);
-
- TRANSPORT_ALWAYS_INLINE uint32_t getMemifId() { return memif_id_; };
-
- private:
- void init();
-
- int doSend();
-
- int createMemif(uint32_t index, uint8_t mode, char *s);
-
- uint32_t getMemifConfiguration();
-
- int deleteMemif();
-
- static int controlFdUpdate(int fd, uint8_t events, void *private_ctx);
-
- static int onConnect(memif_conn_handle_t conn, void *private_ctx);
-
- static int onDisconnect(memif_conn_handle_t conn, void *private_ctx);
-
- static int onInterrupt(memif_conn_handle_t conn, void *private_ctx,
- uint16_t qid);
-
- void threadMain();
-
- int txBurst(uint16_t qid);
-
- int bufferAlloc(long n, uint16_t qid);
-
- void sendCallback(const std::error_code &ec);
-
- void processInputBuffer(std::uint16_t total_packets);
-
- private:
- static utils::EpollEventReactor main_event_reactor_;
- static std::unique_ptr<std::thread> main_worker_;
-
- int epfd;
- std::unique_ptr<std::thread> memif_worker_;
- utils::EpollEventReactor event_reactor_;
- std::atomic_bool timer_set_;
- std::unique_ptr<utils::FdDeadlineTimer> send_timer_;
- std::unique_ptr<utils::FdDeadlineTimer> disconnect_timer_;
- asio::io_service &io_service_;
- asio::executor_work_guard<asio::io_context::executor_type> work_;
- std::unique_ptr<memif_connection_t> memif_connection_;
- uint16_t tx_buf_counter_;
-
- PacketRing input_buffer_;
- bool is_reconnection_;
- bool data_available_;
- uint32_t memif_id_;
- uint8_t memif_mode_;
- std::string app_name_;
- uint16_t transmission_index_;
- utils::SpinLock write_msgs_lock_;
- std::string socket_filename_;
-
- static std::once_flag flag_;
-};
-
-} // end namespace core
-
-} // end namespace transport
diff --git a/libtransport/src/io_modules/memif/memif_vapi.c b/libtransport/src/io_modules/memif/memif_vapi.c
index b3da2b012..54e2c3134 100644
--- a/libtransport/src/io_modules/memif/memif_vapi.c
+++ b/libtransport/src/io_modules/memif/memif_vapi.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -22,8 +22,6 @@
#include <vapi/vapi_safe.h>
#include <vppinfra/clib.h>
-DEFINE_VAPI_MSG_IDS_MEMIF_API_JSON
-
static vapi_error_e memif_details_cb(vapi_ctx_t ctx, void *callback_ctx,
vapi_error_e rv, bool is_last,
vapi_payload_memif_details *reply) {
@@ -45,6 +43,9 @@ static vapi_error_e memif_details_cb(vapi_ctx_t ctx, void *callback_ctx,
int memif_vapi_get_next_memif_id(vapi_ctx_t ctx, uint32_t *memif_id) {
vapi_lock();
vapi_msg_memif_dump *msg = vapi_alloc_memif_dump(ctx);
+
+ // Initialize memif id to 0
+ *memif_id = 0;
int ret = vapi_memif_dump(ctx, msg, memif_details_cb, memif_id);
vapi_unlock();
return ret;
diff --git a/libtransport/src/io_modules/memif/memif_vapi.h b/libtransport/src/io_modules/memif/memif_vapi.h
index bcf06ed43..f5f0639e7 100644
--- a/libtransport/src/io_modules/memif/memif_vapi.h
+++ b/libtransport/src/io_modules/memif/memif_vapi.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -44,6 +44,10 @@ typedef struct memif_output_params_s {
int memif_vapi_get_next_memif_id(vapi_ctx_t ctx, uint32_t *memif_id);
+int memif_vapi_create_socket(vapi_ctx_t ctx,
+ memif_create_params_t *input_params,
+ memif_output_params_t *output_params);
+
int memif_vapi_create_memif(vapi_ctx_t ctx, memif_create_params_t *input_params,
memif_output_params_t *output_params);
diff --git a/libtransport/src/io_modules/memif/vpp_forwarder_module.cc b/libtransport/src/io_modules/memif/vpp_forwarder_module.cc
index 44c8376df..d04c60893 100644
--- a/libtransport/src/io_modules/memif/vpp_forwarder_module.cc
+++ b/libtransport/src/io_modules/memif/vpp_forwarder_module.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 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:
@@ -13,16 +13,16 @@
* limitations under the License.
*/
+#include <core/memif_connector.h>
#include <glog/logging.h>
#include <hicn/transport/config.h>
#include <hicn/transport/errors/not_implemented_exception.h>
#include <io_modules/memif/hicn_vapi.h>
-#include <io_modules/memif/memif_connector.h>
#include <io_modules/memif/memif_vapi.h>
#include <io_modules/memif/vpp_forwarder_module.h>
extern "C" {
-#include <memif/libmemif.h>
+#include <libmemif.h>
};
typedef enum { MASTER = 0, SLAVE = 1 } memif_role_t;
@@ -39,21 +39,25 @@ namespace core {
VPPForwarderModule::VPPForwarderModule()
: IoModule(),
connector_(nullptr),
+ memif_id_(0),
sw_if_index_(~0),
face_id1_(~0),
face_id2_(~0),
is_consumer_(false) {}
-VPPForwarderModule::~VPPForwarderModule() { delete connector_; }
+VPPForwarderModule::~VPPForwarderModule() {}
void VPPForwarderModule::init(
Connector::PacketReceivedCallback &&receive_callback,
+ Connector::PacketSentCallback &&sent_callback,
+ Connector::OnCloseCallback &&close_callback,
Connector::OnReconnectCallback &&reconnect_callback,
asio::io_service &io_service, const std::string &app_name) {
if (!connector_) {
- connector_ =
- new MemifConnector(std::move(receive_callback), 0, 0,
- std::move(reconnect_callback), io_service, app_name);
+ connector_ = std::make_unique<MemifConnector>(
+ std::move(receive_callback), std::move(sent_callback),
+ std::move(close_callback), std::move(reconnect_callback), io_service,
+ app_name);
}
}
@@ -62,7 +66,7 @@ void VPPForwarderModule::processControlMessageReply(
throw errors::NotImplementedException();
}
-bool VPPForwarderModule::isControlMessage(const uint8_t *message) {
+bool VPPForwarderModule::isControlMessage(utils::MemBuf &packet_buffer) {
return false;
}
@@ -73,12 +77,12 @@ void VPPForwarderModule::send(Packet &packet) {
connector_->send(packet);
}
-void VPPForwarderModule::send(const uint8_t *packet, std::size_t len) {
+void VPPForwarderModule::send(const utils::MemBuf::Ptr &buffer) {
counters_.tx_packets++;
- counters_.tx_bytes += len;
+ counters_.tx_bytes += buffer->length();
// Perfect forwarding
- connector_->send(packet, len);
+ connector_->send(buffer);
}
std::uint32_t VPPForwarderModule::getMtu() { return interface_mtu; }
@@ -120,8 +124,8 @@ uint32_t VPPForwarderModule::getMemifConfiguration() {
void VPPForwarderModule::consumerConnection() {
hicn_consumer_input_params input = {0};
hicn_consumer_output_params output = {0};
- ip_address_t ip4_address;
- ip_address_t ip6_address;
+ hicn_ip_address_t ip4_address;
+ hicn_ip_address_t ip6_address;
output.src4 = &ip4_address;
output.src6 = &ip6_address;
@@ -153,7 +157,8 @@ void VPPForwarderModule::connect(bool is_consumer) {
vapi_error_e ret = vapi_connect_safe(&sock_, 0);
while (ret != VAPI_OK && retry > 0) {
- LOG(ERROR) << "Error connecting to VPP through vapi. Retrying..";
+ LOG(ERROR) << "Error connecting to VPP through vapi (error: " << ret
+ << "). Retrying..";
--retry;
ret = vapi_connect_safe(&sock_, 0);
}
@@ -170,16 +175,17 @@ void VPPForwarderModule::connect(bool is_consumer) {
consumerConnection();
}
- connector_->connect(memif_id_, 0);
+ connector_->connect(memif_id_, 0 /* is_master = false */,
+ memif_socket_filename);
connector_->setRole(is_consumer_ ? Connector::Role::CONSUMER
: Connector::Role::PRODUCER);
}
void VPPForwarderModule::registerRoute(const Prefix &prefix) {
- const ip_prefix_t &addr = prefix.toIpPrefixStruct();
+ const hicn_ip_prefix_t &addr = prefix.toIpPrefixStruct();
- ip_prefix_t producer_prefix;
- ip_address_t producer_locator;
+ hicn_ip_prefix_t producer_prefix;
+ hicn_ip_address_t producer_locator;
if (face_id1_ == uint32_t(~0)) {
hicn_producer_input_params input;
@@ -207,7 +213,8 @@ void VPPForwarderModule::registerRoute(const Prefix &prefix) {
throw errors::RuntimeException(hicn_vapi_get_error_string(ret));
}
- inet6_address_ = *output.prod_addr;
+ std::memcpy(inet6_address_.v6.as_u8, output.prod_addr->v6.as_u8,
+ sizeof(inet6_address_));
face_id1_ = output.face_id;
} else {
@@ -228,8 +235,6 @@ void VPPForwarderModule::registerRoute(const Prefix &prefix) {
void VPPForwarderModule::closeConnection() {
if (VPPForwarderModule::sock_) {
- connector_->close();
-
if (is_consumer_) {
hicn_del_face_app_input_params params;
params.face_id = face_id1_;
@@ -242,6 +247,8 @@ void VPPForwarderModule::closeConnection() {
hicn_vapi_face_prod_del(VPPForwarderModule::sock_, &params);
}
+ connector_->close();
+
if (sw_if_index_ != uint32_t(~0)) {
int ret =
memif_vapi_delete_memif(VPPForwarderModule::sock_, sw_if_index_);
@@ -249,7 +256,6 @@ void VPPForwarderModule::closeConnection() {
LOG(ERROR) << "Error deleting memif with sw idx " << sw_if_index_;
}
}
-
vapi_disconnect_safe();
VPPForwarderModule::sock_ = nullptr;
}
diff --git a/libtransport/src/io_modules/memif/vpp_forwarder_module.h b/libtransport/src/io_modules/memif/vpp_forwarder_module.h
index 8c4114fed..5a5358078 100644
--- a/libtransport/src/io_modules/memif/vpp_forwarder_module.h
+++ b/libtransport/src/io_modules/memif/vpp_forwarder_module.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * 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:
@@ -32,7 +32,8 @@ namespace core {
class MemifConnector;
class VPPForwarderModule : public IoModule {
- static constexpr std::uint16_t interface_mtu = 1500;
+ static inline std::uint16_t interface_mtu = 1500;
+ static inline std::string const memif_socket_filename = "/run/vpp/memif.sock";
public:
VPPForwarderModule();
@@ -41,11 +42,13 @@ class VPPForwarderModule : public IoModule {
void connect(bool is_consumer) override;
void send(Packet &packet) override;
- void send(const uint8_t *packet, std::size_t len) override;
+ void send(const utils::MemBuf::Ptr &buffer) override;
bool isConnected() override;
void init(Connector::PacketReceivedCallback &&receive_callback,
+ Connector::PacketSentCallback &&sent_callback,
+ Connector::OnCloseCallback &&close_callback,
Connector::OnReconnectCallback &&reconnect_callback,
asio::io_service &io_service,
const std::string &app_name = "Libtransport") override;
@@ -54,7 +57,7 @@ class VPPForwarderModule : public IoModule {
std::uint32_t getMtu() override;
- bool isControlMessage(const uint8_t *message) override;
+ bool isControlMessage(utils::MemBuf &packet_buffer) override;
void processControlMessageReply(utils::MemBuf &packet_buffer) override;
@@ -66,7 +69,7 @@ class VPPForwarderModule : public IoModule {
void producerConnection();
private:
- MemifConnector *connector_;
+ std::shared_ptr<MemifConnector> connector_;
uint32_t memif_id_;
uint32_t sw_if_index_;
// A consumer socket in vpp has two faces (ipv4 and ipv6)