solanaceae_ngc_ft1/solanaceae/ngc_ft1/cubic.cpp

115 lines
2.8 KiB
C++
Raw Normal View History

2023-08-24 18:04:25 +02:00
#include "./cubic.hpp"
#include <cmath>
#include <iostream>
void CUBIC::updateReductionTimer(float time_delta) {
const auto now {getTimeNow()};
// only keep updating while the cca interaction is not too long ago
2024-05-27 18:07:19 +02:00
if (now - _time_point_last_update <= getCurrentDelay()*4.f) {
_time_since_reduction += time_delta;
}
}
void CUBIC::resetReductionTimer(void) {
_time_since_reduction = 0.f;
}
2023-08-24 18:04:25 +02:00
float CUBIC::getCWnD(void) const {
const double K = cbrt(
(_window_max * (1. - BETA)) / SCALING_CONSTANT
);
const double TK = _time_since_reduction - K;
2023-08-24 18:04:25 +02:00
const double cwnd =
SCALING_CONSTANT
* TK * TK * TK // TK^3
+ _window_max
;
2023-08-30 13:45:09 +02:00
#if 0
std::cout
<< "K:" << K
<< " ts:" << time_since_reduction
<< " TK:" << TK
<< " cwnd:" << cwnd
<< " rtt:" << getCurrentDelay()
<< "\n"
;
2023-08-30 13:45:09 +02:00
#endif
2023-08-24 18:04:25 +02:00
return std::max<float>(cwnd, 2.f * MAXIMUM_SEGMENT_SIZE);
2023-08-24 18:04:25 +02:00
}
void CUBIC::onCongestion(void) {
// 8 is probably too much (800ms for 100ms rtt)
if (_time_since_reduction >= getCurrentDelay()*4.f) {
const auto tmp_old_tp = _time_since_reduction;
2023-09-02 02:28:22 +02:00
const auto current_cwnd = getCWnD(); // TODO: remove, only used by logging?
2023-09-08 00:41:25 +02:00
const auto current_wnd = getWindow(); // respects cwnd and fwnd
_bytes_leftover = 0;
resetReductionTimer();
if (current_cwnd < _window_max) {
// congestion before reaching the inflection point (prev window_max).
// reduce to wnd*beta to be fair
_window_max = current_wnd * BETA;
} else {
_window_max = current_wnd;
}
_window_max = std::max(_window_max, 2.0*MAXIMUM_SEGMENT_SIZE);
2023-08-24 18:04:25 +02:00
2023-09-01 17:34:05 +02:00
#if 1
2023-09-02 02:28:22 +02:00
std::cout << "----CONGESTION!"
2023-09-08 00:41:25 +02:00
<< " cwnd:" << current_cwnd
<< " wnd:" << current_wnd
2023-09-01 17:34:05 +02:00
<< " cwnd_max:" << _window_max
<< " pts:" << tmp_old_tp
<< " rtt:" << getCurrentDelay()
<< "\n"
;
#endif
2023-08-30 13:45:09 +02:00
}
2023-08-24 18:04:25 +02:00
}
2023-09-08 00:41:25 +02:00
float CUBIC::getWindow(void) {
return std::min<float>(getCWnD(), FlowOnly::getWindow());
}
int64_t CUBIC::canSend(float time_delta) {
const auto fspace_pkgs = FlowOnly::canSend(time_delta);
2023-08-24 18:04:25 +02:00
updateReductionTimer(time_delta);
2023-08-30 13:45:09 +02:00
if (fspace_pkgs == 0u) {
return 0u;
}
2023-08-24 18:04:25 +02:00
const auto window = getCWnD();
int64_t cspace_bytes = (window - _in_flight_bytes) + _bytes_leftover;
2023-08-30 13:45:09 +02:00
if (cspace_bytes < MAXIMUM_SEGMENT_DATA_SIZE) {
return 0u;
}
2023-08-24 18:04:25 +02:00
// also limit to max sendrate per tick, which is usually smaller than window
// this is mostly to prevent spikes on empty windows
const auto rate = window / getCurrentDelay();
// we dont want this limit to fall below atleast 1 segment
const int64_t max_bytes_per_tick = std::max<int64_t>(rate * time_delta + 0.5f, MAXIMUM_SEGMENT_SIZE);
cspace_bytes = std::min<int64_t>(cspace_bytes, max_bytes_per_tick);
// limit to whole packets
2023-09-01 17:34:05 +02:00
int64_t cspace_pkgs = (cspace_bytes / MAXIMUM_SEGMENT_DATA_SIZE) * MAXIMUM_SEGMENT_DATA_SIZE;
2023-08-24 18:04:25 +02:00
_bytes_leftover = cspace_bytes - cspace_pkgs;
2023-08-30 13:45:09 +02:00
return std::min(cspace_pkgs, fspace_pkgs);
2023-08-24 18:04:25 +02:00
}