1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
|
/*
* ngtcp2
*
* Copyright (c) 2017 ngtcp2 contributors
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef NGTCP2_ACKTR_H
#define NGTCP2_ACKTR_H
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* defined(HAVE_CONFIG_H) */
#include <ngtcp2/ngtcp2.h>
#include "ngtcp2_mem.h"
#include "ngtcp2_ringbuf.h"
#include "ngtcp2_ksl.h"
#include "ngtcp2_pkt.h"
#include "ngtcp2_objalloc.h"
/* NGTCP2_ACKTR_MAX_ENT is the maximum number of ngtcp2_acktr_entry
which ngtcp2_acktr stores. */
#define NGTCP2_ACKTR_MAX_ENT (NGTCP2_MAX_ACK_RANGES + 1)
typedef struct ngtcp2_log ngtcp2_log;
/*
* ngtcp2_acktr_entry is a range of packets which need to be acked.
*/
typedef struct ngtcp2_acktr_entry {
union {
struct {
/* pkt_num is the largest packet number to acknowledge in this
range. */
int64_t pkt_num;
/* len is the consecutive packets started from pkt_num which
includes pkt_num itself counting in decreasing order. So pkt_num
= 987 and len = 2, this entry includes packet 987 and 986. */
size_t len;
/* tstamp is the timestamp when a packet denoted by pkt_num is
received. */
ngtcp2_tstamp tstamp;
};
ngtcp2_opl_entry oplent;
};
} ngtcp2_acktr_entry;
ngtcp2_objalloc_decl(acktr_entry, ngtcp2_acktr_entry, oplent)
/*
* ngtcp2_acktr_entry_objalloc_new allocates memory for ent, and
* initializes it with the given parameters. The pointer to the
* allocated object is stored to |*ent|.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* NGTCP2_ERR_NOMEM
* Out of memory.
*/
int ngtcp2_acktr_entry_objalloc_new(ngtcp2_acktr_entry **ent, int64_t pkt_num,
ngtcp2_tstamp tstamp,
ngtcp2_objalloc *objalloc);
/*
* ngtcp2_acktr_entry_objalloc_del deallocates memory allocated for
* |ent|.
*/
void ngtcp2_acktr_entry_objalloc_del(ngtcp2_acktr_entry *ent,
ngtcp2_objalloc *objalloc);
typedef struct ngtcp2_acktr_ack_entry {
/* largest_ack is the largest packet number in outgoing ACK frame */
int64_t largest_ack;
/* pkt_num is the packet number that ACK frame is included. */
int64_t pkt_num;
} ngtcp2_acktr_ack_entry;
/* NGTCP2_ACKTR_FLAG_NONE indicates that no flag set. */
#define NGTCP2_ACKTR_FLAG_NONE 0x00u
/* NGTCP2_ACKTR_FLAG_IMMEDIATE_ACK indicates that immediate
acknowledgement is required. */
#define NGTCP2_ACKTR_FLAG_IMMEDIATE_ACK 0x01u
/* NGTCP2_ACKTR_FLAG_ACTIVE_ACK indicates that there are pending
protected packet to be acknowledged. */
#define NGTCP2_ACKTR_FLAG_ACTIVE_ACK 0x02u
/* NGTCP2_ACKTR_FLAG_CANCEL_TIMER is set when ACK delay timer is
expired and canceled. */
#define NGTCP2_ACKTR_FLAG_CANCEL_TIMER 0x0100u
ngtcp2_static_ringbuf_def(acks, 32, sizeof(ngtcp2_acktr_ack_entry))
/*
* ngtcp2_acktr tracks received packets which we have to send ack.
*/
typedef struct ngtcp2_acktr {
ngtcp2_objalloc objalloc;
ngtcp2_static_ringbuf_acks acks;
/* ents includes ngtcp2_acktr_entry sorted by decreasing order of
packet number. */
ngtcp2_ksl ents;
ngtcp2_log *log;
/* flags is bitwise OR of zero, or more of NGTCP2_ACKTR_FLAG_*. */
uint16_t flags;
/* first_unacked_ts is timestamp when ngtcp2_acktr_entry is added
first time after the last outgoing ACK frame. */
ngtcp2_tstamp first_unacked_ts;
/* rx_npkt is the number of ACK eliciting packets received without
sending ACK. */
size_t rx_npkt;
/* max_pkt_num is the largest packet number received so far. */
int64_t max_pkt_num;
/* max_pkt_ts is the timestamp when max_pkt_num packet is
received. */
ngtcp2_tstamp max_pkt_ts;
struct {
/* ect0, ect1, and ce are the number of QUIC packets received
with those markings. */
size_t ect0;
size_t ect1;
size_t ce;
struct {
/* ect0, ect1, ce are the ECN counts received in the latest
ACK frame. */
uint64_t ect0;
uint64_t ect1;
uint64_t ce;
} ack;
} ecn;
} ngtcp2_acktr;
/*
* ngtcp2_acktr_init initializes |acktr|.
*/
void ngtcp2_acktr_init(ngtcp2_acktr *acktr, ngtcp2_log *log,
const ngtcp2_mem *mem);
/*
* ngtcp2_acktr_free frees resources allocated for |acktr|. It frees
* any ngtcp2_acktr_entry added to |acktr|.
*/
void ngtcp2_acktr_free(ngtcp2_acktr *acktr);
/*
* ngtcp2_acktr_add adds packet number |pkt_num| to |acktr|.
* |active_ack| is nonzero if |pkt_num| is retransmittable packet.
*
* This function assumes that |acktr| does not contain |pkt_num|.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* NGTCP2_ERR_NOMEM
* OUt of memory.
*/
int ngtcp2_acktr_add(ngtcp2_acktr *acktr, int64_t pkt_num, int active_ack,
ngtcp2_tstamp ts);
/*
* ngtcp2_acktr_forget removes all entries which have the packet
* number that is equal to or less than ent->pkt_num. This function
* assumes that |acktr| includes |ent|.
*/
void ngtcp2_acktr_forget(ngtcp2_acktr *acktr, ngtcp2_acktr_entry *ent);
/*
* ngtcp2_acktr_get returns the iterator to pointer to the entry which
* has the largest packet number to be acked. If there is no entry,
* returned value satisfies ngtcp2_ksl_it_end(&it) != 0.
*/
ngtcp2_ksl_it ngtcp2_acktr_get(const ngtcp2_acktr *acktr);
/*
* ngtcp2_acktr_empty returns nonzero if it has no packet to
* acknowledge.
*/
int ngtcp2_acktr_empty(const ngtcp2_acktr *acktr);
/*
* ngtcp2_acktr_add_ack records outgoing ACK frame whose largest
* acknowledged packet number is |largest_ack|. |pkt_num| is the
* packet number of a packet in which ACK frame is included. This
* function returns a pointer to the object it adds.
*/
ngtcp2_acktr_ack_entry *
ngtcp2_acktr_add_ack(ngtcp2_acktr *acktr, int64_t pkt_num, int64_t largest_ack);
/*
* ngtcp2_acktr_recv_ack processes the incoming ACK frame |fr|.
* |pkt_num| is a packet number which includes |fr|. If we receive
* ACK which acknowledges the ACKs added by ngtcp2_acktr_add_ack,
* ngtcp2_acktr_entry which the outgoing ACK acknowledges is removed.
*/
void ngtcp2_acktr_recv_ack(ngtcp2_acktr *acktr, const ngtcp2_ack *fr);
/*
* ngtcp2_acktr_commit_ack tells |acktr| that ACK frame is generated.
*/
void ngtcp2_acktr_commit_ack(ngtcp2_acktr *acktr);
/*
* ngtcp2_acktr_require_active_ack returns nonzero if ACK frame should
* be generated actively.
*/
int ngtcp2_acktr_require_active_ack(const ngtcp2_acktr *acktr,
ngtcp2_duration max_ack_delay,
ngtcp2_tstamp ts);
/*
* ngtcp2_acktr_immediate_ack tells |acktr| that immediate
* acknowledgement is required.
*/
void ngtcp2_acktr_immediate_ack(ngtcp2_acktr *acktr);
/*
* ngtcp2_acktr_create_ack_frame creates ACK frame in the object
* pointed by |fr|, and returns |fr| if there are any received packets
* to acknowledge. If there are no packets to acknowledge, this
* function returns NULL. fr->ack.ranges must be able to contain at
* least NGTCP2_MAX_ACK_RANGES elements.
*
* Call ngtcp2_acktr_commit_ack after a created ACK frame is
* successfully serialized into a packet.
*/
ngtcp2_frame *ngtcp2_acktr_create_ack_frame(ngtcp2_acktr *acktr,
ngtcp2_frame *fr, uint8_t type,
ngtcp2_tstamp ts,
ngtcp2_duration ack_delay,
uint64_t ack_delay_exponent);
/*
* ngtcp2_acktr_increase_ecn_counts increases ECN counts from |pi|.
*/
void ngtcp2_acktr_increase_ecn_counts(ngtcp2_acktr *acktr,
const ngtcp2_pkt_info *pi);
#endif /* !defined(NGTCP2_ACKTR_H) */
|