diff options
Diffstat (limited to 'apps/ping')
-rw-r--r-- | apps/ping/.clang-format | 2 | ||||
-rw-r--r-- | apps/ping/CMakeLists.txt | 39 | ||||
-rw-r--r-- | apps/ping/src/ping_client.cc | 538 | ||||
-rw-r--r-- | apps/ping/src/ping_server.cc | 311 |
4 files changed, 446 insertions, 444 deletions
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..ab3fdf56d 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,49 @@ # 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} + INCLUDE_DIRS + PRIVATE ${THIRD_PARTY_INCLUDE_DIRS} ${COMMON_INCLUDE_DIRS} + DEPENDS ${DEPENDENCIES} ${THIRD_PARTY_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} + INCLUDE_DIRS + PRIVATE ${THIRD_PARTY_INCLUDE_DIRS} ${COMMON_INCLUDE_DIRS} + DEPENDS ${DEPENDENCIES} ${THIRD_PARTY_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..08938734b 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-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: @@ -13,18 +13,22 @@ * limitations under the License. */ +#include <hicn/apps/utils/logger.h> +#include <hicn/transport/auth/signer.h> #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 <hicn/transport/utils/traffic_generator.h> #include <asio/signal_set.hpp> #include <asio/steady_timer.hpp> #include <chrono> #include <map> -#define SYN_STATE 1 -#define ACK_STATE 2 +static constexpr uint32_t SYN_STATE = 1; namespace transport { @@ -32,147 +36,131 @@ namespace core { namespace ping { -typedef std::map<uint64_t, uint64_t> SendTimeMap; -typedef auth::AsymmetricVerifier Verifier; +using SendTimeMap = std::map<uint64_t, utils::SteadyTime::TimePoint>; +using Verifier = auth::AsymmetricVerifier; class Configuration { public: - uint64_t interestLifetime_; - uint64_t pingInterval_; - uint64_t maxPing_; - uint64_t first_suffix_; - std::string name_; + static constexpr char TRAFFIC_GENERATOR_RAND[] = "RANDOM"; + + uint32_t num_int_manifest_suffixes_ = + 0; // Number of suffixes in interest manifest (suffix in the header + // is not included in the count) + uint64_t interestLifetime_ = 500; // ms + uint64_t pingInterval_ = 1000000; // us + uint32_t maxPing_ = 10; // number of interests + uint32_t first_suffix_ = 0; + std::string name_ = "b001::1"; std::string certificate_; - uint16_t srcPort_; - uint16_t dstPort_; - bool verbose_; - bool dump_; - bool jump_; - bool open_; - bool always_syn_; - bool always_ack_; - bool quiet_; - uint32_t jump_freq_; - uint32_t jump_size_; - uint8_t ttl_; - - Configuration() { - interestLifetime_ = 500; // ms - pingInterval_ = 1000000; // us - maxPing_ = 10; // number of interests - first_suffix_ = 0; - name_ = "b001::1"; // string - srcPort_ = 9695; - dstPort_ = 8080; - verbose_ = false; - dump_ = false; - jump_ = false; - open_ = false; - always_syn_ = false; - always_ack_ = false; - quiet_ = false; - jump_freq_ = 0; - jump_size_ = 0; - ttl_ = 64; - } + std::string passphrase_; + std::string traffic_generator_type_; + bool jump_ = false; + uint32_t jump_freq_ = 0; + uint32_t jump_size_ = 0; + hicn_packet_format_t packet_format_ = HICN_PACKET_FORMAT_DEFAULT; + + Configuration() = default; }; -class Client : interface::Portal::ConsumerCallback { +class Client : public interface::Portal::TransportCallback { public: - Client(Configuration *c) - : portal_(), signals_(portal_.getIoService(), SIGINT) { + explicit Client(Configuration *c) + : signals_(io_service_, SIGINT), + config_(c), + timer_(std::make_unique<asio::steady_timer>( + portal_.getThread().getIoService())) { // 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())); - config_ = c; - sequence_number_ = config_->first_suffix_; - last_jump_ = 0; - processed_ = 0; - state_ = SYN_STATE; - sent_ = 0; - received_ = 0; - timedout_ = 0; if (!c->certificate_.empty()) { verifier_.useCertificate(c->certificate_); } + + // If interst manifest, sign it + if (c->num_int_manifest_suffixes_ != 0) { + assert(!c->passphrase_.empty()); + signer_ = std::make_unique<auth::SymmetricSigner>( + auth::CryptoSuite::HMAC_SHA256, c->passphrase_); + } + + if (c->traffic_generator_type_ == + std::string(Configuration::TRAFFIC_GENERATOR_RAND)) { + traffic_generator_ = + std::make_unique<RandomTrafficGenerator>(config_->maxPing_); + } else { + traffic_generator_ = std::make_unique<IncrSuffixTrafficGenerator>( + config_->name_, config_->first_suffix_, config_->maxPing_); + } } - virtual ~Client() {} + virtual ~Client() = default; void ping() { - std::cout << "start ping" << std::endl; - doPing(); - portal_.runEventsLoop(); + LoggerInfo() << "Starting ping..."; + + portal_.getThread().add([this]() { + portal_.connect(); + portal_.registerTransportCallback(this); + doPing(); + }); + + io_service_.run(); + } + + void onInterest(Interest &interest) override { + LoggerInfo() << "Unexpected interest received."; } void onContentObject(Interest &interest, ContentObject &object) override { uint64_t 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); - std::cout << "Verification time: " << dt.count() << std::endl; - std::cout << "<<< Signature Ok." << std::endl; + auto t1 = utils::SteadyTime::now(); + auto dt = utils::SteadyTime::getDurationUs(t0, t1); + LoggerInfo() << "Verification time: " << dt.count(); + LoggerInfo() << "<<< Signature Ok."; } else { - std::cout << "<<< Signature verification failed!" << std::endl; + LoggerErr() << "<<< Signature verification failed!"; } } - 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; + if (auto it = send_timestamps_.find(interest.getName().getSuffix()); + it != send_timestamps_.end()) { + rtt = + utils::SteadyTime::getDurationUs(it->second, utils::SteadyTime::now()) + .count(); send_timestamps_.erase(it); } - if (config_->verbose_) { - std::cout << "<<< recevied object. " << std::endl; - std::cout << "<<< interest name: " << interest.getName() - << " src port: " << interest.getSrcPort() - << " dst port: " << interest.getDstPort() - << " flags: " << interest.printFlags() << std::endl; - std::cout << "<<< object name: " << object.getName() - << " src port: " << object.getSrcPort() - << " dst port: " << object.getDstPort() - << " flags: " << object.printFlags() << " path label " - << object.getPathLabel() << " (" - << (object.getPathLabel() >> 24) << ")" - << " TTL: " << (int)object.getTTL() << std::endl; - } else if (!config_->quiet_) { - std::cout << "<<< received object. " << std::endl; - std::cout << "<<< round trip: " << rtt << " [us]" << std::endl; - std::cout << "<<< interest name: " << interest.getName() << std::endl; - std::cout << "<<< object name: " << object.getName() << std::endl; - std::cout << "<<< content object size: " - << object.payloadSize() + object.headerSize() << " [bytes]" - << std::endl; + if (LoggerIsOn(2)) { + LoggerInfo() << "<<< recevied object. "; + LoggerInfo() << "<<< interest name: " << interest.getName().getPrefix() + << " (n_suffixes=" << config_->num_int_manifest_suffixes_ + << ")"; + LoggerInfo() << "<<< object name: " << object.getName() << " path label " + << object.getPathLabel() << " (" + << (object.getPathLabel() >> 24) << ")"; + } else if (LoggerIsOn(1)) { + LoggerInfo() << "<<< received object. "; + LoggerInfo() << "<<< round trip: " << rtt << " [us]"; + LoggerInfo() << "<<< interest name: " << interest.getName().getPrefix(); + + LoggerInfo() << "<<< object name: " << object.getName(); + LoggerInfo() << "<<< content object size: " + << object.payloadSize() + object.headerSize() << " [bytes]"; } - if (config_->dump_) { - std::cout << "----- interest dump -----" << std::endl; + if (LoggerIsOn(3)) { + LoggerInfo() << "----- interest dump -----"; interest.dump(); - std::cout << "-------------------------" << std::endl; - std::cout << "----- object dump -------" << std::endl; + LoggerInfo() << "-------------------------"; + LoggerInfo() << "----- object dump -------"; object.dump(); - std::cout << "-------------------------" << std::endl; - } - - if (!config_->quiet_) std::cout << std::endl; - - if (!config_->always_syn_) { - if (object.testSyn() && object.testAck() && state_ == SYN_STATE) { - state_ = ACK_STATE; - } + LoggerInfo() << "-------------------------"; } + LoggerVerbose(1) << "\n"; received_++; processed_++; @@ -182,178 +170,221 @@ class Client : interface::Portal::ConsumerCallback { } void onTimeout(Interest::Ptr &interest, const Name &name) override { - if (config_->verbose_) { - std::cout << "### timeout for " << name - << " src port: " << interest->getSrcPort() - << " dst port: " << interest->getDstPort() - << " flags: " << interest->printFlags() << std::endl; - } else if (!config_->quiet_) { - std::cout << "### timeout for " << name << std::endl; + if (LoggerIsOn(2)) { + LoggerInfo() << "### timeout for " << name; + } else if (LoggerIsOn(1)) { + LoggerInfo() << "### timeout for " << name; } - if (config_->dump_) { - std::cout << "----- interest dump -----" << std::endl; + if (LoggerIsOn(3)) { + LoggerInfo() << "----- interest dump -----"; interest->dump(); - std::cout << "-------------------------" << std::endl; + LoggerInfo() << "-------------------------"; } - - if (!config_->quiet_) std::cout << std::endl; + LoggerVerbose(1) << "\n"; timedout_++; processed_++; - if (processed_ >= config_->maxPing_) { - afterSignal(); - } + if (processed_ >= config_->maxPing_) afterSignal(); } - void onError(std::error_code ec) override {} + void onError(const std::error_code &ec) override { + LoggerErr() << "Aborting ping due to internal error: " << ec.message(); + afterSignal(); + } + + void checkFamily(hicn_packet_format_t format, int family) { + switch (HICN_PACKET_FORMAT_GET(format, 0)) { + case IPPROTO_IP: + if (family != AF_INET) throw std::runtime_error("Bad packet format"); + break; + case IPPROTO_IPV6: + if (family != AF_INET6) throw std::runtime_error("Bad packet format"); + break; + default: + throw std::runtime_error("Bad packet format"); + } + } void doPing() { - const Name interest_name(config_->name_, (uint32_t)sequence_number_); - hicn_format_t format; - if (interest_name.getAddressFamily() == AF_INET) { - format = HF_INET_TCP; + std::string name = traffic_generator_->getPrefix(); + uint32_t sequence_number = traffic_generator_->getSuffix(); + const Name interest_name(name, sequence_number); + + hicn_packet_format_t format = config_->packet_format_; + + switch (format) { + case HICN_PACKET_FORMAT_NEW: + /* Nothing to do */ + break; + case HICN_PACKET_FORMAT_IPV4_TCP: + case HICN_PACKET_FORMAT_IPV6_TCP: + checkFamily(format, interest_name.getAddressFamily()); + break; + default: + throw std::runtime_error("Bad packet format"); + } + + /* + * Eventually add the AH header if a signer is defined. Raise an error + * if format include the AH header but no signer is defined. + */ + if (HICN_PACKET_FORMAT_IS_AH(format)) { + if (!signer_) throw std::runtime_error("Bad packet format"); } else { - format = HF_INET6_TCP; + if (signer_) format = Packet::toAHFormat(format); } - auto interest = std::make_shared<Interest>(interest_name, format); + auto interest = core::PacketManager<>::getInstance().getPacket<Interest>( + format, signer_ ? signer_->getSignatureFieldSize() : 0); + interest->setName(interest_name); interest->setLifetime(uint32_t(config_->interestLifetime_)); - interest->resetFlags(); - if (config_->open_ || config_->always_syn_) { - if (state_ == SYN_STATE) { - interest->setSyn(); - } else if (state_ == ACK_STATE) { - interest->setAck(); - } - } else if (config_->always_ack_) { - interest->setAck(); + if (LoggerIsOn(2)) { + LoggerInfo() << ">>> send interest " << interest->getName() + << " suffixes in manifest: " + << config_->num_int_manifest_suffixes_; + } else if (LoggerIsOn(1)) { + LoggerInfo() << ">>> send interest " << interest->getName(); } + LoggerVerbose(1) << "\n"; + + send_timestamps_[sequence_number] = utils::SteadyTime::now(); + for (uint32_t i = 0; i < config_->num_int_manifest_suffixes_ && + !traffic_generator_->hasFinished(); + i++) { + uint32_t sequence_number = traffic_generator_->getSuffix(); - interest->setSrcPort(config_->srcPort_); - interest->setDstPort(config_->dstPort_); - interest->setTTL(config_->ttl_); - - if (config_->verbose_) { - std::cout << ">>> send interest " << interest->getName() - << " src port: " << interest->getSrcPort() - << " dst port: " << interest->getDstPort() - << " flags: " << interest->printFlags() - << " TTL: " << (int)interest->getTTL() << std::endl; - } else if (!config_->quiet_) { - std::cout << ">>> send interest " << interest->getName() << std::endl; + interest->appendSuffix(sequence_number); + send_timestamps_[sequence_number] = utils::SteadyTime::now(); } - if (config_->dump_) { - std::cout << "----- interest dump -----" << std::endl; + if (LoggerIsOn(3)) { + LoggerInfo() << "----- interest dump -----"; interest->dump(); - std::cout << "-------------------------" << std::endl; + LoggerInfo() << "-------------------------"; } - if (!config_->quiet_) std::cout << std::endl; + interest->encodeSuffixes(); + if (signer_) signer_->signPacket(interest.get()); + portal_.sendInterest(interest, interest->getLifetime()); - send_timestamps_[sequence_number_] = - std::chrono::duration_cast<std::chrono::microseconds>( - std::chrono::steady_clock::now().time_since_epoch()) - .count(); - - portal_.sendInterest(std::move(interest)); - - sequence_number_++; - sent_++; - - if (sent_ < config_->maxPing_) { + if (!traffic_generator_->hasFinished()) { 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(); + } + }); } } void afterSignal() { - std::cout << "Stop ping" << std::endl; - std::cout << "Sent: " << sent_ << " Received: " << received_ - << " Timeouts: " << timedout_ << std::endl; - portal_.stopEventsLoop(); + LoggerInfo() << "Stopping ping..."; + LoggerInfo() << "Sent: " << traffic_generator_->getSentCount() + << " Received: " << received_ << " Timeouts: " << timedout_; + io_service_.stop(); } void reset() { - timer_.reset(new asio::steady_timer(portal_.getIoService())); - sequence_number_ = config_->first_suffix_; + timer_.reset(new asio::steady_timer(portal_.getThread().getIoService())); + traffic_generator_->reset(); last_jump_ = 0; processed_ = 0; state_ = SYN_STATE; - sent_ = 0; received_ = 0; timedout_ = 0; } private: SendTimeMap send_timestamps_; + asio::io_service io_service_; interface::Portal portal_; asio::signal_set signals_; - uint64_t sequence_number_; - uint64_t last_jump_; - uint64_t processed_; - uint32_t state_; - uint32_t sent_; - uint32_t received_; - uint32_t timedout_; - std::unique_ptr<asio::steady_timer> timer_; Configuration *config_; + std::unique_ptr<asio::steady_timer> timer_; + uint64_t last_jump_ = 0; + uint64_t processed_ = 0; + uint32_t state_ = SYN_STATE; + uint32_t received_ = 0; + uint32_t timedout_ = 0; Verifier verifier_; + std::unique_ptr<auth::Signer> signer_; + std::unique_ptr<TrafficGenerator> traffic_generator_; }; +static std::unordered_map<std::string, hicn_packet_format_t> const + packet_format_map = {{"ipv4_tcp", HICN_PACKET_FORMAT_IPV4_TCP}, + {"ipv6_tcp", HICN_PACKET_FORMAT_IPV6_TCP}, + {"new", HICN_PACKET_FORMAT_NEW}}; + +std::string str_tolower(std::string s) { + std::transform(s.begin(), s.end(), s.begin(), + [](unsigned char c) { return std::tolower(c); }); + return s; +} + void help() { - std::cout << "usage: hicn-consumer-ping [options]" << std::endl; - std::cout << "PING options" << std::endl; - std::cout - << "-i <val> ping interval in microseconds (default 1000000ms)" - << std::endl; - std::cout << "-m <val> maximum number of pings to send (default 10)" - << std::endl; - std::cout << "-s <val> sorce port (default 9695)" << std::endl; - std::cout << "-d <val> destination port (default 8080)" << std::endl; - std::cout << "-t <val> set packet ttl (default 64)" << std::endl; - std::cout << "-O open tcp connection (three way handshake) " - "(default false)" - << std::endl; - std::cout << "-S send always syn messages (default false)" - << std::endl; - std::cout << "-A send always ack messages (default false)" - << std::endl; - std::cout << "HICN options" << std::endl; - std::cout << "-n <val> hicn name (default b001::1)" << std::endl; - std::cout - << "-l <val> interest lifetime in milliseconds (default 500ms)" - << std::endl; - std::cout << "OUTPUT options" << std::endl; - 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 << "-q quiet, not prints (default false)" - << std::endl; - std::cout << "-H prints this message" << std::endl; + LoggerInfo() << "usage: hicn-consumer-ping [options]"; + LoggerInfo() << "PING options"; + LoggerInfo() << "-i <val> ping interval in microseconds (default " + "1000000ms)"; + LoggerInfo() + << "-m <val> maximum number of pings to send (default 10)"; + LoggerInfo() << "-a <val> <pass> set the passphrase and the number of " + "suffixes in interest manifest (default 0);"; + LoggerInfo() + << " e.g. '-m 6 -a -2' sends two interest (0 and " + "3) with 2 suffixes each (1,2 and 4,5 respectively)"; + LoggerInfo() << "HICN options"; + LoggerInfo() << "-n <val> hicn name (default b001::1)"; + LoggerInfo() + << "-l <val> interest lifetime in milliseconds (default " + "500ms)"; + LoggerInfo() << "OUTPUT options"; + LoggerInfo() << "-V verbose, prints statistics about the " + "messagges sent and received (default false)"; + LoggerInfo() << "-D dump, dumps sent and received packets " + "(default false)"; + LoggerInfo() << "-q quiet, not prints (default false)"; + LoggerInfo() + << "-z <io_module> IO module to use. Default: hicnlight_module"; + LoggerInfo() << "-F <conf_file> Path to optional configuration file for " + "libtransport"; + LoggerInfo() << "-b <type> Traffic generator type. Use 'RANDOM' for " + "random prefixes and suffixes. Default: sequential suffixes."; + LoggerInfo() + << "-w <packet_format> Packet format (without signature, defaults " + "to IPV6_TCP)"; + LoggerInfo() << "-H prints this message"; } -int main(int argc, char *argv[]) { +int start(int argc, char *argv[]) { #ifdef _WIN32 WSADATA wsaData = {0}; WSAStartup(MAKEWORD(2, 2), &wsaData); #endif - Configuration *c = new Configuration(); + transport::interface::global_config::GlobalConfigInterface global_conf; + + auto c = std::make_unique<Configuration>(); 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 = "hicnlight_module"; + + while ((opt = getopt(argc, argv, "a:b:i:m:f:n:l:c:z:F:w:H")) != -1) { switch (opt) { - case 't': - c->ttl_ = (uint8_t)std::stoi(optarg); + case 'a': + c->num_int_manifest_suffixes_ = std::stoi(optarg); + c->passphrase_ = argv[optind]; + break; + case 'b': + c->traffic_generator_type_ = optarg; break; case 'i': c->pingInterval_ = std::stoi(optarg); @@ -362,13 +393,7 @@ int main(int argc, char *argv[]) { c->maxPing_ = std::stoi(optarg); break; case 'f': - c->first_suffix_ = std::stoul(optarg); - break; - case 's': - c->srcPort_ = std::stoi(optarg); - break; - case 'd': - c->dstPort_ = std::stoi(optarg); + c->first_suffix_ = uint32_t(std::stoul(optarg)); break; case 'n': c->name_ = optarg; @@ -376,53 +401,48 @@ int main(int argc, char *argv[]) { case 'l': c->interestLifetime_ = std::stoi(optarg); break; - case 'V': - c->verbose_ = true; - ; - break; - case 'D': - c->dump_ = true; - break; - case 'O': - c->always_syn_ = false; - c->always_ack_ = false; - c->open_ = true; - break; - case 'S': - c->always_syn_ = true; - c->always_ack_ = false; - c->open_ = false; + case 'c': + c->certificate_ = std::string(optarg); break; - case 'A': - c->always_syn_ = false; - c->always_ack_ = true; - c->open_ = false; + case 'z': + io_config.name = optarg; break; - case 'q': - c->quiet_ = true; - c->verbose_ = false; - c->dump_ = false; + case 'F': + conf_file = optarg; break; - case 'c': - c->certificate_ = std::string(optarg); + case 'w': { + std::string packet_format_s = std::string(optarg); + packet_format_s = str_tolower(packet_format_s); + auto it = packet_format_map.find(std::string(optarg)); + if (it == packet_format_map.end()) + throw std::runtime_error("Bad packet format"); + c->packet_format_ = it->second; break; - case 'H': + } default: help(); exit(EXIT_FAILURE); } } - auto ping = std::make_unique<Client>(c); + /** + * IO module configuration + */ + io_config.set(); + + /** + * Parse config file + */ + global_conf.parseConfigurationFile(conf_file); + + auto ping = std::make_unique<Client>(c.get()); 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; + LoggerInfo() << "Elapsed time: " + << utils::SteadyTime::getDurationMs(t0, t1).count() << "ms"; #ifdef _WIN32 WSACleanup(); @@ -437,5 +457,5 @@ int main(int argc, char *argv[]) { } // namespace transport int main(int argc, char *argv[]) { - return transport::core::ping::main(argc, argv); + return transport::core::ping::start(argc, argv); } diff --git a/apps/ping/src/ping_server.cc b/apps/ping/src/ping_server.cc index baf9c6698..900da18ca 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-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: @@ -21,10 +21,13 @@ #include <openssl/applink.c> #endif -#include <hicn/transport/auth/identity.h> +#include <hicn/apps/utils/logger.h> #include <hicn/transport/auth/signer.h> +#include <hicn/transport/auth/verifier.h> #include <hicn/transport/core/content_object.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/utils/string_tokenizer.h> #include <asio.hpp> @@ -36,170 +39,128 @@ 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) - : 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), - content_objects_index_(0), - verbose_(verbose), - dump_(dump), - quite_(quite), - flags_(flags), - reset_(reset), - ttl_(ttl), - identity_(identity), - sign_(sign) { - core::Packet::Format format; - - if (prefix.getAddressFamily() == AF_INET) { - format = core::Packet::Format::HF_INET_TCP; - if (sign_) { - format = core::Packet::Format::HF_INET_TCP_AH; - } - } else { - format = core::Packet::Format::HF_INET6_TCP; - if (sign_) { - format = core::Packet::Format::HF_INET6_TCP_AH; - } + private: + std::shared_ptr<ContentObject> createContentObject(const Name &name, + uint32_t lifetime, + const Interest &interest) { + auto content_object = + core::PacketManager<>::getInstance().getPacket<ContentObject>( + interest.getFormat(), + (sign_ && signer_) ? signer_->getSignatureFieldSize() : 0); + + content_object->setName(name); + content_object->setLifetime(lifetime); + content_object->setLocator(interest.getLocator()); + + if (LoggerIsOn(2)) { + LoggerInfo() << ">>> send object " << content_object->getName(); + } else if (LoggerIsOn(1)) { + LoggerInfo() << ">>> send object " << content_object->getName(); } - for (int i = 0; i < (1 << log2_content_object_buffer_size); i++) { - content_objects_[i] = std::make_shared<ContentObject>( - prefix, format, 0, (const uint8_t *)buffer_.data(), buffer_.size()); - content_objects_[i]->setLifetime(lifetime); + if (LoggerIsOn(3)) { + LoggerInfo() << "----- object dump -----"; + content_object->dump(); + LoggerInfo() << "-----------------------"; } + + if (sign_ && signer_) signer_->signPacket(content_object.get()); + return content_object; } - void processInterest(ProducerSocket &p, const Interest &interest, + public: + CallbackContainer([[maybe_unused]] const Name &prefix, uint32_t object_size, + auth::Signer *signer, bool sign, std::string passphrase, + [[maybe_unused]] uint32_t lifetime) + : buffer_(object_size, 'X'), signer_(signer), sign_(sign) { + // Verifier for interest manifests + if (!passphrase.empty()) + verifier_ = std::make_unique<auth::SymmetricVerifier>(passphrase); + } + + void processInterest(ProducerSocket &p, Interest &interest, uint32_t lifetime) { - if (verbose_) { - std::cout << "<<< received interest " << interest.getName() - << " src port: " << interest.getSrcPort() - << " dst port: " << interest.getDstPort() - << " flags: " << interest.printFlags() - << "TTL: " << (int)interest.getTTL() << std::endl; - } else if (!quite_) { - std::cout << "<<< received interest " << interest.getName() << std::endl; + if (verifier_ && interest.hasManifest()) { + auto t0 = utils::SteadyTime::now(); + if (verifier_->verifyPacket(&interest)) { + auto t1 = utils::SteadyTime::now(); + auto dt = utils::SteadyTime::getDurationUs(t0, t1); + LoggerInfo() << "Verification time: " << dt.count(); + LoggerInfo() << "<<< Signature Ok."; + } else { + LoggerErr() << "<<< Signature verification failed!"; + } } - if (dump_) { - std::cout << "----- interest dump -----" << std::endl; - interest.dump(); - std::cout << "-------------------------" << std::endl; + if (LoggerIsOn(2)) { + LoggerInfo() << "<<< received interest " << interest.getName() + << " suffixes in manifest: " << interest.numberOfSuffixes(); + } else if (LoggerIsOn(1)) { + LoggerInfo() << "<<< received interest " << interest.getName(); } - if (interest.testRst()) { - std::cout << "!!!got a reset, I don't reply" << std::endl; - } else { - auto &content_object = content_objects_[content_objects_index_++ & mask_]; - - content_object->setName(interest.getName()); - content_object->setLifetime(lifetime); - content_object->setLocator(interest.getLocator()); - content_object->setSrcPort(interest.getDstPort()); - content_object->setDstPort(interest.getSrcPort()); - content_object->setTTL(ttl_); - - if (!sign_) { - content_object->resetFlags(); - } - - if (flags_) { - if (interest.testSyn()) { - content_object->setSyn(); - content_object->setAck(); - } else if (interest.testAck()) { - content_object->setAck(); - } // here I may need to handle the FIN flag; - } else if (reset_) { - content_object->setRst(); - } + if (LoggerIsOn(3)) { + LoggerInfo() << "----- interest dump -----"; + interest.dump(); + LoggerInfo() << "-------------------------"; + } - if (verbose_) { - std::cout << ">>> send object " << content_object->getName() - << " src port: " << content_object->getSrcPort() - << " dst port: " << content_object->getDstPort() - << " flags: " << content_object->printFlags() - << " TTL: " << (int)content_object->getTTL() << std::endl; - } else if (!quite_) { - std::cout << ">>> send object " << content_object->getName() - << std::endl; - } + if (!interest.isValid()) throw std::runtime_error("Bad interest format"); + Name name = interest.getName(); - if (dump_) { - std::cout << "----- object dump -----" << std::endl; - content_object->dump(); - std::cout << "-----------------------" << std::endl; - } + if (!interest.hasManifest()) { // Single interest + auto content_object = createContentObject(name, lifetime, interest); + p.produce(*content_object); + } else { // Interest manifest + uint32_t _; + const uint32_t *suffix = NULL; + UNUSED(_); - if (!quite_) std::cout << std::endl; + interest_manifest_foreach_suffix(interest.getIntManifestHeader(), suffix, + _) { + name.setSuffix(*suffix); - if (sign_) { - identity_->getSigner()->signPacket(content_object.get()); + auto content_object = createContentObject(name, lifetime, interest); + p.produce(*content_object); } - - p.produce(*content_object); } + + LoggerVerbose(1) << "\n"; } private: std::string buffer_; - std::vector<std::shared_ptr<ContentObject>> content_objects_; - std::uint16_t mask_; - std::uint16_t content_objects_index_; - bool verbose_; - bool dump_; - bool quite_; - bool flags_; - bool reset_; - uint8_t ttl_; - auth::Identity *identity_; + auth::Signer *signer_; bool sign_; + std::unique_ptr<auth::Verifier> verifier_; }; 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::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::endl; - std::cout << "-D dump, dumps sent and received packets (default false)" - << std::endl; - std::cout << "-q quite, not prints (default false)" << std::endl; + LoggerInfo() << "usage: hicn-preoducer-ping [options]"; + LoggerInfo() << "PING options"; + LoggerInfo() << "-s <val> object content size (default 1350B)"; + LoggerInfo() << "-n <val> hicn name (default b001::/64)"; + LoggerInfo() << "-l data lifetime"; + LoggerInfo() << "OUTPUT options"; + LoggerInfo() << "-V verbose, prints statistics about the " + "messagges sent " + " and received (default false)"; + LoggerInfo() << "-D dump, dumps sent and received packets " + "(default false)"; + LoggerInfo() << "-q quiet, not prints (default false)"; + LoggerInfo() + << "-z <io_module> IO module to use. Default: hicnlight_module"; + LoggerInfo() << "-F <conf_file> Path to optional configuration file for " + "libtransport"; #ifndef _WIN32 - std::cout << "-d daemon mode" << std::endl; + LoggerInfo() << "-d daemon mode"; #endif - std::cout << "-H prints this message" << std::endl; + LoggerInfo() << "-H prints this message"; } -int main(int argc, char **argv) { +int ping_main(int argc, char **argv) { + transport::interface::global_config::GlobalConfigInterface global_conf; #ifdef _WIN32 WSADATA wsaData = {0}; WSAStartup(MAKEWORD(2, 2), &wsaData); @@ -208,59 +169,41 @@ int main(int argc, char **argv) { #endif std::string name_prefix = "b001::0/64"; std::string delimiter = "/"; - bool verbose = false; - bool dump = false; - bool quite = false; - bool flags = false; - bool reset = false; uint32_t object_size = 1250; - uint8_t ttl = 64; std::string keystore_path = "./rsa_crypto_material.p12"; std::string keystore_password = "cisco"; + std::string passphrase = ""; 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 = "hicnlight_module"; + int opt; #ifndef _WIN32 - while ((opt = getopt(argc, argv, "s:n:t:l:qfrVDdHk:p:")) != -1) { + while ((opt = getopt(argc, argv, "a:s:n:t:l:frdHk: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:frHk:p:z:F:")) != -1) { #endif switch (opt) { + case 'a': + passphrase = optarg; + break; case 's': object_size = std::stoi(optarg); break; case 'n': name_prefix = optarg; break; - case 't': - ttl = (uint8_t)std::stoi(optarg); - break; case 'l': data_lifetime = std::stoi(optarg); break; - case 'V': - verbose = true; - break; - case 'D': - dump = true; - break; - case 'q': - verbose = false; - dump = false; - quite = true; - break; #ifndef _WIN32 case 'd': daemon = true; break; #endif - case 'f': - flags = true; - break; - case 'r': - reset = true; - break; case 'k': keystore_path = optarg; sign = true; @@ -268,7 +211,12 @@ int main(int argc, char **argv) { case 'p': keystore_password = optarg; break; - case 'H': + case 'z': + io_config.name = optarg; + break; + case 'F': + conf_file = optarg; + break; default: help(); exit(EXIT_FAILURE); @@ -281,6 +229,16 @@ int main(int argc, char **argv) { } #endif + /** + * IO module configuration + */ + io_config.set(); + + /** + * Parse config file + */ + global_conf.parseConfigurationFile(conf_file); + core::Prefix producer_namespace(name_prefix); utils::StringTokenizer tokenizer(name_prefix, delimiter); @@ -290,21 +248,23 @@ 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::Signer> 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, signer.get(), sign, + passphrase, data_lifetime); } else { - auth::Identity *identity = nullptr; - stubs = new CallbackContainer(n, object_size, verbose, dump, quite, flags, - reset, ttl, identity, sign, data_lifetime); + auth::Signer *signer = nullptr; + stubs = new CallbackContainer(n, object_size, signer, sign, passphrase, + data_lifetime); } ProducerSocket p; p.registerPrefix(producer_namespace); + p.setSocketOption(GeneralTransportOptions::MANIFEST_MAX_CAPACITY, 0U); p.setSocketOption(GeneralTransportOptions::OUTPUT_BUFFER_SIZE, 0U); p.setSocketOption( ProducerCallbacksOptions::CACHE_MISS, @@ -313,12 +273,13 @@ 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); signal_set.async_wait( [&p, &io_service](const std::error_code &, const int &) { - std::cout << "STOPPING!!" << std::endl; + LoggerInfo() << "STOPPING!!"; p.stop(); io_service.stop(); }); @@ -336,5 +297,5 @@ int main(int argc, char **argv) { } // end namespace transport int main(int argc, char **argv) { - return transport::interface::main(argc, argv); + return transport::interface::ping_main(argc, argv); } |