From d875ae92a7fa1eaab3bc2616aeeedfc64a81fea4 Mon Sep 17 00:00:00 2001 From: Mauro Sardara Date: Fri, 4 Sep 2020 08:21:02 +0000 Subject: [HICN-635] Expose protocol API in libtransport. Signed-off-by: Mauro Sardara Change-Id: I626acb5f79a85b167d50da5c07fa597a9ff4d239 --- .../src/protocols/raaqm_transport_algorithm.cc | 255 +++++++++++++++++++++ 1 file changed, 255 insertions(+) create mode 100644 libtransport/src/protocols/raaqm_transport_algorithm.cc (limited to 'libtransport/src/protocols/raaqm_transport_algorithm.cc') diff --git a/libtransport/src/protocols/raaqm_transport_algorithm.cc b/libtransport/src/protocols/raaqm_transport_algorithm.cc new file mode 100644 index 000000000..09e3a47ab --- /dev/null +++ b/libtransport/src/protocols/raaqm_transport_algorithm.cc @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2020 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 + +namespace transport { +namespace protocol { + +RaaqmTransportAlgorithm::RaaqmTransportAlgorithm( + interface::TransportStatistics *stats, IcnRateEstimator *rate_estimator, + double drop_factor, double minimum_drop_probability, double gamma, + double beta, uint32_t sample_number, uint32_t interest_lifetime, + double beta_wifi, double drop_wifi, double beta_lte, double drop_lte, + unsigned int wifi_delay, unsigned int lte_delay, double max_window, + double min_window) + : current_window_size_(1), + cur_path_(nullptr), + rate_estimator_(rate_estimator), + stats_(stats), + drop_factor_(drop_factor), + minimum_drop_probability_(minimum_drop_probability), + gamma_(gamma), + beta_(beta), + sample_number_(sample_number), + interest_lifetime_(interest_lifetime), + beta_wifi_(beta_wifi), + drop_wifi_(drop_wifi), + beta_lte_(beta_lte), + drop_lte_(drop_lte), + wifi_delay_(wifi_delay), + lte_delay_(lte_delay), + max_window_(max_window), + min_window_(min_window) {} + +RaaqmTransportAlgorithm::~RaaqmTransportAlgorithm() {} + +void RaaqmTransportAlgorithm::reset() { + if (rate_estimator_) { + rate_estimator_->onStart(); + } + + if (!cur_path_) { + // Current path + auto cur_path = std::make_unique( + drop_factor_, minimum_drop_probability_, interest_lifetime_ * 1000, + sample_number_); + cur_path_ = cur_path.get(); + path_table_[interface::default_values::path_id] = std::move(cur_path); + } +} + +void RaaqmTransportAlgorithm::increaseWindow() { + if (current_window_size_ < max_window_) { + current_window_size_ += gamma_ / current_window_size_; + } + + if (rate_estimator_) { + rate_estimator_->onWindowIncrease(current_window_size_); + } +} + +void RaaqmTransportAlgorithm::decreaseWindow() { + if (current_window_size_ > min_window_) { + current_window_size_ = current_window_size_ * beta_; + if (current_window_size_ < min_window_) { + current_window_size_ = min_window_; + } + } + + if (rate_estimator_) { + rate_estimator_->onWindowDecrease(current_window_size_); + } +} + +void RaaqmTransportAlgorithm::updateRtt(uint32_t suffix) { + if (TRANSPORT_EXPECT_FALSE(!cur_path_)) { + throw std::runtime_error("RAAQM ERROR: no current path found, exit"); + } else { + auto now = utils::SteadyClock::now(); + utils::Microseconds rtt = std::chrono::duration_cast( + now - interest_timepoints_[suffix & mask]); + + updateStats(suffix, rtt.count(), now); + + if (rate_estimator_) { + rate_estimator_->onRttUpdate((double)rtt.count()); + } + + cur_path_->insertNewRtt(rtt.count(), now); + cur_path_->smoothTimer(); + + if (cur_path_->newPropagationDelayAvailable()) { + checkDropProbability(); + } + } +} + +void RaaqmTransportAlgorithm::RAAQM() { + if (!cur_path_) { + throw errors::RuntimeException("ERROR: no current path found, exit"); + exit(EXIT_FAILURE); + } else { + // Change drop probability according to RTT statistics + cur_path_->updateDropProb(); + + double coin = ((double)rand() / (RAND_MAX)); + if (coin <= cur_path_->getDropProb()) { + decreaseWindow(); + } + } +} + +void RaaqmTransportAlgorithm::updatePathTable(uint32_t path_label) { + uint32_t path_id = path_label; + + if (path_table_.find(path_id) == path_table_.end()) { + if (TRANSPORT_EXPECT_TRUE(cur_path_ != nullptr)) { + // Create a new path with some default param + + if (TRANSPORT_EXPECT_FALSE(path_table_.empty())) { + throw errors::RuntimeException( + "[RAAQM] No path initialized for path table, error could be in " + "default path initialization."); + } + + // Initiate the new path default param + auto new_path = std::make_unique( + *(path_table_.at(interface::default_values::path_id))); + + // Insert the new path into hash table + path_table_[path_id] = std::move(new_path); + } else { + throw errors::RuntimeException( + "UNEXPECTED ERROR: when running,current path not found."); + } + } + + cur_path_ = path_table_[path_id].get(); +} + +void RaaqmTransportAlgorithm::checkDropProbability() { + if (!raaqm_autotune_) { + return; + } + + unsigned int max_pd = 0; + PathTable::iterator it; + for (auto it = path_table_.begin(); it != path_table_.end(); ++it) { + if (it->second->getPropagationDelay() > max_pd && + it->second->getPropagationDelay() != UINT_MAX && + !it->second->isStale()) { + max_pd = it->second->getPropagationDelay(); + } + } + + double drop_prob = 0; + double beta = 0; + if (max_pd < wifi_delay_) { // only ethernet paths + drop_prob = drop_factor_; + beta = beta_; + } else if (max_pd < lte_delay_) { // at least one wifi path + drop_prob = drop_wifi_; + beta = beta_wifi_; + } else { // at least one lte path + drop_prob = drop_lte_; + beta = beta_lte_; + } + + double old_drop_prob = 0; + double old_beta = 0; + // socket_->getSocketOption(RaaqmTransportOptions::BETA_VALUE, old_beta); + // socket_->getSocketOption(RaaqmTransportOptions::DROP_FACTOR, + // old_drop_prob); + + if (drop_prob == old_drop_prob && beta == old_beta) { + return; + } + + // socket_->setSocketOption(RaaqmTransportOptions::BETA_VALUE, beta); + // socket_->setSocketOption(RaaqmTransportOptions::DROP_FACTOR, drop_prob); + + for (it = path_table_.begin(); it != path_table_.end(); it++) { + it->second->setDropProb(drop_prob); + } +} + +void RaaqmTransportAlgorithm::checkForStalePaths() { + if (!raaqm_autotune_) { + return; + } + + bool stale = false; + PathTable::iterator it; + for (it = path_table_.begin(); it != path_table_.end(); ++it) { + if (it->second->isStale()) { + stale = true; + break; + } + } + if (stale) { + checkDropProbability(); + } +} + +void RaaqmTransportAlgorithm::updateStats(uint32_t suffix, uint64_t rtt, + utils::TimePoint &now) { + // Update RTT statistics + if (stats_) { + stats_->updateAverageRtt(rtt); + stats_->updateAverageWindowSize(current_window_size_); + } +} + +uint32_t RaaqmTransportAlgorithm::onContentObject(uint32_t suffix, + uint32_t path_label) { + updatePathTable(path_label); + increaseWindow(); + updateRtt(suffix); + + // Set drop probablility and window size accordingly + RAAQM(); + + return current_window_size_; +} + +uint32_t RaaqmTransportAlgorithm::onInterestTimeout(uint32_t suffix) { + checkForStalePaths(); + // Decrease the window because the timeout happened + decreaseWindow(); + + return current_window_size_; +} + +void RaaqmTransportAlgorithm::onInterestSent(uint32_t suffix) { + interest_timepoints_[suffix & mask] = utils::SteadyClock::now(); +} + +void RaaqmTransportAlgorithm::sessionEnd() { + rate_estimator_->onDownloadFinished(); +} + +} // namespace protocol +} // namespace transport \ No newline at end of file -- cgit 1.2.3-korg