forked from microsoft/msquic
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpath.h
323 lines (276 loc) · 7.42 KB
/
path.h
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
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
/*++
Copyright (c) Microsoft Corporation.
Licensed under the MIT License.
--*/
//
// ECN validation state transition:
//
// ECN_VALIDATION_TESTING: when a new path is created AND ECN is enabled.
//
// ECN_VALIDATION_TESTING -> ECN_VALIDATION_UNKNOWN: after sending packets with ECT bit set for 3 PTOs.
//
// {ECN_VALIDATION_TESTING | ECN_VALIDATION_UNKNOWN} -> ECN_VALIDATION_CAPABLE:
// when ECN validation passes.
//
// {ANY} -> ECN_VALIDATION_FAILED: when ECN validation fails.
//
// In ECN_VALIDATION_TESTING or ECN_VALIDATION_CAPABLE state, packets sent are marked with ECT bit.
//
// This algorithm is a slightly simplified and relaxed version of the sample ECN validation in
// RFC9000 A.4. The main differences are:
//
// 1. Our algorithm can transition into capable state right from testing state if ECN validation passes.
//
// 2. The sample algorithm fails ECN validation when all packets sent in testing are considered lost.
// Our algorithm does not do that. However, in that case, our algorithm stays in unknown state, where
// we send packets without ECT mark, which is effectively the same as failing the validation.
//
//
// Different state of ECN validation for the network path.
//
typedef enum ECN_VALIDATION_STATE {
ECN_VALIDATION_TESTING,
ECN_VALIDATION_UNKNOWN,
ECN_VALIDATION_CAPABLE,
ECN_VALIDATION_FAILED, // or not enabled by the app.
} ECN_VALIDATION_STATE;
//
// Represents all the per-path information of a connection.
//
typedef struct QUIC_PATH {
//
// Unique identifier;
//
uint8_t ID;
//
// Indicates the path object is actively in use.
//
BOOLEAN InUse : 1;
//
// Indicates this is the primary path being used by the connection.
//
BOOLEAN IsActive : 1;
//
// Indicates whether this connection initiated a CID change, and therefore
// shouldn't respond to the peer's next CID change with one of its own.
//
BOOLEAN InitiatedCidUpdate : 1;
//
// Indicates that the first RTT sample has been taken. Until this is set,
// the RTT estimate is set to a default value.
//
BOOLEAN GotFirstRttSample : 1;
//
// Indicates a valid (not dropped) packet has been received on this path.
//
BOOLEAN GotValidPacket : 1;
//
// Indicates the peer's source IP address has been validated.
//
BOOLEAN IsPeerValidated : 1;
//
// Indicates the minimum MTU has been validated.
//
BOOLEAN IsMinMtuValidated : 1;
//
// Current value to encode in the short header spin bit field.
//
BOOLEAN SpinBit : 1;
//
// The current path challenge needs to be sent out.
//
BOOLEAN SendChallenge : 1;
//
// The current path response needs to be sent out.
//
BOOLEAN SendResponse : 1;
//
// Indicates the partition has updated for this path.
//
uint8_t PartitionUpdated : 1;
//
// ECN validation state.
//
uint8_t EcnValidationState : 2;
//
// Indicates whether this connection offloads encryption workload to HW
//
BOOLEAN EncryptionOffloading : 1;
//
// The ending time of ECN validation testing state in microseconds.
//
uint64_t EcnTestingEndingTime;
//
// The currently calculated path MTU.
//
uint16_t Mtu;
//
// The local socket MTU.
//
uint16_t LocalMtu;
//
// MTU Discovery logic.
//
QUIC_MTU_DISCOVERY MtuDiscovery;
//
// The binding used for sending/receiving UDP packets.
//
QUIC_BINDING* Binding;
//
// The network route.
//
CXPLAT_ROUTE Route;
//
// The destination CID used for sending on this path.
//
QUIC_CID_LIST_ENTRY* DestCid;
//
// RTT moving average, computed as in RFC6298. Units of microseconds.
//
uint64_t SmoothedRtt;
uint64_t LatestRttSample;
uint64_t MinRtt;
uint64_t MaxRtt;
uint64_t RttVariance;
uint64_t OneWayDelay;
uint64_t OneWayDelayLatest;
//
// Used on the server side until the client's IP address has been validated
// to prevent the server from being used for amplification attacks. A value
// of UINT32_MAX indicates this variable does not apply.
//
uint32_t Allowance;
//
// The last path challenge we received and needs to be sent back as in a
// PATH_RESPONSE frame.
//
uint8_t Response[8];
//
// The current path challenge to send and wait for the peer to echo back.
//
uint8_t Challenge[8];
//
// Time when path validation was begun. Used for timing out path validation.
//
uint64_t PathValidationStartTime;
} QUIC_PATH;
#if DEBUG
#define QuicPathValidate(Path) \
CXPLAT_DBG_ASSERT( \
(Path)->DestCid == NULL || \
(Path)->DestCid->CID.Length == 0 || \
((Path)->DestCid->AssignedPath == (Path) && \
(Path)->DestCid->CID.UsedLocally))
#else
#define QuicPathValidate(Path) UNREFERENCED_PARAMETER(Path)
#endif
CXPLAT_STATIC_ASSERT(
sizeof(QUIC_PATH) < 256,
"Ensure path struct stays small since we prealloc them");
_IRQL_requires_max_(PASSIVE_LEVEL)
void
QuicPathInitialize(
_In_ QUIC_CONNECTION* Connection,
_In_ QUIC_PATH* Path
);
_IRQL_requires_max_(PASSIVE_LEVEL)
void
QuicPathRemove(
_In_ QUIC_CONNECTION* Connection,
_In_ uint8_t Index
);
_IRQL_requires_max_(PASSIVE_LEVEL)
void
QuicPathSetAllowance(
_In_ QUIC_CONNECTION* Connection,
_In_ QUIC_PATH* Path,
_In_ uint32_t NewAllowance
);
_IRQL_requires_max_(PASSIVE_LEVEL)
inline
void
QuicPathIncrementAllowance(
_In_ QUIC_CONNECTION* Connection,
_In_ QUIC_PATH* Path,
_In_ uint32_t Amount
)
{
QuicPathSetAllowance(Connection, Path, Path->Allowance + Amount);
}
_IRQL_requires_max_(PASSIVE_LEVEL)
inline
void
QuicPathDecrementAllowance(
_In_ QUIC_CONNECTION* Connection,
_In_ QUIC_PATH* Path,
_In_ uint32_t Amount
)
{
QuicPathSetAllowance(
Connection,
Path,
Path->Allowance <= Amount ? 0 : (Path->Allowance - Amount));
}
//
// Calculates the maximum size datagram payload from the path's MTU.
//
inline
uint16_t
QuicPathGetDatagramPayloadSize(
_In_ const QUIC_PATH* Path
)
{
return
MaxUdpPayloadSizeForFamily(
QuicAddrGetFamily(&Path->Route.RemoteAddress), Path->Mtu);
}
typedef enum QUIC_PATH_VALID_REASON {
QUIC_PATH_VALID_INITIAL_TOKEN,
QUIC_PATH_VALID_HANDSHAKE_PACKET,
QUIC_PATH_VALID_PATH_RESPONSE
} QUIC_PATH_VALID_REASON;
_IRQL_requires_max_(PASSIVE_LEVEL)
void
QuicPathSetValid(
_In_ QUIC_CONNECTION* Connection,
_In_ QUIC_PATH* Path,
_In_ QUIC_PATH_VALID_REASON Reason
);
_IRQL_requires_max_(PASSIVE_LEVEL)
void
QuicPathSetActive(
_In_ QUIC_CONNECTION* Connection,
_In_ QUIC_PATH* Path
);
_IRQL_requires_max_(PASSIVE_LEVEL)
_Ret_maybenull_
_Success_(return != NULL)
QUIC_PATH*
QuicConnGetPathByID(
_In_ QUIC_CONNECTION* Connection,
_In_ uint8_t ID,
_Out_ uint8_t* Index
);
_IRQL_requires_max_(PASSIVE_LEVEL)
_Ret_maybenull_
QUIC_PATH*
QuicConnGetPathForPacket(
_In_ QUIC_CONNECTION* Connection,
_In_ const QUIC_RX_PACKET* Packet
);
_IRQL_requires_max_(PASSIVE_LEVEL)
void
QuicCopyRouteInfo(
_Inout_ CXPLAT_ROUTE* DstRoute,
_In_ CXPLAT_ROUTE* SrcRoute
);
//
// Plumbs new or removes existing QUIC encryption offload information.
//
_IRQL_requires_max_(PASSIVE_LEVEL)
void
QuicPathUpdateQeo(
_In_ QUIC_CONNECTION* Connection,
_In_ QUIC_PATH* Path,
_In_ CXPLAT_QEO_OPERATION Operation
);