diff options
author | Luca Muscariello <lumuscar@cisco.com> | 2022-03-30 22:29:28 +0200 |
---|---|---|
committer | Mauro Sardara <msardara@cisco.com> | 2022-03-31 19:51:47 +0200 |
commit | c46e5df56b67bb8ea7a068d39324c640084ead2b (patch) | |
tree | eddeb17785938e09bc42eec98ee09b8a28846de6 /apps | |
parent | 18fa668f25d3cc5463417ce7df6637e31578e898 (diff) |
feat: boostrap hicn 22.02
The current patch provides several new features, improvements,
bug fixes and also complete rewrite of entire components.
- lib
The hicn packet parser has been improved with a new packet
format fully based on UDP. The TCP header is still temporarily
supported but the UDP header will replace completely the new hicn
packet format. Improvements have been made to make sure every
packet parsing operation is made via this library. The current
new header can be used as header between the payload and the
UDP header or as trailer in the UDP surplus area to be tested
when UDP options will start to be used.
- hicn-light
The portable packet forwarder has been completely rewritten from
scratch with the twofold objective to improve performance and
code size but also to drop dependencies such as libparc which is
now removed by the current implementation.
- hicn control
the control library is the agent that is used to program the
packet forwarders via their binary API. This component has
benefited from significant improvements in terms of interaction
model which is now event driven and more robust to failures.
- VPP plugin has been updated to support VPP 22.02
- transport
Major improvement have been made to the RTC protocol, to the
support of IO modules and to the security sub system. Signed
manifests are the default data authenticity and integrity framework.
Confidentiality can be enabled by sharing the encryption key to the
prod/cons layer. The library has been tested with group key based
applications such as broadcast/multicast and real-time on-line
meetings with trusted server keys or MLS.
- testing
Unit testing has been introduced using GoogleTest. One third of
the code base is covered by unit testing with priority on
critical features. Functional testing has also been introduce
using Docker, linux bridging and Robot Framework to define
test with Less Code techniques to facilitate the extension
of the coverage.
Co-authored-by: Mauro Sardara <msardara@cisco.com>
Co-authored-by: Jordan Augé <jordan.auge+fdio@cisco.com>
Co-authored-by: Michele Papalini <micpapal@cisco.com>
Co-authored-by: Angelo Mantellini <manangel@cisco.com>
Co-authored-by: Jacques Samain <jsamain@cisco.com>
Co-authored-by: Olivier Roques <oroques+fdio@cisco.com>
Co-authored-by: Enrico Loparco <eloparco@cisco.com>
Co-authored-by: Giulio Grassi <gigrassi@cisco.com>
Change-Id: I75d0ef70f86d921e3ef503c99271216ff583c215
Signed-off-by: Luca Muscariello <muscariello@ieee.org>
Signed-off-by: Mauro Sardara <msardara@cisco.com>
Diffstat (limited to 'apps')
34 files changed, 1156 insertions, 573 deletions
diff --git a/apps/.clang-format b/apps/.clang-format index cd21e2017..adc73c6fd 100644 --- a/apps/.clang-format +++ b/apps/.clang-format @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2021 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: diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index df1b9fc7c..b06d7bcb4 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2019 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,37 +11,68 @@ # See the License for the specific language governing permissions and # limitations under the License. +############################################################## +# Project and cmake version +############################################################## cmake_minimum_required(VERSION 3.10 FATAL_ERROR) -set(CMAKE_CXX_STANDARD 14) - project(apps) + +############################################################## +# C Standard +############################################################## +set(CMAKE_CXX_STANDARD 17) + + +############################################################## +# Cmake modules +############################################################## +include("${CMAKE_CURRENT_SOURCE_DIR}/../versions.cmake") set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} - "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/Modules" - "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules" + ${CMAKE_CURRENT_SOURCE_DIR}/../cmake/Modules ) -if (NOT CMAKE_BUILD_TYPE) - message(STATUS "${PROJECT_NAME}: No build type selected, default to Release") - set(CMAKE_BUILD_TYPE "Release") -endif () - -include(BuildMacros) -include(WindowsMacros) +############################################################## +# Libs and Bins names +############################################################## set(HICN_APPS hicn-apps CACHE INTERNAL "" FORCE) +set(HIGET higet) +set(HTTP_PROXY hicn-http-proxy) +set(LIBHTTP_PROXY hicnhttpproxy) +set(LIBHTTP_PROXY_STATIC ${LIBHTTP_PROXY}.static) + +############################################################## +# Dependencies and third party libs +############################################################## find_package(Threads REQUIRED) -find_package(Libconfig++ REQUIRED) +find_package(Libconfig++ ${LIBCONFIG_DEFAULT_VERSION} REQUIRED) + +############################################################## +# Check if building as subproject or as root project +############################################################## if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) - find_package(Libtransport REQUIRED) - find_package(Libhicn REQUIRED) - find_package(hicnctrl REQUIRED) + include(CommonSetup) + + find_package(Libhicn ${CURRENT_VERSION} REQUIRED NO_MODULE) + find_package(Libhicnctrl ${CURRENT_VERSION} REQUIRED NO_MODULE) + find_package(Libhicntransport ${CURRENT_VERSION} REQUIRED NO_MODULE) + + if (DISABLE_SHARED_LIBRARIES) + set(LIBTYPE static) + else() + set(LIBTYPE shared) + endif() + + list(APPEND LIBHICN_LIBRARIES hicn::hicn.${LIBTYPE}) + list(APPEND LIBTRANSPORT_LIBRARIES hicn::hicntransport.${LIBTYPE}) + list(APPEND LIBHICNCTRL_LIBRARIES hicn::hicnctrl.${LIBTYPE}) else() if (DISABLE_SHARED_LIBRARIES) - find_package(OpenSSL REQUIRED) + find_package(OpenSSL ${OPENSSL_DEFAULT_VERSION} REQUIRED) set(LIBTRANSPORT_LIBRARIES ${LIBTRANSPORT_STATIC}) set(LIBHICN_LIBRARIES ${LIBHICN_STATIC}) set(LIBHICNCTRL_LIBRARIES ${LIBHICNCTRL_STATIC}) @@ -56,20 +87,18 @@ else() ) endif() -if (WIN32) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4200 /wd4996") -endif () -include(Packaging) +############################################################## +# Packaging and versioning +############################################################## +include(${CMAKE_CURRENT_SOURCE_DIR}/../versions.cmake) +include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/packaging.cmake) + +############################################################## +# Subdirectories +############################################################## add_subdirectory(ping) add_subdirectory(hiperf) - -set(HIGET higet) -set(HTTP_PROXY hicn-http-proxy) - -if (NOT WIN32) - add_subdirectory(http-proxy) -endif () - +add_subdirectory(http-proxy) add_subdirectory(higet) diff --git a/apps/cmake/Modules/Packaging.cmake b/apps/cmake/packaging.cmake index 981eb728e..9142598ad 100644 --- a/apps/cmake/Modules/Packaging.cmake +++ b/apps/cmake/packaging.cmake @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2019 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: @@ -18,21 +18,34 @@ useful for testing and debugging within a hicn network." ) set(${HICN_APPS}_DEB_DEPENDENCIES - "lib${LIBTRANSPORT} (>= stable_version), lib${LIBHICNCTRL} (>= stable_version)" + "lib${LIBTRANSPORT} (= stable_version), lib${LIBHICNCTRL} (= stable_version)" CACHE STRING "Dependencies for deb/rpm package." ) set(${HICN_APPS}-dev_DEB_DEPENDENCIES - "${HICN_APPS} (>= stable_version), lib${LIBTRANSPORT}-dev (>= stable_version), lib${LIBHICNCTRL}-dev (>= stable_version)" + "${HICN_APPS} (= stable_version), lib${LIBTRANSPORT}-dev (= stable_version), lib${LIBHICNCTRL}-dev (= stable_version)" CACHE STRING "Dependencies for deb/rpm package." ) set(${HICN_APPS}_RPM_DEPENDENCIES - "lib${LIBTRANSPORT} >= stable_version, lib${LIBHICNCTRL} >= stable_version" + "lib${LIBTRANSPORT} = stable_version, lib${LIBHICNCTRL} = stable_version" CACHE STRING "Dependencies for deb/rpm package." ) set(${HICN_APPS}-dev_RPM_DEPENDENCIES - "${HICN_APPS} >= stable_version, lib${LIBTRANSPORT}-dev >= stable_version, lib${LIBHICNCTRL}-dev >= stable_version" + "${HICN_APPS} = stable_version, lib${LIBTRANSPORT}-dev = stable_version, lib${LIBHICNCTRL}-dev = stable_version" CACHE STRING "Dependencies for deb/rpm package." -)
\ No newline at end of file +) + +if (INTERNAL_ENVIRONMENT) + include(CheckSsl) + CheckSsl() + set(${HICN_APPS}_DEB_DEPENDENCIES + "${${HICN_APPS}_DEB_DEPENDENCIES}, ${OPENSSL_DEPENDENCY}" + CACHE STRING "Dependencies for deb/rpm package." + ) + set(${HICN_APPS}-dev_DEB_DEPENDENCIES + "${${HICN_APPS}-dev_DEB_DEPENDENCIES}, ${OPENSSL_DEPENDENCY_DEV}" + CACHE STRING "Dependencies for deb/rpm package." + ) +endif ()
\ No newline at end of file diff --git a/apps/higet/CMakeLists.txt b/apps/higet/CMakeLists.txt index 8d112d3a3..f4d2d4ec4 100644 --- a/apps/higet/CMakeLists.txt +++ b/apps/higet/CMakeLists.txt @@ -1,4 +1,4 @@ -# 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: @@ -11,36 +11,40 @@ # See the License for the specific language governing permissions and # limitations under the License. -cmake_minimum_required(VERSION 3.10 FATAL_ERROR) -set(CMAKE_CXX_STANDARD 14) - -project(utils) - -find_package(Threads REQUIRED) - -set(CMAKE_MODULE_PATH - ${CMAKE_MODULE_PATH} - "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/Modules" - "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules" -) - -if (NOT CMAKE_BUILD_TYPE) - message(STATUS "${PROJECT_NAME}: No build type selected, default to Release") - set(CMAKE_BUILD_TYPE "Release") -endif () - +############################################################## +# Source files +############################################################## list(APPEND APPS_SRC higet.cc ) + +############################################################## +# Linker flags +############################################################## if (WIN32) - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /NODEFAULTLIB:\"LIBCMT\"" ) + set(CMAKE_EXE_LINKER_FLAGS + "${CMAKE_EXE_LINKER_FLAGS} /NODEFAULTLIB:\"LIBCMT\"" + ) endif() + +############################################################## +# Compiler options +############################################################## +set(COMPILER_OPTIONS + ${DEFAULT_COMPILER_OPTIONS} +) + + +############################################################## +# Build higet +############################################################## if (NOT DISABLE_EXECUTABLES) build_executable(${HIGET} SOURCES ${APPS_SRC} LINK_LIBRARIES + ${LIBHICN_LIBRARIES} ${LIBTRANSPORT_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${WSOCK32_LIBRARY} @@ -49,5 +53,6 @@ if (NOT DISABLE_EXECUTABLES) COMPONENT ${HICN_APPS} DEFINITIONS ${COMPILER_DEFINITIONS} LINK_FLAGS ${LINK_FLAGS} + COMPILE_OPTIONS ${COMPILER_OPTIONS} ) endif () diff --git a/apps/higet/higet.cc b/apps/higet/higet.cc index 9ae869731..d72d7d74f 100644 --- a/apps/higet/higet.cc +++ b/apps/higet/higet.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 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: @@ -14,23 +14,20 @@ */ #include <hicn/transport/http/client_connection.h> +#include <hicn/transport/utils/chrono_typedefs.h> #include <algorithm> +#include <asio.hpp> #include <fstream> #include <functional> #include <map> +#ifndef ASIO_STANDALONE #define ASIO_STANDALONE +#endif #include <asio.hpp> -#undef ASIO_STANDALONE - #include <thread> -typedef std::chrono::time_point<std::chrono::system_clock> Time; -typedef std::chrono::milliseconds TimeDuration; - -Time t1; - #define DEFAULT_BETA 0.99 #define DEFAULT_GAMMA 0.07 @@ -181,7 +178,7 @@ class ReadBytesCallbackImplementation }); } - void onError(const std::error_code ec) { + void onError(const std::error_code &ec) { io_service_.post([this]() { of_.close(); delete out_; @@ -345,8 +342,6 @@ int main(int argc, char **argv) { connection.setVerifier(verifier); } - t1 = std::chrono::system_clock::now(); - http::ReadBytesCallbackImplementation readBytesCallback(conf.file_name, yetDownloaded); diff --git a/apps/hiperf/CMakeLists.txt b/apps/hiperf/CMakeLists.txt index 564525e67..6986c90aa 100644 --- a/apps/hiperf/CMakeLists.txt +++ b/apps/hiperf/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2019 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: @@ -12,6 +12,9 @@ # limitations under the License. if (NOT DISABLE_EXECUTABLES) +############################################################## +# Source files +############################################################## list(APPEND HIPERF_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/client.cc ${CMAKE_CURRENT_SOURCE_DIR}/src/main.cc @@ -19,26 +22,40 @@ if (NOT DISABLE_EXECUTABLES) ${CMAKE_CURRENT_SOURCE_DIR}/src/forwarder_interface.cc ) + +############################################################## +# Libraries +############################################################## list (APPEND HIPERF_LIBRARIES - ${LIBTRANSPORT_LIBRARIES} - ${LIBHICNCTRL_LIBRARIES} - ${LIBHICN_LIBRARIES} - ${CMAKE_THREAD_LIBS_INIT} - ${LIBCONFIG_CPP_LIBRARIES} - ${WSOCK32_LIBRARY} - ${WS2_32_LIBRARY} + PRIVATE ${LIBTRANSPORT_LIBRARIES} + PRIVATE ${LIBHICNCTRL_LIBRARIES} + PRIVATE ${LIBHICN_LIBRARIES} + PRIVATE ${CMAKE_THREAD_LIBS_INIT} + PRIVATE ${LIBCONFIG_CPP_LIBRARIES} + PRIVATE ${WSOCK32_LIBRARY} + PRIVATE ${WS2_32_LIBRARY} + ) + +############################################################## +# Compiler options +############################################################## + set(COMPILER_OPTIONS + ${DEFAULT_COMPILER_OPTIONS} ) + +############################################################## +# Build hiperf +############################################################## build_executable(hiperf SOURCES ${HIPERF_SRC} LINK_LIBRARIES ${HIPERF_LIBRARIES} INCLUDE_DIRS - ${CMAKE_CURRENT_SOURCE_DIR}/src - ${LIBTRANSPORT_INCLUDE_DIRS} - ${LIBHICNCTRL_INCLUDE_DIRS} - ${LIBCONFIG_CPP_INCLUDE_DIRS} + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src + PRIVATE ${LIBCONFIG_CPP_INCLUDE_DIRS} DEPENDS ${DEPENDENCIES} COMPONENT ${HICN_APPS} LINK_FLAGS ${LINK_FLAGS} + COMPILE_OPTIONS ${COMPILER_OPTIONS} ) endif()
\ No newline at end of file diff --git a/apps/hiperf/src/client.cc b/apps/hiperf/src/client.cc index 820ebf0ce..319fa82ab 100644 --- a/apps/hiperf/src/client.cc +++ b/apps/hiperf/src/client.cc @@ -31,17 +31,12 @@ class Callback; * Hiperf client class: configure and setup an hicn consumer following the * ClientConfiguration. */ -class HIperfClient::Impl -#ifdef FORWARDER_INTERFACE - : ForwarderInterface::ICallback -#endif -{ - typedef std::chrono::time_point<std::chrono::steady_clock> Time; - typedef std::chrono::microseconds TimeDuration; - +class HIperfClient::Impl : ForwarderInterface::ICallback { friend class Callback; friend class RTCCallback; + static const constexpr uint16_t log2_header_counter = 4; + struct nack_packet_t { uint64_t timestamp; uint32_t prod_rate; @@ -76,21 +71,29 @@ class HIperfClient::Impl delay_sample_(0), received_bytes_(0), received_data_pkt_(0), + auth_alerts_(0), data_delays_(""), signals_(io_service_), rtc_callback_(*this), callback_(*this), socket_(io_service_), - done_(false), - switch_threshold_(~0) -#ifdef FORWARDER_INTERFACE - , - forwarder_interface_(io_service_, this) -#endif - { + // switch_threshold_(~0), + fwd_connected_(false), + use_bestpath_(false), + rtt_threshold_(~0), + loss_threshold_(~0), + prefix_name_(""), + prefix_len_(0), + // done_(false), + header_counter_mask_((1 << log2_header_counter) - 1), + header_counter_(0), + print_headers_(configuration_.print_headers_), + first_(true), + forwarder_interface_(io_service_) { + setForwarderConnection(conf.forwarder_type_); } - ~Impl() {} + virtual ~Impl() {} void checkReceivedRtcContent(ConsumerSocket &c, const ContentObject &contentObject) {} @@ -104,174 +107,187 @@ class HIperfClient::Impl void handleTimerExpiration(ConsumerSocket &c, const TransportStatistics &stats) { const char separator = ' '; - const int width = 15; + const int width = 18; - utils::TimePoint t2 = utils::SteadyClock::now(); - auto exact_duration = - std::chrono::duration_cast<utils::Milliseconds>(t2 - t_stats_); + utils::SteadyTime::TimePoint t2 = utils::SteadyTime::Clock::now(); + auto exact_duration = utils::SteadyTime::getDurationMs(t_stats_, t2); - std::stringstream interval; - interval << total_duration_milliseconds_ / 1000 << "-" - << total_duration_milliseconds_ / 1000 + - exact_duration.count() / 1000; + std::stringstream interval_ms; + interval_ms << total_duration_milliseconds_ << "-" + << total_duration_milliseconds_ + exact_duration.count(); std::stringstream bytes_transferred; bytes_transferred << std::fixed << std::setprecision(3) << (stats.getBytesRecv() - old_bytes_value_) / 1000000.0 - << std::setfill(separator) << "[MB]"; + << std::setfill(separator); std::stringstream bandwidth; bandwidth << ((stats.getBytesRecv() - old_bytes_value_) * 8) / (exact_duration.count()) / 1000.0 - << std::setfill(separator) << "[Mbps]"; + << std::setfill(separator); std::stringstream window; - window << stats.getAverageWindowSize() << std::setfill(separator) - << "[Int]"; + window << stats.getAverageWindowSize() << std::setfill(separator); std::stringstream avg_rtt; - avg_rtt << stats.getAverageRtt() << std::setfill(separator) << "[ms]"; + avg_rtt << stats.getAverageRtt() << std::setfill(separator); if (configuration_.rtc_) { - // we get rtc stats more often, thus we need ms in the interval - std::stringstream interval_ms; - interval_ms << total_duration_milliseconds_ << "-" - << total_duration_milliseconds_ + exact_duration.count(); - std::stringstream lost_data; lost_data << stats.getLostData() - old_lost_data_value_ - << std::setfill(separator) << "[pkt]"; + << std::setfill(separator); std::stringstream bytes_recovered_data; bytes_recovered_data << stats.getBytesRecoveredData() - old_bytes_recovered_value_ - << std::setfill(separator) << "[pkt]"; + << std::setfill(separator); std::stringstream definitely_lost_data; definitely_lost_data << stats.getDefinitelyLostData() - old_definitely_lost_data_value_ - << std::setfill(separator) << "[pkt]"; + << std::setfill(separator); std::stringstream data_delay; - data_delay << avg_data_delay_ << std::setfill(separator) << "[ms]"; + data_delay << std::fixed << std::setprecision(3) << avg_data_delay_ + << std::setfill(separator); std::stringstream received_data_pkt; - received_data_pkt << received_data_pkt_ << std::setfill(separator) - << "[pkt]"; + received_data_pkt << received_data_pkt_ << std::setfill(separator); std::stringstream goodput; - goodput << (received_bytes_ * 8.0) / (exact_duration.count()) / 1000.0 - << std::setfill(separator) << "[Mbps]"; + goodput << std::fixed << std::setprecision(3) + << (received_bytes_ * 8.0) / (exact_duration.count()) / 1000.0 + << std::setfill(separator); std::stringstream loss_rate; loss_rate << std::fixed << std::setprecision(2) - << stats.getLossRatio() * 100.0 << std::setfill(separator) - << "[%]"; + << stats.getLossRatio() * 100.0 << std::setfill(separator); std::stringstream retx_sent; retx_sent << stats.getRetxCount() - old_retx_value_ - << std::setfill(separator) << "[pkt]"; + << std::setfill(separator); std::stringstream interest_sent; interest_sent << stats.getInterestTx() - old_sent_int_value_ - << std::setfill(separator) << "[pkt]"; + << std::setfill(separator); std::stringstream nacks; nacks << stats.getReceivedNacks() - old_received_nacks_value_ - << std::setfill(separator) << "[pkt]"; + << std::setfill(separator); std::stringstream fec_pkt; fec_pkt << stats.getReceivedFEC() - old_fec_pkt_ - << std::setfill(separator) << "[pkt]"; + << std::setfill(separator); std::stringstream queuing_delay; - queuing_delay << stats.getQueuingDelay() << std::setfill(separator) - << "[ms]"; + queuing_delay << std::fixed << std::setprecision(3) + << stats.getQueuingDelay() << std::setfill(separator); -#ifdef FORWARDER_INTERFACE - if (!done_ && stats.getQueuingDelay() >= switch_threshold_ && - total_duration_milliseconds_ > 1000) { - std::cout << "Switching due to queuing delay" << std::endl; - forwarder_interface_.createFaceAndRoutes(backup_routes_); - forwarder_interface_.deleteFaceAndRoutes(main_routes_); - std::swap(backup_routes_, main_routes_); - done_ = true; + std::stringstream residual_losses; + double rl_perc = stats.getResidualLossRate() * 100; + residual_losses << std::fixed << std::setprecision(2) << rl_perc + << std::setfill(separator); + + std::stringstream quality_score; + quality_score << std::fixed << (int)stats.getQualityScore() + << std::setfill(separator); + + std::stringstream alerts; + alerts << stats.getAlerts() << std::setfill(separator); + + std::stringstream auth_alerts; + auth_alerts << auth_alerts_ << std::setfill(separator); + + if (fwd_connected_ && use_bestpath_ && + ((stats.getAverageRtt() > rtt_threshold_) || + ((stats.getResidualLossRate() * 100) > loss_threshold_))) { + forwarder_interface_.setStrategy(prefix_name_, prefix_len_, "bestpath"); } -#endif - // statistics not yet available in the transport - // std::stringstream interest_fec_tx; - // interest_fec_tx << stats.getInterestFecTxCount() - - // old_fec_interest_tx_value_ << std::setfill(separator) << "[pkt]"; - // std::stringstream bytes_fec_recv; - // bytes_fec_recv << stats.getBytesFecRecv() - old_fec_data_rx_value_ - // << std::setfill(separator) << "[bytes]"; - std::cout << std::left << std::setw(width) << "Interval"; - std::cout << std::left << std::setw(width) << "RecvData"; - std::cout << std::left << std::setw(width) << "Bandwidth"; - std::cout << std::left << std::setw(width) << "Goodput"; - std::cout << std::left << std::setw(width) << "LossRate"; - std::cout << std::left << std::setw(width) << "Retr"; - std::cout << std::left << std::setw(width) << "InterestSent"; - std::cout << std::left << std::setw(width) << "ReceivedNacks"; - std::cout << std::left << std::setw(width) << "SyncWnd"; - std::cout << std::left << std::setw(width) << "MinRtt"; - std::cout << std::left << std::setw(width) << "QueuingDelay"; - std::cout << std::left << std::setw(width) << "LostData"; - std::cout << std::left << std::setw(width) << "RecoveredData"; - std::cout << std::left << std::setw(width) << "DefinitelyLost"; - std::cout << std::left << std::setw(width) << "State"; - std::cout << std::left << std::setw(width) << "DataDelay"; - std::cout << std::left << std::setw(width) << "FecPkt" << std::endl; - - std::cout << std::left << std::setw(width) << interval_ms.str(); - std::cout << std::left << std::setw(width) << received_data_pkt.str(); - std::cout << std::left << std::setw(width) << bandwidth.str(); - std::cout << std::left << std::setw(width) << goodput.str(); - std::cout << std::left << std::setw(width) << loss_rate.str(); - std::cout << std::left << std::setw(width) << retx_sent.str(); - std::cout << std::left << std::setw(width) << interest_sent.str(); - std::cout << std::left << std::setw(width) << nacks.str(); - std::cout << std::left << std::setw(width) << window.str(); - std::cout << std::left << std::setw(width) << avg_rtt.str(); - std::cout << std::left << std::setw(width) << queuing_delay.str(); - std::cout << std::left << std::setw(width) << lost_data.str(); - std::cout << std::left << std::setw(width) << bytes_recovered_data.str(); - std::cout << std::left << std::setw(width) << definitely_lost_data.str(); - std::cout << std::left << std::setw(width) << stats.getCCStatus(); - std::cout << std::left << std::setw(width) << data_delay.str(); - std::cout << std::left << std::setw(width) << fec_pkt.str(); + if ((header_counter_ == 0 && print_headers_) || first_) { + std::cout << std::right << std::setw(width) << "Interval[ms]"; + std::cout << std::right << std::setw(width) << "RecvData[pkt]"; + std::cout << std::right << std::setw(width) << "Bandwidth[Mbps]"; + std::cout << std::right << std::setw(width) << "Goodput[Mbps]"; + std::cout << std::right << std::setw(width) << "LossRate[%]"; + std::cout << std::right << std::setw(width) << "Retr[pkt]"; + std::cout << std::right << std::setw(width) << "InterestSent"; + std::cout << std::right << std::setw(width) << "ReceivedNacks"; + std::cout << std::right << std::setw(width) << "SyncWnd[pkt]"; + std::cout << std::right << std::setw(width) << "MinRtt[ms]"; + std::cout << std::right << std::setw(width) << "QueuingDelay[ms]"; + std::cout << std::right << std::setw(width) << "LostData[pkt]"; + std::cout << std::right << std::setw(width) << "RecoveredData"; + std::cout << std::right << std::setw(width) << "DefinitelyLost"; + std::cout << std::right << std::setw(width) << "State"; + std::cout << std::right << std::setw(width) << "DataDelay[ms]"; + std::cout << std::right << std::setw(width) << "FecPkt"; + std::cout << std::right << std::setw(width) << "Congestion"; + std::cout << std::right << std::setw(width) << "ResidualLosses"; + std::cout << std::right << std::setw(width) << "QualityScore"; + std::cout << std::right << std::setw(width) << "Alerts"; + std::cout << std::right << std::setw(width) << "AuthAlerts" + << std::endl; + + first_ = false; + } + + std::cout << std::right << std::setw(width) << interval_ms.str(); + std::cout << std::right << std::setw(width) << received_data_pkt.str(); + std::cout << std::right << std::setw(width) << bandwidth.str(); + std::cout << std::right << std::setw(width) << goodput.str(); + std::cout << std::right << std::setw(width) << loss_rate.str(); + std::cout << std::right << std::setw(width) << retx_sent.str(); + std::cout << std::right << std::setw(width) << interest_sent.str(); + std::cout << std::right << std::setw(width) << nacks.str(); + std::cout << std::right << std::setw(width) << window.str(); + std::cout << std::right << std::setw(width) << avg_rtt.str(); + std::cout << std::right << std::setw(width) << queuing_delay.str(); + std::cout << std::right << std::setw(width) << lost_data.str(); + std::cout << std::right << std::setw(width) << bytes_recovered_data.str(); + std::cout << std::right << std::setw(width) << definitely_lost_data.str(); + std::cout << std::right << std::setw(width) << stats.getCCStatus(); + std::cout << std::right << std::setw(width) << data_delay.str(); + std::cout << std::right << std::setw(width) << fec_pkt.str(); + std::cout << std::right << std::setw(width) << stats.isCongested(); + std::cout << std::right << std::setw(width) << residual_losses.str(); + std::cout << std::right << std::setw(width) << quality_score.str(); + std::cout << std::right << std::setw(width) << alerts.str(); + std::cout << std::right << std::setw(width) << auth_alerts.str(); std::cout << std::endl; if (configuration_.test_mode_) { if (data_delays_.size() > 0) data_delays_.pop_back(); - uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>( - std::chrono::system_clock::now().time_since_epoch()) - .count(); - std::cout << now << " DATA-DELAYS:[" << data_delays_ << "]" - << std::endl; + auto now = utils::SteadyTime::nowMs(); + std::cout << std::fixed << std::setprecision(0) << now.count() + << " DATA-DELAYS:[" << data_delays_ << "]" << std::endl; } // statistics not yet available in the transport - // std::cout << std::left << std::setw(width) << interest_fec_tx.str(); - // std::cout << std::left << std::setw(width) << bytes_fec_recv.str(); + // std::cout << std::right << std::setw(width) << interest_fec_tx.str(); + // std::cout << std::right << std::setw(width) << bytes_fec_recv.str(); } else { - std::cout << std::left << std::setw(width) << "Interval"; - std::cout << std::left << std::setw(width) << "Transfer"; - std::cout << std::left << std::setw(width) << "Bandwidth"; - std::cout << std::left << std::setw(width) << "Retr"; - std::cout << std::left << std::setw(width) << "Cwnd"; - std::cout << std::left << std::setw(width) << "AvgRtt" << std::endl; - - std::cout << std::left << std::setw(width) << interval.str(); - std::cout << std::left << std::setw(width) << bytes_transferred.str(); - std::cout << std::left << std::setw(width) << bandwidth.str(); - std::cout << std::left << std::setw(width) << stats.getRetxCount(); - std::cout << std::left << std::setw(width) << window.str(); - std::cout << std::left << std::setw(width) << avg_rtt.str() << std::endl; - std::cout << std::endl; + if ((header_counter_ == 0 && print_headers_) || first_) { + std::cout << std::right << std::setw(width) << "Interval[ms]"; + std::cout << std::right << std::setw(width) << "Transfer[MB]"; + std::cout << std::right << std::setw(width) << "Bandwidth[Mbps]"; + std::cout << std::right << std::setw(width) << "Retr[pkt]"; + std::cout << std::right << std::setw(width) << "Cwnd[Int]"; + std::cout << std::right << std::setw(width) << "AvgRtt[ms]" + << std::endl; + + first_ = false; + } + + std::cout << std::right << std::setw(width) << interval_ms.str(); + std::cout << std::right << std::setw(width) << bytes_transferred.str(); + std::cout << std::right << std::setw(width) << bandwidth.str(); + std::cout << std::right << std::setw(width) << stats.getRetxCount(); + std::cout << std::right << std::setw(width) << window.str(); + std::cout << std::right << std::setw(width) << avg_rtt.str() << std::endl; } + total_duration_milliseconds_ += (uint32_t)exact_duration.count(); old_bytes_value_ = stats.getBytesRecv(); old_lost_data_value_ = stats.getLostData(); @@ -289,9 +305,95 @@ class HIperfClient::Impl received_data_pkt_ = 0; data_delays_ = ""; - t_stats_ = utils::SteadyClock::now(); + t_stats_ = utils::SteadyTime::Clock::now(); + + header_counter_ = (header_counter_ + 1) & header_counter_mask_; + + if (--configuration_.nb_iterations_ == 0) { + // We reached the maximum nb of runs. Stop now. + io_service_.stop(); + } } + bool setForwarderConnection(forwarder_type_t forwarder_type) { + using namespace libconfig; + Config cfg; + + const char *conf_file = getenv("FORWARDER_CONFIG"); + if (!conf_file) return false; + + if ((forwarder_type != HICNLIGHT) && (forwarder_type != HICNLIGHT_NG)) + return false; + + try { + cfg.readFile(conf_file); + } catch (const FileIOException &fioex) { + std::cerr << "I/O error while reading file." << std::endl; + return false; + } catch (const ParseException &pex) { + std::cerr << "Parse error at " << pex.getFile() << ":" << pex.getLine() + << " - " << pex.getError() << std::endl; + return false; + } + + Setting &config = cfg.getRoot(); + + /* conf file example + * + * use_bestpath = "ON | OFF" + * rtt_threshold = 200 //ms + * loss_threshold = 20 //% + * name = "b001::/16" + */ + + if (config.exists("use_bestpath")) { + std::string val; + config.lookupValue("use_bestpath", val); + if (val.compare("ON") == 0) use_bestpath_ = true; + } + + if (config.exists("rtt_threshold")) { + unsigned val; + config.lookupValue("rtt_threshold", val); + rtt_threshold_ = val; + } + + if (config.exists("loss_threshold")) { + unsigned val; + config.lookupValue("loss_threshold", val); + loss_threshold_ = val; + } + + if (config.exists("name")) { + std::string route; + config.lookupValue("name", route); + + std::string delimiter = "/"; + size_t pos = 0; + + if ((pos = route.find(delimiter)) != std::string::npos) { + prefix_name_ = route.substr(0, pos); + route.erase(0, pos + delimiter.length()); + prefix_len_ = std::stoul(route.substr(0)); + } + } + + forwarder_interface_.initForwarderInterface(this, forwarder_type); + + return true; + } + + void onHicnServiceReady() override { + std::cout << "Successfully connected to local forwarder!" << std::endl; + fwd_connected_ = true; + } + + void onRouteConfigured( + std::vector<ForwarderInterface::RouteInfoPtr> &route_info) override { + std::cout << "Routes successfully configured!" << std::endl; + } + +#ifdef FORWARDER_INTERFACE bool parseConfig(const char *conf_file) { using namespace libconfig; Config cfg; @@ -439,7 +541,6 @@ class HIperfClient::Impl return true; } -#ifdef FORWARDER_INTERFACE void onHicnServiceReady() override { std::cout << "Successfully connected to local forwarder!" << std::endl; @@ -541,6 +642,13 @@ class HIperfClient::Impl } #endif + transport::auth::VerificationPolicy onAuthFailed( + transport::auth::Suffix suffix, + transport::auth::VerificationPolicy policy) { + auth_alerts_++; + return transport::auth::VerificationPolicy::ACCEPT; + } + int setup() { int ret; @@ -557,6 +665,7 @@ class HIperfClient::Impl producer_socket_ = std::make_unique<ProducerSocket>(production_protocol); producer_socket_->registerPrefix(configuration_.relay_name_); producer_socket_->connect(); + producer_socket_->start(); } if (configuration_.output_stream_mode_ && configuration_.rtc_) { @@ -586,6 +695,17 @@ class HIperfClient::Impl GeneralTransportOptions::INTEREST_LIFETIME, configuration_.interest_lifetime_); + consumer_socket_->setSocketOption( + GeneralTransportOptions::MAX_UNVERIFIED_TIME, + configuration_.unverified_delay_); + + if (consumer_socket_->setSocketOption( + GeneralTransportOptions::PACKET_FORMAT, + configuration_.packet_format_) == SOCKET_OPTION_NOT_SET) { + std::cerr << "ERROR -- Impossible to set the packet format." << std::endl; + return ERROR_SETUP; + } + #if defined(DEBUG) && defined(__linux__) std::shared_ptr<transport::BasePortal> portal; consumer_socket_->getSocketOption(GeneralTransportOptions::PORTAL, portal); @@ -623,20 +743,24 @@ class HIperfClient::Impl } } + std::shared_ptr<Verifier> verifier = std::make_shared<VoidVerifier>(); + if (!configuration_.producer_certificate.empty()) { - std::shared_ptr<Verifier> verifier = std::make_shared<AsymmetricVerifier>( + verifier = std::make_shared<AsymmetricVerifier>( configuration_.producer_certificate); - if (consumer_socket_->setSocketOption(GeneralTransportOptions::VERIFIER, - verifier) == SOCKET_OPTION_NOT_SET) - return ERROR_SETUP; } if (!configuration_.passphrase.empty()) { - std::shared_ptr<Verifier> verifier = - std::make_shared<SymmetricVerifier>(configuration_.passphrase); - if (consumer_socket_->setSocketOption(GeneralTransportOptions::VERIFIER, - verifier) == SOCKET_OPTION_NOT_SET) - return ERROR_SETUP; + verifier = std::make_shared<SymmetricVerifier>(configuration_.passphrase); + } + + verifier->setVerificationFailedCallback( + std::bind(&HIperfClient::Impl::onAuthFailed, this, + std::placeholders::_1, std::placeholders::_2)); + + if (consumer_socket_->setSocketOption(GeneralTransportOptions::VERIFIER, + verifier) == SOCKET_OPTION_NOT_SET) { + return ERROR_SETUP; } ret = consumer_socket_->setSocketOption( @@ -662,6 +786,65 @@ class HIperfClient::Impl } if (configuration_.rtc_) { + if (configuration_.recovery_strategy_ == 1) { // unreliable + ret = consumer_socket_->setSocketOption( + RtcTransportOptions::RECOVERY_STRATEGY, + (uint32_t)RtcTransportRecoveryStrategies::RECOVERY_OFF); + } else if (configuration_.recovery_strategy_ == 2) { // rtx only + ret = consumer_socket_->setSocketOption( + RtcTransportOptions::RECOVERY_STRATEGY, + (uint32_t)RtcTransportRecoveryStrategies::RTX_ONLY); + } else if (configuration_.recovery_strategy_ == 3) { // fec only + ret = consumer_socket_->setSocketOption( + RtcTransportOptions::RECOVERY_STRATEGY, + (uint32_t)RtcTransportRecoveryStrategies::FEC_ONLY); + } else if (configuration_.recovery_strategy_ == 4) { // delay based + ret = consumer_socket_->setSocketOption( + RtcTransportOptions::RECOVERY_STRATEGY, + (uint32_t)RtcTransportRecoveryStrategies::DELAY_BASED); + } else if (configuration_.recovery_strategy_ == 5) { // low rate flow + ret = consumer_socket_->setSocketOption( + RtcTransportOptions::RECOVERY_STRATEGY, + (uint32_t)RtcTransportRecoveryStrategies::LOW_RATE); + } else if (configuration_.recovery_strategy_ == + 6) { // low rate + bestpath + ret = consumer_socket_->setSocketOption( + RtcTransportOptions::RECOVERY_STRATEGY, + (uint32_t)RtcTransportRecoveryStrategies::LOW_RATE_AND_BESTPATH); + } else if (configuration_.recovery_strategy_ == + 7) { // low rate + replication + ret = consumer_socket_->setSocketOption( + RtcTransportOptions::RECOVERY_STRATEGY, + (uint32_t)RtcTransportRecoveryStrategies::LOW_RATE_AND_REPLICATION); + } else if (configuration_.recovery_strategy_ == + 8) { // low rate + bestpath or replication + ret = consumer_socket_->setSocketOption( + RtcTransportOptions::RECOVERY_STRATEGY, + (uint32_t)RtcTransportRecoveryStrategies:: + LOW_RATE_AND_ALL_FWD_STRATEGIES); + } else { + // default + ret = consumer_socket_->setSocketOption( + RtcTransportOptions::RECOVERY_STRATEGY, + (uint32_t)RtcTransportRecoveryStrategies::RTX_ONLY); + } + + if (ret == SOCKET_OPTION_NOT_SET) { + return ERROR_SETUP; + } + } + + if (configuration_.rtc_) { + ret = consumer_socket_->setSocketOption( + RtcTransportOptions::AGGREGATED_DATA, + configuration_.aggregated_data_); + + if (ret == SOCKET_OPTION_NOT_SET) { + return ERROR_SETUP; + } + } + + if (configuration_.rtc_) { ret = consumer_socket_->setSocketOption( ConsumerCallbacksOptions::CONTENT_OBJECT_INPUT, (ConsumerContentObjectCallback)std::bind( @@ -673,6 +856,15 @@ class HIperfClient::Impl } if (configuration_.rtc_) { + ret = consumer_socket_->setSocketOption(GeneralTransportOptions::FEC_TYPE, + configuration_.fec_type_); + + if (ret == SOCKET_OPTION_NOT_SET) { + return ERROR_SETUP; + } + } + + if (configuration_.rtc_) { std::shared_ptr<TransportStatistics> transport_stats; consumer_socket_->getSocketOption( OtherOptions::STATISTICS, (TransportStatistics **)&transport_stats); @@ -708,10 +900,10 @@ class HIperfClient::Impl signals_.async_wait( [this](const std::error_code &, const int &) { io_service_.stop(); }); - t_download_ = t_stats_ = std::chrono::steady_clock::now(); - consumer_socket_->asyncConsume(configuration_.name); - io_service_.run(); + t_download_ = t_stats_ = utils::SteadyTime::now(); + consumer_socket_->consume(configuration_.name); + io_service_.run(); consumer_socket_->stop(); return ERROR_SUCCESS; @@ -719,11 +911,15 @@ class HIperfClient::Impl private: class RTCCallback : public ConsumerSocket::ReadCallback { - static constexpr std::size_t mtu = 1500; + static constexpr std::size_t mtu = HIPERF_MTU; public: RTCCallback(Impl &hiperf_client) : client_(hiperf_client) { client_.configuration_.receive_buffer = utils::MemBuf::create(mtu); + Packet::Format format = + PayloadSize::getFormatFromName(client_.configuration_.name, false); + payload_size_max_ = + PayloadSize(format).getPayloadSizeMax(RTC_HEADER_SIZE); } bool isBufferMovable() noexcept override { return false; } @@ -743,9 +939,7 @@ class HIperfClient::Impl uint64_t *senderTimeStamp = (uint64_t *)client_.configuration_.receive_buffer->writableData(); - uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>( - std::chrono::system_clock::now().time_since_epoch()) - .count(); + auto now = utils::SystemTime::nowMs().count(); double new_delay = (double)(now - *senderTimeStamp); if (*senderTimeStamp > now) @@ -765,7 +959,7 @@ class HIperfClient::Impl client_.producer_socket_->produceDatagram( client_.configuration_.relay_name_.getName(), client_.configuration_.receive_buffer->writableData(), - length < 1400 ? length : 1400); + length < payload_size_max_ ? length : payload_size_max_); } if (client_.configuration_.output_stream_mode_) { uint8_t *start = @@ -778,7 +972,7 @@ class HIperfClient::Impl size_t maxBufferSize() const override { return mtu; } - void readError(const std::error_code ec) noexcept override { + void readError(const std::error_code &ec) noexcept override { std::cerr << "Error while reading from RTC socket" << std::endl; client_.io_service_.stop(); } @@ -789,6 +983,7 @@ class HIperfClient::Impl private: Impl &client_; + std::size_t payload_size_max_; }; class Callback : public ConsumerSocket::ReadCallback { @@ -816,16 +1011,15 @@ class HIperfClient::Impl return client_.configuration_.receive_buffer_size_; } - void readError(const std::error_code ec) noexcept override { + void readError(const std::error_code &ec) noexcept override { std::cerr << "Error " << ec.message() << " while reading from socket" << std::endl; client_.io_service_.stop(); } void readSuccess(std::size_t total_size) noexcept override { - Time t2 = std::chrono::steady_clock::now(); - TimeDuration dt = - std::chrono::duration_cast<TimeDuration>(t2 - client_.t_download_); + auto t2 = utils::SteadyTime::now(); + auto dt = utils::SteadyTime::getDurationUs(client_.t_download_, t2); long usec = (long)dt.count(); std::cout << "Content retrieved. Size: " << total_size << " [Bytes]" @@ -843,8 +1037,8 @@ class HIperfClient::Impl }; hiperf::ClientConfiguration configuration_; - Time t_stats_; - Time t_download_; + utils::SteadyTime::TimePoint t_stats_; + utils::SteadyTime::TimePoint t_download_; uint32_t total_duration_milliseconds_; uint64_t old_bytes_value_; uint64_t old_interest_tx_value_; @@ -865,6 +1059,7 @@ class HIperfClient::Impl uint32_t received_bytes_; uint32_t received_data_pkt_; + uint32_t auth_alerts_; std::string data_delays_; @@ -878,19 +1073,44 @@ class HIperfClient::Impl asio::ip::udp::endpoint remote_; ForwarderConfiguration config_; - uint16_t switch_threshold_; /* ms */ - bool done_; + // uint16_t switch_threshold_; /* ms */ + bool fwd_connected_; + bool use_bestpath_; + uint32_t rtt_threshold_; /* ms */ + uint32_t loss_threshold_; /* ms */ + std::string prefix_name_; // bestpath route + uint32_t prefix_len_; + // bool done_; + std::vector<ForwarderInterface::RouteInfoPtr> main_routes_; std::vector<ForwarderInterface::RouteInfoPtr> backup_routes_; -#ifdef FORWARDER_INTERFACE + uint16_t header_counter_mask_; + uint16_t header_counter_; + + bool print_headers_; + bool first_; + ForwarderInterface forwarder_interface_; -#endif }; HIperfClient::HIperfClient(const ClientConfiguration &conf) { impl_ = new Impl(conf); } +HIperfClient::HIperfClient(HIperfClient &&other) { + impl_ = other.impl_; + other.impl_ = nullptr; +} + +HIperfClient &HIperfClient::operator=(HIperfClient &&other) { + if (this != &other) { + impl_ = other.impl_; + other.impl_ = nullptr; + } + + return *this; +} + HIperfClient::~HIperfClient() { delete impl_; } int HIperfClient::setup() { return impl_->setup(); } diff --git a/apps/hiperf/src/client.h b/apps/hiperf/src/client.h index f45b9af43..bc80c874c 100644 --- a/apps/hiperf/src/client.h +++ b/apps/hiperf/src/client.h @@ -16,12 +16,16 @@ #pragma once #include <common.h> +#include <hicn/transport/utils/noncopyable.h> namespace hiperf { -class HIperfClient { +class HIperfClient : ::utils::NonCopyable { public: HIperfClient(const ClientConfiguration &conf); + HIperfClient(HIperfClient &&other); + HIperfClient &operator=(HIperfClient &&other); + ~HIperfClient(); int setup(); void run(); diff --git a/apps/hiperf/src/common.h b/apps/hiperf/src/common.h index e6ba526f9..13c9dcc1d 100644 --- a/apps/hiperf/src/common.h +++ b/apps/hiperf/src/common.h @@ -15,7 +15,7 @@ #pragma once -#include <hicn/transport/auth/identity.h> +#include <forwarder_interface.h> #include <hicn/transport/auth/signer.h> #include <hicn/transport/config.h> #include <hicn/transport/core/content_object.h> @@ -45,6 +45,9 @@ #endif #define ERROR_SETUP -5 #define MIN_PROBE_SEQ 0xefffffff +#define RTC_HEADER_SIZE 12 +#define FEC_HEADER_MAX_SIZE 36 +#define HIPERF_MTU 1500 using namespace transport::interface; using namespace transport::auth; @@ -73,11 +76,51 @@ static inline uint64_t _htonll(const uint64_t *input) { namespace hiperf { /** + * Class to retrieve the maximum payload size given the MTU and packet headers. + */ +class PayloadSize { + public: + PayloadSize(Packet::Format format, std::size_t mtu = HIPERF_MTU) + : mtu_(mtu), format_(format) {} + + std::size_t getPayloadSizeMax(std::size_t transport_size = 0, + std::size_t fec_size = 0, + std::size_t signature_size = 0) { + return mtu_ - Packet::getHeaderSizeFromFormat(format_, signature_size) - + transport_size - fec_size; + } + + static Packet::Format getFormatFromName(Name name, bool ah = false) { + switch (name.getAddressFamily()) { + case AF_INET: + return ah ? HF_INET_TCP_AH : HF_INET_TCP; + case AF_INET6: + return ah ? HF_INET6_TCP_AH : HF_INET6_TCP; + default: + return HF_UNSPEC; + } + } + + private: + std::size_t mtu_; + Packet::Format format_; +}; + +/** * Class for handling the production rate for the RTC producer. */ class Rate { public: Rate() : rate_kbps_(0) {} + ~Rate() {} + + Rate &operator=(const Rate &other) { + if (this != &other) { + rate_kbps_ = other.rate_kbps_; + } + + return *this; + } Rate(const std::string &rate) { std::size_t found = rate.find("kbps"); @@ -137,9 +180,16 @@ struct ClientConfiguration { secure_(false), producer_prefix_(), interest_lifetime_(500), + unverified_delay_(2000), relay_name_("c001::abcd/64"), output_stream_mode_(false), - port_(0) {} + port_(0), + recovery_strategy_(4), + aggregated_data_(false), + fec_type_(""), + packet_format_(default_values::packet_format), + print_headers_(true), + nb_iterations_(std::numeric_limits<decltype(nb_iterations_)>::max()) {} Name name; double beta; @@ -158,9 +208,17 @@ struct ClientConfiguration { bool secure_; Prefix producer_prefix_; uint32_t interest_lifetime_; + uint32_t unverified_delay_; Prefix relay_name_; bool output_stream_mode_; uint16_t port_; + uint32_t recovery_strategy_; + bool aggregated_data_; + std::string fec_type_; + Packet::Format packet_format_; + bool print_headers_; + std::uint32_t nb_iterations_; + forwarder_type_t forwarder_type_; }; /** @@ -170,11 +228,11 @@ struct ServerConfiguration { ServerConfiguration() : name("b001::abcd/64"), virtual_producer(true), - manifest(false), + manifest(0), live_production(false), content_lifetime(600000000_U32), download_size(20 * 1024 * 1024), - hash_algorithm(CryptoHashType::SHA256), + hash_algorithm_(CryptoHashType::SHA256), keystore_name(""), passphrase(""), keystore_password("cisco"), @@ -185,18 +243,21 @@ struct ServerConfiguration { trace_index_(0), trace_file_(nullptr), production_rate_(std::string("2048kbps")), - payload_size_(1400), + payload_size_(1384), secure_(false), input_stream_mode_(false), - port_(0) {} + port_(0), + aggregated_data_(false), + fec_type_(""), + packet_format_(default_values::packet_format) {} Prefix name; bool virtual_producer; - bool manifest; + std::uint32_t manifest; bool live_production; std::uint32_t content_lifetime; std::uint32_t download_size; - CryptoHashType hash_algorithm; + CryptoHashType hash_algorithm_; std::string keystore_name; std::string passphrase; std::string keystore_password; @@ -212,6 +273,9 @@ struct ServerConfiguration { bool input_stream_mode_; uint16_t port_; std::vector<struct packet_t> trace_; + bool aggregated_data_; + std::string fec_type_; + Packet::Format packet_format_; }; } // namespace hiperf diff --git a/apps/hiperf/src/forwarder_config.h b/apps/hiperf/src/forwarder_config.h index 655ac3b66..aaac14839 100644 --- a/apps/hiperf/src/forwarder_config.h +++ b/apps/hiperf/src/forwarder_config.h @@ -94,4 +94,4 @@ class ForwarderConfiguration { std::size_t n_threads_; }; -}
\ No newline at end of file +} // namespace hiperf
\ No newline at end of file diff --git a/apps/hiperf/src/forwarder_interface.cc b/apps/hiperf/src/forwarder_interface.cc index 864208239..e87a5953d 100644 --- a/apps/hiperf/src/forwarder_interface.cc +++ b/apps/hiperf/src/forwarder_interface.cc @@ -25,6 +25,7 @@ extern "C" { #include <hicn/error.h> #include <hicn/util/ip_address.h> +#include <hicn/util/sstrncpy.h> } // XXX the main listener should be retrieve in this class at initialization, aka @@ -36,27 +37,14 @@ extern "C" { namespace hiperf { +ForwarderInterface::ForwarderInterface(asio::io_service &io_service) + : external_ioservice_(io_service), timer_(io_service) {} + ForwarderInterface::ForwarderInterface(asio::io_service &io_service, - ICallback *callback) - : external_ioservice_(io_service), - forwarder_interface_callback_(callback), - work_(std::make_unique<asio::io_service::work>(internal_ioservice_)), - sock_(nullptr), - thread_(std::make_unique<std::thread>([this]() { - std::cout << "Starting Forwarder Interface thread" << std::endl; - internal_ioservice_.run(); - std::cout << "Stopping Forwarder Interface thread" << std::endl; - })), - // set_route_callback_(std::forward<Callback &&>(setRouteCallback)), - check_routes_timer_(nullptr), - pending_add_route_counter_(0), - hicn_listen_port_(9695), - /* We start in disabled state even when a forwarder is always available */ - state_(State::Disabled), - timer_(io_service), - num_reattempts(0) { - std::cout << "Forwarder interface created... connecting to forwarder...\n"; - internal_ioservice_.post([this]() { onHicnServiceAvailable(true); }); + ICallback *callback, + forwarder_type_t fwd_type) + : external_ioservice_(io_service), timer_(io_service) { + initForwarderInterface(callback, fwd_type); } ForwarderInterface::~ForwarderInterface() { @@ -72,8 +60,27 @@ ForwarderInterface::~ForwarderInterface() { thread_->join(); } +} - std::cout << "ForwarderInterface::~ForwarderInterface" << std::endl; +void ForwarderInterface::initForwarderInterface(ICallback *callback, + forwarder_type_t fwd_type) { + forwarder_interface_callback_ = callback; + work_ = std::make_unique<asio::io_service::work>(internal_ioservice_); + sock_ = nullptr; + thread_ = std::make_unique<std::thread>([this]() { + std::cout << "Starting Forwarder Interface thread" << std::endl; + internal_ioservice_.run(); + std::cout << "Stopping Forwarder Interface thread" << std::endl; + }); + check_routes_timer_ = nullptr; + pending_add_route_counter_ = 0; + hicn_listen_port_ = 9695; + /* We start in disabled state even when a forwarder is always available */ + state_ = State::Disabled; + fwd_type_ = fwd_type; + num_reattempts = 0; + std::cout << "Forwarder interface created... connecting to forwarder...\n"; + internal_ioservice_.post([this]() { onHicnServiceAvailable(true); }); } void ForwarderInterface::onHicnServiceAvailable(bool flag) { @@ -93,26 +100,15 @@ void ForwarderInterface::onHicnServiceAvailable(bool flag) { std::cout << "Connected to forwarder... cancelling reconnection timer" << std::endl; + timer_.cancel(); num_reattempts = 0; - // case State::Connected: - // checkListener(); - - // if (state_ != State::Ready) { - // std::cout << "Listener not found" << std::endl; - // goto REATTEMPT; - // } - // state_ = State::Ready; - - // timer_.cancel(); - // num_reattempts = 0; - std::cout << "Forwarder interface is ready... communicate to controller" << std::endl; forwarder_interface_callback_->onHicnServiceReady(); - + case State::Connected: case State::Ready: break; } @@ -136,14 +132,14 @@ REATTEMPT: std::chrono::milliseconds(ForwarderInterface::REATTEMPT_DELAY_MS)); // timer_.async_wait(std::bind(&ForwarderInterface::onHicnServiceAvailable, // this, flag, std::placeholders::_1)); - timer_.async_wait([this, flag](std::error_code ec) { + timer_.async_wait([this, flag](const std::error_code &ec) { if (ec) return; onHicnServiceAvailable(flag); }); } int ForwarderInterface::connectToForwarder() { - sock_ = hc_sock_create(); + sock_ = hc_sock_create_forwarder(fwd_type_); if (!sock_) { std::cout << "Could not create socket" << std::endl; goto ERR_SOCK; @@ -256,6 +252,27 @@ void ForwarderInterface::deleteFaceAndRoutes( }); } +void ForwarderInterface::setStrategy(std::string prefix, uint32_t prefix_len, + std::string strategy) { + if (!sock_) return; + + ip_address_t ip_prefix; + if (ip_address_pton(prefix.c_str(), &ip_prefix) < 0) { + return; + } + + strategy_type_t strategy_type = strategy_type_from_str(strategy.c_str()); + if (strategy_type == STRATEGY_TYPE_UNDEFINED) return; + + hc_strategy_t strategy_conf; + strategy_conf.address = ip_prefix; + strategy_conf.len = prefix_len; + strategy_conf.family = AF_INET6; + strategy_conf.type = strategy_type; + + hc_strategy_set(sock_, &strategy_conf); +} + void ForwarderInterface::internalDeleteFaceAndRoute( const RouteInfoPtr &route_info) { if (!sock_) return; @@ -346,10 +363,11 @@ void ForwarderInterface::internalCreateFaceAndRoutes( } max_try--; timer->expires_from_now(std::chrono::milliseconds(500)); - timer->async_wait([this, failed, max_try, timer](std::error_code ec) { - if (ec) return; - internalCreateFaceAndRoutes(failed, max_try, timer); - }); + timer->async_wait( + [this, failed, max_try, timer](const std::error_code &ec) { + if (ec) return; + internalCreateFaceAndRoutes(failed, max_try, timer); + }); return; } @@ -422,16 +440,18 @@ int ForwarderInterface::tryToCreateFace(RouteInfo *route_info, std::string name = "l_" + route_info->name; listener.local_addr = local_address; - listener.type = CONNECTION_TYPE_UDP; + listener.type = FACE_TYPE_UDP; listener.family = AF_INET; listener.local_port = route_info->local_port; - strncpy(listener.name, name.c_str(), sizeof(listener.name)); - strncpy(listener.interface_name, route_info->interface.c_str(), - sizeof(listener.interface_name)); + int ret = strcpy_s(listener.name, SYMBOLIC_NAME_LEN - 1, name.c_str()); + if (ret < EOK) goto ERR; + ret = strcpy_s(listener.interface_name, INTERFACE_LEN - 1, + route_info->interface.c_str()); + if (ret < EOK) goto ERR; std::cout << "------------> " << route_info->interface << std::endl; - int ret = hc_listener_create(sock_, &listener); + ret = hc_listener_create(sock_, &listener); if (ret < 0) { std::cerr << "Error creating listener." << std::endl; @@ -520,7 +540,7 @@ int ForwarderInterface::tryToCreateRoute(RouteInfo *route_info, #if 0 // not used void ForwarderInterface::checkRoutesLoop() { check_routes_timer_->expires_from_now(std::chrono::milliseconds(1000)); - check_routes_timer_->async_wait([this](std::error_code ec) { + check_routes_timer_->async_wait([this](const std::error_code &ec) { if (ec) return; if (pending_add_route_counter_ == 0) checkRoutes(); }); @@ -580,7 +600,7 @@ void ForwarderInterface::checkRoutes() { } else { // XXX This should be moved somewhere else getMainListener( - [this](std::error_code ec, uint32_t hicn_listen_port) { + [this](const std::error_code &ec, uint32_t hicn_listen_port) { if (!ec) { hicn_listen_port_ = hicn_listen_port; @@ -597,7 +617,7 @@ void ForwarderInterface::checkRoutes() { tryToConnectToForwarder(); } private: - void doGetMainListener(std::error_code ec) + void doGetMainListener(const std::error_code &ec) { if (!ec) { @@ -607,7 +627,7 @@ void ForwarderInterface::checkRoutes() { { // Since without the main listener of the forwarder the proxy cannot // work, we can stop the program here until we get the listener port. - std::cout << + std::cout << "Could not retrieve main listener port from the forwarder. " "Retrying."; @@ -635,7 +655,7 @@ void ForwarderInterface::checkRoutes() { doTryToConnectToForwarder(std::make_error_code(std::errc(0))); } - void doTryToConnectToForwarder(std::error_code ec) + void doTryToConnectToForwarder(const std::error_code &ec) { if (!ec) { @@ -673,4 +693,4 @@ void ForwarderInterface::checkRoutes() { constexpr uint32_t ForwarderInterface::REATTEMPT_DELAY_MS; constexpr uint32_t ForwarderInterface::MAX_REATTEMPT; -} // namespace hiperf
\ No newline at end of file +} // namespace hiperf diff --git a/apps/hiperf/src/forwarder_interface.h b/apps/hiperf/src/forwarder_interface.h index 7591ea257..e58989295 100644 --- a/apps/hiperf/src/forwarder_interface.h +++ b/apps/hiperf/src/forwarder_interface.h @@ -15,6 +15,8 @@ #pragma once +#include <hicn/transport/utils/noncopyable.h> + extern "C" { #ifndef WITH_POLICY #define WITH_POLICY @@ -27,14 +29,13 @@ extern "C" { #define ASIO_STANDALONE #endif #include <asio.hpp> - #include <functional> #include <thread> #include <unordered_map> namespace hiperf { -class ForwarderInterface { +class ForwarderInterface : ::utils::NonCopyable { static const uint32_t REATTEMPT_DELAY_MS = 500; static const uint32_t MAX_REATTEMPT = 10; @@ -68,10 +69,14 @@ class ForwarderInterface { }; public: - ForwarderInterface(asio::io_service &io_service, ICallback *callback); + explicit ForwarderInterface(asio::io_service &io_service); + explicit ForwarderInterface(asio::io_service &io_service, ICallback *callback, + forwarder_type_t fwd_type); ~ForwarderInterface(); + void initForwarderInterface(ICallback *callback, forwarder_type_t fwd_type); + State getState(); void setState(State state); @@ -88,11 +93,16 @@ class ForwarderInterface { void deleteFaceAndRoute(const RouteInfoPtr &route_info); + void setStrategy(std::string prefix, uint32_t prefix_len, + std::string strategy); + void close(); uint16_t getHicnListenerPort() { return hicn_listen_port_; } private: + ForwarderInterface &operator=(const ForwarderInterface &other) = delete; + int connectToForwarder(); int checkListener(); @@ -123,6 +133,8 @@ class ForwarderInterface { State state_; + forwarder_type_t fwd_type_; + /* Reattempt timer */ asio::steady_timer timer_; unsigned num_reattempts; diff --git a/apps/hiperf/src/main.cc b/apps/hiperf/src/main.cc index b2d99c4a4..b69392de8 100644 --- a/apps/hiperf/src/main.cc +++ b/apps/hiperf/src/main.cc @@ -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: @@ -14,13 +14,13 @@ */ #include <client.h> -#include <server.h> #include <forwarder_interface.h> +#include <server.h> namespace hiperf { void usage() { - std::cerr << "HIPERF - A tool for performing network throughput " + std::cerr << "HIPERF - Instrumentation tool for performing active network" "measurements with hICN" << std::endl; std::cerr << "usage: hiperf [-S|-C] [options] [prefix|name]" << std::endl; @@ -34,19 +34,27 @@ void usage() { std::cerr << "-f\t<filename>\t\t\t" << "Log file" << std::endl; std::cerr << "-z\t<io_module>\t\t\t" - << "IO module to use. Default: hicnlight_module" << std::endl; + << "IO module to use. Default: hicnlightng_module" << std::endl; + std::cerr << "-F\t<conf_file>\t\t\t" + << "Path to optional configuration file for libtransport" + << std::endl; + std::cerr << "-a\t\t\t\t\t" + << "Enables data packet aggregation. " + << "Works only in RTC mode" << std::endl; + std::cerr << "-X\t<param>\t\t\t\t" + << "Set FEC params. Options are Rely_K#_N# or RS_K#_N#" + << std::endl; #endif std::cerr << std::endl; std::cerr << "SERVER SPECIFIC:" << std::endl; std::cerr << "-A\t<content_size>\t\t\t" - "Size of the content to publish. This " - "is not the size of the packet (see -s for it)." - << std::endl; - std::cerr << "-s\t<packet_size>\t\t\tSize of the payload of each data packet." + "Sends an application data unit in bytes that is published once " + "before exit" << std::endl; + std::cerr << "-s\t<packet_size>\t\t\tData packet payload size." << std::endl; std::cerr << "-r\t\t\t\t\t" << "Produce real content of <content_size> bytes" << std::endl; - std::cerr << "-m\t\t\t\t\t" + std::cerr << "-m\t<manifest_capacity>\t\t" << "Produce transport manifest" << std::endl; std::cerr << "-l\t\t\t\t\t" << "Start producing content upon the reception of the " @@ -60,20 +68,17 @@ void usage() { << "String from which a 128-bit symmetric key will be " "derived for signing packets" << std::endl; + std::cerr << "-p\t<password>\t\t\t" + << "Password for p12 keystore" << std::endl; std::cerr << "-y\t<hash_algorithm>\t\t" << "Use the selected hash algorithm for " - "calculating manifest digests" + "computing manifest digests (default: SHA256)" << std::endl; - std::cerr << "-p\t<password>\t\t\t" - << "Password for p12 keystore" << std::endl; std::cerr << "-x\t\t\t\t\t" - << "Produce a content of <content_size>, then after downloading " - "it produce a new content of" - << "\n\t\t\t\t\t<content_size> without resetting " - "the suffix to 0." - << std::endl; + << "Produces application data units of size <content_size> " + << "without resetting the name suffix to 0." << std::endl; std::cerr << "-B\t<bitrate>\t\t\t" - << "Bitrate for RTC producer, to be used with the -R option." + << "RTC producer data bitrate, to be used with the -R option." << std::endl; #ifndef _WIN32 std::cerr << "-I\t\t\t\t\t" @@ -92,8 +97,8 @@ void usage() { "file containing the " "crypto material used for the TLS handshake" << std::endl; - std::cerr << "-G\t<port>\t\t\t" - << "input stream from localhost at the specified port" << std::endl; + std::cerr << "-G\t<port>\t\t\t\t" + << "Input stream from localhost at the specified port" << std::endl; #endif std::cerr << std::endl; std::cerr << "CLIENT SPECIFIC:" << std::endl; @@ -105,6 +110,8 @@ void usage() { << std::endl; std::cerr << "-L\t<interest lifetime>\t\t" << "Set interest lifetime." << std::endl; + std::cerr << "-u\t<delay>\t\t\t\t" + << "Set max lifetime of unverified packets." << std::endl; std::cerr << "-M\t<input_buffer_size>\t\t" << "Size of consumer input buffer. If 0, reassembly of packets " "will be disabled." @@ -127,17 +134,31 @@ void usage() { std::cerr << "-t\t\t\t\t\t" "Test mode, check if the client is receiving the " "correct data. This is an RTC specific option, to be " - "used with the -R (default false)" + "used with the -R (default: false)" << std::endl; std::cerr << "-P\t\t\t\t\t" << "Prefix of the producer where to do the handshake" << std::endl; std::cerr << "-j\t<relay_name>\t\t\t" - << "Publish the received content under the name relay_name." + << "Publish received content under the name relay_name." "This is an RTC specific option, to be " - "used with the -R (default false)" + "used with the -R (default: false)" + << std::endl; + std::cerr << "-g\t<port>\t\t\t\t" + << "Output stream to localhost at the specified port" << std::endl; + std::cerr << "-e\t<strategy>\t\t\t" + << "Enance the network with a realiability strategy. Options 1:" + << " unreliable, 2: rtx only, 3: fec only, " + << "4: delay based, 5: low rate, 6: low rate and best path " + << "7: low rate and replication, 8: low rate and best" + << " path/replication" + << "(default: 2 = rtx only) " << std::endl; + std::cerr << "-H\t\t\t\t\t" + << "Disable periodic print headers in stats report." << std::endl; + std::cerr << "-n\t<nb_iterations>\t\t\t" + << "Print the stats report <nb_iterations> times and exit.\n" + << "\t\t\t\t\tThis option limits the duration of the run to " + "<nb_iterations> * <stats_interval> milliseconds." << std::endl; - std::cerr << "-g\t<port>\t\t\t" - << "output stream to localhost at the specified port" << std::endl; } int main(int argc, char *argv[]) { @@ -156,7 +177,7 @@ int main(int argc, char *argv[]) { char *log_file = nullptr; transport::interface::global_config::IoModuleConfiguration config; std::string conf_file; - config.name = "hicnlight_module"; + config.name = "hicnlightng_module"; // Consumer ClientConfiguration client_configuration; @@ -166,10 +187,9 @@ int main(int argc, char *argv[]) { int opt; #ifndef _WIN32 - while ((opt = getopt( - argc, argv, - "DSCf:b:d:W:RM:c:vA:s:rmlK:k:y:p:hi:xE:P:B:ItL:z:T:F:j:g:G:")) != - -1) { + while ((opt = getopt(argc, argv, + "DSCf:b:d:W:RM:c:vA:s:rm:lK:k:y:p:hi:xE:P:B:ItL:z:T:F:j:" + "g:G:e:awHn:X:u:")) != -1) { switch (opt) { // Common case 'D': { @@ -202,9 +222,11 @@ int main(int argc, char *argv[]) { break; } #else - while ((opt = getopt(argc, argv, - "SCf:b:d:W:RM:c:vA:s:rmlK:k:y:p:hi:xB:E:P:tL:z:F:j:")) != - -1) { + while ( + (opt = getopt( + argc, argv, + "SCf:b:d:W:RM:c:vA:s:rm:lK:k:y:p:hi:xB:E:P:tL:z:F:j:e:awHn:X:u:")) != + -1) { switch (opt) { #endif case 'f': { @@ -216,6 +238,21 @@ int main(int argc, char *argv[]) { server_configuration.rtc_ = true; break; } + case 'a': { + client_configuration.aggregated_data_ = true; + server_configuration.aggregated_data_ = true; + break; + } + case 'X': { + client_configuration.fec_type_ = std::string(optarg); + server_configuration.fec_type_ = std::string(optarg); + break; + } + case 'w': { + client_configuration.packet_format_ = Packet::Format::HF_INET6_UDP; + server_configuration.packet_format_ = Packet::Format::HF_INET6_UDP; + break; + } case 'z': { config.name = optarg; break; @@ -286,12 +323,27 @@ int main(int argc, char *argv[]) { options = 1; break; } + case 'u': { + client_configuration.unverified_delay_ = std::stoul(optarg); + options = 1; + break; + } case 'j': { client_configuration.relay_ = true; client_configuration.relay_name_ = Prefix(optarg); options = 1; break; } + case 'H': { + client_configuration.print_headers_ = false; + options = 1; + break; + } + case 'n': { + client_configuration.nb_iterations_ = std::stoul(optarg); + options = 1; + break; + } // Server specific case 'A': { server_configuration.download_size = std::stoul(optarg); @@ -309,7 +361,7 @@ int main(int argc, char *argv[]) { break; } case 'm': { - server_configuration.manifest = true; + server_configuration.manifest = std::stoul(optarg); options = -1; break; } @@ -324,18 +376,19 @@ int main(int argc, char *argv[]) { break; } case 'y': { + CryptoHashType hash_algorithm = CryptoHashType::SHA256; if (strncasecmp(optarg, "sha256", 6) == 0) { - server_configuration.hash_algorithm = CryptoHashType::SHA256; + hash_algorithm = CryptoHashType::SHA256; } else if (strncasecmp(optarg, "sha512", 6) == 0) { - server_configuration.hash_algorithm = CryptoHashType::SHA512; + hash_algorithm = CryptoHashType::SHA512; } else if (strncasecmp(optarg, "blake2b512", 10) == 0) { - server_configuration.hash_algorithm = CryptoHashType::BLAKE2B512; + hash_algorithm = CryptoHashType::BLAKE2B512; } else if (strncasecmp(optarg, "blake2s256", 10) == 0) { - server_configuration.hash_algorithm = CryptoHashType::BLAKE2S256; + hash_algorithm = CryptoHashType::BLAKE2S256; } else { - std::cerr << "Ignored unknown hash algorithm. Using SHA 256." - << std::endl; + std::cerr << "Unknown hash algorithm. Using SHA 256." << std::endl; } + server_configuration.hash_algorithm_ = hash_algorithm; options = -1; break; } @@ -361,6 +414,11 @@ int main(int argc, char *argv[]) { server_configuration.secure_ = true; break; } + case 'e': { + client_configuration.recovery_strategy_ = std::stoul(optarg); + options = 1; + break; + } case 'h': default: usage(); @@ -430,6 +488,13 @@ int main(int argc, char *argv[]) { transport::interface::global_config::parseConfigurationFile(conf_file); if (role > 0) { + // set forwarder type + client_configuration.forwarder_type_ = UNDEFINED; + if (config.name.compare("hicnlightng_module") == 0) + client_configuration.forwarder_type_ = HICNLIGHT; + else if (config.name.compare("hicnlightng_module") == 0) + client_configuration.forwarder_type_ = HICNLIGHT_NG; + HIperfClient c(client_configuration); if (c.setup() != ERROR_SETUP) { c.run(); diff --git a/apps/hiperf/src/server.cc b/apps/hiperf/src/server.cc index 968d42e2c..7101e7a4a 100644 --- a/apps/hiperf/src/server.cc +++ b/apps/hiperf/src/server.cc @@ -21,7 +21,7 @@ namespace hiperf { * Hiperf server class: configure and setup an hicn producer following the * ServerConfiguration. */ -class HIperfServer::Impl { +class HIperfServer::Impl : public ProducerSocket::Callback { const std::size_t log2_content_object_buffer_size = 8; public: @@ -35,11 +35,8 @@ class HIperfServer::Impl { mask_((std::uint16_t)(1 << log2_content_object_buffer_size) - 1), last_segment_(0), #ifndef _WIN32 - ptr_last_segment_(&last_segment_), input_(io_service_), rtc_running_(false), -#else - ptr_last_segment_(&last_segment_), #endif flow_name_(configuration_.name.getName()), socket_(io_service_), @@ -54,14 +51,16 @@ class HIperfServer::Impl { #endif for (int i = 0; i < (1 << log2_content_object_buffer_size); i++) { - content_objects_[i] = ContentObject::Ptr( - new ContentObject(conf.name.getName(), HF_INET6_TCP, 0, - (const uint8_t *)buffer.data(), buffer.size())); + content_objects_[i] = ContentObject::Ptr(new ContentObject( + configuration_.name.getName(), configuration_.packet_format_, 0, + (const uint8_t *)buffer.data(), buffer.size())); content_objects_[i]->setLifetime( default_values::content_object_expiry_time); } } + virtual ~Impl() {} + void virtualProcessInterest(ProducerSocket &p, const Interest &interest) { content_objects_[content_objects_index_ & mask_]->setName( interest.getName()); @@ -91,16 +90,14 @@ class HIperfServer::Impl { if (suffix == 0) { last_segment_ = 0; - ptr_last_segment_ = &last_segment_; unsatisfied_interests_.clear(); } - // The suffix will either be the one from the received interest or the - // smallest suffix of a previous interest not satisfed + // The suffix will either come from the received interest or will be set to + // the smallest suffix of a previous interest not satisfied if (!unsatisfied_interests_.empty()) { - auto it = - std::lower_bound(unsatisfied_interests_.begin(), - unsatisfied_interests_.end(), *ptr_last_segment_); + auto it = std::lower_bound(unsatisfied_interests_.begin(), + unsatisfied_interests_.end(), last_segment_); if (it != unsatisfied_interests_.end()) { suffix = *it; } @@ -121,27 +118,28 @@ class HIperfServer::Impl { b->append(configuration_.download_size); uint32_t total; - utils::TimePoint t0 = utils::SteadyClock::now(); + utils::SteadyTime::TimePoint t0 = utils::SteadyTime::Clock::now(); total = p.produceStream(content_name, std::move(b), !configuration_.multiphase_produce_, suffix); - utils::TimePoint t1 = utils::SteadyClock::now(); + utils::SteadyTime::TimePoint t1 = utils::SteadyTime::Clock::now(); - std::cout - << "Written " << total - << " data packets in output buffer (Segmentation time: " - << std::chrono::duration_cast<utils::Microseconds>(t1 - t0).count() - << " us)" << std::endl; + std::cout << "Written " << total + << " data packets in output buffer (Segmentation time: " + << utils::SteadyTime::getDurationUs(t0, t1).count() << " us)" + << std::endl; } void produceContentAsync(ProducerSocket &p, Name content_name, uint32_t suffix) { - auto b = utils::MemBuf::create(configuration_.download_size); - std::memset(b->writableData(), '?', configuration_.download_size); - b->append(configuration_.download_size); - - p.asyncProduce(content_name, std::move(b), - !configuration_.multiphase_produce_, suffix, - &ptr_last_segment_); + produce_thread_.add([this, suffix, content_name]() { + auto b = utils::MemBuf::create(configuration_.download_size); + std::memset(b->writableData(), '?', configuration_.download_size); + b->append(configuration_.download_size); + + last_segment_ = suffix + producer_socket_->produceStream( + content_name, std::move(b), + !configuration_.multiphase_produce_, suffix); + }); } void cacheMiss(ProducerSocket &p, const Interest &interest) { @@ -156,27 +154,22 @@ class HIperfServer::Impl { std::placeholders::_1, std::placeholders::_2)); } - std::shared_ptr<Identity> getProducerIdentity(std::string &keystore_path, - std::string &keystore_pwd, - CryptoHashType &hash_type) { - if (access(keystore_path.c_str(), F_OK) != -1) { - return std::make_shared<Identity>(keystore_path, keystore_pwd, hash_type); - } - return std::make_shared<Identity>(keystore_path, keystore_pwd, - CryptoSuite::RSA_SHA256, 1024, 365, - "producer-test"); + void produceError(const std::error_code &err) noexcept override { + std::cerr << "Error from producer transport: " << err.message() + << std::endl; + producer_socket_->stop(); + io_service_.stop(); } int setup() { int ret; int production_protocol; + std::shared_ptr<Signer> signer = std::make_shared<VoidSigner>(); if (configuration_.secure_) { - auto identity = getProducerIdentity(configuration_.keystore_name, - configuration_.keystore_password, - configuration_.hash_algorithm); producer_socket_ = std::make_unique<P2PSecureProducerSocket>( - configuration_.rtc_, identity); + configuration_.rtc_, configuration_.keystore_name, + configuration_.keystore_password); } else { if (!configuration_.rtc_) { production_protocol = ProductionProtocolAlgorithms::BYTE_STREAM; @@ -188,36 +181,79 @@ class HIperfServer::Impl { } if (producer_socket_->setSocketOption( + ProducerCallbacksOptions::PRODUCER_CALLBACK, this) == + SOCKET_OPTION_NOT_SET) { + std::cerr << "Failed to set producer callback." << std::endl; + return ERROR_SETUP; + } + + if (producer_socket_->setSocketOption( GeneralTransportOptions::MAKE_MANIFEST, configuration_.manifest) == SOCKET_OPTION_NOT_SET) { return ERROR_SETUP; } + if (producer_socket_->setSocketOption( + GeneralTransportOptions::HASH_ALGORITHM, + configuration_.hash_algorithm_) == SOCKET_OPTION_NOT_SET) { + return ERROR_SETUP; + } + + if (producer_socket_->setSocketOption(PACKET_FORMAT, + configuration_.packet_format_) == + SOCKET_OPTION_NOT_SET) { + std::cerr << "ERROR -- Impossible to set the packet format." << std::endl; + return ERROR_SETUP; + } + if (!configuration_.passphrase.empty()) { - std::shared_ptr<Signer> signer = std::make_shared<SymmetricSigner>( - CryptoSuite::HMAC_SHA256, configuration_.passphrase); - producer_socket_->setSocketOption(GeneralTransportOptions::SIGNER, - signer); + signer = std::make_shared<SymmetricSigner>(CryptoSuite::HMAC_SHA256, + configuration_.passphrase); } if (!configuration_.keystore_name.empty()) { - auto identity = getProducerIdentity(configuration_.keystore_name, - configuration_.keystore_password, - configuration_.hash_algorithm); - std::shared_ptr<Signer> signer = identity->getSigner(); - producer_socket_->setSocketOption(GeneralTransportOptions::SIGNER, - signer); + signer = std::make_shared<AsymmetricSigner>( + configuration_.keystore_name, configuration_.keystore_password); + } + + producer_socket_->setSocketOption(GeneralTransportOptions::SIGNER, signer); + + // Compute maximum payload size + Packet::Format format = PayloadSize::getFormatFromName( + configuration_.name.getName(), !configuration_.manifest); + payload_size_max_ = PayloadSize(format).getPayloadSizeMax( + configuration_.rtc_ ? RTC_HEADER_SIZE : 0, + configuration_.fec_type_.empty() ? 0 : FEC_HEADER_MAX_SIZE, + !configuration_.manifest ? signer->getSignatureFieldSize() : 0); + + if (configuration_.payload_size_ > payload_size_max_) { + std::cerr << "WARNING: Payload has size " << configuration_.payload_size_ + << ", maximum is " << payload_size_max_ + << ". Payload will be truncated to fit." << std::endl; + } + + if (configuration_.rtc_) { + ret = producer_socket_->setSocketOption( + RtcTransportOptions::AGGREGATED_DATA, + configuration_.aggregated_data_); + + if (ret == SOCKET_OPTION_NOT_SET) { + return ERROR_SETUP; + } + } + + if (configuration_.rtc_) { + ret = producer_socket_->setSocketOption(GeneralTransportOptions::FEC_TYPE, + configuration_.fec_type_); + + if (ret == SOCKET_OPTION_NOT_SET) { + return ERROR_SETUP; + } } - uint32_t rtc_header_size = 0; - if (configuration_.rtc_) rtc_header_size = 12; - producer_socket_->setSocketOption( - GeneralTransportOptions::DATA_PACKET_SIZE, - (uint32_t)( - configuration_.payload_size_ + rtc_header_size + - (configuration_.name.getAddressFamily() == AF_INET ? 40 : 60))); producer_socket_->registerPrefix(configuration_.name); producer_socket_->connect(); + producer_socket_->start(); if (configuration_.rtc_) { std::cout << "Running RTC producer: the prefix length will be ignored." @@ -239,6 +275,13 @@ class HIperfServer::Impl { return ERROR_SETUP; } + if (producer_socket_->setSocketOption( + GeneralTransportOptions::MAX_SEGMENT_SIZE, + static_cast<uint32_t>(configuration_.payload_size_)) == + SOCKET_OPTION_NOT_SET) { + return ERROR_SETUP; + } + if (!configuration_.live_production) { produceContent(*producer_socket_, configuration_.name.getName(), 0); } else { @@ -283,7 +326,7 @@ class HIperfServer::Impl { void receiveStream() { socket_.async_receive_from( asio::buffer(recv_buffer_.first, recv_buffer_.second), remote_, - [this](std::error_code ec, std::size_t length) { + [this](const std::error_code &ec, std::size_t length) { if (ec) return; sendRTCContentFromStream(recv_buffer_.first, length); receiveStream(); @@ -296,9 +339,8 @@ class HIperfServer::Impl { // this is used to compute the data packet delay // Used only for performance evaluation // It requires clock synchronization between producer and consumer - uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>( - std::chrono::system_clock::now().time_since_epoch()) - .count(); + uint64_t now = utils::SystemTime::nowMs().count(); + uint8_t *start = (uint8_t *)payload->writableData(); std::memcpy(start, &now, sizeof(uint64_t)); std::memcpy(start + sizeof(uint64_t), buff, len); @@ -306,7 +348,7 @@ class HIperfServer::Impl { len + sizeof(uint64_t)); } - void sendRTCContentObjectCallback(std::error_code ec) { + void sendRTCContentObjectCallback(const std::error_code &ec) { if (ec) return; rtc_timer_.expires_from_now( configuration_.production_rate_.getMicrosecondsForPacket( @@ -319,18 +361,17 @@ class HIperfServer::Impl { // this is used to compute the data packet delay // Used only for performance evaluation // It requires clock synchronization between producer and consumer - uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>( - std::chrono::system_clock::now().time_since_epoch()) - .count(); + uint64_t now = utils::SystemTime::nowMs().count(); std::memcpy(payload->writableData(), &now, sizeof(uint64_t)); - producer_socket_->produceDatagram( - flow_name_, payload->data(), - payload->length() < 1400 ? payload->length() : 1400); + producer_socket_->produceDatagram(flow_name_, payload->data(), + payload->length() < payload_size_max_ + ? payload->length() + : payload_size_max_); } - void sendRTCContentObjectCallbackWithTrace(std::error_code ec) { + void sendRTCContentObjectCallbackWithTrace(const std::error_code &ec) { if (ec) return; auto payload = @@ -342,14 +383,11 @@ class HIperfServer::Impl { // this is used to compute the data packet delay // used only for performance evaluation // it requires clock synchronization between producer and consumer - uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>( - std::chrono::system_clock::now().time_since_epoch()) - .count(); - + uint64_t now = utils::SystemTime::nowMs().count(); std::memcpy(payload->writableData(), &now, sizeof(uint64_t)); if (packet_len > payload->length()) packet_len = payload->length(); - if (packet_len > 1400) packet_len = 1400; + if (packet_len > payload_size_max_) packet_len = payload_size_max_; producer_socket_->produceDatagram(flow_name_, payload->data(), packet_len); @@ -450,13 +488,13 @@ class HIperfServer::Impl { std::placeholders::_1)); } else if (configuration_.input_stream_mode_) { rtc_running_ = true; - // crate socket + // create socket remote_ = asio::ip::udp::endpoint( asio::ip::address::from_string("127.0.0.1"), configuration_.port_); socket_.open(asio::ip::udp::v4()); socket_.bind(remote_); - recv_buffer_.first = (uint8_t *)malloc(1500); - recv_buffer_.second = 1500; + recv_buffer_.first = (uint8_t *)malloc(HIPERF_MTU); + recv_buffer_.second = HIPERF_MTU; receiveStream(); } else { rtc_running_ = true; @@ -490,8 +528,9 @@ class HIperfServer::Impl { std::uint16_t content_objects_index_; std::uint16_t mask_; std::uint32_t last_segment_; - std::uint32_t *ptr_last_segment_; std::unique_ptr<ProducerSocket> producer_socket_; + ::utils::EventThread produce_thread_; + std::size_t payload_size_max_; #ifndef _WIN32 asio::posix::stream_descriptor input_; asio::streambuf input_buffer_; @@ -507,6 +546,20 @@ HIperfServer::HIperfServer(const ServerConfiguration &conf) { impl_ = new Impl(conf); } +HIperfServer::HIperfServer(HIperfServer &&other) { + impl_ = other.impl_; + other.impl_ = nullptr; +} + +HIperfServer &HIperfServer::operator=(HIperfServer &&other) { + if (this != &other) { + impl_ = other.impl_; + other.impl_ = nullptr; + } + + return *this; +} + HIperfServer::~HIperfServer() { delete impl_; } int HIperfServer::setup() { return impl_->setup(); } diff --git a/apps/hiperf/src/server.h b/apps/hiperf/src/server.h index 05407a807..73ac72123 100644 --- a/apps/hiperf/src/server.h +++ b/apps/hiperf/src/server.h @@ -22,6 +22,9 @@ namespace hiperf { class HIperfServer { public: HIperfServer(const ServerConfiguration &conf); + HIperfServer(HIperfServer &&other); + HIperfServer &operator=(HIperfServer &&other); + ~HIperfServer(); int setup(); void run(); diff --git a/apps/http-proxy/CMakeLists.txt b/apps/http-proxy/CMakeLists.txt index 66b9c1bab..dbe9bc51c 100644 --- a/apps/http-proxy/CMakeLists.txt +++ b/apps/http-proxy/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2019 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,8 +11,12 @@ # See the License for the specific language governing permissions and # limitations under the License. -cmake_minimum_required(VERSION 3.10 FATAL_ERROR) -set(CMAKE_CXX_STANDARD 14) +############################################################## +# Compiler options +############################################################## +set(COMPILER_OPTIONS + ${DEFAULT_COMPILER_OPTIONS} +) # -Wno-c99-designator issue # @@ -22,20 +26,22 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") EXECUTE_PROCESS( COMMAND ${CMAKE_CXX_COMPILER} --version OUTPUT_VARIABLE clang_full_version_string ) string (REGEX REPLACE ".*clang version ([0-9]+\\.[0-9]+).*" "\\1" CLANG_VERSION_STRING ${clang_full_version_string}) if (CLANG_VERSION_STRING VERSION_GREATER_EQUAL 11) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-c99-designator") + list(APPEND COMPILER_OPTIONS + "-Wno-c99-designator" + ) endif() endif() -set(CMAKE_MODULE_PATH - ${CMAKE_MODULE_PATH} - "${CMAKE_SOURCE_DIR}/cmake/Modules/" -) -if (NOT CMAKE_BUILD_TYPE) - message(STATUS "${PROJECT_NAME}: No build type selected, default to Release") - set(CMAKE_BUILD_TYPE "Release") -endif () +############################################################## +# Includes subdirectory +############################################################## +add_subdirectory(includes/hicn/http-proxy) + +############################################################## +# Source files +############################################################## set(LIB_SOURCE_FILES src/http_session.cc src/http_proxy.cc @@ -48,41 +54,45 @@ set(APP_SOURCE_FILES main.cc ) -add_subdirectory(includes/hicn/http-proxy) -set(LIBHTTP_PROXY hicnhttpproxy) -set(LIBHTTP_PROXY_STATIC ${LIBHTTP_PROXY}.static) - -list(APPEND COMPILER_DEFINITIONS - -DWITH_POLICY -) - +############################################################## +# Libraries to link +############################################################## list(APPEND HTTP_PROXY_LIBRARIES - ${LIBTRANSPORT_LIBRARIES} - ${LIBHICNCTRL_LIBRARIES} - ${LIBHICN_LIBRARIES} - ${OPENSSL_LIBRARIES} - ${CMAKE_THREAD_LIBS_INIT} + PUBLIC ${LIBTRANSPORT_LIBRARIES} + PUBLIC ${LIBHICNCTRL_LIBRARIES} + PUBLIC ${LIBHICN_LIBRARIES} + PRIVATE ${CMAKE_THREAD_LIBS_INIT} ) + +############################################################## +# Build http proxy library +############################################################## build_library(${LIBHTTP_PROXY} STATIC SOURCES ${LIB_SOURCE_FILES} LINK_LIBRARIES ${HTTP_PROXY_LIBRARIES} DEPENDS ${DEPENDENCIES} INSTALL_HEADERS ${LIBPROXY_TO_INSTALL_HEADER_FILES} - INCLUDE_DIRS ${LIBTRANSPORT_INCLUDE_DIRS} ${LIBHICNCTRL_INCLUDE_DIRS} ${LIBPROXY_INCLUDE_DIRS} + INCLUDE_DIRS + PUBLIC + $<BUILD_INTERFACE:${LIBPROXY_INCLUDE_DIRS}> + $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> COMPONENT ${HICN_APPS} LINK_FLAGS ${LINK_FLAGS} - DEFINITIONS ${COMPILER_DEFINITIONS} + COMPILE_OPTIONS ${COMPILER_OPTIONS} ) + +############################################################## +# Build http proxy executable +############################################################## if (NOT DISABLE_EXECUTABLES) build_executable(${HTTP_PROXY} SOURCES ${APP_SOURCE_FILES} LINK_LIBRARIES ${LIBHTTP_PROXY_STATIC} DEPENDS ${LIBHTTP_PROXY_STATIC} COMPONENT ${HICN_APPS} - DEFINITIONS ${COMPILER_DEFINITIONS} LINK_FLAGS ${LINK_FLAGS} ) endif () diff --git a/apps/http-proxy/includes/hicn/http-proxy/CMakeLists.txt b/apps/http-proxy/includes/hicn/http-proxy/CMakeLists.txt index 5cc80a168..18f5704d1 100644 --- a/apps/http-proxy/includes/hicn/http-proxy/CMakeLists.txt +++ b/apps/http-proxy/includes/hicn/http-proxy/CMakeLists.txt @@ -1,4 +1,4 @@ -# 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: @@ -24,7 +24,7 @@ list(APPEND HEADER_FILES set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE) set(LIBPROXY_INCLUDE_DIRS - ${CMAKE_CURRENT_SOURCE_DIR}/../.. "" + ${CMAKE_CURRENT_SOURCE_DIR}/../.. CACHE INTERNAL "" FORCE ) @@ -34,4 +34,3 @@ set(LIBPROXY_TO_INSTALL_HEADER_FILES CACHE INTERNAL "" FORCE ) - diff --git a/apps/http-proxy/includes/hicn/http-proxy/forwarder_config.h b/apps/http-proxy/includes/hicn/http-proxy/forwarder_config.h index e02b9d9a7..935b85e78 100644 --- a/apps/http-proxy/includes/hicn/http-proxy/forwarder_config.h +++ b/apps/http-proxy/includes/hicn/http-proxy/forwarder_config.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 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: @@ -60,7 +60,7 @@ class ForwarderConfig { doTryToConnectToForwarder(std::make_error_code(std::errc(0))); } - void doTryToConnectToForwarder(std::error_code ec) { + void doTryToConnectToForwarder(const std::error_code& ec) { if (!ec) { // ec == 0 --> timer expired int ret = forwarder_interface_.connectToForwarder(); @@ -84,7 +84,7 @@ class ForwarderConfig { } } - void doGetMainListener(std::error_code ec) { + void doGetMainListener(const std::error_code& ec) { if (!ec) { // ec == 0 --> timer expired int ret = forwarder_interface_.getMainListenerPort(); @@ -114,7 +114,7 @@ class ForwarderConfig { TRANSPORT_ALWAYS_INLINE bool parseHicnHeader(std::string& header, Callback&& callback) { std::stringstream ss(header); - route_info_t* ret = new route_info_t(); + RouteInfoPtr ret = std::make_shared<route_info_t>(); std::string port_string; while (ss.good()) { @@ -174,9 +174,9 @@ class ForwarderConfig { ret->family = AF_INET; std::string _prefix = ret->route_addr; forwarder_interface_.createFaceAndRoute( - RouteInfoPtr(ret), [callback = std::forward<Callback>(callback), - configured_prefix = std::move(_prefix)]( - uint32_t route_id, bool result) { + std::move(ret), [callback = std::forward<Callback>(callback), + configured_prefix = std::move(_prefix)]( + uint32_t route_id, bool result) { callback(result, configured_prefix); }); diff --git a/apps/http-proxy/includes/hicn/http-proxy/forwarder_interface.h b/apps/http-proxy/includes/hicn/http-proxy/forwarder_interface.h index 54941a4ba..1741aedc6 100644 --- a/apps/http-proxy/includes/hicn/http-proxy/forwarder_interface.h +++ b/apps/http-proxy/includes/hicn/http-proxy/forwarder_interface.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 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: diff --git a/apps/http-proxy/includes/hicn/http-proxy/http_1x_message_fast_parser.h b/apps/http-proxy/includes/hicn/http-proxy/http_1x_message_fast_parser.h index 7c035c83b..87a5c7d4e 100644 --- a/apps/http-proxy/includes/hicn/http-proxy/http_1x_message_fast_parser.h +++ b/apps/http-proxy/includes/hicn/http-proxy/http_1x_message_fast_parser.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 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: diff --git a/apps/http-proxy/includes/hicn/http-proxy/http_proxy.h b/apps/http-proxy/includes/hicn/http-proxy/http_proxy.h index a4139a620..efb9f850e 100644 --- a/apps/http-proxy/includes/hicn/http-proxy/http_proxy.h +++ b/apps/http-proxy/includes/hicn/http-proxy/http_proxy.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 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: @@ -22,7 +22,9 @@ #include "http_session.h" #include "icn_receiver.h" +#ifndef ASIO_STANDALONE #define ASIO_STANDALONE +#endif #include <asio.hpp> #include <asio/version.hpp> #include <unordered_set> @@ -50,9 +52,9 @@ class TcpListener { void doAccept() { #if ((ASIO_VERSION / 100 % 1000) >= 12) acceptor_.async_accept( - [this](std::error_code ec, asio::ip::tcp::socket socket) { + [this](const std::error_code& ec, asio::ip::tcp::socket socket) { #else - acceptor_.async_accept(socket_, [this](std::error_code ec) { + acceptor_.async_accept(socket_, [this](const std::error_code& ec) { auto socket = std::move(socket_); #endif if (!ec) { diff --git a/apps/http-proxy/includes/hicn/http-proxy/http_session.h b/apps/http-proxy/includes/hicn/http-proxy/http_session.h index f4a3dbdee..ee9380a8c 100644 --- a/apps/http-proxy/includes/hicn/http-proxy/http_session.h +++ b/apps/http-proxy/includes/hicn/http-proxy/http_session.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 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: @@ -17,13 +17,12 @@ #include <hicn/transport/core/packet.h> -#include "http_1x_message_fast_parser.h" - -#define ASIO_STANDALONE #include <asio.hpp> #include <deque> #include <functional> +#include "http_1x_message_fast_parser.h" + namespace transport { using asio::ip::tcp; @@ -98,7 +97,7 @@ class HTTPSession { bool checkConnected(); private: - void handleRead(std::error_code ec, std::size_t length); + void handleRead(const std::error_code &ec, std::size_t length); void tryReconnection(); void startConnectionTimer(); void handleDeadline(const std::error_code &ec); diff --git a/apps/http-proxy/includes/hicn/http-proxy/icn_receiver.h b/apps/http-proxy/includes/hicn/http-proxy/icn_receiver.h index 780037665..ab90fab07 100644 --- a/apps/http-proxy/includes/hicn/http-proxy/icn_receiver.h +++ b/apps/http-proxy/includes/hicn/http-proxy/icn_receiver.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 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: @@ -13,6 +13,7 @@ * limitations under the License. */ +#include <hicn/http-proxy/http_session.h> #include <hicn/transport/core/prefix.h> #include <hicn/transport/interfaces/publication_options.h> #include <hicn/transport/interfaces/socket_producer.h> @@ -23,8 +24,6 @@ #include <cstring> #include <queue> #include <utility> - -#include <hicn/http-proxy/http_session.h> //#include "http_session.h" namespace transport { diff --git a/apps/http-proxy/includes/hicn/http-proxy/utils.h b/apps/http-proxy/includes/hicn/http-proxy/utils.h index d87c796d0..0df24dfd9 100644 --- a/apps/http-proxy/includes/hicn/http-proxy/utils.h +++ b/apps/http-proxy/includes/hicn/http-proxy/utils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 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: @@ -35,14 +35,13 @@ TRANSPORT_ALWAYS_INLINE std::string generatePrefix( str += pos; uint32_t locator_hash = utils::hash::fnv32_buf(str, strlen(str)); + uint16_t* word = (uint16_t*)&locator_hash; std::stringstream stream; stream << first_ipv6_word << ":0"; - for (uint16_t* word = (uint16_t*)&locator_hash; - std::size_t(word) < (std::size_t(&locator_hash) + sizeof(locator_hash)); - word++) { - stream << ":" << std::hex << *word; + for (std::size_t i = 0; i < sizeof(locator_hash) / 2; i++) { + stream << ":" << std::hex << word[i]; } stream << "::"; diff --git a/apps/http-proxy/main.cc b/apps/http-proxy/main.cc index d9c29ecde..9bd97e02e 100644 --- a/apps/http-proxy/main.cc +++ b/apps/http-proxy/main.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 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: @@ -139,7 +139,6 @@ int main(int argc, char** argv) { case 'h': default: return usage(argv[0]); - break; } } diff --git a/apps/http-proxy/src/forwarder_interface.cc b/apps/http-proxy/src/forwarder_interface.cc index c2448de9a..1c034f60f 100644 --- a/apps/http-proxy/src/forwarder_interface.cc +++ b/apps/http-proxy/src/forwarder_interface.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 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: @@ -163,7 +163,7 @@ void ForwarderInterface::internalCreateFaceAndRoute(RouteInfoPtr route_info, max_try--; timer->expires_from_now(std::chrono::milliseconds(500)); timer->async_wait([this, _route_info = std::move(route_info), max_try, - timer, callback](std::error_code ec) { + timer, callback](const std::error_code &ec) { if (ec) return; internalCreateFaceAndRoute(std::move(_route_info), max_try, timer, std::move(callback)); diff --git a/apps/http-proxy/src/http_1x_message_fast_parser.cc b/apps/http-proxy/src/http_1x_message_fast_parser.cc index 4b6b78d55..e97c33161 100644 --- a/apps/http-proxy/src/http_1x_message_fast_parser.cc +++ b/apps/http-proxy/src/http_1x_message_fast_parser.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 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: diff --git a/apps/http-proxy/src/http_proxy.cc b/apps/http-proxy/src/http_proxy.cc index 2040f7cfa..5abe8780f 100644 --- a/apps/http-proxy/src/http_proxy.cc +++ b/apps/http-proxy/src/http_proxy.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 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: @@ -36,7 +36,7 @@ class HTTPClientConnectionCallback : interface::ConsumerSocket::ReadCallback { : tcp_receiver_(tcp_receiver), thread_(thread), prefix_hash_(tcp_receiver_.prefix_hash_), - consumer_(TransportProtocolAlgorithms::RAAQM, thread_.getIoService()), + consumer_(TransportProtocolAlgorithms::RAAQM, thread_), session_(nullptr), current_size_(0) { consumer_.setSocketOption(ConsumerCallbacksOptions::READ_CALLBACK, this); @@ -69,8 +69,8 @@ class HTTPClientConnectionCallback : interface::ConsumerSocket::ReadCallback { std::uint16_t remote_port = socket.remote_endpoint().port(); TRANSPORT_LOG_INFO << "Client " << remote_address << ":" << remote_port << "disconnected."; - } catch (std::system_error& e) { - // Do nothing + } catch (asio::system_error& e) { + TRANSPORT_LOG_INFO << "Client disconnected."; } consumer_.stop(); @@ -191,7 +191,7 @@ class HTTPClientConnectionCallback : interface::ConsumerSocket::ReadCallback { session_->send(_buffer, []() {}); } - void readError(const std::error_code ec) noexcept { + void readError(const std::error_code& ec) noexcept { TRANSPORT_LOG_ERROR << "Error reading from hicn consumer socket. Closing session."; session_->close(); @@ -265,7 +265,7 @@ TcpReceiver::TcpReceiver(std::uint16_t port, const std::string& prefix, prefix_hash_(generatePrefix(prefix_, ipv6_first_word_)), forwarder_config_( thread_.getIoService(), - [this](std::error_code ec) { + [this](const std::error_code& ec) { if (!ec) { listener_.doAccept(); for (int i = 0; i < 10; i++) { diff --git a/apps/http-proxy/src/http_session.cc b/apps/http-proxy/src/http_session.cc index 84c814cbd..870f188cd 100644 --- a/apps/http-proxy/src/http_session.cc +++ b/apps/http-proxy/src/http_session.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 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: @@ -92,7 +92,7 @@ void HTTPSession::send(const uint8_t *packet, std::size_t len, io_service_.dispatch([this, packet, len, content_sent]() { asio::async_write(socket_, asio::buffer(packet, len), [content_sent = std::move(content_sent)]( - std::error_code ec, std::size_t /*length*/) { + const std::error_code &ec, std::size_t /*length*/) { if (!ec) { content_sent(); } @@ -131,7 +131,7 @@ void HTTPSession::doWrite() { auto &buffer = write_msgs_.front().first; asio::async_write(socket_, asio::buffer(buffer->data(), buffer->length()), - [this](std::error_code ec, std::size_t length) { + [this](const std::error_code &ec, std::size_t length) { if (TRANSPORT_EXPECT_FALSE(!ec)) { write_msgs_.front().second(); write_msgs_.pop_front(); @@ -142,7 +142,7 @@ void HTTPSession::doWrite() { }); } // namespace transport -void HTTPSession::handleRead(std::error_code ec, std::size_t length) { +void HTTPSession::handleRead(const std::error_code &ec, std::size_t length) { if (TRANSPORT_EXPECT_TRUE(!ec)) { content_length_ -= length; const uint8_t *buffer = @@ -207,7 +207,7 @@ void HTTPSession::doReadBody(std::size_t body_size, void HTTPSession::doReadChunkedHeader() { asio::async_read_until( socket_, input_buffer_, "\r\n", - [this](std::error_code ec, std::size_t length) { + [this](const std::error_code &ec, std::size_t length) { if (TRANSPORT_EXPECT_TRUE(!ec)) { const uint8_t *buffer = asio::buffer_cast<const uint8_t *>(input_buffer_.data()); @@ -226,7 +226,7 @@ void HTTPSession::doReadChunkedHeader() { void HTTPSession::doReadHeader() { asio::async_read_until( socket_, input_buffer_, "\r\n\r\n", - [this](std::error_code ec, std::size_t length) { + [this](const std::error_code &ec, std::size_t length) { if (TRANSPORT_EXPECT_TRUE(!ec)) { const uint8_t *buffer = asio::buffer_cast<const uint8_t *>(input_buffer_.data()); @@ -287,7 +287,7 @@ void HTTPSession::tryReconnection() { void HTTPSession::doConnect() { asio::async_connect( socket_, endpoint_iterator_, - [this](std::error_code ec, tcp::resolver::iterator) { + [this](const std::error_code &ec, tcp::resolver::iterator) { if (!ec) { timer_.cancel(); state_ = ConnectorState::CONNECTED; diff --git a/apps/http-proxy/src/icn_receiver.cc b/apps/http-proxy/src/icn_receiver.cc index ea8ac7191..954861e3a 100644 --- a/apps/http-proxy/src/icn_receiver.cc +++ b/apps/http-proxy/src/icn_receiver.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 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: @@ -112,6 +112,7 @@ void AsyncConsumerProducer::doReceive() { }); producer_socket_.connect(); + producer_socket_.start(); } void AsyncConsumerProducer::manageIncomingInterest( @@ -128,9 +129,9 @@ void AsyncConsumerProducer::manageIncomingInterest( if (seg >= _it->second.first) { // TRANSPORT_LOGD( - // "Ignoring interest with name %s for a content object which does not " - // "exist. (Request: %u, max: %u)", - // name.toString().c_str(), (uint32_t)seg, (uint32_t)_it->second.first); + // "Ignoring interest with name %s for a content object which does not + // " "exist. (Request: %u, max: %u)", name.toString().c_str(), + // (uint32_t)seg, (uint32_t)_it->second.first); return; } } @@ -168,7 +169,8 @@ void AsyncConsumerProducer::publishContent(const uint8_t* data, options.getLifetime()); if (TRANSPORT_EXPECT_FALSE(ret != SOCKET_OPTION_SET)) { - TRANSPORT_LOG_WARNING << "Warning: content object lifetime has not been set."; + TRANSPORT_LOG_WARNING + << "Warning: content object lifetime has not been set."; } const interface::Name& name = options.getName(); diff --git a/apps/ping/.clang-format b/apps/ping/.clang-format index cd21e2017..adc73c6fd 100644 --- a/apps/ping/.clang-format +++ b/apps/ping/.clang-format @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2021 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: diff --git a/apps/ping/CMakeLists.txt b/apps/ping/CMakeLists.txt index 42f7f98c1..a094cebe3 100644 --- a/apps/ping/CMakeLists.txt +++ b/apps/ping/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2019 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: @@ -12,28 +12,45 @@ # limitations under the License. if (NOT DISABLE_EXECUTABLES) +############################################################## +# Compiler options +############################################################## +set(COMPILER_OPTIONS + ${DEFAULT_COMPILER_OPTIONS} +) + +############################################################## +# Libraries to link +############################################################## list (APPEND PING_LIBRARIES - ${LIBTRANSPORT_LIBRARIES} - ${CMAKE_THREAD_LIBS_INIT} - ${WSOCK32_LIBRARY} - ${WS2_32_LIBRARY} + PRIVATE ${LIBHICN_LIBRARIES} + PRIVATE ${LIBTRANSPORT_LIBRARIES} + PRIVATE ${CMAKE_THREAD_LIBS_INIT} + PRIVATE ${WSOCK32_LIBRARY} + PRIVATE ${WS2_32_LIBRARY} ) +############################################################## +# Build ping server +############################################################## build_executable(hicn-ping-server SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/ping_server.cc LINK_LIBRARIES ${PING_LIBRARIES} - INCLUDE_DIRS ${LIBTRANSPORT_INCLUDE_DIRS} DEPENDS ${DEPENDENCIES} COMPONENT ${HICN_APPS} LINK_FLAGS ${LINK_FLAGS} + COMPILE_OPTIONS ${COMPILER_OPTIONS} ) +############################################################## +# Build ping client +############################################################## build_executable(hicn-ping-client SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/ping_client.cc LINK_LIBRARIES ${PING_LIBRARIES} - INCLUDE_DIRS ${LIBTRANSPORT_INCLUDE_DIRS} DEPENDS ${DEPENDENCIES} COMPONENT ${HICN_APPS} LINK_FLAGS ${LINK_FLAGS} + COMPILE_OPTIONS ${COMPILER_OPTIONS} ) endif ()
\ No newline at end of file diff --git a/apps/ping/src/ping_client.cc b/apps/ping/src/ping_client.cc index 24e0bf3ed..0217f2f8c 100644 --- a/apps/ping/src/ping_client.cc +++ b/apps/ping/src/ping_client.cc @@ -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: @@ -16,7 +16,9 @@ #include <hicn/transport/auth/verifier.h> #include <hicn/transport/core/global_object_pool.h> #include <hicn/transport/core/interest.h> +#include <hicn/transport/interfaces/global_conf_interface.h> #include <hicn/transport/interfaces/portal.h> +#include <hicn/transport/utils/chrono_typedefs.h> #include <asio/signal_set.hpp> #include <asio/steady_timer.hpp> @@ -32,7 +34,7 @@ namespace core { namespace ping { -typedef std::map<uint64_t, uint64_t> SendTimeMap; +typedef std::map<uint64_t, utils::SteadyTime::TimePoint> SendTimeMap; typedef auth::AsymmetricVerifier Verifier; class Configuration { @@ -77,17 +79,12 @@ class Configuration { } }; -class Client : interface::Portal::ConsumerCallback { +class Client : interface::Portal::TransportCallback { public: - Client(Configuration *c) - : portal_(), signals_(portal_.getIoService(), SIGINT) { + Client(Configuration *c) : portal_(), signals_(io_service_, SIGINT) { // Let the main thread to catch SIGINT - portal_.connect(); - portal_.setConsumerCallback(this); - signals_.async_wait(std::bind(&Client::afterSignal, this)); - - timer_.reset(new asio::steady_timer(portal_.getIoService())); + timer_.reset(new asio::steady_timer(portal_.getThread().getIoService())); config_ = c; sequence_number_ = config_->first_suffix_; last_jump_ = 0; @@ -105,19 +102,28 @@ class Client : interface::Portal::ConsumerCallback { void ping() { std::cout << "start ping" << std::endl; - doPing(); - portal_.runEventsLoop(); + + portal_.getThread().add([this]() { + portal_.connect(); + portal_.registerTransportCallback(this); + doPing(); + }); + + io_service_.run(); + } + + void onInterest(Interest &interest) override { + throw errors::RuntimeException("Unexpected interest received."); } void onContentObject(Interest &interest, ContentObject &object) override { - uint64_t rtt = 0; + double rtt = 0; if (!config_->certificate_.empty()) { - auto t0 = std::chrono::steady_clock::now(); + auto t0 = utils::SteadyTime::now(); if (verifier_.verifyPacket(&object)) { - auto t1 = std::chrono::steady_clock::now(); - auto dt = - std::chrono::duration_cast<std::chrono::microseconds>(t1 - t0); + auto t1 = utils::SteadyTime::now(); + auto dt = utils::SteadyTime::getDurationUs(t0, t1); std::cout << "Verification time: " << dt.count() << std::endl; std::cout << "<<< Signature Ok." << std::endl; } else { @@ -127,10 +133,9 @@ class Client : interface::Portal::ConsumerCallback { auto it = send_timestamps_.find(interest.getName().getSuffix()); if (it != send_timestamps_.end()) { - rtt = std::chrono::duration_cast<std::chrono::microseconds>( - std::chrono::steady_clock::now().time_since_epoch()) - .count() - - it->second; + rtt = + utils::SteadyTime::getDurationUs(it->second, utils::SteadyTime::now()) + .count(); send_timestamps_.erase(it); } @@ -206,7 +211,11 @@ class Client : interface::Portal::ConsumerCallback { } } - void onError(std::error_code ec) override {} + void onError(const std::error_code &ec) override { + std::cout << "Aborting ping due to internal error: " << ec.message() + << std::endl; + afterSignal(); + } void doPing() { const Name interest_name(config_->name_, (uint32_t)sequence_number_); @@ -254,10 +263,7 @@ class Client : interface::Portal::ConsumerCallback { if (!config_->quiet_) std::cout << std::endl; - send_timestamps_[sequence_number_] = - std::chrono::duration_cast<std::chrono::microseconds>( - std::chrono::steady_clock::now().time_since_epoch()) - .count(); + send_timestamps_[sequence_number_] = utils::SteadyTime::now(); portal_.sendInterest(std::move(interest)); @@ -267,7 +273,11 @@ class Client : interface::Portal::ConsumerCallback { if (sent_ < config_->maxPing_) { this->timer_->expires_from_now( std::chrono::microseconds(config_->pingInterval_)); - this->timer_->async_wait([this](const std::error_code e) { doPing(); }); + this->timer_->async_wait([this](const std::error_code e) { + if (!e) { + doPing(); + } + }); } } @@ -275,11 +285,11 @@ class Client : interface::Portal::ConsumerCallback { std::cout << "Stop ping" << std::endl; std::cout << "Sent: " << sent_ << " Received: " << received_ << " Timeouts: " << timedout_ << std::endl; - portal_.stopEventsLoop(); + io_service_.stop(); } void reset() { - timer_.reset(new asio::steady_timer(portal_.getIoService())); + timer_.reset(new asio::steady_timer(portal_.getThread().getIoService())); sequence_number_ = config_->first_suffix_; last_jump_ = 0; processed_ = 0; @@ -291,6 +301,7 @@ class Client : interface::Portal::ConsumerCallback { private: SendTimeMap send_timestamps_; + asio::io_service io_service_; interface::Portal portal_; asio::signal_set signals_; uint64_t sequence_number_; @@ -337,6 +348,11 @@ void help() { << std::endl; std::cout << "-q quiet, not prints (default false)" << std::endl; + std::cerr << "-z <io_module> IO module to use. Default: hicnlightng_module" + << std::endl; + std::cerr << "-F <conf_file> Path to optional configuration file for " + "libtransport" + << std::endl; std::cout << "-H prints this message" << std::endl; } @@ -350,7 +366,11 @@ int main(int argc, char *argv[]) { int opt; std::string producer_certificate = ""; - while ((opt = getopt(argc, argv, "j::t:i:m:s:d:n:l:f:c:SAOqVDH")) != -1) { + std::string conf_file; + transport::interface::global_config::IoModuleConfiguration io_config; + io_config.name = "hicnlightng_module"; + + while ((opt = getopt(argc, argv, "j::t:i:m:s:d:n:l:f:c:SAOqVDHz:F:")) != -1) { switch (opt) { case 't': c->ttl_ = (uint8_t)std::stoi(optarg); @@ -406,6 +426,12 @@ int main(int argc, char *argv[]) { case 'c': c->certificate_ = std::string(optarg); break; + case 'z': + io_config.name = optarg; + break; + case 'F': + conf_file = optarg; + break; case 'H': default: help(); @@ -413,16 +439,24 @@ int main(int argc, char *argv[]) { } } + /** + * IO module configuration + */ + io_config.set(); + + /** + * Parse config file + */ + transport::interface::global_config::parseConfigurationFile(conf_file); + auto ping = std::make_unique<Client>(c); auto t0 = std::chrono::steady_clock::now(); ping->ping(); auto t1 = std::chrono::steady_clock::now(); - std::cout - << "Elapsed time: " - << std::chrono::duration_cast<std::chrono::microseconds>(t1 - t0).count() - << std::endl; + std::cout << "Elapsed time: " + << utils::SteadyTime::getDurationUs(t0, t1).count() << std::endl; #ifdef _WIN32 WSACleanup(); diff --git a/apps/ping/src/ping_server.cc b/apps/ping/src/ping_server.cc index baf9c6698..3ffbc7325 100644 --- a/apps/ping/src/ping_server.cc +++ b/apps/ping/src/ping_server.cc @@ -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: @@ -21,10 +21,10 @@ #include <openssl/applink.c> #endif -#include <hicn/transport/auth/identity.h> #include <hicn/transport/auth/signer.h> #include <hicn/transport/core/content_object.h> #include <hicn/transport/core/interest.h> +#include <hicn/transport/interfaces/global_conf_interface.h> #include <hicn/transport/utils/string_tokenizer.h> #include <asio.hpp> @@ -36,24 +36,13 @@ namespace interface { using HashAlgorithm = core::HashAlgorithm; using CryptoSuite = auth::CryptoSuite; -auth::Identity setProducerIdentity(std::string keystore_name, - std::string keystore_password, - auth::CryptoHashType hash_algorithm) { - if (access(keystore_name.c_str(), F_OK) != -1) { - return auth::Identity(keystore_name, keystore_password, hash_algorithm); - } else { - return auth::Identity(keystore_name, keystore_password, - CryptoSuite::RSA_SHA256, 1024, 365, "producer-test"); - } -} - class CallbackContainer { const std::size_t log2_content_object_buffer_size = 12; public: CallbackContainer(const Name &prefix, uint32_t object_size, bool verbose, bool dump, bool quite, bool flags, bool reset, uint8_t ttl, - auth::Identity *identity, bool sign, uint32_t lifetime) + auth::Signer *signer, bool sign, uint32_t lifetime) : buffer_(object_size, 'X'), content_objects_((std::uint32_t)(1 << log2_content_object_buffer_size)), mask_((std::uint16_t)(1 << log2_content_object_buffer_size) - 1), @@ -64,7 +53,7 @@ class CallbackContainer { flags_(flags), reset_(reset), ttl_(ttl), - identity_(identity), + signer_(signer), sign_(sign) { core::Packet::Format format; @@ -151,8 +140,8 @@ class CallbackContainer { if (!quite_) std::cout << std::endl; - if (sign_) { - identity_->getSigner()->signPacket(content_object.get()); + if (sign_ && signer_) { + signer_->signPacket(content_object.get()); } p.produce(*content_object); @@ -170,33 +159,43 @@ class CallbackContainer { bool flags_; bool reset_; uint8_t ttl_; - auth::Identity *identity_; + auth::Signer *signer_; bool sign_; }; void help() { std::cout << "usage: hicn-preoducer-ping [options]" << std::endl; std::cout << "PING options" << std::endl; - std::cout << "-s <val> object content size (default 1350B)" << std::endl; - std::cout << "-n <val> hicn name (default b001::/64)" << std::endl; - std::cout << "-f set tcp flags according to the flag received " - "(default false)" + std::cout << "-s <val> object content size (default 1350B)" << std::endl; - std::cout << "-l data lifetime" << std::endl; - std::cout << "-r always reply with a reset flag (default false)" + std::cout << "-n <val> hicn name (default b001::/64)" << std::endl; + std::cout << "-f set tcp flags according to the flag received " + " (default false)" << std::endl; - std::cout << "-t set ttl (default 64)" << std::endl; + std::cout << "-l data lifetime" << std::endl; + std::cout + << "-r always reply with a reset flag (default false)" + << std::endl; + std::cout << "-t set ttl (default 64)" << std::endl; std::cout << "OUTPUT options" << std::endl; - std::cout << "-V verbose, prints statistics about the messagges sent " - "and received (default false)" + std::cout << "-V verbose, prints statistics about the " + "messagges sent " + " and received (default false)" + << std::endl; + std::cout << "-D dump, dumps sent and received packets " + "(default false)" << std::endl; - std::cout << "-D dump, dumps sent and received packets (default false)" + std::cout << "-q quite, not prints (default false)" + << std::endl; + std::cerr << "-z <io_module> IO module to use. Default: hicnlightng_module" + << std::endl; + std::cerr << "-F <conf_file> Path to optional configuration file for " + "libtransport" << std::endl; - std::cout << "-q quite, not prints (default false)" << std::endl; #ifndef _WIN32 - std::cout << "-d daemon mode" << std::endl; + std::cout << "-d daemon mode" << std::endl; #endif - std::cout << "-H prints this message" << std::endl; + std::cout << "-H prints this message" << std::endl; } int main(int argc, char **argv) { @@ -220,11 +219,15 @@ int main(int argc, char **argv) { bool sign = false; uint32_t data_lifetime = default_values::content_object_expiry_time; + std::string conf_file; + transport::interface::global_config::IoModuleConfiguration io_config; + io_config.name = "hicnlightng_module"; + int opt; #ifndef _WIN32 - while ((opt = getopt(argc, argv, "s:n:t:l:qfrVDdHk:p:")) != -1) { + while ((opt = getopt(argc, argv, "s:n:t:l:qfrVDdHk:p:z:F:")) != -1) { #else - while ((opt = getopt(argc, argv, "s:n:t:l:qfrVDHk:p:")) != -1) { + while ((opt = getopt(argc, argv, "s:n:t:l:qfrVDHk:p:z:F:")) != -1) { #endif switch (opt) { case 's': @@ -268,6 +271,12 @@ int main(int argc, char **argv) { case 'p': keystore_password = optarg; break; + case 'z': + io_config.name = optarg; + break; + case 'F': + conf_file = optarg; + break; case 'H': default: help(); @@ -281,6 +290,16 @@ int main(int argc, char **argv) { } #endif + /** + * IO module configuration + */ + io_config.set(); + + /** + * Parse config file + */ + transport::interface::global_config::parseConfigurationFile(conf_file); + core::Prefix producer_namespace(name_prefix); utils::StringTokenizer tokenizer(name_prefix, delimiter); @@ -290,21 +309,24 @@ int main(int argc, char **argv) { if (object_size > 1350) object_size = 1350; CallbackContainer *stubs; - auth::Identity identity = setProducerIdentity( - keystore_path, keystore_password, auth::CryptoHashType::SHA256); + std::unique_ptr<auth::AsymmetricSigner> signer; if (sign) { - stubs = new CallbackContainer(n, object_size, verbose, dump, quite, flags, - reset, ttl, &identity, sign, data_lifetime); + signer = std::make_unique<auth::AsymmetricSigner>(keystore_path, + keystore_password); + stubs = + new CallbackContainer(n, object_size, verbose, dump, quite, flags, + reset, ttl, signer.get(), sign, data_lifetime); } else { - auth::Identity *identity = nullptr; + auth::Signer *signer = nullptr; stubs = new CallbackContainer(n, object_size, verbose, dump, quite, flags, - reset, ttl, identity, sign, data_lifetime); + reset, ttl, signer, sign, data_lifetime); } ProducerSocket p; p.registerPrefix(producer_namespace); + p.setSocketOption(GeneralTransportOptions::MAKE_MANIFEST, false); p.setSocketOption(GeneralTransportOptions::OUTPUT_BUFFER_SIZE, 0U); p.setSocketOption( ProducerCallbacksOptions::CACHE_MISS, @@ -313,6 +335,7 @@ int main(int argc, char **argv) { std::placeholders::_2, data_lifetime)); p.connect(); + p.start(); asio::io_service io_service; asio::signal_set signal_set(io_service, SIGINT); |