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 #ifndef NGTCP2_PV_H 26 #define NGTCP2_PV_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_cid.h" 35 #include "ngtcp2_ringbuf.h" 36 37 /* NGTCP2_PV_MAX_ENTRIES is the maximum number of entries that 38 ngtcp2_pv can contain. It must be power of 2. */ 39 #define NGTCP2_PV_MAX_ENTRIES 8 40 /* NGTCP2_PV_NUM_PROBE_PKT is the number of probe packets containing 41 PATH_CHALLENGE sent at a time. */ 42 #define NGTCP2_PV_NUM_PROBE_PKT 2 43 44 typedef struct ngtcp2_log ngtcp2_log; 45 46 typedef struct ngtcp2_frame_chain ngtcp2_frame_chain; 47 48 /* NGTCP2_PV_ENTRY_FLAG_NONE indicates that no flag is set. */ 49 #define NGTCP2_PV_ENTRY_FLAG_NONE 0x00u 50 /* NGTCP2_PV_ENTRY_FLAG_UNDERSIZED indicates that UDP datagram which 51 contains PATH_CHALLENGE is undersized (< 1200 bytes) */ 52 #define NGTCP2_PV_ENTRY_FLAG_UNDERSIZED 0x01u 53 54 typedef struct ngtcp2_pv_entry { 55 /* expiry is the timestamp when this PATH_CHALLENGE expires. */ 56 ngtcp2_tstamp expiry; 57 /* flags is zero or more of NGTCP2_PV_ENTRY_FLAG_*. */ 58 uint8_t flags; 59 /* data is a byte string included in PATH_CHALLENGE. */ 60 uint8_t data[8]; 61 } ngtcp2_pv_entry; 62 63 void ngtcp2_pv_entry_init(ngtcp2_pv_entry *pvent, const uint8_t *data, 64 ngtcp2_tstamp expiry, uint8_t flags); 65 66 /* NGTCP2_PV_FLAG_NONE indicates no flag is set. */ 67 #define NGTCP2_PV_FLAG_NONE 0x00u 68 /* NGTCP2_PV_FLAG_DONT_CARE indicates that the outcome of path 69 validation should be ignored entirely. */ 70 #define NGTCP2_PV_FLAG_DONT_CARE 0x01u 71 /* NGTCP2_PV_FLAG_CANCEL_TIMER indicates that the expiry timer is 72 cancelled. */ 73 #define NGTCP2_PV_FLAG_CANCEL_TIMER 0x02u 74 /* NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE indicates that fallback DCID is 75 available in ngtcp2_pv. If path validation fails, fallback to the 76 fallback DCID. If path validation succeeds, fallback DCID is 77 retired if it does not equal to the current DCID. */ 78 #define NGTCP2_PV_FLAG_FALLBACK_ON_FAILURE 0x04u 79 /* NGTCP2_PV_FLAG_MTU_PROBE indicates that a validation must probe 80 least MTU that QUIC requires, which is 1200 bytes. If it fails, a 81 path is not viable. */ 82 #define NGTCP2_PV_FLAG_MTU_PROBE 0x08u 83 /* NGTCP2_PV_FLAG_PREFERRED_ADDR indicates that client is migrating to 84 server's preferred address. This flag is only used by client. */ 85 #define NGTCP2_PV_FLAG_PREFERRED_ADDR 0x10u 86 87 typedef struct ngtcp2_pv ngtcp2_pv; 88 89 ngtcp2_static_ringbuf_def(pv_ents, NGTCP2_PV_MAX_ENTRIES, 90 sizeof(ngtcp2_pv_entry)); 91 /* 92 * ngtcp2_pv is the context of a single path validation. 93 */ 94 struct ngtcp2_pv { 95 const ngtcp2_mem *mem; 96 ngtcp2_log *log; 97 /* dcid is DCID and path this path validation uses. */ 98 ngtcp2_dcid dcid; 99 /* fallback_dcid is the usually validated DCID and used as a 100 fallback if this path validation fails. */ 101 ngtcp2_dcid fallback_dcid; 102 /* ents is the ring buffer of ngtcp2_pv_entry */ 103 ngtcp2_static_ringbuf_pv_ents ents; 104 /* timeout is the duration within which this path validation should 105 succeed. */ 106 ngtcp2_duration timeout; 107 /* fallback_pto is PTO of fallback connection. */ 108 ngtcp2_duration fallback_pto; 109 /* started_ts is the timestamp this path validation starts. */ 110 ngtcp2_tstamp started_ts; 111 /* round is the number of times that probe_pkt_left is reset. */ 112 size_t round; 113 /* probe_pkt_left is the number of probe packets containing 114 PATH_CHALLENGE which can be send without waiting for an 115 expiration of a previous flight. */ 116 size_t probe_pkt_left; 117 /* flags is bitwise-OR of zero or more of NGTCP2_PV_FLAG_*. */ 118 uint8_t flags; 119 }; 120 121 /* 122 * ngtcp2_pv_new creates new ngtcp2_pv object and assigns its pointer 123 * to |*ppv|. This function makes a copy of |dcid|. |timeout| is a 124 * duration within which this path validation must succeed. 125 * 126 * This function returns 0 if it succeeds, or one of the following 127 * negative error codes: 128 * 129 * NGTCP2_ERR_NOMEM 130 * Out of memory 131 */ 132 int ngtcp2_pv_new(ngtcp2_pv **ppv, const ngtcp2_dcid *dcid, 133 ngtcp2_duration timeout, uint8_t flags, ngtcp2_log *log, 134 const ngtcp2_mem *mem); 135 136 /* 137 * ngtcp2_pv_del deallocates |pv|. This function frees memory |pv| 138 * points too. 139 */ 140 void ngtcp2_pv_del(ngtcp2_pv *pv); 141 142 /* 143 * ngtcp2_pv_add_entry adds new entry with |data|. |expiry| is the 144 * expiry time of the entry. 145 */ 146 void ngtcp2_pv_add_entry(ngtcp2_pv *pv, const uint8_t *data, 147 ngtcp2_tstamp expiry, uint8_t flags, ngtcp2_tstamp ts); 148 149 /* 150 * ngtcp2_pv_full returns nonzero if |pv| is full of ngtcp2_pv_entry. 151 */ 152 int ngtcp2_pv_full(ngtcp2_pv *pv); 153 154 /* 155 * ngtcp2_pv_validate validates that the received |data| matches the 156 * one of the existing entry. The flag of ngtcp2_pv_entry that 157 * matches |data| is assigned to |*pflags| if this function succeeds. 158 * 159 * This function returns 0 if it succeeds, or one of the following 160 * negative error codes: 161 * 162 * NGTCP2_ERR_PATH_VALIDATION_FAILED 163 * path validation has failed and must be abandoned 164 * NGTCP2_ERR_INVALID_STATE 165 * |pv| includes no entry 166 * NGTCP2_ERR_INVALID_ARGUMENT 167 * |pv| does not have an entry which has |data| and |path| 168 */ 169 int ngtcp2_pv_validate(ngtcp2_pv *pv, uint8_t *pflags, const uint8_t *data); 170 171 /* 172 * ngtcp2_pv_handle_entry_expiry checks expiry of existing entries. 173 */ 174 void ngtcp2_pv_handle_entry_expiry(ngtcp2_pv *pv, ngtcp2_tstamp ts); 175 176 /* 177 * ngtcp2_pv_should_send_probe returns nonzero if new entry can be 178 * added by ngtcp2_pv_add_entry. 179 */ 180 int ngtcp2_pv_should_send_probe(ngtcp2_pv *pv); 181 182 /* 183 * ngtcp2_pv_validation_timed_out returns nonzero if the path 184 * validation fails because of timeout. 185 */ 186 int ngtcp2_pv_validation_timed_out(ngtcp2_pv *pv, ngtcp2_tstamp ts); 187 188 /* 189 * ngtcp2_pv_next_expiry returns the earliest expiry. 190 */ 191 ngtcp2_tstamp ngtcp2_pv_next_expiry(ngtcp2_pv *pv); 192 193 /* 194 * ngtcp2_pv_cancel_expired_timer cancels the expired timer. 195 */ 196 void ngtcp2_pv_cancel_expired_timer(ngtcp2_pv *pv, ngtcp2_tstamp ts); 197 198 #endif /* NGTCP2_PV_H */ 199