From bac3da61644515f05663789b122554dc77549286 Mon Sep 17 00:00:00 2001 From: Luca Muscariello Date: Thu, 17 Jan 2019 13:47:57 +0100 Subject: This is the first commit of the hicn project Change-Id: I6f2544ad9b9f8891c88cc4bcce3cf19bd3cc863f Signed-off-by: Luca Muscariello --- .../hicn/transport/core/vpp_forwarder_interface.cc | 184 +++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100755 libtransport/src/hicn/transport/core/vpp_forwarder_interface.cc (limited to 'libtransport/src/hicn/transport/core/vpp_forwarder_interface.cc') diff --git a/libtransport/src/hicn/transport/core/vpp_forwarder_interface.cc b/libtransport/src/hicn/transport/core/vpp_forwarder_interface.cc new file mode 100755 index 000000000..3a748c821 --- /dev/null +++ b/libtransport/src/hicn/transport/core/vpp_forwarder_interface.cc @@ -0,0 +1,184 @@ +/* + * 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 + +#ifdef __vpp__ + +#include +#include +#include + +typedef enum { MASTER = 0, SLAVE = 1 } memif_role_t; + +#define MEMIF_DEFAULT_RING_SIZE 2048 +#define MEMIF_DEFAULT_RX_QUEUES 1 +#define MEMIF_DEFAULT_TX_QUEUES 1 +#define MEMIF_DEFAULT_BUFFER_SIZE 2048 + +namespace transport { + +namespace core { + +vpp_binary_api_t *VPPForwarderInterface::api_ = nullptr; +vpp_plugin_binary_api_t *VPPForwarderInterface::memif_api_ = nullptr; +vpp_plugin_binary_api_t *VPPForwarderInterface::hicn_api_ = nullptr; +std::mutex VPPForwarderInterface::global_lock_; + +VPPForwarderInterface::VPPForwarderInterface(MemifConnector &connector) + : ForwarderInterface(connector), + sw_if_index_(~0), + face_id_(~0) {} + +VPPForwarderInterface::~VPPForwarderInterface() {} + +/** + * @brief Create a memif interface in the local VPP forwarder. + */ +uint32_t VPPForwarderInterface::getMemifConfiguration() { + memif_create_params_t input_params = {0}; + + memif_id_ = + memif_binary_api_get_next_memif_id(VPPForwarderInterface::memif_api_); + + input_params.id = memif_id_; + input_params.role = memif_role_t::MASTER; + input_params.mode = memif_interface_mode_t::MEMIF_INTERFACE_MODE_IP; + input_params.rx_queues = MEMIF_DEFAULT_RX_QUEUES; + input_params.tx_queues = MEMIF_DEFAULT_TX_QUEUES; + input_params.ring_size = MEMIF_DEFAULT_RING_SIZE; + input_params.buffer_size = MEMIF_DEFAULT_BUFFER_SIZE; + + memif_output_params_t output_params = {0}; + + if (memif_binary_api_create_memif(VPPForwarderInterface::memif_api_, + &input_params, &output_params) < 0) { + throw errors::RuntimeException( + "Error creating memif interface in the local VPP forwarder."); + } + + return output_params.sw_if_index; +} + +void VPPForwarderInterface::consumerConnection() { + hicn_consumer_input_params input = {0}; + hicn_consumer_output_params output; + + std::memset(&output, 0, sizeof(hicn_consumer_output_params)); + + input.swif = sw_if_index_; + + if (int ret = hicn_binary_api_register_cons_app( + VPPForwarderInterface::hicn_api_, &input, &output) < 0) { + throw errors::RuntimeException(hicn_binary_api_get_error_string(ret)); + } + + inet_address_.family = AF_INET; + inet_address_.prefix_len = output.src4.prefix_length; + std::memcpy(inet_address_.buffer, output.src4.ip4.as_u8, IPV4_ADDR_LEN); + + inet6_address_.family = AF_INET6; + inet6_address_.prefix_len = output.src6.prefix_length; + std::memcpy(inet6_address_.buffer, output.src6.ip6.as_u8, IPV6_ADDR_LEN); +} + +void VPPForwarderInterface::producerConnection() { + // Producer connection will be set when we set the first route. +} + +void VPPForwarderInterface::connect(bool is_consumer) { + std::lock_guard connection_lock(global_lock_); + + srand(time(NULL)); + int secret = rand() % (1 << 10); + std::stringstream app_name; + app_name << "Libtransport_" << secret; + + if (!VPPForwarderInterface::memif_api_) { + VPPForwarderInterface::api_ = vpp_binary_api_init(app_name.str().c_str()); + } + + VPPForwarderInterface::memif_api_ = + memif_binary_api_init(VPPForwarderInterface::api_); + + sw_if_index_ = getMemifConfiguration(); + + VPPForwarderInterface::hicn_api_ = + hicn_binary_api_init(VPPForwarderInterface::api_); + if (is_consumer) { + consumerConnection(); + } + + connector_.connect(memif_id_, 0); +} + +void VPPForwarderInterface::registerRoute(Prefix &prefix) { + auto &addr = prefix.toIpAddressStruct(); + + if (face_id_ == uint32_t(~0)) { + hicn_producer_input_params input; + std::memset(&input, 0, sizeof(input)); + + hicn_producer_output_params output; + std::memset(&output, 0, sizeof(output)); + + // Here we have to ask to the actual connector what is the + // memif_id, since this function should be called after the + // memif creation. + input.swif = sw_if_index_; + input.prefix.ip6.as_u64[0] = addr.as_u64[0]; + input.prefix.ip6.as_u64[1] = addr.as_u64[1]; + input.prefix.type = addr.family == AF_INET6 ? IP_TYPE_IP6 : IP_TYPE_IP4; + input.prefix.prefix_length = addr.prefix_len; + input.cs_reserved = content_store_reserved_; + + if (int ret = hicn_binary_api_register_prod_app( + VPPForwarderInterface::hicn_api_, &input, &output) < 0) { + throw errors::RuntimeException(hicn_binary_api_get_error_string(ret)); + } + + if (addr.family == AF_INET6) { + inet6_address_.prefix_len = output.prod_addr.prefix_length; + std::memcpy(inet6_address_.buffer, output.prod_addr.ip6.as_u8, + IPV6_ADDR_LEN); + } else { + inet_address_.prefix_len = output.prod_addr.prefix_length; + // The ipv4 is written in the last 4 bytes of the ipv6 address, so we need + // to copy from the byte 12 + std::memcpy(inet_address_.buffer, output.prod_addr.ip6.as_u8 + 12, + IPV4_ADDR_LEN); + } + + face_id_ = output.face_id; + } else { + hicn_producer_set_route_params params; + params.prefix.ip6.as_u64[0] = addr.as_u64[0]; + params.prefix.ip6.as_u64[1] = addr.as_u64[1]; + params.prefix.type = addr.family == AF_INET6 ? IP_TYPE_IP6 : IP_TYPE_IP4; + params.prefix.prefix_length = addr.prefix_len; + params.face_id = face_id_; + + if (int ret = hicn_binary_api_register_route( + VPPForwarderInterface::hicn_api_, ¶ms) < 0) { + throw errors::RuntimeException(hicn_binary_api_get_error_string(ret)); + } + } +} + +} // namespace core + +} // namespace transport + +#endif \ No newline at end of file -- cgit 1.2.3-korg