1+ #include " dcqcn.hpp"
2+
3+ #include " scheduler/scheduler.hpp"
4+
5+ namespace sim {
6+ DCQCN::DCQCN (const ParamsDQCCN& a_params)
7+ : m_params(a_params),
8+ m_current_rate (a_params.rpg_min_rate),
9+ m_target_rate(m_current_rate),
10+ m_alpha(m_params.initial_alpha_value) {}
11+
12+ void DCQCN::start () {
13+ Scheduler& sched = Scheduler::get_instance ();
14+ TimeNs now = sched.get_current_time ();
15+
16+ // enqueue first alpha update event
17+ sched.add (now + m_params.dce_tcp_rtt , [this ]() { on_alpha_timer (); });
18+
19+ // enqueue first rate increase timer event
20+ sched.add (now + m_params.rpg_time_reset , [this , last_cnp = m_last_cnp]() {
21+ on_rate_increase_timer (last_cnp);
22+ });
23+
24+ sched.add (now + m_params.rate_reduce_monitor_period ,
25+ [this ]() { on_rate_reduce_monitor_period (); });
26+ }
27+
28+ void DCQCN::stop () { m_stop_request = true ; }
29+
30+ void DCQCN::on_cnp () {
31+ if (m_stop_request) {
32+ return ;
33+ }
34+
35+ TimeNs now = Scheduler::get_instance ().get_current_time ();
36+ m_last_cnp = now;
37+ m_bytes_from_last_byte_reset = SizeByte (0ul );
38+ m_time_counter = 0 ;
39+ }
40+
41+ void DCQCN::on_data_delivery (SizeByte size) {
42+ if (m_stop_request) {
43+ return ;
44+ }
45+
46+ m_bytes_from_last_byte_reset += size;
47+ while (m_bytes_from_last_byte_reset >= m_params.rpg_byte_reset ) {
48+ m_bytes_from_last_byte_reset -= m_params.rpg_byte_reset ;
49+ m_byte_counter++;
50+ on_rate_increase_event ();
51+ }
52+ }
53+
54+ SpeedMbps DCQCN::get_rate () const { return m_current_rate; }
55+
56+ void DCQCN::on_rate_reduce_monitor_period () {
57+ if (m_stop_request) {
58+ return ;
59+ }
60+
61+ Scheduler& sched = Scheduler::get_instance ();
62+ TimeNs now = sched.get_current_time ();
63+ if (m_last_cnp &&
64+ now <= m_last_cnp.value () + m_params.rate_reduce_monitor_period ) {
65+ // found CNP over last m_params.rate_reduce_monitor_period => reset
66+ // timers
67+
68+ if (m_params.clamp_tgt_rate && !m_dec_target_rate) {
69+ m_target_rate = m_current_rate;
70+ }
71+ m_dec_target_rate = true ;
72+
73+ // decrement current rate
74+ m_current_rate =
75+ m_current_rate *
76+ std::max (m_params.rpg_min_dec_fac ,
77+ (1 - m_alpha / static_cast <double >(1 << m_params.rpg_gd )));
78+ m_current_rate = std::max (m_current_rate, m_params.rpg_min_rate );
79+ m_bytes_from_last_byte_reset = SizeByte (0ul );
80+ m_byte_counter = 0 ;
81+ m_time_counter = 0 ;
82+ }
83+
84+ sched.add (now + m_params.rpg_time_reset , [this , last_cnp = m_last_cnp]() {
85+ on_rate_increase_timer (last_cnp);
86+ });
87+ }
88+
89+ void DCQCN::on_alpha_timer () {
90+ if (m_stop_request) {
91+ return ;
92+ }
93+
94+ Scheduler& sched = Scheduler::get_instance ();
95+ TimeNs now = sched.get_current_time ();
96+ static constexpr int two_pow = (1 << 10 );
97+ if (m_last_cnp && now <= m_last_cnp.value () + m_params.dce_tcp_rtt ) {
98+ // cnp detected over last m_params.dce_tcp_rtt => increment alpha
99+ m_alpha =
100+ (m_params.dce_tcp_g / static_cast <double >(two_pow)) * m_alpha +
101+ two_pow - m_params.dce_tcp_g ;
102+ } else {
103+ // no cnp over last last m_params.dce_tcp_rtt => decrement alpha
104+ m_alpha = (m_params.dce_tcp_g / static_cast <double >(two_pow)) * m_alpha;
105+ }
106+ }
107+
108+ void DCQCN::on_rate_increase_timer (std::optional<TimeNs> last_elapced_cnp) {
109+ if (m_stop_request) {
110+ return ;
111+ }
112+
113+ if (m_last_cnp != last_elapced_cnp) {
114+ // there was cnp over m_params.rpg_time_reset => event should be
115+ // cancelled
116+ return ;
117+ }
118+ // no cnp over last m_params.rpg_time_reset => update time counter &
119+ // reschedule event
120+ m_time_counter++;
121+ on_rate_increase_event ();
122+ Scheduler& sched = Scheduler::get_instance ();
123+ TimeNs now = sched.get_current_time ();
124+ sched.add (now + m_params.rpg_time_reset ,
125+ [this , new_last_elapced_cnp = m_last_cnp]() {
126+ on_rate_increase_timer (new_last_elapced_cnp);
127+ });
128+ }
129+
130+ void DCQCN::on_rate_increase_event () {
131+ if (m_stop_request) {
132+ return ;
133+ }
134+
135+ if (std::max (m_time_counter, m_byte_counter) < m_params.rpg_threshold ) {
136+ // fast recovery; no target rate update
137+ } else if (std::min (m_time_counter, m_byte_counter) <=
138+ m_params.rpg_threshold ) {
139+ // additive increase
140+ m_target_rate += m_params.rpg_ai_rate ;
141+ } else {
142+ // hyper increase
143+ m_target_rate += m_params.rpg_hai_rate ;
144+ }
145+ m_current_rate = (m_current_rate + m_target_rate) / 2.0 ;
146+ }
147+
148+ } // namespace sim
0 commit comments