/src/samba/third_party/ngtcp2/lib/ngtcp2_pmtud.c
Line | Count | Source |
1 | | /* |
2 | | * ngtcp2 |
3 | | * |
4 | | * Copyright (c) 2022 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_pmtud.h" |
26 | | |
27 | | #include <assert.h> |
28 | | |
29 | | #include "ngtcp2_mem.h" |
30 | | #include "ngtcp2_macro.h" |
31 | | |
32 | | /* NGTCP2_PMTUD_PROBE_NUM_MAX is the maximum number of packets sent |
33 | | for each probe. */ |
34 | 0 | #define NGTCP2_PMTUD_PROBE_NUM_MAX 3 |
35 | | |
36 | | static uint16_t pmtud_default_probes[] = { |
37 | | 1454 - 48, /* The well known MTU used by a domestic optic fiber |
38 | | service in Japan. */ |
39 | | 1390 - 48, /* Typical Tunneled MTU */ |
40 | | 1280 - 48, /* IPv6 minimum MTU */ |
41 | | 1492 - 48, /* PPPoE */ |
42 | | }; |
43 | | |
44 | | int ngtcp2_pmtud_new(ngtcp2_pmtud **ppmtud, size_t max_udp_payload_size, |
45 | | size_t hard_max_udp_payload_size, int64_t tx_pkt_num, |
46 | | const uint16_t *probes, size_t probeslen, |
47 | 0 | const ngtcp2_mem *mem) { |
48 | 0 | ngtcp2_pmtud *pmtud = ngtcp2_mem_malloc(mem, sizeof(ngtcp2_pmtud)); |
49 | |
|
50 | 0 | if (pmtud == NULL) { |
51 | 0 | return NGTCP2_ERR_NOMEM; |
52 | 0 | } |
53 | | |
54 | 0 | pmtud->mem = mem; |
55 | 0 | pmtud->mtu_idx = 0; |
56 | 0 | pmtud->num_pkts_sent = 0; |
57 | 0 | pmtud->expiry = UINT64_MAX; |
58 | 0 | pmtud->tx_pkt_num = tx_pkt_num; |
59 | 0 | pmtud->max_udp_payload_size = max_udp_payload_size; |
60 | 0 | pmtud->hard_max_udp_payload_size = hard_max_udp_payload_size; |
61 | 0 | pmtud->min_fail_udp_payload_size = SIZE_MAX; |
62 | |
|
63 | 0 | if (probeslen) { |
64 | 0 | pmtud->probes = probes; |
65 | 0 | pmtud->probeslen = probeslen; |
66 | 0 | } else { |
67 | 0 | pmtud->probes = pmtud_default_probes; |
68 | 0 | pmtud->probeslen = ngtcp2_arraylen(pmtud_default_probes); |
69 | 0 | } |
70 | |
|
71 | 0 | for (; pmtud->mtu_idx < pmtud->probeslen; ++pmtud->mtu_idx) { |
72 | 0 | if (pmtud->probes[pmtud->mtu_idx] > pmtud->hard_max_udp_payload_size) { |
73 | 0 | continue; |
74 | 0 | } |
75 | 0 | if (pmtud->probes[pmtud->mtu_idx] > pmtud->max_udp_payload_size) { |
76 | 0 | break; |
77 | 0 | } |
78 | 0 | } |
79 | |
|
80 | 0 | *ppmtud = pmtud; |
81 | |
|
82 | 0 | return 0; |
83 | 0 | } |
84 | | |
85 | 0 | void ngtcp2_pmtud_del(ngtcp2_pmtud *pmtud) { |
86 | 0 | if (!pmtud) { |
87 | 0 | return; |
88 | 0 | } |
89 | | |
90 | 0 | ngtcp2_mem_free(pmtud->mem, pmtud); |
91 | 0 | } |
92 | | |
93 | 0 | size_t ngtcp2_pmtud_probelen(ngtcp2_pmtud *pmtud) { |
94 | 0 | assert(pmtud->mtu_idx < pmtud->probeslen); |
95 | |
|
96 | 0 | return pmtud->probes[pmtud->mtu_idx]; |
97 | 0 | } |
98 | | |
99 | | void ngtcp2_pmtud_probe_sent(ngtcp2_pmtud *pmtud, ngtcp2_duration pto, |
100 | 0 | ngtcp2_tstamp ts) { |
101 | 0 | ngtcp2_tstamp timeout; |
102 | |
|
103 | 0 | if (++pmtud->num_pkts_sent < NGTCP2_PMTUD_PROBE_NUM_MAX) { |
104 | 0 | timeout = pto; |
105 | 0 | } else { |
106 | 0 | timeout = 3 * pto; |
107 | 0 | } |
108 | |
|
109 | 0 | pmtud->expiry = ts + timeout; |
110 | 0 | } |
111 | | |
112 | 0 | int ngtcp2_pmtud_require_probe(ngtcp2_pmtud *pmtud) { |
113 | 0 | return pmtud->expiry == UINT64_MAX; |
114 | 0 | } |
115 | | |
116 | 0 | static void pmtud_next_probe(ngtcp2_pmtud *pmtud) { |
117 | 0 | assert(pmtud->mtu_idx < pmtud->probeslen); |
118 | |
|
119 | 0 | ++pmtud->mtu_idx; |
120 | 0 | pmtud->num_pkts_sent = 0; |
121 | 0 | pmtud->expiry = UINT64_MAX; |
122 | |
|
123 | 0 | for (; pmtud->mtu_idx < pmtud->probeslen; ++pmtud->mtu_idx) { |
124 | 0 | if (pmtud->probes[pmtud->mtu_idx] <= pmtud->max_udp_payload_size || |
125 | 0 | pmtud->probes[pmtud->mtu_idx] > pmtud->hard_max_udp_payload_size) { |
126 | 0 | continue; |
127 | 0 | } |
128 | | |
129 | 0 | if (pmtud->probes[pmtud->mtu_idx] < pmtud->min_fail_udp_payload_size) { |
130 | 0 | break; |
131 | 0 | } |
132 | 0 | } |
133 | 0 | } |
134 | | |
135 | 0 | void ngtcp2_pmtud_probe_success(ngtcp2_pmtud *pmtud, size_t payloadlen) { |
136 | 0 | pmtud->max_udp_payload_size = |
137 | 0 | ngtcp2_max_size(pmtud->max_udp_payload_size, payloadlen); |
138 | |
|
139 | 0 | assert(pmtud->mtu_idx < pmtud->probeslen); |
140 | |
|
141 | 0 | if (pmtud->probes[pmtud->mtu_idx] > pmtud->max_udp_payload_size) { |
142 | 0 | return; |
143 | 0 | } |
144 | | |
145 | 0 | pmtud_next_probe(pmtud); |
146 | 0 | } |
147 | | |
148 | 0 | void ngtcp2_pmtud_handle_expiry(ngtcp2_pmtud *pmtud, ngtcp2_tstamp ts) { |
149 | 0 | if (ts < pmtud->expiry) { |
150 | 0 | return; |
151 | 0 | } |
152 | | |
153 | 0 | pmtud->expiry = UINT64_MAX; |
154 | |
|
155 | 0 | if (pmtud->num_pkts_sent < NGTCP2_PMTUD_PROBE_NUM_MAX) { |
156 | 0 | return; |
157 | 0 | } |
158 | | |
159 | 0 | pmtud->min_fail_udp_payload_size = ngtcp2_min_size( |
160 | 0 | pmtud->min_fail_udp_payload_size, pmtud->probes[pmtud->mtu_idx]); |
161 | |
|
162 | 0 | pmtud_next_probe(pmtud); |
163 | 0 | } |
164 | | |
165 | 0 | int ngtcp2_pmtud_finished(ngtcp2_pmtud *pmtud) { |
166 | 0 | return pmtud->mtu_idx >= pmtud->probeslen; |
167 | 0 | } |