1/*
2 * ngtcp2
3 *
4 * Copyright (c) 2017 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#ifndef NGTCP2_RTB_H
26#define NGTCP2_RTB_H
27
28#ifdef HAVE_CONFIG_H
29#  include <config.h>
30#endif /* HAVE_CONFIG_H */
31
32#include <ngtcp2/ngtcp2.h>
33
34#include "ngtcp2_pkt.h"
35#include "ngtcp2_ksl.h"
36#include "ngtcp2_pq.h"
37#include "ngtcp2_objalloc.h"
38
39typedef struct ngtcp2_conn ngtcp2_conn;
40typedef struct ngtcp2_pktns ngtcp2_pktns;
41typedef struct ngtcp2_log ngtcp2_log;
42typedef struct ngtcp2_qlog ngtcp2_qlog;
43typedef struct ngtcp2_strm ngtcp2_strm;
44typedef struct ngtcp2_rst ngtcp2_rst;
45typedef struct ngtcp2_cc ngtcp2_cc;
46
47/* NGTCP2_FRAME_CHAIN_BINDER_FLAG_NONE indicates that no flag is
48   set. */
49#define NGTCP2_FRAME_CHAIN_BINDER_FLAG_NONE 0x00u
50/* NGTCP2_FRAME_CHAIN_BINDER_FLAG_ACK indicates that an information
51   which a frame carries has been acknowledged. */
52#define NGTCP2_FRAME_CHAIN_BINDER_FLAG_ACK 0x01u
53
54/*
55 * ngtcp2_frame_chain_binder binds 2 or more of ngtcp2_frame_chain to
56 * share the acknowledgement state.  In general, all
57 * ngtcp2_frame_chains bound to the same binder must have the same
58 * information.
59 */
60typedef struct ngtcp2_frame_chain_binder {
61  size_t refcount;
62  /* flags is bitwise OR of zero or more of
63     NGTCP2_FRAME_CHAIN_BINDER_FLAG_*. */
64  uint32_t flags;
65} ngtcp2_frame_chain_binder;
66
67int ngtcp2_frame_chain_binder_new(ngtcp2_frame_chain_binder **pbinder,
68                                  const ngtcp2_mem *mem);
69
70typedef struct ngtcp2_frame_chain ngtcp2_frame_chain;
71
72/*
73 * ngtcp2_frame_chain chains frames in a single packet.
74 */
75struct ngtcp2_frame_chain {
76  union {
77    struct {
78      ngtcp2_frame_chain *next;
79      ngtcp2_frame_chain_binder *binder;
80      ngtcp2_frame fr;
81    };
82
83    ngtcp2_opl_entry oplent;
84  };
85};
86
87ngtcp2_objalloc_def(frame_chain, ngtcp2_frame_chain, oplent);
88
89/*
90 * ngtcp2_bind_frame_chains binds two frame chains |a| and |b| using
91 * new or existing ngtcp2_frame_chain_binder.  |a| might have non-NULL
92 * a->binder.  |b| must not have non-NULL b->binder.
93 *
94 * This function returns 0 if it succeeds, or one of the following
95 * negative error codes:
96 *
97 * NGTCP2_ERR_NOMEM
98 *     Out of memory
99 */
100int ngtcp2_bind_frame_chains(ngtcp2_frame_chain *a, ngtcp2_frame_chain *b,
101                             const ngtcp2_mem *mem);
102
103/* NGTCP2_MAX_STREAM_DATACNT is the maximum number of ngtcp2_vec that
104   a ngtcp2_stream can include. */
105#define NGTCP2_MAX_STREAM_DATACNT 256
106
107/* NGTCP2_MAX_CRYPTO_DATACNT is the maximum number of ngtcp2_vec that
108   a ngtcp2_crypto can include. */
109#define NGTCP2_MAX_CRYPTO_DATACNT 8
110
111/*
112 * ngtcp2_frame_chain_new allocates ngtcp2_frame_chain object and
113 * assigns its pointer to |*pfrc|.
114 *
115 * This function returns 0 if it succeeds, or one of the following
116 * negative error codes:
117 *
118 * NGTCP2_ERR_NOMEM
119 *     Out of memory.
120 */
121int ngtcp2_frame_chain_new(ngtcp2_frame_chain **pfrc, const ngtcp2_mem *mem);
122
123/*
124 * ngtcp2_frame_chain_objalloc_new behaves like
125 * ngtcp2_frame_chain_new, but it uses |objalloc| to allocate the object.
126 */
127int ngtcp2_frame_chain_objalloc_new(ngtcp2_frame_chain **pfrc,
128                                    ngtcp2_objalloc *objalloc);
129
130/*
131 * ngtcp2_frame_chain_extralen_new works like ngtcp2_frame_chain_new,
132 * but it allocates extra memory |extralen| in order to extend
133 * ngtcp2_frame.
134 */
135int ngtcp2_frame_chain_extralen_new(ngtcp2_frame_chain **pfrc, size_t extralen,
136                                    const ngtcp2_mem *mem);
137
138/*
139 * ngtcp2_frame_chain_stream_datacnt_objalloc_new works like
140 * ngtcp2_frame_chain_new, but it allocates enough data to store
141 * additional |datacnt| - 1 ngtcp2_vec object after ngtcp2_stream
142 * object.  If no additional space is required,
143 * ngtcp2_frame_chain_objalloc_new is called internally.
144 */
145int ngtcp2_frame_chain_stream_datacnt_objalloc_new(ngtcp2_frame_chain **pfrc,
146                                                   size_t datacnt,
147                                                   ngtcp2_objalloc *objalloc,
148                                                   const ngtcp2_mem *mem);
149
150/*
151 * ngtcp2_frame_chain_crypto_datacnt_objalloc_new works like
152 * ngtcp2_frame_chain_new, but it allocates enough data to store
153 * additional |datacnt| - 1 ngtcp2_vec object after ngtcp2_crypto
154 * object.  If no additional space is required,
155 * ngtcp2_frame_chain_objalloc_new is called internally.
156 */
157int ngtcp2_frame_chain_crypto_datacnt_objalloc_new(ngtcp2_frame_chain **pfrc,
158                                                   size_t datacnt,
159                                                   ngtcp2_objalloc *objalloc,
160                                                   const ngtcp2_mem *mem);
161
162int ngtcp2_frame_chain_new_token_objalloc_new(ngtcp2_frame_chain **pfrc,
163                                              const ngtcp2_vec *token,
164                                              ngtcp2_objalloc *objalloc,
165                                              const ngtcp2_mem *mem);
166
167/*
168 * ngtcp2_frame_chain_del deallocates |frc|.  It also deallocates the
169 * memory pointed by |frc|.
170 */
171void ngtcp2_frame_chain_del(ngtcp2_frame_chain *frc, const ngtcp2_mem *mem);
172
173/*
174 * ngtcp2_frame_chain_objalloc_del adds |frc| to |objalloc| for reuse.
175 * It might just delete |frc| depending on the frame type and the size
176 * of |frc|.
177 */
178void ngtcp2_frame_chain_objalloc_del(ngtcp2_frame_chain *frc,
179                                     ngtcp2_objalloc *objalloc,
180                                     const ngtcp2_mem *mem);
181
182/*
183 * ngtcp2_frame_chain_init initializes |frc|.
184 */
185void ngtcp2_frame_chain_init(ngtcp2_frame_chain *frc);
186
187/*
188 * ngtcp2_frame_chain_list_objalloc_del adds all ngtcp2_frame_chain
189 * linked from |frc| to |objalloc| for reuse.  Depending on the frame type
190 * and its size, ngtcp2_frame_chain might be deleted instead.
191 */
192void ngtcp2_frame_chain_list_objalloc_del(ngtcp2_frame_chain *frc,
193                                          ngtcp2_objalloc *objalloc,
194                                          const ngtcp2_mem *mem);
195
196/* NGTCP2_RTB_ENTRY_FLAG_NONE indicates that no flag is set. */
197#define NGTCP2_RTB_ENTRY_FLAG_NONE 0x00u
198/* NGTCP2_RTB_ENTRY_FLAG_PROBE indicates that the entry includes a
199   probe packet. */
200#define NGTCP2_RTB_ENTRY_FLAG_PROBE 0x01u
201/* NGTCP2_RTB_ENTRY_FLAG_RETRANSMITTABLE indicates that the entry
202   includes a frame which must be retransmitted until it is
203   acknowledged.  In most cases, this flag is used along with
204   NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING and
205   NGTCP2_RTB_ENTRY_FLAG_PTO_ELICITING. */
206#define NGTCP2_RTB_ENTRY_FLAG_RETRANSMITTABLE 0x02u
207/* NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING indicates that the entry
208   elicits acknowledgement. */
209#define NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING 0x04u
210/* NGTCP2_RTB_ENTRY_FLAG_PTO_RECLAIMED indicates that the packet has
211   been reclaimed on PTO.  It is not marked lost yet and still
212   consumes congestion window. */
213#define NGTCP2_RTB_ENTRY_FLAG_PTO_RECLAIMED 0x08u
214/* NGTCP2_RTB_ENTRY_FLAG_LOST_RETRANSMITTED indicates that the entry
215   has been marked lost and, optionally, scheduled to retransmit. */
216#define NGTCP2_RTB_ENTRY_FLAG_LOST_RETRANSMITTED 0x10u
217/* NGTCP2_RTB_ENTRY_FLAG_ECN indicates that the entry is included in a
218   UDP datagram with ECN marking. */
219#define NGTCP2_RTB_ENTRY_FLAG_ECN 0x20u
220/* NGTCP2_RTB_ENTRY_FLAG_DATAGRAM indicates that the entry includes
221   DATAGRAM frame. */
222#define NGTCP2_RTB_ENTRY_FLAG_DATAGRAM 0x40u
223/* NGTCP2_RTB_ENTRY_FLAG_PMTUD_PROBE indicates that the entry includes
224   a PMTUD probe packet. */
225#define NGTCP2_RTB_ENTRY_FLAG_PMTUD_PROBE 0x80u
226/* NGTCP2_RTB_ENTRY_FLAG_PTO_ELICITING indicates that the entry
227   includes a packet which elicits PTO probe packets. */
228#define NGTCP2_RTB_ENTRY_FLAG_PTO_ELICITING 0x100u
229
230typedef struct ngtcp2_rtb_entry ngtcp2_rtb_entry;
231
232/*
233 * ngtcp2_rtb_entry is an object stored in ngtcp2_rtb.  It corresponds
234 * to the one packet which is waiting for its ACK.
235 */
236struct ngtcp2_rtb_entry {
237  union {
238    struct {
239      ngtcp2_rtb_entry *next;
240
241      struct {
242        int64_t pkt_num;
243        uint8_t type;
244        uint8_t flags;
245      } hd;
246      ngtcp2_frame_chain *frc;
247      /* ts is the time point when a packet included in this entry is sent
248         to a peer. */
249      ngtcp2_tstamp ts;
250      /* lost_ts is the time when this entry is marked lost. */
251      ngtcp2_tstamp lost_ts;
252      /* pktlen is the length of QUIC packet */
253      size_t pktlen;
254      struct {
255        uint64_t delivered;
256        ngtcp2_tstamp delivered_ts;
257        ngtcp2_tstamp first_sent_ts;
258        uint64_t tx_in_flight;
259        uint64_t lost;
260        int is_app_limited;
261      } rst;
262      /* flags is bitwise-OR of zero or more of
263         NGTCP2_RTB_ENTRY_FLAG_*. */
264      uint16_t flags;
265    };
266
267    ngtcp2_opl_entry oplent;
268  };
269};
270
271ngtcp2_objalloc_def(rtb_entry, ngtcp2_rtb_entry, oplent);
272
273/*
274 * ngtcp2_rtb_entry_new allocates ngtcp2_rtb_entry object, and assigns
275 * its pointer to |*pent|.
276 */
277int ngtcp2_rtb_entry_objalloc_new(ngtcp2_rtb_entry **pent,
278                                  const ngtcp2_pkt_hd *hd,
279                                  ngtcp2_frame_chain *frc, ngtcp2_tstamp ts,
280                                  size_t pktlen, uint16_t flags,
281                                  ngtcp2_objalloc *objalloc);
282
283/*
284 * ngtcp2_rtb_entry_objalloc_del adds |ent| to |objalloc| for reuse.
285 * ngtcp2_frame_chain linked from ent->frc are also added to
286 * |frc_objalloc| depending on their frame type and size.
287 */
288void ngtcp2_rtb_entry_objalloc_del(ngtcp2_rtb_entry *ent,
289                                   ngtcp2_objalloc *objalloc,
290                                   ngtcp2_objalloc *frc_objalloc,
291                                   const ngtcp2_mem *mem);
292
293/*
294 * ngtcp2_rtb tracks sent packets, and its ACK timeout for
295 * retransmission.
296 */
297typedef struct ngtcp2_rtb {
298  ngtcp2_objalloc *frc_objalloc;
299  ngtcp2_objalloc *rtb_entry_objalloc;
300  /* ents includes ngtcp2_rtb_entry sorted by decreasing order of
301     packet number. */
302  ngtcp2_ksl ents;
303  /* crypto is CRYPTO stream. */
304  ngtcp2_strm *crypto;
305  ngtcp2_rst *rst;
306  ngtcp2_cc *cc;
307  ngtcp2_log *log;
308  ngtcp2_qlog *qlog;
309  const ngtcp2_mem *mem;
310  /* largest_acked_tx_pkt_num is the largest packet number
311     acknowledged by the peer. */
312  int64_t largest_acked_tx_pkt_num;
313  /* num_ack_eliciting is the number of ACK eliciting entries. */
314  size_t num_ack_eliciting;
315  /* num_retransmittable is the number of packets which contain frames
316     that must be retransmitted on loss. */
317  size_t num_retransmittable;
318  /* num_pto_eliciting is the number of packets that elicit PTO probe
319     packets. */
320  size_t num_pto_eliciting;
321  /* probe_pkt_left is the number of probe packet to send */
322  size_t probe_pkt_left;
323  /* pktns_id is the identifier of packet number space. */
324  ngtcp2_pktns_id pktns_id;
325  /* cc_pkt_num is the smallest packet number that is contributed to
326     ngtcp2_conn_stat.bytes_in_flight. */
327  int64_t cc_pkt_num;
328  /* cc_bytes_in_flight is the number of in-flight bytes that is
329     contributed to ngtcp2_conn_stat.bytes_in_flight.  It only
330     includes the bytes after congestion state is reset. */
331  uint64_t cc_bytes_in_flight;
332  /* persistent_congestion_start_ts is the time when persistent
333     congestion evaluation is started.  It happens roughly after
334     handshake is confirmed. */
335  ngtcp2_tstamp persistent_congestion_start_ts;
336  /* num_lost_pkts is the number entries in ents which has
337     NGTCP2_RTB_ENTRY_FLAG_LOST_RETRANSMITTED flag set. */
338  size_t num_lost_pkts;
339  /* num_lost_pmtud_pkts is the number of entries in ents which have
340     both NGTCP2_RTB_ENTRY_FLAG_LOST_RETRANSMITTED and
341     NGTCP2_RTB_ENTRY_FLAG_PMTUD_PROBE flags set. */
342  size_t num_lost_pmtud_pkts;
343} ngtcp2_rtb;
344
345/*
346 * ngtcp2_rtb_init initializes |rtb|.
347 */
348void ngtcp2_rtb_init(ngtcp2_rtb *rtb, ngtcp2_pktns_id pktns_id,
349                     ngtcp2_strm *crypto, ngtcp2_rst *rst, ngtcp2_cc *cc,
350                     ngtcp2_log *log, ngtcp2_qlog *qlog,
351                     ngtcp2_objalloc *rtb_entry_objalloc,
352                     ngtcp2_objalloc *frc_objalloc, const ngtcp2_mem *mem);
353
354/*
355 * ngtcp2_rtb_free deallocates resources allocated for |rtb|.
356 */
357void ngtcp2_rtb_free(ngtcp2_rtb *rtb);
358
359/*
360 * ngtcp2_rtb_add adds |ent| to |rtb|.
361 *
362 * This function returns 0 if it succeeds, or one of the following
363 * negative error codes:
364 *
365 * NGTCP2_ERR_NOMEM
366 *     Out of memory
367 */
368int ngtcp2_rtb_add(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent,
369                   ngtcp2_conn_stat *cstat);
370
371/*
372 * ngtcp2_rtb_head returns the iterator which points to the entry
373 * which has the largest packet number.  If there is no entry,
374 * returned value satisfies ngtcp2_ksl_it_end(&it) != 0.
375 */
376ngtcp2_ksl_it ngtcp2_rtb_head(ngtcp2_rtb *rtb);
377
378/*
379 * ngtcp2_rtb_recv_ack removes acked ngtcp2_rtb_entry from |rtb|.
380 * |pkt_num| is a packet number which includes |fr|.  |pkt_ts| is the
381 * timestamp when packet is received.  |ts| should be the current
382 * time.  Usually they are the same, but for buffered packets,
383 * |pkt_ts| would be earlier than |ts|.
384 *
385 * This function returns the number of newly acknowledged packets if
386 * it succeeds, or one of the following negative error codes:
387 *
388 * NGTCP2_ERR_CALLBACK_FAILURE
389 *     User callback failed
390 * NGTCP2_ERR_NOMEM
391 *     Out of memory
392 */
393ngtcp2_ssize ngtcp2_rtb_recv_ack(ngtcp2_rtb *rtb, const ngtcp2_ack *fr,
394                                 ngtcp2_conn_stat *cstat, ngtcp2_conn *conn,
395                                 ngtcp2_pktns *pktns, ngtcp2_tstamp pkt_ts,
396                                 ngtcp2_tstamp ts);
397
398/*
399 * ngtcp2_rtb_detect_lost_pkt detects lost packets and prepends the
400 * frames contained them to |*pfrc|.  Even when this function fails,
401 * some frames might be prepended to |*pfrc| and the caller should
402 * handle them.
403 */
404int ngtcp2_rtb_detect_lost_pkt(ngtcp2_rtb *rtb, ngtcp2_conn *conn,
405                               ngtcp2_pktns *pktns, ngtcp2_conn_stat *cstat,
406                               ngtcp2_tstamp ts);
407
408/*
409 * ngtcp2_rtb_remove_expired_lost_pkt removes expired lost packet.
410 */
411void ngtcp2_rtb_remove_expired_lost_pkt(ngtcp2_rtb *rtb, ngtcp2_duration pto,
412                                        ngtcp2_tstamp ts);
413
414/*
415 * ngtcp2_rtb_lost_pkt_ts returns the earliest time when the still
416 * retained packet was lost.  It returns UINT64_MAX if no such packet
417 * exists.
418 */
419ngtcp2_tstamp ngtcp2_rtb_lost_pkt_ts(ngtcp2_rtb *rtb);
420
421/*
422 * ngtcp2_rtb_remove_all removes all packets from |rtb| and prepends
423 * all frames to |*pfrc|.  Even when this function fails, some frames
424 * might be prepended to |*pfrc| and the caller should handle them.
425 */
426int ngtcp2_rtb_remove_all(ngtcp2_rtb *rtb, ngtcp2_conn *conn,
427                          ngtcp2_pktns *pktns, ngtcp2_conn_stat *cstat);
428
429/*
430 * ngtcp2_rtb_remove_early_data removes all entries for 0RTT packets.
431 */
432void ngtcp2_rtb_remove_early_data(ngtcp2_rtb *rtb, ngtcp2_conn_stat *cstat);
433
434/*
435 * ngtcp2_rtb_empty returns nonzero if |rtb| have no entry.
436 */
437int ngtcp2_rtb_empty(ngtcp2_rtb *rtb);
438
439/*
440 * ngtcp2_rtb_reset_cc_state resets congestion state in |rtb|.
441 * |cc_pkt_num| is the next outbound packet number which is sent under
442 * new congestion state.
443 */
444void ngtcp2_rtb_reset_cc_state(ngtcp2_rtb *rtb, int64_t cc_pkt_num);
445
446/*
447 * ngtcp2_rtb_remove_expired_lost_pkt ensures that the number of lost
448 * packets at most |n|.
449 */
450void ngtcp2_rtb_remove_excessive_lost_pkt(ngtcp2_rtb *rtb, size_t n);
451
452/*
453 * ngtcp2_rtb_reclaim_on_pto reclaims up to |num_pkts| packets which
454 * are in-flight and not marked lost to send them in PTO probe.  The
455 * reclaimed frames are chained to |*pfrc|.
456 *
457 * This function returns the number of packets reclaimed if it
458 * succeeds, or one of the following negative error codes:
459 *
460 * NGTCP2_ERR_NOMEM
461 *     Out of memory
462 */
463ngtcp2_ssize ngtcp2_rtb_reclaim_on_pto(ngtcp2_rtb *rtb, ngtcp2_conn *conn,
464                                       ngtcp2_pktns *pktns, size_t num_pkts);
465
466#endif /* NGTCP2_RTB_H */
467