aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMauro Sardara <msardara+fdio@cisco.com>2018-02-23 15:25:32 +0100
committerMauro Sardara <msardara+fdio@cisco.com>2018-02-23 18:34:34 +0100
commit95f3619c8be677bcd9cf3bb320c7262bbe6dc44b (patch)
treedce5ef7a24e987797f79a90a6009b40e667e1be5
parent9b35eadcca5b19078c55a10e68abeace81cf032c (diff)
Added native PING application
Change-Id: If76818fdc90e7223e811ece0c21f8a7c67defa4c Signed-off-by: Mauro Sardara <msardara+fdio@cisco.com>
-rwxr-xr-xapps/consumers/CMakeLists.txt6
-rw-r--r--apps/consumers/icnet_ping_client.cc265
-rw-r--r--apps/http/icnet_iget.cc2
-rwxr-xr-xapps/producers/CMakeLists.txt7
-rw-r--r--apps/producers/icnet_ping_server.cc122
-rw-r--r--icnet/ccnx/icnet_ccnx_content_object.cc2
-rw-r--r--icnet/ccnx/icnet_ccnx_content_object.h2
7 files changed, 403 insertions, 3 deletions
diff --git a/apps/consumers/CMakeLists.txt b/apps/consumers/CMakeLists.txt
index 757d0219..4cf2d2a2 100755
--- a/apps/consumers/CMakeLists.txt
+++ b/apps/consumers/CMakeLists.txt
@@ -15,6 +15,7 @@ cmake_minimum_required(VERSION 3.2)
set(CONSUMER_SOURCE_FILES icnet_consumer_test.cc)
set(CONSUMER__HELLO_WORLD_SOURCE_FILES icnet_consumer_hello_world.cc)
+set(CONSUMER_PING_CLIENT_SOURCE_FILES icnet_ping_client.cc)
add_executable(consumer-test ${CONSUMER_SOURCE_FILES})
@@ -25,3 +26,8 @@ add_executable(consumer-hello-world ${CONSUMER__HELLO_WORLD_SOURCE_FILES})
target_link_libraries(consumer-hello-world icnet ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
install(TARGETS consumer-hello-world DESTINATION ${CMAKE_INSTALL_PREFIX}/bin COMPONENT library)
+
+add_executable(icnet-ping-client ${CONSUMER_PING_CLIENT_SOURCE_FILES})
+
+target_link_libraries(icnet-ping-client icnet ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
+install(TARGETS icnet-ping-client DESTINATION ${CMAKE_INSTALL_PREFIX}/bin COMPONENT library)
diff --git a/apps/consumers/icnet_ping_client.cc b/apps/consumers/icnet_ping_client.cc
new file mode 100644
index 00000000..42a0ab19
--- /dev/null
+++ b/apps/consumers/icnet_ping_client.cc
@@ -0,0 +1,265 @@
+/*
+ * Copyright (c) 2017 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 "icnet_ccnx_portal.h"
+#include "icnet_ccnx_name.h"
+
+#include <boost/asio/steady_timer.hpp>
+
+#include <iostream>
+#include <iomanip>
+
+namespace icnet {
+
+namespace ccnx {
+
+namespace ping {
+
+typedef std::map<uint64_t, uint64_t> SendTimeMap;
+
+class Configuration {
+ public:
+ uint64_t interestLifetime_;
+ uint64_t pingInterval_;
+ uint64_t maxPing_;
+ std::string name_;
+ uint8_t ttl_;
+
+ Configuration() {
+ interestLifetime_ = 500; //ms
+ pingInterval_ = 1000000; //us
+ maxPing_ = std::numeric_limits<uint64_t>::max(); //number of interests
+ name_ = "ccnx:/pingserver"; //string
+ ttl_ = 64;
+ }
+};
+
+class Client {
+ public:
+ Client(Configuration &c)
+ : config_(c),
+ sequence_number_(0),
+ sent_(0),
+ received_(0),
+ timedout_(0),
+ duplicated_(0),
+ rtt_sum_(0),
+ rtt_sum2_(0),
+ rtt_min_(std::numeric_limits<uint64_t>::max()),
+ rtt_max_(0),
+ timer_(new boost::asio::steady_timer(portal_.getIoService())),
+ signals_(new boost::asio::signal_set(portal_.getIoService(), SIGINT, SIGQUIT)) {
+ signals_->async_wait(std::bind(&Client::afterSignal,
+ this,
+ std::placeholders::_1,
+ std::placeholders::_2));
+ }
+
+ void ping() {
+ doPing();
+ portal_.runEventsLoop();
+ }
+
+ void OnContentObjectCallback(const Interest &interest, const ContentObject &object) {
+
+ uint64_t rtt = 0;
+
+ auto it = send_timestamps_.find(interest.getName().get(-1).toSegment());
+
+ if (it != send_timestamps_.end()) {
+ rtt = std::chrono::duration_cast<std::chrono::microseconds>(
+ std::chrono::steady_clock::now().time_since_epoch()).count() - it->second;
+
+ send_timestamps_.erase(it);
+
+ if (rtt > rtt_max_) {
+ rtt_max_ = rtt;
+ }
+
+ if (rtt < rtt_min_) {
+ rtt_min_ = rtt;
+ }
+
+ rtt_sum_ += rtt;
+ rtt_sum2_ += rtt * rtt;
+ } else {
+ // Duplicated packet!!!!
+ duplicated_++;
+ }
+
+ std::cout << object.getContent().size() << " bytes content object with name ";
+ std::cout << object.getName().getPrefix(-1);
+ std::cout << ": ping_seq=" << object.getName().get(-1).toSegment();
+ if (rtt) {
+ std::cout << " time=" << std::fixed << std::setprecision(1) << float(rtt) / 1000 << " ms" << std::endl;
+ } else {
+ std::cout << "DUPLICATED!!!";
+ return;
+ }
+
+ received_++;
+ if (sent_ >= config_.maxPing_) {
+ stopPing();
+ }
+ }
+
+ void OnInterestTimeoutCallback(const Interest &interest) {
+ timedout_++;
+ if (sent_ >= config_.maxPing_) {
+ stopPing();
+ }
+ }
+
+ void doPing() {
+
+ Name interest_name(config_.name_);
+ interest_name.appendSegment(sequence_number_);
+ std::shared_ptr<Interest> interest = std::make_shared<Interest>(std::move(interest_name));
+
+ interest->setInterestLifetime(uint32_t(config_.interestLifetime_));
+ interest->setHopLimit(config_.ttl_);
+
+ portal_.sendInterest(*interest,
+ std::bind(&Client::OnContentObjectCallback,
+ this,
+ std::placeholders::_1,
+ std::placeholders::_2),
+ std::bind(&Client::OnInterestTimeoutCallback, this, std::placeholders::_1));
+
+ send_timestamps_[sequence_number_] =
+ std::chrono::duration_cast<std::chrono::microseconds>(
+ std::chrono::steady_clock::now().time_since_epoch()).count();
+
+ sequence_number_++;
+ sent_++;
+
+ if (sent_ < config_.maxPing_) {
+ this->timer_->expires_from_now(std::chrono::microseconds(config_.pingInterval_));
+ this->timer_->async_wait([this](const boost::system::error_code e) {
+ doPing();
+ });
+ }
+ }
+
+ void stopPing() {
+
+ std::cout << std::endl;
+ std::cout << "--- " << config_.name_ << " ping statistics ---" << std::endl;
+ std::cout << sent_ << " packets transmitted, " << received_ << " packets received, ";
+ std::cout << std::fixed << std::setprecision(1) << (1 - float(received_) / float(sent_)) * 100;
+ std::cout << " % packet loss" << std::endl;
+
+ if (received_ > 0) {
+ float rtt_avg = float(rtt_sum_) / float(received_);
+ float rtt2_avg = float(rtt_sum2_) / float(received_);
+ float rtt_mdev = std::sqrt(rtt2_avg - rtt_avg * rtt_avg);
+
+ std::cout << "rtt min/avg/max/mdev = ";
+ std::cout << std::fixed << std::setprecision(3) << float(rtt_min_) / 1000
+ << "/";
+ std::cout << std::fixed << std::setprecision(3) << rtt_avg / 1000 << "/";
+ std::cout << std::fixed << std::setprecision(3) << float(rtt_max_) / 1000
+ << "/";
+ std::cout << std::fixed << std::setprecision(3) << rtt_mdev / 1000
+ << " ms";
+ }
+
+ portal_.stopEventsLoop();
+ }
+
+ void afterSignal(const boost::system::error_code& ec, int signal_number) {
+ stopPing();
+ }
+
+ private:
+ Portal portal_;
+
+ Configuration config_;
+ SendTimeMap send_timestamps_;
+ uint64_t sequence_number_;
+ uint32_t sent_;
+ uint32_t received_;
+ uint32_t timedout_;
+ uint32_t duplicated_;
+ uint64_t rtt_sum_;
+ uint64_t rtt_sum2_;
+ uint64_t rtt_min_;
+ uint64_t rtt_max_;
+ std::unique_ptr<boost::asio::steady_timer> timer_;
+ std::unique_ptr<boost::asio::signal_set> signals_;
+};
+
+void help(char * program_name) {
+ std::cout << "usage: " << program_name << " [options]" << std::endl;
+ std::cout << "PING options" << std::endl;
+ std::cout << "-i <val> ping interval in microseconds (default 1000ms)" << std::endl;
+ std::cout << "-m <val> maximum number of pings to send (default unlimited)" << std::endl;
+ std::cout << "-t <val> set packet ttl (default 64)" << std::endl;
+ //std::cout << "-j <val1> <val2> jump <val2> sequence numbers every <val1> interests (default disabled)" << std::endl;
+ std::cout << "ICN options" << std::endl;
+ std::cout << "-n <val> icn name (default ccnx:/pingserver)" << std::endl;
+ std::cout << "-l <val> interest lifetime in milliseconds (default 500ms)" << std::endl;
+ std::cout << "OUTPUT options" << std::endl;
+ std::cout << "-H prints this message" << std::endl;
+}
+
+int main(int argc, char *argv[]) {
+
+ Configuration c;
+ int opt;
+
+ while ((opt = getopt(argc, argv, "j::t:i:m:s:d:n:l:SAOqVDH")) != -1) {
+ switch (opt) {
+ case 't':
+ c.ttl_ = (uint8_t) std::stoi(optarg);
+ break;
+ case 'i':
+ c.pingInterval_ = std::stoi(optarg);
+ break;
+ case 'm':
+ c.maxPing_ = std::stoi(optarg);
+ break;
+ case 'l':
+ c.interestLifetime_ = std::stoi(optarg);
+ break;
+ case 'H':
+ default:
+ help(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if (argv[optind] == 0) {
+ std::cerr << "Using default name " << c.name_ << std::endl;
+ } else {
+ c.name_ = argv[optind];
+ }
+
+ Client *ping = new Client(c);
+ ping->ping();
+
+ exit(1);
+}
+
+//close name spaces
+}
+
+}
+
+}
+
+int main(int argc, char *argv[]) {
+ return icnet::ccnx::ping::main(argc, argv);
+}
diff --git a/apps/http/icnet_iget.cc b/apps/http/icnet_iget.cc
index 4a507864..0e5121e9 100644
--- a/apps/http/icnet_iget.cc
+++ b/apps/http/icnet_iget.cc
@@ -66,7 +66,7 @@ int main(int argc, char **argv) {
} // end namespace http
-} // end namespace hicnet
+} // end namespace icnet
int main(int argc, char **argv) {
return icnet::http::main(argc, argv);
diff --git a/apps/producers/CMakeLists.txt b/apps/producers/CMakeLists.txt
index 37366362..2d97eb2e 100755
--- a/apps/producers/CMakeLists.txt
+++ b/apps/producers/CMakeLists.txt
@@ -20,11 +20,18 @@ set(PRODUCER_SOURCE_FILES
set(PRODUCER_HELLO_WORLD_SOURCE_FILES
icnet_producer_hello_world.cc)
+set(PRODUCER_PING_SOURCE_FILES
+ icnet_ping_server.cc)
+
add_executable(producer-test ${PRODUCER_SOURCE_FILES})
add_executable(producer-hello-world ${PRODUCER_HELLO_WORLD_SOURCE_FILES})
+add_executable(icnet-ping-server ${PRODUCER_PING_SOURCE_FILES})
+
target_link_libraries(producer-test icnet ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
target_link_libraries(producer-hello-world icnet ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
+target_link_libraries(icnet-ping-server icnet ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
install(TARGETS producer-test DESTINATION ${CMAKE_INSTALL_PREFIX}/bin COMPONENT library)
install(TARGETS producer-hello-world DESTINATION ${CMAKE_INSTALL_PREFIX}/bin COMPONENT library)
+install(TARGETS icnet-ping-server DESTINATION ${CMAKE_INSTALL_PREFIX}/bin COMPONENT library)
diff --git a/apps/producers/icnet_ping_server.cc b/apps/producers/icnet_ping_server.cc
new file mode 100644
index 00000000..57f0d88f
--- /dev/null
+++ b/apps/producers/icnet_ping_server.cc
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2017 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 "icnet_transport_socket_producer.h"
+#include "icnet_utils_daemonizator.h"
+
+namespace icnet {
+
+namespace transport {
+
+class CallbackContainer {
+ public:
+ CallbackContainer(const std::string &prefix,
+ uint32_t object_size)
+ : buffer_(object_size, 0xFF),
+ content_object_(std::make_shared<ContentObject>(Name(prefix), (const uint8_t *) buffer_.data(), buffer_.size())) {
+ content_object_->setExpiryTime(0);
+ }
+
+ void processInterest(ProducerSocket &p, const Interest &interest) {
+
+ std::cout << "<<< received interest " << interest.getName() << std::endl;
+ content_object_->setName(interest.getName());
+ std::cout << ">>> send object " << content_object_->getName() << std::endl;
+ std::cout << std::endl;
+
+ p.produce(*content_object_);
+ }
+
+ private:
+ std::string buffer_;
+ std::shared_ptr<ContentObject> content_object_;
+};
+
+void help(char * program_name) {
+ std::cout << "usage: " << program_name <<" [options]" << std::endl;
+ std::cout << "PING options" << std::endl;
+ std::cout << "-s <val> object content size (default 64B)" << std::endl;
+ std::cout << "-n <val> icn name (default ccnx:/webserver)" << std::endl;
+ std::cout << "OUTPUT options" << std::endl;
+ std::cout << "-H prints this message" << std::endl;
+}
+
+int main(int argc, char **argv) {
+ std::string name_prefix = "ccnx:/pingserver";
+ bool daemon = false;
+ uint32_t object_size = 64;
+ uint8_t ttl = 64;
+
+ int opt;
+ while ((opt = getopt(argc, argv, "s:n:t:dH")) != -1) {
+ switch (opt) {
+ case 's':
+ object_size = std::stoi(optarg);
+ break;
+ case 't':
+ ttl = (uint8_t) std::stoi(optarg);
+ break;
+ case 'd':
+ daemon = true;
+ break;
+ case 'H':
+ default:
+ help(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if (argv[optind] != 0) {
+ name_prefix = argv[optind];
+ }
+
+ if (daemon) {
+ utils::Daemonizator::daemonize();
+ }
+
+ if (object_size > 1350)
+ object_size = 1350;
+
+ std::cout << "Using prefix [" << name_prefix << "]" << std::endl;
+
+ CallbackContainer stubs(name_prefix, object_size);
+
+ boost::asio::io_service io_service;
+
+ ProducerSocket p(Name(name_prefix.c_str()));
+ p.setSocketOption(GeneralTransportOptions::MAKE_MANIFEST, false);
+
+ // setting callbacks
+ p.setSocketOption(ProducerCallbacksOptions::INTEREST_INPUT,
+ (ProducerInterestCallback) bind(&CallbackContainer::processInterest,
+ &stubs,
+ std::placeholders::_1,
+ std::placeholders::_2));
+
+ p.attach();
+
+ p.serveForever();
+
+ return 0;
+}
+
+} // end namespace transport
+
+} // end namespace icnet
+
+int main(int argc, char **argv) {
+ return icnet::transport::main(argc, argv);
+}
+
diff --git a/icnet/ccnx/icnet_ccnx_content_object.cc b/icnet/ccnx/icnet_ccnx_content_object.cc
index e4070194..da9a71f2 100644
--- a/icnet/ccnx/icnet_ccnx_content_object.cc
+++ b/icnet/ccnx/icnet_ccnx_content_object.cc
@@ -29,7 +29,7 @@ ContentObject::ContentObject()
content_type_(PayloadType::DATA) {
}
-ContentObject::ContentObject(const Name &name, uint8_t *payload, std::size_t size)
+ContentObject::ContentObject(const Name &name, const uint8_t *payload, std::size_t size)
: name_(name), content_type_(PayloadType::DATA) {
PARCBuffer *buffer = parcBuffer_CreateFromArray(payload, size);
buffer = parcBuffer_Flip(buffer);
diff --git a/icnet/ccnx/icnet_ccnx_content_object.h b/icnet/ccnx/icnet_ccnx_content_object.h
index e7e641e6..367df0be 100644
--- a/icnet/ccnx/icnet_ccnx_content_object.h
+++ b/icnet/ccnx/icnet_ccnx_content_object.h
@@ -59,7 +59,7 @@ class ContentObject : public std::enable_shared_from_this<ContentObject> {
public:
ContentObject();
- ContentObject(const Name &name, uint8_t *payload, std::size_t size);
+ ContentObject(const Name &name, const uint8_t *payload, std::size_t size);
ContentObject(const CCNxContentObjectStructure *content_object);