1 /*
2 * ngtcp2
3 *
4 * Copyright (c) 2019 ngtcp2 contributors
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25 #include "ngtcp2_rst.h"
26
27 #include <assert.h>
28
29 #include "ngtcp2_rtb.h"
30 #include "ngtcp2_cc.h"
31 #include "ngtcp2_macro.h"
32
ngtcp2_rs_init(ngtcp2_rs * rs)33 void ngtcp2_rs_init(ngtcp2_rs *rs) {
34 rs->interval = UINT64_MAX;
35 rs->delivered = 0;
36 rs->prior_delivered = 0;
37 rs->prior_ts = 0;
38 rs->tx_in_flight = 0;
39 rs->lost = 0;
40 rs->prior_lost = 0;
41 rs->send_elapsed = 0;
42 rs->ack_elapsed = 0;
43 rs->is_app_limited = 0;
44 }
45
ngtcp2_rst_init(ngtcp2_rst * rst)46 void ngtcp2_rst_init(ngtcp2_rst *rst) {
47 ngtcp2_rs_init(&rst->rs);
48 ngtcp2_window_filter_init(&rst->wf, 12);
49 rst->delivered = 0;
50 rst->delivered_ts = 0;
51 rst->first_sent_ts = 0;
52 rst->app_limited = 0;
53 rst->next_round_delivered = 0;
54 rst->round_count = 0;
55 rst->is_cwnd_limited = 0;
56 rst->lost = 0;
57 }
58
ngtcp2_rst_on_pkt_sent(ngtcp2_rst * rst,ngtcp2_rtb_entry * ent,const ngtcp2_conn_stat * cstat)59 void ngtcp2_rst_on_pkt_sent(ngtcp2_rst *rst, ngtcp2_rtb_entry *ent,
60 const ngtcp2_conn_stat *cstat) {
61 if (cstat->bytes_in_flight == 0) {
62 rst->first_sent_ts = rst->delivered_ts = ent->ts;
63 }
64 ent->rst.first_sent_ts = rst->first_sent_ts;
65 ent->rst.delivered_ts = rst->delivered_ts;
66 ent->rst.delivered = rst->delivered;
67 ent->rst.is_app_limited = rst->app_limited != 0;
68 ent->rst.tx_in_flight = cstat->bytes_in_flight + ent->pktlen;
69 ent->rst.lost = rst->lost;
70 }
71
ngtcp2_rst_on_ack_recv(ngtcp2_rst * rst,ngtcp2_conn_stat * cstat,uint64_t pkt_delivered)72 int ngtcp2_rst_on_ack_recv(ngtcp2_rst *rst, ngtcp2_conn_stat *cstat,
73 uint64_t pkt_delivered) {
74 ngtcp2_rs *rs = &rst->rs;
75 uint64_t rate;
76
77 if (rst->app_limited && rst->delivered > rst->app_limited) {
78 rst->app_limited = 0;
79 }
80
81 if (pkt_delivered >= rst->next_round_delivered) {
82 rst->next_round_delivered = pkt_delivered;
83 ++rst->round_count;
84 }
85
86 if (rs->prior_ts == 0) {
87 return 0;
88 }
89
90 rs->interval = ngtcp2_max(rs->send_elapsed, rs->ack_elapsed);
91
92 rs->delivered = rst->delivered - rs->prior_delivered;
93 rs->lost = rst->lost - rs->prior_lost;
94
95 if (rs->interval < cstat->min_rtt) {
96 rs->interval = UINT64_MAX;
97 return 0;
98 }
99
100 if (!rs->interval) {
101 return 0;
102 }
103
104 rate = rs->delivered * NGTCP2_SECONDS / rs->interval;
105
106 if (rate > ngtcp2_window_filter_get_best(&rst->wf) || !rst->app_limited) {
107 ngtcp2_window_filter_update(&rst->wf, rate, rst->round_count);
108 cstat->delivery_rate_sec = ngtcp2_window_filter_get_best(&rst->wf);
109 }
110
111 return 0;
112 }
113
ngtcp2_rst_update_rate_sample(ngtcp2_rst * rst,const ngtcp2_rtb_entry * ent,ngtcp2_tstamp ts)114 void ngtcp2_rst_update_rate_sample(ngtcp2_rst *rst, const ngtcp2_rtb_entry *ent,
115 ngtcp2_tstamp ts) {
116 ngtcp2_rs *rs = &rst->rs;
117
118 rst->delivered += ent->pktlen;
119 rst->delivered_ts = ts;
120
121 if (ent->rst.delivered > rs->prior_delivered) {
122 rs->prior_delivered = ent->rst.delivered;
123 rs->prior_ts = ent->rst.delivered_ts;
124 rs->is_app_limited = ent->rst.is_app_limited;
125 rs->send_elapsed = ent->ts - ent->rst.first_sent_ts;
126 rs->ack_elapsed = rst->delivered_ts - ent->rst.delivered_ts;
127 rs->tx_in_flight = ent->rst.tx_in_flight;
128 rs->prior_lost = ent->rst.lost;
129 rst->first_sent_ts = ent->ts;
130 }
131 }
132
ngtcp2_rst_update_app_limited(ngtcp2_rst * rst,ngtcp2_conn_stat * cstat)133 void ngtcp2_rst_update_app_limited(ngtcp2_rst *rst, ngtcp2_conn_stat *cstat) {
134 (void)rst;
135 (void)cstat;
136 /* TODO Not implemented */
137 }
138