diff --git a/solanaceae/ngc_ft1/cubic.cpp b/solanaceae/ngc_ft1/cubic.cpp index 77a50f8..2c5ccfd 100644 --- a/solanaceae/ngc_ft1/cubic.cpp +++ b/solanaceae/ngc_ft1/cubic.cpp @@ -8,7 +8,9 @@ float CUBIC::getCWnD(void) const { (_window_max * (1. - BETA)) / SCALING_CONSTANT ); - const double TK = _time_since_reduction - K; + const auto time_since_reduction = getTimeNow() - _time_point_reduction; + + const double TK = time_since_reduction - K; const double cwnd = SCALING_CONSTANT @@ -16,34 +18,42 @@ float CUBIC::getCWnD(void) const { + _window_max ; - std::cout << "K:" << K << " TK:" << TK << " cwnd:" << cwnd << " rtt:" << getCurrentDelay() << "\n"; + std::cout + << "K:" << K + << " ts:" << time_since_reduction + << " TK:" << TK + << " cwnd:" << cwnd + << " rtt:" << getCurrentDelay() + << "\n" + ; - return cwnd; + return std::max(cwnd, 2.f * MAXIMUM_SEGMENT_SIZE); } -float CUBIC::getCurrentDelay(void) const { - return _rtt_ema; -} +void CUBIC::onCongestion(void) { + const auto current_cwnd = getCWnD(); + _time_point_reduction = getTimeNow(); + _window_max = current_cwnd; -void CUBIC::addRTT(float new_delay) { - // lerp(new_delay, rtt_ema, 0.1) - _rtt_ema = RTT_EMA_ALPHA * new_delay + (1.f - RTT_EMA_ALPHA) * _rtt_ema; + //std::cout << "CONGESTION!\n"; } size_t CUBIC::canSend(void) { - return 0; -} - -std::vector CUBIC::getTimeouts(void) const { - return {}; -} - -void CUBIC::onSent(SeqIDType seq, size_t data_size) { -} - -void CUBIC::onAck(std::vector seqs) { -} - -void CUBIC::onLoss(SeqIDType seq, bool discard) { + const auto flow_space = FlowOnly::canSend(); + + if (flow_space == 0) { + return 0; + } + + const int64_t cspace = getCWnD() - _in_flight_bytes; + if (cspace < MAXIMUM_SEGMENT_DATA_SIZE) { + return 0u; + } + + // limit to whole packets + size_t space = std::ceil(cspace / MAXIMUM_SEGMENT_DATA_SIZE) + * MAXIMUM_SEGMENT_DATA_SIZE; + + return std::min(space, flow_space); } diff --git a/solanaceae/ngc_ft1/cubic.hpp b/solanaceae/ngc_ft1/cubic.hpp index b73489e..e146d72 100644 --- a/solanaceae/ngc_ft1/cubic.hpp +++ b/solanaceae/ngc_ft1/cubic.hpp @@ -1,11 +1,11 @@ #pragma once -#include "./cca.hpp" +#include "./flow_only.hpp" #include -struct CUBIC : public CCAI { - using clock = std::chrono::steady_clock; +struct CUBIC : public FlowOnly { + //using clock = std::chrono::steady_clock; public: // config static constexpr float BETA {0.7f}; @@ -15,34 +15,22 @@ struct CUBIC : public CCAI { private: // window size before last reduciton double _window_max {2.f * MAXIMUM_SEGMENT_SIZE}; // start with mss*2 - double _window_last_max {2.f * MAXIMUM_SEGMENT_SIZE}; - double _time_since_reduction {0.}; - - // initialize to low value, will get corrected very fast - float _fwnd {0.01f * max_byterate_allowed}; // in bytes - - // rtt exponental moving average - float _rtt_ema {0.5f}; - - clock::time_point _time_start_offset; + //double _window_last_max {2.f * MAXIMUM_SEGMENT_SIZE}; + double _time_point_reduction {getTimeNow()}; private: float getCWnD(void) const; - // make values relative to algo start for readability (and precision) - // get timestamp in seconds - double getTimeNow(void) const { - return std::chrono::duration{clock::now() - _time_start_offset}.count(); - } - // moving avg over the last few delay samples // VERY sensitive to bundling acks - float getCurrentDelay(void) const; + //float getCurrentDelay(void) const; - void addRTT(float new_delay); + //void addRTT(float new_delay); + + void onCongestion(void) override; public: // api - CUBIC(size_t maximum_segment_data_size) : CCAI(maximum_segment_data_size) {} + CUBIC(size_t maximum_segment_data_size) : FlowOnly(maximum_segment_data_size) {} // TODO: api for how much data we should send // take time since last sent into account @@ -50,15 +38,15 @@ struct CUBIC : public CCAI { size_t canSend(void) override; // get the list of timed out seq_ids - std::vector getTimeouts(void) const override; + //std::vector getTimeouts(void) const override; public: // callbacks // data size is without overhead - void onSent(SeqIDType seq, size_t data_size) override; + //void onSent(SeqIDType seq, size_t data_size) override; - void onAck(std::vector seqs) override; + //void onAck(std::vector seqs) override; // if discard, not resent, not inflight - void onLoss(SeqIDType seq, bool discard) override; + //void onLoss(SeqIDType seq, bool discard) override; }; diff --git a/solanaceae/ngc_ft1/flow_only.cpp b/solanaceae/ngc_ft1/flow_only.cpp index 4643931..cedaae1 100644 --- a/solanaceae/ngc_ft1/flow_only.cpp +++ b/solanaceae/ngc_ft1/flow_only.cpp @@ -86,6 +86,9 @@ void FlowOnly::onAck(std::vector seqs) { if (it != _in_flight.begin()) { // not next expected seq -> skip detected // TODO: congestion event + + std::cout << "CONGESTION out of order\n"; + onCongestion(); //if (getTimeNow() >= _last_congestion_event + _last_congestion_rtt) { //_recently_lost_data = true; //_last_congestion_event = getTimeNow(); @@ -95,6 +98,13 @@ void FlowOnly::onAck(std::vector seqs) { // only mesure delay, if not a congestion addRTT(now - std::get<1>(*it)); } + } else { + // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +#if 0 + // assume we got a duplicated packet + std::cout << "CONGESTION duplicate\n"; + onCongestion(); +#endif } } diff --git a/solanaceae/ngc_ft1/flow_only.hpp b/solanaceae/ngc_ft1/flow_only.hpp index 51e72b4..ce2a036 100644 --- a/solanaceae/ngc_ft1/flow_only.hpp +++ b/solanaceae/ngc_ft1/flow_only.hpp @@ -7,19 +7,22 @@ #include struct FlowOnly : public CCAI { - using clock = std::chrono::steady_clock; + protected: + using clock = std::chrono::steady_clock; public: // config static constexpr float RTT_EMA_ALPHA = 0.1f; // might need over time static constexpr float RTT_MAX = 2.f; // 2 sec is probably too much + //float max_byterate_allowed {100.f*1024*1024}; // 100MiB/s + float max_byterate_allowed {10.f*1024*1024}; // 10MiB/s //float max_byterate_allowed {1.f*1024*1024}; // 1MiB/s - //float max_byterate_allowed {0.6f*1024*1024}; // 600MiB/s - float max_byterate_allowed {0.5f*1024*1024}; // 500MiB/s + //float max_byterate_allowed {0.6f*1024*1024}; // 600KiB/s + //float max_byterate_allowed {0.5f*1024*1024}; // 500KiB/s //float max_byterate_allowed {0.05f*1024*1024}; // 50KiB/s //float max_byterate_allowed {0.15f*1024*1024}; // 150KiB/s - private: + protected: // initialize to low value, will get corrected very fast float _fwnd {0.01f * max_byterate_allowed}; // in bytes @@ -32,7 +35,7 @@ struct FlowOnly : public CCAI { clock::time_point _time_start_offset; - private: + protected: // make values relative to algo start for readability (and precision) // get timestamp in seconds double getTimeNow(void) const { @@ -47,6 +50,8 @@ struct FlowOnly : public CCAI { void updateWindow(void); + virtual void onCongestion(void) {}; + public: // api FlowOnly(size_t maximum_segment_data_size) : CCAI(maximum_segment_data_size) {} diff --git a/solanaceae/ngc_ft1/ngcft1.cpp b/solanaceae/ngc_ft1/ngcft1.cpp index bd86bc9..409d18d 100644 --- a/solanaceae/ngc_ft1/ngcft1.cpp +++ b/solanaceae/ngc_ft1/ngcft1.cpp @@ -712,7 +712,7 @@ bool NGCFT1::onToxEvent(const Tox_Event_Group_Peer_Exit* e) { } // reset cca - peer.cca = std::make_unique(500-4); // TODO: replace with tox_group_max_custom_lossy_packet_length()-4 + peer.cca = std::make_unique(500-4); // TODO: replace with tox_group_max_custom_lossy_packet_length()-4 return false; } diff --git a/solanaceae/ngc_ft1/ngcft1.hpp b/solanaceae/ngc_ft1/ngcft1.hpp index b8560a8..7515ff5 100644 --- a/solanaceae/ngc_ft1/ngcft1.hpp +++ b/solanaceae/ngc_ft1/ngcft1.hpp @@ -6,8 +6,9 @@ #include #include -#include "./flow_only.hpp" -#include "./ledbat.hpp" +#include "./cubic.hpp" +//#include "./flow_only.hpp" +//#include "./ledbat.hpp" #include "./rcv_buf.hpp" #include "./snd_buf.hpp" @@ -140,7 +141,7 @@ class NGCFT1 : public ToxEventI, public NGCEXTEventI, public NGCFT1EventProvider struct Group { struct Peer { - std::unique_ptr cca = std::make_unique(500-4); // TODO: replace with tox_group_max_custom_lossy_packet_length()-4 + std::unique_ptr cca = std::make_unique(500-4); // TODO: replace with tox_group_max_custom_lossy_packet_length()-4 struct RecvTransfer { uint32_t file_kind;