aboutsummaryrefslogtreecommitdiffstats
path: root/libtransport/src/io_modules/hicn-light
diff options
context:
space:
mode:
Diffstat (limited to 'libtransport/src/io_modules/hicn-light')
-rw-r--r--libtransport/src/io_modules/hicn-light/CMakeLists.txt63
-rw-r--r--libtransport/src/io_modules/hicn-light/hicn_forwarder_module.cc282
-rw-r--r--libtransport/src/io_modules/hicn-light/hicn_forwarder_module.h150
3 files changed, 495 insertions, 0 deletions
diff --git a/libtransport/src/io_modules/hicn-light/CMakeLists.txt b/libtransport/src/io_modules/hicn-light/CMakeLists.txt
new file mode 100644
index 000000000..ae3aec52d
--- /dev/null
+++ b/libtransport/src/io_modules/hicn-light/CMakeLists.txt
@@ -0,0 +1,63 @@
+# 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:
+#
+# 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.
+
+if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
+ find_package(Libhicnctrl ${HICN_CURRENT_VERSION} REQUIRED NO_MODULE)
+
+ if (DISABLE_SHARED_LIBRARIES)
+ set(LIBTYPE static)
+ else()
+ set(LIBTYPE shared)
+ endif()
+
+ list(APPEND LIBHICNCTRL_LIBRARIES hicn::hicnctrl.${LIBTYPE})
+else()
+ if (DISABLE_SHARED_LIBRARIES)
+ if (WIN32)
+ set(LIBHICNCTRL_LIBRARIES ${LIBHICNCTRL_STATIC})
+ else ()
+ set(LIBHICNCTRL_LIBRARIES ${LIBHICNCTRL_STATIC} log)
+ endif ()
+ list(APPEND DEPENDENCIES
+ ${LIBHICNCTRL_STATIC}
+ )
+ else()
+ set(LIBHICNCTRL_LIBRARIES ${LIBHICNCTRL_SHARED})
+ list(APPEND DEPENDENCIES
+ ${LIBHICNCTRL_SHARED}
+ )
+ endif()
+endif()
+
+list(APPEND MODULE_HEADER_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn_forwarder_module.h
+)
+
+list(APPEND MODULE_SOURCE_FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/hicn_forwarder_module.cc
+)
+
+build_module(hicnlight_module
+ SHARED
+ SOURCES ${MODULE_SOURCE_FILES}
+ DEPENDS ${DEPENDENCIES}
+ COMPONENT ${LIBTRANSPORT_COMPONENT}
+ LINK_LIBRARIES PRIVATE ${LIBHICNCTRL_LIBRARIES}
+ INCLUDE_DIRS
+ PRIVATE
+ ${LIBTRANSPORT_INTERNAL_INCLUDE_DIRS}
+ ${Libhicn_INCLUDE_DIRS}
+ ${Libhicnctrl_INCLUDE_DIRS}
+ DEFINITIONS ${COMPILER_DEFINITIONS}
+ COMPILE_OPTIONS ${COMPILER_OPTIONS}
+)
diff --git a/libtransport/src/io_modules/hicn-light/hicn_forwarder_module.cc b/libtransport/src/io_modules/hicn-light/hicn_forwarder_module.cc
new file mode 100644
index 000000000..98bd42fb5
--- /dev/null
+++ b/libtransport/src/io_modules/hicn-light/hicn_forwarder_module.cc
@@ -0,0 +1,282 @@
+/*
+ * 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:
+ *
+ * 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 <core/udp_connector.h>
+#include <hicn/transport/utils/uri.h>
+#include <io_modules/hicn-light/hicn_forwarder_module.h>
+
+extern "C" {
+#include <hicn/ctrl/hicn-light.h>
+}
+
+namespace transport {
+
+namespace core {
+
+HicnForwarderModule::ForwarderUrlInitializer
+ HicnForwarderModule::forwarder_url_initializer_;
+
+HicnForwarderModule::HicnForwarderModule()
+ : IoModule(), connector_(nullptr), seq_(0) {}
+
+HicnForwarderModule::~HicnForwarderModule() {}
+
+void HicnForwarderModule::connect(bool is_consumer) {
+ if (!connector_->isConnected()) {
+ // Parse forwarder URI
+ utils::Uri uri;
+ uri.parse(forwarder_url_initializer_.getForwarderUrl());
+
+ // Safechecks
+ CHECK(uri.getProtocol() == "hicn")
+ << "The protocol of the forwarder url should be hicn";
+ uint16_t port_min = (1 << 10);
+ uint16_t port_max = (1 << 16) - 1;
+
+ uint16_t port = std::stoul(uri.getPort());
+
+ CHECK(port > port_min && port < port_max)
+ << "The port should be between " << port_min << " and " << port_max;
+
+ VLOG(1) << "Connecting to " << uri.getLocator() << ":" << uri.getPort();
+
+ connector_->connect(uri.getLocator(), port);
+ connector_->setRole(is_consumer ? Connector::Role::CONSUMER
+ : Connector::Role::PRODUCER);
+ }
+}
+
+bool HicnForwarderModule::isConnected() { return connector_->isConnected(); }
+
+void HicnForwarderModule::send(Packet &packet) {
+ IoModule::send(packet);
+ packet.setChecksum();
+ connector_->send(packet);
+}
+
+void HicnForwarderModule::send(const utils::MemBuf::Ptr &packet) {
+ counters_.tx_packets++;
+ counters_.tx_bytes += packet->length();
+
+ // Perfect forwarding
+ connector_->send(packet);
+}
+
+void HicnForwarderModule::registerRoute(const Prefix &prefix) {
+ auto command = createCommandRoute(prefix.toSockaddr(),
+ (uint8_t)prefix.getPrefixLength());
+ if (!command) {
+ // TODO error
+ return;
+ }
+ send(command);
+}
+
+void HicnForwarderModule::sendMapme() {
+ auto command = createCommandMapmeSendUpdate();
+ if (!command) {
+ // TODO error
+ return;
+ }
+ send(command);
+}
+
+void HicnForwarderModule::setForwardingStrategy(const Prefix &prefix,
+ std::string &strategy) {
+ auto command = createCommandSetForwardingStrategy(
+ prefix.toSockaddr(), (uint8_t)prefix.getPrefixLength(), strategy);
+ if (!command) {
+ // TODO error
+ return;
+ }
+ send(command);
+}
+
+void HicnForwarderModule::closeConnection() {
+ auto command = createCommandDeleteConnection();
+ if (!command) {
+ // TODO error
+ return;
+ }
+
+ connector_->setSentCallback([](Connector *c, const std::error_code &ec) {
+ if (!ec) {
+ c->close();
+ }
+ });
+
+ send(command);
+}
+
+void HicnForwarderModule::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_.reset(new UdpTunnelConnector(
+ io_service, std::move(receive_callback), std::move(sent_callback),
+ std::move(close_callback), std::move(reconnect_callback)));
+ }
+}
+
+void HicnForwarderModule::processControlMessageReply(
+ utils::MemBuf &packet_buffer) {
+ if (packet_buffer.data()[0] == NACK_LIGHT) {
+ throw errors::RuntimeException(
+ "Received Nack message from hicn light forwarder.");
+ }
+}
+
+std::uint32_t HicnForwarderModule::getMtu() { return interface_mtu; }
+
+bool HicnForwarderModule::isControlMessage(utils::MemBuf &packet_buffer) {
+ return packet_buffer.data()[0] == ACK_LIGHT ||
+ packet_buffer.data()[0] == NACK_LIGHT;
+}
+
+/**
+ * @return A valid msg_route_add_t structure if the command was successful, or
+ * with .command_id == COMMAND_TYPE_UNDEFINED in case of error.
+ */
+utils::MemBuf::Ptr HicnForwarderModule::createCommandRoute(
+ std::unique_ptr<sockaddr> &&addr, uint8_t prefix_length) {
+ auto ret = PacketManager<>::getInstance().getMemBuf();
+ auto command = reinterpret_cast<msg_route_add_t *>(ret->writableData());
+ ret->append(sizeof(msg_route_add_t));
+ std::memset(command, 0, sizeof(*command));
+
+ if (!IS_VALID_FAMILY(addr->sa_family)) return nullptr;
+
+ *command = {
+ .header =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_ROUTE_ADD,
+ .length = 1,
+ .seq_num = 0,
+ },
+ .payload =
+ {
+ .cost = 1,
+ .family = (uint8_t)addr->sa_family,
+ .len = prefix_length,
+ },
+ };
+
+ switch (addr->sa_family) {
+ case AF_INET:
+ command->payload.address.v4.as_inaddr =
+ ((sockaddr_in *)addr.get())->sin_addr;
+ break;
+ case AF_INET6:
+ command->payload.address.v6.as_in6addr =
+ ((sockaddr_in6 *)addr.get())->sin6_addr;
+ break;
+ }
+ snprintf(command->payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%s",
+ "SELF");
+
+ return ret;
+}
+
+utils::MemBuf::Ptr HicnForwarderModule::createCommandDeleteConnection() {
+ auto ret = PacketManager<>::getInstance().getMemBuf();
+ auto command =
+ reinterpret_cast<msg_connection_remove_t *>(ret->writableData());
+ ret->append(sizeof(msg_connection_remove_t));
+ std::memset(command, 0, sizeof(*command));
+
+ *command = {
+ .header =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_CONNECTION_REMOVE,
+ .length = 1,
+ .seq_num = 0,
+ },
+ };
+
+ snprintf(command->payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%s",
+ "SELF");
+
+ return ret;
+}
+
+utils::MemBuf::Ptr HicnForwarderModule::createCommandMapmeSendUpdate() {
+ auto ret = PacketManager<>::getInstance().getMemBuf();
+ auto command = reinterpret_cast<msg_mapme_add_t *>(ret->writableData());
+ ret->append(sizeof(msg_mapme_add_t));
+ std::memset(command, 0, sizeof(*command));
+
+ *command = {.header = {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_MAPME_ADD,
+ .length = 1,
+ .seq_num = seq_++,
+ }};
+
+ return ret;
+}
+
+utils::MemBuf::Ptr HicnForwarderModule::createCommandSetForwardingStrategy(
+ std::unique_ptr<sockaddr> &&addr, uint32_t prefix_len,
+ std::string strategy) {
+ auto ret = PacketManager<>::getInstance().getMemBuf();
+ auto command = reinterpret_cast<msg_strategy_set_t *>(ret->writableData());
+ ret->append(sizeof(msg_strategy_set_t));
+ std::memset(command, 0, sizeof(*command));
+
+ if (!IS_VALID_FAMILY(addr->sa_family)) return nullptr;
+
+ strategy_type_t strategy_type = strategy_type_from_str(strategy.c_str());
+ if (strategy_type == STRATEGY_TYPE_UNDEFINED) return nullptr;
+
+ *command = {
+ .header =
+ {
+ .message_type = REQUEST_LIGHT,
+ .command_id = COMMAND_TYPE_STRATEGY_SET,
+ .length = 1,
+ .seq_num = seq_++,
+ },
+ .payload =
+ {
+ .family = (uint8_t)addr->sa_family,
+ .len = (uint8_t)prefix_len,
+ .type = (uint8_t)strategy_type,
+ },
+ };
+
+ switch (addr->sa_family) {
+ case AF_INET:
+ command->payload.address.v4.as_inaddr =
+ ((sockaddr_in *)addr.get())->sin_addr;
+ break;
+ case AF_INET6:
+ command->payload.address.v6.as_in6addr =
+ ((sockaddr_in6 *)addr.get())->sin6_addr;
+ break;
+ }
+
+ return ret;
+}
+
+extern "C" IoModule *create_module(void) { return new HicnForwarderModule(); }
+
+} // namespace core
+
+} // namespace transport
diff --git a/libtransport/src/io_modules/hicn-light/hicn_forwarder_module.h b/libtransport/src/io_modules/hicn-light/hicn_forwarder_module.h
new file mode 100644
index 000000000..2378b93f8
--- /dev/null
+++ b/libtransport/src/io_modules/hicn-light/hicn_forwarder_module.h
@@ -0,0 +1,150 @@
+/*
+ * 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:
+ *
+ * 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 <core/global_configuration.h>
+#include <hicn/transport/core/io_module.h>
+#include <hicn/transport/core/prefix.h>
+
+#include <libconfig.h++>
+
+extern "C" {
+#include <hicn/ctrl/hicn-light.h>
+}
+
+namespace transport {
+
+namespace core {
+
+class UdpTunnelConnector;
+
+class HicnForwarderModule : public IoModule {
+ static constexpr std::uint16_t interface_mtu = 1500;
+
+ public:
+#if 0
+ union addressLight {
+ uint32_t ipv4;
+ struct in6_addr ipv6;
+ };
+
+ struct route_to_self_command {
+ uint8_t messageType;
+ uint8_t commandID;
+ uint16_t length;
+ uint32_t seqNum;
+ char symbolicOrConnid[16];
+ union addressLight address;
+ uint16_t cost;
+ uint8_t addressType;
+ uint8_t len;
+ };
+
+ using route_to_self_command = struct route_to_self_command;
+#endif
+
+ HicnForwarderModule();
+
+ ~HicnForwarderModule();
+
+ void connect(bool is_consumer) override;
+
+ void send(Packet &packet) 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;
+
+ void registerRoute(const Prefix &prefix) override;
+
+ void sendMapme() override;
+
+ void setForwardingStrategy(const Prefix &prefix,
+ std::string &strategy) override;
+
+ std::uint32_t getMtu() override;
+
+ bool isControlMessage(utils::MemBuf &packet_buffer) override;
+
+ void processControlMessageReply(utils::MemBuf &packet_buffer) override;
+
+ void closeConnection() override;
+
+ private:
+ utils::MemBuf::Ptr createCommandRoute(std::unique_ptr<sockaddr> &&addr,
+ uint8_t prefix_length);
+ utils::MemBuf::Ptr createCommandDeleteConnection();
+ utils::MemBuf::Ptr createCommandMapmeSendUpdate();
+ utils::MemBuf::Ptr createCommandSetForwardingStrategy(
+ std::unique_ptr<sockaddr> &&addr, uint32_t prefix_len,
+ std::string strategy);
+
+ static void parseForwarderConfiguration(const libconfig::Setting &io_config,
+ std::error_code &ec);
+ static std::string initForwarderUrl();
+
+ private:
+ std::shared_ptr<UdpTunnelConnector> connector_;
+ /* Sequence number used for sending control messages */
+ uint32_t seq_;
+
+ class ForwarderUrlInitializer {
+ static inline char default_hicnlight_url[] = "hicn://127.0.0.1:9695";
+ static inline char hicnlight_configuration_section[] = "hicnlight";
+
+ public:
+ ForwarderUrlInitializer()
+ : forwarder_url_(ForwarderUrlInitializer::default_hicnlight_url) {
+ using namespace std::placeholders;
+ GlobalConfiguration::getInstance().registerConfigurationParser(
+ ForwarderUrlInitializer::hicnlight_configuration_section,
+ std::bind(&ForwarderUrlInitializer::parseForwarderConfiguration, this,
+ _1, _2));
+ }
+
+ std::string getForwarderUrl() { return forwarder_url_; }
+
+ private:
+ void parseForwarderConfiguration(const libconfig::Setting &forwarder_config,
+ std::error_code &ec) {
+ using namespace libconfig;
+
+ // forwarder url hicn://127.0.0.1:12345
+ if (forwarder_config.exists("forwarder_url")) {
+ // Get number of threads
+ forwarder_config.lookupValue("forwarder_url", forwarder_url_);
+ VLOG(1) << "Forwarder URL from config file: " << forwarder_url_;
+ }
+ }
+
+ // Url of the forwarder
+ std::string forwarder_url_;
+ };
+
+ static ForwarderUrlInitializer forwarder_url_initializer_;
+};
+
+extern "C" IoModule *create_module(void);
+
+} // namespace core
+
+} // namespace transport