summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMauro Sardara <msardara@cisco.com>2022-09-14 15:23:25 +0000
committerGerrit Code Review <gerrit@fd.io>2022-09-14 15:23:25 +0000
commitf7567c8987065582d4ffde710ec54b7abdb619a2 (patch)
treee3a192ef3fa8f690cfec50e172c6a8e8fe82bea6
parent34e32b751d8060f93646d3fa542ddea73de901c4 (diff)
parentab38321508d886f0acd535f0f5f07a3d44e29591 (diff)
Merge "feat(hicn-ping): allow usage of random prefixes/suffixes in hicn-ping"
-rw-r--r--apps/ping/src/ping_client.cc77
-rw-r--r--apps/ping/src/ping_server.cc90
-rw-r--r--hicn-light/src/hicn/core/forwarder.c3
-rw-r--r--lib/includes/hicn/name.h3
-rw-r--r--lib/src/name.c6
-rw-r--r--libtransport/includes/hicn/transport/core/interest.h2
-rw-r--r--libtransport/includes/hicn/transport/core/name.h2
-rw-r--r--libtransport/includes/hicn/transport/utils/CMakeLists.txt1
-rw-r--r--libtransport/includes/hicn/transport/utils/traffic_generator.h72
-rw-r--r--libtransport/src/core/interest.cc10
-rw-r--r--libtransport/src/core/name.cc7
-rw-r--r--libtransport/src/test/CMakeLists.txt1
-rw-r--r--libtransport/src/test/test_traffic_generator.cc119
-rw-r--r--libtransport/src/utils/CMakeLists.txt1
-rw-r--r--libtransport/src/utils/traffic_generator.cc87
-rw-r--r--tests/1-node.yml1
-rw-r--r--tests/Makefile13
-rwxr-xr-xtests/config.sh95
-rw-r--r--tests/functional-tests/hicn-light-ping.robot26
19 files changed, 530 insertions, 86 deletions
diff --git a/apps/ping/src/ping_client.cc b/apps/ping/src/ping_client.cc
index 3e95b8896..747f4bd1b 100644
--- a/apps/ping/src/ping_client.cc
+++ b/apps/ping/src/ping_client.cc
@@ -20,6 +20,7 @@
#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>
@@ -40,8 +41,11 @@ using Verifier = auth::AsymmetricVerifier;
class Configuration {
public:
- uint64_t num_int_manifest_suffixes_ =
- 0; // Number of suffixes in interest manifest
+ 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
@@ -49,6 +53,7 @@ class Configuration {
std::string name_ = "b001::1";
std::string certificate_;
std::string passphrase_;
+ std::string traffic_generator_type_;
uint16_t srcPort_ = 9695;
uint16_t dstPort_ = 8080;
bool verbose_ = false;
@@ -68,8 +73,7 @@ class Client : private interface::Portal::TransportCallback {
: signals_(io_service_, SIGINT),
config_(c),
timer_(std::make_unique<asio::steady_timer>(
- portal_.getThread().getIoService())),
- sequence_number_(config_->first_suffix_) {
+ portal_.getThread().getIoService())) {
// Let the main thread to catch SIGINT
signals_.async_wait(std::bind(&Client::afterSignal, this));
@@ -83,6 +87,15 @@ class Client : private interface::Portal::TransportCallback {
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() = default;
@@ -128,8 +141,8 @@ class Client : private interface::Portal::TransportCallback {
if (config_->verbose_) {
std::cout << "<<< recevied object. " << std::endl;
- std::cout << "<<< interest name: " << interest.getName()
- << " (n_suffixes=" << interest.numberOfSuffixes() << ")"
+ std::cout << "<<< interest name: " << interest.getName().getPrefix()
+ << " (n_suffixes=" << config_->num_int_manifest_suffixes_ << ")"
<< " src port: " << interest.getSrcPort()
<< " dst port: " << interest.getDstPort() << std::endl;
std::cout << "<<< object name: " << object.getName()
@@ -141,7 +154,8 @@ class Client : private interface::Portal::TransportCallback {
} 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 << "<<< interest name: " << interest.getName().getPrefix()
+ << std::endl;
std::cout << "<<< object name: " << object.getName() << std::endl;
std::cout << "<<< content object size: "
<< object.payloadSize() + object.headerSize() << " [bytes]"
@@ -197,7 +211,10 @@ class Client : private interface::Portal::TransportCallback {
}
void doPing() {
- const Name interest_name(config_->name_, sequence_number_);
+ 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;
if (interest_name.getAddressFamily() == AF_INET) {
format = signer_ ? HICN_PACKET_FORMAT_IPV4_TCP_AH
@@ -217,12 +234,6 @@ class Client : private interface::Portal::TransportCallback {
interest->setSrcPort(config_->srcPort_);
interest->setDstPort(config_->dstPort_);
interest->setTTL(config_->ttl_);
- uint32_t seq_offset = 1;
- while (seq_offset <= config_->num_int_manifest_suffixes_ &&
- sequence_number_ + seq_offset < config_->maxPing_) {
- interest->appendSuffix(sequence_number_ + seq_offset);
- seq_offset++;
- }
if (config_->verbose_) {
std::cout << ">>> send interest " << interest->getName()
@@ -237,11 +248,15 @@ class Client : private interface::Portal::TransportCallback {
if (!config_->quiet_) std::cout << std::endl;
- send_timestamps_[sequence_number_] = utils::SteadyTime::now();
- for (uint64_t i = 1; i < seq_offset; i++)
- send_timestamps_[sequence_number_ + i] = utils::SteadyTime::now();
+ send_timestamps_[sequence_number] = utils::SteadyTime::now();
+ for (int i = 0; i < config_->num_int_manifest_suffixes_ &&
+ !traffic_generator_->hasFinished();
+ i++) {
+ uint32_t sequence_number = traffic_generator_->getSuffix();
- if (signer_) signer_->signPacket(interest.get());
+ interest->appendSuffix(sequence_number);
+ send_timestamps_[sequence_number] = utils::SteadyTime::now();
+ }
if (config_->dump_) {
std::cout << "----- interest dump -----" << std::endl;
@@ -250,13 +265,10 @@ class Client : private interface::Portal::TransportCallback {
}
interest->encodeSuffixes();
-
+ if (signer_) signer_->signPacket(interest.get());
portal_.sendInterest(interest, interest->getLifetime());
- sequence_number_ += seq_offset;
- sent_ += seq_offset;
-
- 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) {
@@ -269,18 +281,18 @@ class Client : private interface::Portal::TransportCallback {
void afterSignal() {
std::cout << "Stop ping" << std::endl;
- std::cout << "Sent: " << sent_ << " Received: " << received_
- << " Timeouts: " << timedout_ << std::endl;
+ std::cout << "Sent: " << traffic_generator_->getSentCount()
+ << " Received: " << received_ << " Timeouts: " << timedout_
+ << std::endl;
io_service_.stop();
}
void reset() {
timer_.reset(new asio::steady_timer(portal_.getThread().getIoService()));
- sequence_number_ = config_->first_suffix_;
+ traffic_generator_->reset();
last_jump_ = 0;
processed_ = 0;
state_ = SYN_STATE;
- sent_ = 0;
received_ = 0;
timedout_ = 0;
}
@@ -292,15 +304,14 @@ class Client : private interface::Portal::TransportCallback {
asio::signal_set signals_;
Configuration *config_;
std::unique_ptr<asio::steady_timer> timer_;
- uint32_t sequence_number_;
uint64_t last_jump_ = 0;
uint64_t processed_ = 0;
uint32_t state_ = SYN_STATE;
- uint32_t sent_ = 0;
uint32_t received_ = 0;
uint32_t timedout_ = 0;
Verifier verifier_;
std::unique_ptr<auth::Signer> signer_;
+ std::unique_ptr<TrafficGenerator> traffic_generator_;
};
void help() {
@@ -339,6 +350,9 @@ void help() {
std::cerr << "-F <conf_file> Path to optional configuration file for "
"libtransport"
<< std::endl;
+ std::cout << "-b <type> Traffic generator type. Use 'RANDOM' for "
+ "random prefixes and suffixes. Default: sequential suffixes."
+ << std::endl;
std::cout << "-H prints this message" << std::endl;
}
@@ -358,13 +372,16 @@ int start(int argc, char *argv[]) {
transport::interface::global_config::IoModuleConfiguration io_config;
io_config.name = "hicnlight_module";
- while ((opt = getopt(argc, argv, "a:j::t:i:m:s:d:n:l:f:c:SAOqVDHz:F:")) !=
+ while ((opt = getopt(argc, argv, "a:b:j::t:i:m:s:d:n:l:f:c:SAOqVDHz:F:")) !=
-1) {
switch (opt) {
case 'a':
c->num_int_manifest_suffixes_ = std::stoi(optarg);
c->passphrase_ = argv[optind];
break;
+ case 'b':
+ c->traffic_generator_type_ = optarg;
+ break;
case 't':
c->ttl_ = uint8_t(std::stoi(optarg));
break;
diff --git a/apps/ping/src/ping_server.cc b/apps/ping/src/ping_server.cc
index 876efd133..b91b2c612 100644
--- a/apps/ping/src/ping_server.cc
+++ b/apps/ping/src/ping_server.cc
@@ -40,6 +40,38 @@ using CryptoSuite = auth::CryptoSuite;
class CallbackContainer {
const std::size_t log2_content_object_buffer_size = 12;
+ private:
+ std::shared_ptr<ContentObject> createContentObject(const Name &name,
+ uint32_t lifetime,
+ const Interest &interest) {
+ auto &content_object = content_objects_[content_objects_index_++ & mask_];
+
+ content_object->setName(name);
+ content_object->setLifetime(lifetime);
+ content_object->setLocator(interest.getLocator());
+ content_object->setSrcPort(interest.getDstPort());
+ content_object->setDstPort(interest.getSrcPort());
+ content_object->setTTL(ttl_);
+
+ if (verbose_) {
+ std::cout << ">>> send object " << content_object->getName()
+ << " src port: " << content_object->getSrcPort()
+ << " dst port: " << content_object->getDstPort()
+ << " TTL: " << (int)content_object->getTTL() << std::endl;
+ } else if (!quiet_) {
+ std::cout << ">>> send object " << content_object->getName() << std::endl;
+ }
+
+ if (dump_) {
+ std::cout << "----- object dump -----" << std::endl;
+ content_object->dump();
+ std::cout << "-----------------------" << std::endl;
+ }
+
+ if (sign_ && signer_) signer_->signPacket(content_object.get());
+ return content_object;
+ }
+
public:
CallbackContainer(const Name &prefix, uint32_t object_size, bool verbose,
bool dump, bool quiet, uint8_t ttl, auth::Signer *signer,
@@ -109,58 +141,22 @@ class CallbackContainer {
std::cout << "-------------------------" << std::endl;
}
- uint32_t *suffix = interest.firstSuffix();
- uint32_t n_suffixes_in_manifest = interest.numberOfSuffixes();
- hicn_uword *request_bitmap = interest.getRequestBitmap();
if (!interest.isValid()) throw std::runtime_error("Bad interest format");
-
Name name = interest.getName();
- uint32_t pos = 0; // Position of current suffix in manifest
- do {
- // If suffix can be processed, i.e. no manifest with bitmap excluding it
- if (!interest.hasManifest() ||
- bitmap_is_set_no_check(request_bitmap, pos)) {
- 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 (verbose_) {
- std::cout << ">>> send object " << content_object->getName()
- << " src port: " << content_object->getSrcPort()
- << " dst port: " << content_object->getDstPort()
- << " TTL: " << (int)content_object->getTTL() << std::endl;
- } else if (!quiet_) {
- std::cout << ">>> send object " << content_object->getName()
- << std::endl;
- }
-
- if (dump_) {
- std::cout << "----- object dump -----" << std::endl;
- content_object->dump();
- std::cout << "-----------------------" << std::endl;
- }
-
- if (sign_ && signer_) {
- signer_->signPacket(content_object.get());
- }
-
- p.produce(*content_object);
- }
- if (interest.hasManifest()) {
- uint32_t seq = *suffix;
- suffix++;
+ if (!interest.hasManifest()) { // Single interest
+ auto content_object = createContentObject(name, lifetime, interest);
+ p.produce(*content_object);
+ } else { // Interest manifest
+ uint32_t _, *suffix = NULL;
+ interest_manifest_foreach_suffix(interest.getIntManifestHeader(), suffix,
+ _) {
+ name.setSuffix(*suffix);
- Name name = interest.getName();
- interest.setName(name.setSuffix(seq));
+ auto content_object = createContentObject(name, lifetime, interest);
+ p.produce(*content_object);
}
- } while (pos++ < n_suffixes_in_manifest);
+ }
if (!quiet_) std::cout << std::endl;
}
diff --git a/hicn-light/src/hicn/core/forwarder.c b/hicn-light/src/hicn/core/forwarder.c
index 60493a9c5..fbf7040e3 100644
--- a/hicn-light/src/hicn/core/forwarder.c
+++ b/hicn-light/src/hicn/core/forwarder.c
@@ -1013,8 +1013,7 @@ static ssize_t forwarder_process_aggregated_interest(
WITH_DEBUG({
char buf[MAXSZ_HICN_PREFIX];
- int rc =
- hicn_name_snprintf(buf, MAXSZ_HICN_NAME, msgbuf_get_name(msgbuf));
+ int rc = hicn_name_snprintf(buf, MAXSZ_HICN_NAME, &name_copy);
if (rc < 0 || rc >= MAXSZ_HICN_PREFIX)
snprintf(buf, MAXSZ_HICN_PREFIX, "(error)");
DEBUG("Next in manifest: %s", buf);
diff --git a/lib/includes/hicn/name.h b/lib/includes/hicn/name.h
index 895b86341..a1b8e1fc1 100644
--- a/lib/includes/hicn/name.h
+++ b/lib/includes/hicn/name.h
@@ -270,6 +270,9 @@ bool hicn_name_is_v4 (const hicn_name_t *name);
int hicn_name_snprintf (char *s, size_t size, const hicn_name_t *name);
+int hicn_name_no_suffix_snprintf (char *s, size_t size,
+ const hicn_name_t *name);
+
int hicn_name_cmp (const hicn_name_t *n1, const hicn_name_t *n2);
bool hicn_name_equals (const hicn_name_t *n1, const hicn_name_t *n2);
diff --git a/lib/src/name.c b/lib/src/name.c
index 04c48cb4d..1c933d466 100644
--- a/lib/src/name.c
+++ b/lib/src/name.c
@@ -242,6 +242,12 @@ hicn_name_snprintf (char *s, size_t size, const hicn_name_t *name)
}
int
+hicn_name_no_suffix_snprintf (char *s, size_t size, const hicn_name_t *name)
+{
+ return hicn_ip_address_snprintf (s, size, &name->prefix);
+}
+
+int
hicn_prefix_create_from_ip_prefix (const hicn_ip_prefix_t *hicn_ip_prefix,
hicn_prefix_t *prefix)
{
diff --git a/libtransport/includes/hicn/transport/core/interest.h b/libtransport/includes/hicn/transport/core/interest.h
index 59da5b91f..270ea7027 100644
--- a/libtransport/includes/hicn/transport/core/interest.h
+++ b/libtransport/includes/hicn/transport/core/interest.h
@@ -104,6 +104,8 @@ class Interest
hicn_uword *getRequestBitmap();
+ interest_manifest_header_t *getIntManifestHeader();
+
void setRequestBitmap(const uint32_t *request_bitmap);
bool isValid();
diff --git a/libtransport/includes/hicn/transport/core/name.h b/libtransport/includes/hicn/transport/core/name.h
index 90b665c15..14ea10898 100644
--- a/libtransport/includes/hicn/transport/core/name.h
+++ b/libtransport/includes/hicn/transport/core/name.h
@@ -98,6 +98,8 @@ class Name {
hicn_ip_prefix_t toIpAddress() const;
+ std::string getPrefix() const;
+
void copyPrefixToDestination(uint8_t *destination) const;
int getAddressFamily() const;
diff --git a/libtransport/includes/hicn/transport/utils/CMakeLists.txt b/libtransport/includes/hicn/transport/utils/CMakeLists.txt
index 1dba94451..060b83b63 100644
--- a/libtransport/includes/hicn/transport/utils/CMakeLists.txt
+++ b/libtransport/includes/hicn/transport/utils/CMakeLists.txt
@@ -34,6 +34,7 @@ list(APPEND HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/shared_ptr_utils.h
${CMAKE_CURRENT_SOURCE_DIR}/noncopyable.h
${CMAKE_CURRENT_SOURCE_DIR}/singleton.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/traffic_generator.h
)
if(NOT WIN32)
diff --git a/libtransport/includes/hicn/transport/utils/traffic_generator.h b/libtransport/includes/hicn/transport/utils/traffic_generator.h
new file mode 100644
index 000000000..abd84886d
--- /dev/null
+++ b/libtransport/includes/hicn/transport/utils/traffic_generator.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2022 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <random>
+#include <string>
+
+namespace transport {
+
+class TrafficGenerator {
+ public:
+ TrafficGenerator(uint32_t count);
+ virtual ~TrafficGenerator() = default;
+ bool hasFinished();
+ uint32_t getSentCount();
+ virtual std::pair<std::string, uint32_t> getPrefixAndSuffix();
+
+ virtual std::string getPrefix() = 0;
+ virtual uint32_t getSuffix() = 0;
+ virtual void reset();
+
+ protected:
+ void onSuffixGenerated();
+
+ uint32_t count_;
+ uint32_t sent_;
+};
+
+/* Fixed prefix, incremental suffix */
+class IncrSuffixTrafficGenerator : public TrafficGenerator {
+ public:
+ explicit IncrSuffixTrafficGenerator(std::string prefix, uint32_t suffix,
+ uint32_t count);
+ std::string getPrefix() override;
+ uint32_t getSuffix() override;
+ void reset() override;
+
+ private:
+ std::string prefix_;
+ uint32_t suffix_;
+ uint32_t initial_suffix_;
+};
+
+/* Random prefix, random suffix */
+class RandomTrafficGenerator : public TrafficGenerator {
+ public:
+ static constexpr char NET_PREFIX[] = "2001:db8:1::/64";
+
+ RandomTrafficGenerator(uint32_t count, std::string net_prefix = NET_PREFIX);
+ std::string getPrefix() override;
+ uint32_t getSuffix() override;
+
+ private:
+ std::string net_prefix_;
+ std::default_random_engine rand_engine_;
+ std::uniform_int_distribution<uint32_t> uniform_distribution_;
+};
+
+} // namespace transport \ No newline at end of file
diff --git a/libtransport/src/core/interest.cc b/libtransport/src/core/interest.cc
index 6348a8d3e..c3eb7c379 100644
--- a/libtransport/src/core/interest.cc
+++ b/libtransport/src/core/interest.cc
@@ -170,9 +170,6 @@ void Interest::encodeSuffixes() {
(interest_manifest_header_t *)(writableData() + headerSize());
interest_manifest_init(int_manifest_header, name_.getSuffix());
- memset(int_manifest_header->request_bitmap, 0xFFFFFFFF,
- BITMAP_SIZE * sizeof(hicn_uword));
-
for (auto it = suffix_set_.begin(); it != suffix_set_.end(); it++) {
interest_manifest_add_suffix(int_manifest_header, *it);
}
@@ -237,6 +234,13 @@ hicn_uword *Interest::getRequestBitmap() {
return header->request_bitmap;
}
+interest_manifest_header_t *Interest::getIntManifestHeader() {
+ if (!hasManifest()) return nullptr;
+
+ auto header = (interest_manifest_header_t *)(writableData() + headerSize());
+ return header;
+};
+
void Interest::setRequestBitmap(const uint32_t *request_bitmap) {
if (!hasManifest()) return;
diff --git a/libtransport/src/core/name.cc b/libtransport/src/core/name.cc
index 02cc79be6..4f8ba7873 100644
--- a/libtransport/src/core/name.cc
+++ b/libtransport/src/core/name.cc
@@ -168,6 +168,13 @@ hicn_ip_prefix_t Name::toIpAddress() const {
return ret;
}
+std::string Name::getPrefix() const {
+ char prefix[MAXSZ_HICN_NAME];
+ hicn_name_no_suffix_snprintf(prefix, MAXSZ_HICN_NAME, &name_);
+
+ return std::string(prefix);
+}
+
int Name::getAddressFamily() const {
int ret = 0;
diff --git a/libtransport/src/test/CMakeLists.txt b/libtransport/src/test/CMakeLists.txt
index 356ee0067..864006e5d 100644
--- a/libtransport/src/test/CMakeLists.txt
+++ b/libtransport/src/test/CMakeLists.txt
@@ -33,6 +33,7 @@ list(APPEND TESTS_SRC
test_thread_pool.cc
test_quadloop.cc
test_prefix.cc
+ test_traffic_generator.cc
)
if (ENABLE_RELY)
diff --git a/libtransport/src/test/test_traffic_generator.cc b/libtransport/src/test/test_traffic_generator.cc
new file mode 100644
index 000000000..88cb2de75
--- /dev/null
+++ b/libtransport/src/test/test_traffic_generator.cc
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2022 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <hicn/transport/utils/traffic_generator.h>
+
+static constexpr int NUM_PINGS = 10;
+static constexpr char PREFIX[] = "b001:1:2:3::";
+static constexpr uint32_t FIRST_SUFFIX = 5;
+
+namespace utils {
+
+using transport::IncrSuffixTrafficGenerator;
+using transport::RandomTrafficGenerator;
+
+class TrafficGeneratorTest : public ::testing::Test {
+ protected:
+ TrafficGeneratorTest() {}
+ virtual ~TrafficGeneratorTest() {}
+};
+
+TEST_F(TrafficGeneratorTest, IncrSuffixGetPrefixAndSuffix) {
+ auto traffic_generator_ = std::make_unique<IncrSuffixTrafficGenerator>(
+ PREFIX, FIRST_SUFFIX, NUM_PINGS);
+
+ std::string prefix = traffic_generator_->getPrefix();
+ EXPECT_EQ(prefix, PREFIX);
+ uint32_t suffix = traffic_generator_->getSuffix();
+ EXPECT_EQ(suffix, FIRST_SUFFIX);
+}
+
+TEST_F(TrafficGeneratorTest, IncrSuffixGetMultipleSuffixes) {
+ auto traffic_generator_ = std::make_unique<IncrSuffixTrafficGenerator>(
+ PREFIX, FIRST_SUFFIX, NUM_PINGS);
+
+ std::string prefix = traffic_generator_->getPrefix();
+ EXPECT_EQ(prefix, PREFIX);
+ EXPECT_EQ(prefix, traffic_generator_->getPrefix());
+
+ for (int i = 0; i < NUM_PINGS; i++)
+ EXPECT_EQ(traffic_generator_->getSuffix(), FIRST_SUFFIX + i);
+}
+
+TEST_F(TrafficGeneratorTest, IncrSuffixReset) {
+ auto traffic_generator_ = std::make_unique<IncrSuffixTrafficGenerator>(
+ PREFIX, FIRST_SUFFIX, NUM_PINGS);
+
+ for (int i = 0; i < NUM_PINGS; i++) traffic_generator_->getSuffix();
+
+ traffic_generator_->reset();
+ EXPECT_EQ(traffic_generator_->getPrefix(), PREFIX);
+ EXPECT_EQ(traffic_generator_->getSuffix(), FIRST_SUFFIX);
+ EXPECT_EQ(traffic_generator_->getSuffix(), FIRST_SUFFIX + 1);
+}
+
+TEST_F(TrafficGeneratorTest, IncrSuffixRequestTooManySuffixes) {
+ auto traffic_generator_ = std::make_unique<IncrSuffixTrafficGenerator>(
+ PREFIX, FIRST_SUFFIX, NUM_PINGS);
+
+ for (int i = 0; i < NUM_PINGS; i++) traffic_generator_->getSuffix();
+ EXPECT_THROW(traffic_generator_->getSuffix(), std::runtime_error);
+}
+
+TEST_F(TrafficGeneratorTest, IncrSuffixGetPrefixAndSuffixTogether) {
+ auto traffic_generator_ = std::make_unique<IncrSuffixTrafficGenerator>(
+ PREFIX, FIRST_SUFFIX, NUM_PINGS);
+
+ auto [prefix, suffix] = traffic_generator_->getPrefixAndSuffix();
+ EXPECT_EQ(prefix, PREFIX);
+ EXPECT_EQ(suffix, FIRST_SUFFIX);
+}
+
+TEST_F(TrafficGeneratorTest, IncrSuffixCheckSentCount) {
+ auto traffic_generator_ = std::make_unique<IncrSuffixTrafficGenerator>(
+ PREFIX, FIRST_SUFFIX, NUM_PINGS);
+
+ for (int i = 0; i < NUM_PINGS; i++) {
+ EXPECT_EQ(traffic_generator_->getSentCount(), i);
+ EXPECT_FALSE(traffic_generator_->hasFinished());
+ traffic_generator_->getSuffix();
+ }
+ EXPECT_TRUE(traffic_generator_->hasFinished());
+}
+
+TEST_F(TrafficGeneratorTest, RandomGetPrefixAndSuffix) {
+ auto traffic_generator_ = std::make_unique<RandomTrafficGenerator>(NUM_PINGS);
+
+ std::string prefix1 = traffic_generator_->getPrefix();
+ std::string prefix2 = traffic_generator_->getPrefix();
+ EXPECT_NE(prefix1, prefix2);
+
+ uint32_t suffix1 = traffic_generator_->getSuffix();
+ uint32_t suffix2 = traffic_generator_->getSuffix();
+ EXPECT_NE(suffix1, suffix2);
+}
+
+TEST_F(TrafficGeneratorTest, RandomGetPrefixAndSuffixWithNetPrefix) {
+ auto traffic_generator_ = std::make_unique<RandomTrafficGenerator>(
+ NUM_PINGS, std::string(PREFIX) + "/64");
+
+ for (int i = 0; i < NUM_PINGS; i++)
+ EXPECT_THAT(traffic_generator_->getPrefix(),
+ testing::StartsWith(std::string(PREFIX)));
+}
+
+} // namespace utils \ No newline at end of file
diff --git a/libtransport/src/utils/CMakeLists.txt b/libtransport/src/utils/CMakeLists.txt
index 5bb76303a..e7c1c03ea 100644
--- a/libtransport/src/utils/CMakeLists.txt
+++ b/libtransport/src/utils/CMakeLists.txt
@@ -17,6 +17,7 @@ list(APPEND SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/log.cc
${CMAKE_CURRENT_SOURCE_DIR}/membuf.cc
${CMAKE_CURRENT_SOURCE_DIR}/content_store.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/traffic_generator.cc
)
diff --git a/libtransport/src/utils/traffic_generator.cc b/libtransport/src/utils/traffic_generator.cc
new file mode 100644
index 000000000..a617e3dc9
--- /dev/null
+++ b/libtransport/src/utils/traffic_generator.cc
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2022 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <hicn/transport/core/prefix.h>
+#include <hicn/transport/utils/traffic_generator.h>
+
+#include <iostream>
+
+namespace transport {
+
+/* TrafficGenerator */
+
+TrafficGenerator::TrafficGenerator(uint32_t count) : count_(count), sent_(0) {}
+
+bool TrafficGenerator::hasFinished() { return sent_ >= count_; }
+
+uint32_t TrafficGenerator::getSentCount() { return sent_; }
+
+std::pair<std::string, uint32_t> TrafficGenerator::getPrefixAndSuffix() {
+ return std::make_pair(getPrefix(), getSuffix());
+}
+
+void TrafficGenerator::reset() { sent_ = 0; };
+
+void TrafficGenerator::onSuffixGenerated() {
+ if (hasFinished()) throw std::runtime_error("Too many pings");
+ sent_++;
+};
+
+/* IncrSuffixTrafficGenerator */
+
+IncrSuffixTrafficGenerator::IncrSuffixTrafficGenerator(std::string prefix,
+ uint32_t suffix,
+ uint32_t count)
+ : TrafficGenerator(count),
+ prefix_(prefix),
+ suffix_(suffix),
+ initial_suffix_(suffix) {}
+
+std::string IncrSuffixTrafficGenerator::getPrefix() { return prefix_; }
+
+uint32_t IncrSuffixTrafficGenerator::getSuffix() {
+ TrafficGenerator::onSuffixGenerated();
+ return suffix_++;
+}
+
+void IncrSuffixTrafficGenerator::reset() {
+ TrafficGenerator::reset();
+ suffix_ = initial_suffix_;
+};
+
+/* RandomTrafficGenerator */
+
+RandomTrafficGenerator::RandomTrafficGenerator(uint32_t count,
+ std::string net_prefix)
+ : TrafficGenerator(count),
+ net_prefix_(net_prefix),
+ rand_engine_((std::random_device())()),
+ uniform_distribution_(0, std::numeric_limits<uint32_t>::max()) {}
+
+std::string RandomTrafficGenerator::getPrefix() {
+ // Generate random prefix
+ core::Prefix prefix(net_prefix_);
+ core::Name name = prefix.makeRandomName();
+ return name.getPrefix();
+}
+
+uint32_t RandomTrafficGenerator::getSuffix() {
+ TrafficGenerator::onSuffixGenerated();
+
+ // Generate random suffix
+ return uniform_distribution_(rand_engine_);
+}
+
+} // namespace transport \ No newline at end of file
diff --git a/tests/1-node.yml b/tests/1-node.yml
index eb8c19f34..859d1b838 100644
--- a/tests/1-node.yml
+++ b/tests/1-node.yml
@@ -16,7 +16,6 @@ services:
command:
- |
if [ -d /workspace/build-dev ]; then
- git config --global --add safe.directory \*
sudo ninja -C /workspace/build-dev install
fi
diff --git a/tests/Makefile b/tests/Makefile
index f9c166b8d..a31a6f1a6 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -1,4 +1,4 @@
-# Use when building for the fist time,
+# Use when building for the first time,
# then `make test` forces a rebuild if local changes
build:
DOCKERFILE=Dockerfile.dev BUILD_SOFTWARE=1 \
@@ -28,8 +28,15 @@ shell:
down:
docker-compose -f 1-node.yml down
-functional:
+functional-ctrl:
sleep 1 # Wait for the forwarder to be ready
bash config.sh ctrl listeners
bash config.sh ctrl connections
- bash config.sh ctrl routes \ No newline at end of file
+ bash config.sh ctrl routes
+
+functional-ping-manifest:
+ bash config.sh ping manifest
+functional-ping-signature:
+ bash config.sh ping signature
+functional-ping-timeout:
+ bash config.sh ping timeout \ No newline at end of file
diff --git a/tests/config.sh b/tests/config.sh
index a6bc6ad2d..16000bff6 100755
--- a/tests/config.sh
+++ b/tests/config.sh
@@ -465,6 +465,97 @@ function ctrl() {
${ctrl_tests[${type}]}
}
+################################################################
+# Test ping
+################################################################
+function test_ping_manifest() {
+ docker exec forwarder bash -c 'hicn-ping-server -a intmanifest >/tmp/ping_server.log 2>&1 &'
+ sleep 1
+
+ # 2 interests w/ 3 suffixes each (1 in header + 2 in manifest)
+ docker exec forwarder bash -c 'hicn-ping-client -m 6 -a 2 intmanifest | grep "Sent" >>/tmp/ping_client.log'
+ sleep 1
+
+ # 2 interests w/ 3 suffixes each + 1 single interest
+ docker exec forwarder bash -c 'hicn-ping-client -m 7 -a 2 intmanifest | grep "Sent" >>/tmp/ping_client.log'
+ sleep 1
+
+ # 2 interests w/ 3 suffixes each + 1 interest w/ 2 suffixes
+ docker exec forwarder bash -c 'hicn-ping-client -m 8 -a 2 intmanifest | grep "Sent" >>/tmp/ping_client.log'
+ sleep 1
+
+ # 2 interests w/ 3 suffixes each + 1 single interest,
+ # using random prefix/suffix generation
+ docker exec forwarder bash -c 'hicn-ping-client -m 7 -a 2 intmanifest -b RANDOM | grep "Sent" >>/tmp/ping_client.log'
+
+ # No 'failed' expected
+ ping_server_logs=$(docker exec forwarder cat /tmp/ping_server.log)
+ if [[ $(echo $ping_server_logs | grep failed | wc -l) -ne 0 ]]; then
+ echo "******** Server logs (ping) ********"
+ echo "$ping_server_logs"
+ exit 1
+ fi
+
+ # No 'Timeouts: 0' expected
+ ping_client_logs=$(docker exec forwarder cat /tmp/ping_client.log)
+ if [[ $(echo $ping_client_logs | grep -v "Timeouts: 0" | wc -l) -ne 0 ]]; then
+ echo "******** Client logs (ping) ********"
+ echo "$ping_client_logs"
+ exit 1
+ fi
+}
+
+function test_ping_wrong_signature() {
+ docker exec forwarder bash -c 'hicn-ping-server -a intmanifest >/tmp/ping_server.log 2>&1 &'
+ sleep 1
+
+ # Signature mismatch ('intmamifest' on server vs 'wrong_sign' on client)
+ docker exec forwarder bash -c 'hicn-ping-client -m 6 -a 2 wrong_sig | grep "Sent" >>/tmp/ping_client.log'
+
+ # 'failed' expected
+ ping_server_logs=$(docker exec forwarder cat /tmp/ping_server.log)
+ if [[ $(echo $ping_server_logs | grep "failed" | wc -l) -eq 0 ]]; then
+ echo "******** Server logs (signature fail) ********"
+ echo "$ping_server_logs"
+ exit 1
+ fi
+}
+
+function test_ping_no_server() {
+ # Server not started to check for ping client timeout
+ docker exec forwarder bash -c 'hicn-ping-client -m 6 | grep "Sent" >>/tmp/ping_client.log'
+
+ # 'Timeouts: 6' expected
+ ping_client_logs=$(docker exec forwarder cat /tmp/ping_client.log)
+ if [[ $(echo $ping_client_logs | grep "Timeouts: 6" | wc -l) -eq 0 ]]; then
+ echo "******** Client logs (timeout) ********"
+ echo "$ping_client_logs"
+ exit 1
+ fi
+}
+
+declare -A ping_tests=(
+ ["manifest"]="test_ping_manifest"
+ ["signature"]="test_ping_wrong_signature"
+ ["timeout"]="test_ping_no_server"
+)
+
+function ping_test_exists() {
+ [[ "${!ping_tests[*]}" =~ ${1} ]] && return 0 || return 1
+}
+
+function ping() {
+ type=$1
+ if ! ping_test_exists "${type}"; then
+ error "Error: hicn-ping test does not exist."
+ exit 1
+ fi
+
+ ${ping_tests[${type}]}
+}
+
+#--------------------------------------------------------------#
+
while (("${#}")); do
case "$1" in
'build')
@@ -510,6 +601,10 @@ while (("${#}")); do
ctrl "${2}"
break
;;
+ 'ping')
+ ping "${2}"
+ break
+ ;;
*)
exit 1
;;
diff --git a/tests/functional-tests/hicn-light-ping.robot b/tests/functional-tests/hicn-light-ping.robot
new file mode 100644
index 000000000..238f49e0e
--- /dev/null
+++ b/tests/functional-tests/hicn-light-ping.robot
@@ -0,0 +1,26 @@
+*** Settings ***
+Resource resources/libraries/robot/common.robot
+Test Setup Run Keywords
+... Build Topology 1-node AND
+... Check Environment
+Test Teardown Run Keywords
+... Destroy Topology
+
+*** Test Cases ***
+Ping with manifest
+ Log to console Test ping with manifest
+ ${result} = Run Process ${EXECDIR}/config.sh ping manifest
+ Log Many stdout: ${result.stdout}
+ Should Be Equal As Integers ${result.rc} 0
+
+Ping wrong signature
+ Log to console Test ping with wrong signature
+ ${result} = Run Process ${EXECDIR}/config.sh ping signature
+ Log Many stdout: ${result.stdout}
+ Should Be Equal As Integers ${result.rc} 0
+
+Ping timeout
+ Log to console Test ping timeout
+ ${result} = Run Process ${EXECDIR}/config.sh ping timeout
+ Log Many stdout: ${result.stdout}
+ Should Be Equal As Integers ${result.rc} 0