1*e7be843bSPierre Pronchery /*
2*e7be843bSPierre Pronchery * Copyright 2022-2024 The OpenSSL Project Authors. All Rights Reserved.
3*e7be843bSPierre Pronchery *
4*e7be843bSPierre Pronchery * Licensed under the Apache License 2.0 (the "License"). You may not use
5*e7be843bSPierre Pronchery * this file except in compliance with the License. You can obtain a copy
6*e7be843bSPierre Pronchery * in the file LICENSE in the source distribution or at
7*e7be843bSPierre Pronchery * https://www.openssl.org/source/license.html
8*e7be843bSPierre Pronchery */
9*e7be843bSPierre Pronchery
10*e7be843bSPierre Pronchery #include "internal/quic_fifd.h"
11*e7be843bSPierre Pronchery #include "internal/quic_wire.h"
12*e7be843bSPierre Pronchery #include "internal/qlog_event_helpers.h"
13*e7be843bSPierre Pronchery
14*e7be843bSPierre Pronchery DEFINE_LIST_OF(tx_history, OSSL_ACKM_TX_PKT);
15*e7be843bSPierre Pronchery
ossl_quic_fifd_init(QUIC_FIFD * fifd,QUIC_CFQ * cfq,OSSL_ACKM * ackm,QUIC_TXPIM * txpim,QUIC_SSTREAM * (* get_sstream_by_id)(uint64_t stream_id,uint32_t pn_space,void * arg),void * get_sstream_by_id_arg,void (* regen_frame)(uint64_t frame_type,uint64_t stream_id,QUIC_TXPIM_PKT * pkt,void * arg),void * regen_frame_arg,void (* confirm_frame)(uint64_t frame_type,uint64_t stream_id,QUIC_TXPIM_PKT * pkt,void * arg),void * confirm_frame_arg,void (* sstream_updated)(uint64_t stream_id,void * arg),void * sstream_updated_arg,QLOG * (* get_qlog_cb)(void * arg),void * get_qlog_cb_arg)16*e7be843bSPierre Pronchery int ossl_quic_fifd_init(QUIC_FIFD *fifd,
17*e7be843bSPierre Pronchery QUIC_CFQ *cfq,
18*e7be843bSPierre Pronchery OSSL_ACKM *ackm,
19*e7be843bSPierre Pronchery QUIC_TXPIM *txpim,
20*e7be843bSPierre Pronchery /* stream_id is UINT64_MAX for the crypto stream */
21*e7be843bSPierre Pronchery QUIC_SSTREAM *(*get_sstream_by_id)(uint64_t stream_id,
22*e7be843bSPierre Pronchery uint32_t pn_space,
23*e7be843bSPierre Pronchery void *arg),
24*e7be843bSPierre Pronchery void *get_sstream_by_id_arg,
25*e7be843bSPierre Pronchery /* stream_id is UINT64_MAX if not applicable */
26*e7be843bSPierre Pronchery void (*regen_frame)(uint64_t frame_type,
27*e7be843bSPierre Pronchery uint64_t stream_id,
28*e7be843bSPierre Pronchery QUIC_TXPIM_PKT *pkt,
29*e7be843bSPierre Pronchery void *arg),
30*e7be843bSPierre Pronchery void *regen_frame_arg,
31*e7be843bSPierre Pronchery void (*confirm_frame)(uint64_t frame_type,
32*e7be843bSPierre Pronchery uint64_t stream_id,
33*e7be843bSPierre Pronchery QUIC_TXPIM_PKT *pkt,
34*e7be843bSPierre Pronchery void *arg),
35*e7be843bSPierre Pronchery void *confirm_frame_arg,
36*e7be843bSPierre Pronchery void (*sstream_updated)(uint64_t stream_id,
37*e7be843bSPierre Pronchery void *arg),
38*e7be843bSPierre Pronchery void *sstream_updated_arg,
39*e7be843bSPierre Pronchery QLOG *(*get_qlog_cb)(void *arg),
40*e7be843bSPierre Pronchery void *get_qlog_cb_arg)
41*e7be843bSPierre Pronchery {
42*e7be843bSPierre Pronchery if (cfq == NULL || ackm == NULL || txpim == NULL
43*e7be843bSPierre Pronchery || get_sstream_by_id == NULL || regen_frame == NULL)
44*e7be843bSPierre Pronchery return 0;
45*e7be843bSPierre Pronchery
46*e7be843bSPierre Pronchery fifd->cfq = cfq;
47*e7be843bSPierre Pronchery fifd->ackm = ackm;
48*e7be843bSPierre Pronchery fifd->txpim = txpim;
49*e7be843bSPierre Pronchery fifd->get_sstream_by_id = get_sstream_by_id;
50*e7be843bSPierre Pronchery fifd->get_sstream_by_id_arg = get_sstream_by_id_arg;
51*e7be843bSPierre Pronchery fifd->regen_frame = regen_frame;
52*e7be843bSPierre Pronchery fifd->regen_frame_arg = regen_frame_arg;
53*e7be843bSPierre Pronchery fifd->confirm_frame = confirm_frame;
54*e7be843bSPierre Pronchery fifd->confirm_frame_arg = confirm_frame_arg;
55*e7be843bSPierre Pronchery fifd->sstream_updated = sstream_updated;
56*e7be843bSPierre Pronchery fifd->sstream_updated_arg = sstream_updated_arg;
57*e7be843bSPierre Pronchery fifd->get_qlog_cb = get_qlog_cb;
58*e7be843bSPierre Pronchery fifd->get_qlog_cb_arg = get_qlog_cb_arg;
59*e7be843bSPierre Pronchery return 1;
60*e7be843bSPierre Pronchery }
61*e7be843bSPierre Pronchery
ossl_quic_fifd_cleanup(QUIC_FIFD * fifd)62*e7be843bSPierre Pronchery void ossl_quic_fifd_cleanup(QUIC_FIFD *fifd)
63*e7be843bSPierre Pronchery {
64*e7be843bSPierre Pronchery /* No-op. */
65*e7be843bSPierre Pronchery }
66*e7be843bSPierre Pronchery
on_acked(void * arg)67*e7be843bSPierre Pronchery static void on_acked(void *arg)
68*e7be843bSPierre Pronchery {
69*e7be843bSPierre Pronchery QUIC_TXPIM_PKT *pkt = arg;
70*e7be843bSPierre Pronchery QUIC_FIFD *fifd = pkt->fifd;
71*e7be843bSPierre Pronchery const QUIC_TXPIM_CHUNK *chunks = ossl_quic_txpim_pkt_get_chunks(pkt);
72*e7be843bSPierre Pronchery size_t i, num_chunks = ossl_quic_txpim_pkt_get_num_chunks(pkt);
73*e7be843bSPierre Pronchery QUIC_SSTREAM *sstream;
74*e7be843bSPierre Pronchery QUIC_CFQ_ITEM *cfq_item, *cfq_item_next;
75*e7be843bSPierre Pronchery
76*e7be843bSPierre Pronchery /* STREAM and CRYPTO stream chunks, FINs and stream FC frames */
77*e7be843bSPierre Pronchery for (i = 0; i < num_chunks; ++i) {
78*e7be843bSPierre Pronchery sstream = fifd->get_sstream_by_id(chunks[i].stream_id,
79*e7be843bSPierre Pronchery pkt->ackm_pkt.pkt_space,
80*e7be843bSPierre Pronchery fifd->get_sstream_by_id_arg);
81*e7be843bSPierre Pronchery if (sstream == NULL)
82*e7be843bSPierre Pronchery continue;
83*e7be843bSPierre Pronchery
84*e7be843bSPierre Pronchery if (chunks[i].end >= chunks[i].start)
85*e7be843bSPierre Pronchery /* coverity[check_return]: Best effort - we cannot fail here. */
86*e7be843bSPierre Pronchery ossl_quic_sstream_mark_acked(sstream,
87*e7be843bSPierre Pronchery chunks[i].start, chunks[i].end);
88*e7be843bSPierre Pronchery
89*e7be843bSPierre Pronchery if (chunks[i].has_fin && chunks[i].stream_id != UINT64_MAX)
90*e7be843bSPierre Pronchery ossl_quic_sstream_mark_acked_fin(sstream);
91*e7be843bSPierre Pronchery
92*e7be843bSPierre Pronchery if (chunks[i].has_stop_sending && chunks[i].stream_id != UINT64_MAX)
93*e7be843bSPierre Pronchery fifd->confirm_frame(OSSL_QUIC_FRAME_TYPE_STOP_SENDING,
94*e7be843bSPierre Pronchery chunks[i].stream_id, pkt,
95*e7be843bSPierre Pronchery fifd->confirm_frame_arg);
96*e7be843bSPierre Pronchery
97*e7be843bSPierre Pronchery if (chunks[i].has_reset_stream && chunks[i].stream_id != UINT64_MAX)
98*e7be843bSPierre Pronchery fifd->confirm_frame(OSSL_QUIC_FRAME_TYPE_RESET_STREAM,
99*e7be843bSPierre Pronchery chunks[i].stream_id, pkt,
100*e7be843bSPierre Pronchery fifd->confirm_frame_arg);
101*e7be843bSPierre Pronchery
102*e7be843bSPierre Pronchery if (ossl_quic_sstream_is_totally_acked(sstream))
103*e7be843bSPierre Pronchery fifd->sstream_updated(chunks[i].stream_id, fifd->sstream_updated_arg);
104*e7be843bSPierre Pronchery }
105*e7be843bSPierre Pronchery
106*e7be843bSPierre Pronchery /* GCR */
107*e7be843bSPierre Pronchery for (cfq_item = pkt->retx_head; cfq_item != NULL; cfq_item = cfq_item_next) {
108*e7be843bSPierre Pronchery cfq_item_next = cfq_item->pkt_next;
109*e7be843bSPierre Pronchery ossl_quic_cfq_release(fifd->cfq, cfq_item);
110*e7be843bSPierre Pronchery }
111*e7be843bSPierre Pronchery
112*e7be843bSPierre Pronchery ossl_quic_txpim_pkt_release(fifd->txpim, pkt);
113*e7be843bSPierre Pronchery }
114*e7be843bSPierre Pronchery
fifd_get_qlog(QUIC_FIFD * fifd)115*e7be843bSPierre Pronchery static QLOG *fifd_get_qlog(QUIC_FIFD *fifd)
116*e7be843bSPierre Pronchery {
117*e7be843bSPierre Pronchery if (fifd->get_qlog_cb == NULL)
118*e7be843bSPierre Pronchery return NULL;
119*e7be843bSPierre Pronchery
120*e7be843bSPierre Pronchery return fifd->get_qlog_cb(fifd->get_qlog_cb_arg);
121*e7be843bSPierre Pronchery }
122*e7be843bSPierre Pronchery
on_lost(void * arg)123*e7be843bSPierre Pronchery static void on_lost(void *arg)
124*e7be843bSPierre Pronchery {
125*e7be843bSPierre Pronchery QUIC_TXPIM_PKT *pkt = arg;
126*e7be843bSPierre Pronchery QUIC_FIFD *fifd = pkt->fifd;
127*e7be843bSPierre Pronchery const QUIC_TXPIM_CHUNK *chunks = ossl_quic_txpim_pkt_get_chunks(pkt);
128*e7be843bSPierre Pronchery size_t i, num_chunks = ossl_quic_txpim_pkt_get_num_chunks(pkt);
129*e7be843bSPierre Pronchery QUIC_SSTREAM *sstream;
130*e7be843bSPierre Pronchery QUIC_CFQ_ITEM *cfq_item, *cfq_item_next;
131*e7be843bSPierre Pronchery int sstream_updated;
132*e7be843bSPierre Pronchery
133*e7be843bSPierre Pronchery ossl_qlog_event_recovery_packet_lost(fifd_get_qlog(fifd), pkt);
134*e7be843bSPierre Pronchery
135*e7be843bSPierre Pronchery /* STREAM and CRYPTO stream chunks, FIN and stream FC frames */
136*e7be843bSPierre Pronchery for (i = 0; i < num_chunks; ++i) {
137*e7be843bSPierre Pronchery sstream = fifd->get_sstream_by_id(chunks[i].stream_id,
138*e7be843bSPierre Pronchery pkt->ackm_pkt.pkt_space,
139*e7be843bSPierre Pronchery fifd->get_sstream_by_id_arg);
140*e7be843bSPierre Pronchery if (sstream == NULL)
141*e7be843bSPierre Pronchery continue;
142*e7be843bSPierre Pronchery
143*e7be843bSPierre Pronchery sstream_updated = 0;
144*e7be843bSPierre Pronchery
145*e7be843bSPierre Pronchery if (chunks[i].end >= chunks[i].start) {
146*e7be843bSPierre Pronchery /*
147*e7be843bSPierre Pronchery * Note: If the stream is being reset, we do not need to retransmit
148*e7be843bSPierre Pronchery * old data as this is pointless. In this case this will be handled
149*e7be843bSPierre Pronchery * by (sstream == NULL) above as the QSM will free the QUIC_SSTREAM
150*e7be843bSPierre Pronchery * and our call to get_sstream_by_id above will return NULL.
151*e7be843bSPierre Pronchery */
152*e7be843bSPierre Pronchery ossl_quic_sstream_mark_lost(sstream,
153*e7be843bSPierre Pronchery chunks[i].start, chunks[i].end);
154*e7be843bSPierre Pronchery sstream_updated = 1;
155*e7be843bSPierre Pronchery }
156*e7be843bSPierre Pronchery
157*e7be843bSPierre Pronchery if (chunks[i].has_fin && chunks[i].stream_id != UINT64_MAX) {
158*e7be843bSPierre Pronchery ossl_quic_sstream_mark_lost_fin(sstream);
159*e7be843bSPierre Pronchery sstream_updated = 1;
160*e7be843bSPierre Pronchery }
161*e7be843bSPierre Pronchery
162*e7be843bSPierre Pronchery if (chunks[i].has_stop_sending && chunks[i].stream_id != UINT64_MAX)
163*e7be843bSPierre Pronchery fifd->regen_frame(OSSL_QUIC_FRAME_TYPE_STOP_SENDING,
164*e7be843bSPierre Pronchery chunks[i].stream_id, pkt,
165*e7be843bSPierre Pronchery fifd->regen_frame_arg);
166*e7be843bSPierre Pronchery
167*e7be843bSPierre Pronchery if (chunks[i].has_reset_stream && chunks[i].stream_id != UINT64_MAX)
168*e7be843bSPierre Pronchery fifd->regen_frame(OSSL_QUIC_FRAME_TYPE_RESET_STREAM,
169*e7be843bSPierre Pronchery chunks[i].stream_id, pkt,
170*e7be843bSPierre Pronchery fifd->regen_frame_arg);
171*e7be843bSPierre Pronchery
172*e7be843bSPierre Pronchery /*
173*e7be843bSPierre Pronchery * Inform caller that stream needs an FC frame.
174*e7be843bSPierre Pronchery *
175*e7be843bSPierre Pronchery * Note: We could track whether an FC frame was sent originally for the
176*e7be843bSPierre Pronchery * stream to determine if it really needs to be regenerated or not.
177*e7be843bSPierre Pronchery * However, if loss has occurred, it's probably better to ensure the
178*e7be843bSPierre Pronchery * peer has up-to-date flow control data for the stream. Given that
179*e7be843bSPierre Pronchery * these frames are extremely small, we may as well always send it when
180*e7be843bSPierre Pronchery * handling loss.
181*e7be843bSPierre Pronchery */
182*e7be843bSPierre Pronchery fifd->regen_frame(OSSL_QUIC_FRAME_TYPE_MAX_STREAM_DATA,
183*e7be843bSPierre Pronchery chunks[i].stream_id,
184*e7be843bSPierre Pronchery pkt,
185*e7be843bSPierre Pronchery fifd->regen_frame_arg);
186*e7be843bSPierre Pronchery
187*e7be843bSPierre Pronchery if (sstream_updated && chunks[i].stream_id != UINT64_MAX)
188*e7be843bSPierre Pronchery fifd->sstream_updated(chunks[i].stream_id,
189*e7be843bSPierre Pronchery fifd->sstream_updated_arg);
190*e7be843bSPierre Pronchery }
191*e7be843bSPierre Pronchery
192*e7be843bSPierre Pronchery /* GCR */
193*e7be843bSPierre Pronchery for (cfq_item = pkt->retx_head; cfq_item != NULL; cfq_item = cfq_item_next) {
194*e7be843bSPierre Pronchery cfq_item_next = cfq_item->pkt_next;
195*e7be843bSPierre Pronchery ossl_quic_cfq_mark_lost(fifd->cfq, cfq_item, UINT32_MAX);
196*e7be843bSPierre Pronchery }
197*e7be843bSPierre Pronchery
198*e7be843bSPierre Pronchery /* Regenerate flag frames */
199*e7be843bSPierre Pronchery if (pkt->had_handshake_done_frame)
200*e7be843bSPierre Pronchery fifd->regen_frame(OSSL_QUIC_FRAME_TYPE_HANDSHAKE_DONE,
201*e7be843bSPierre Pronchery UINT64_MAX, pkt,
202*e7be843bSPierre Pronchery fifd->regen_frame_arg);
203*e7be843bSPierre Pronchery
204*e7be843bSPierre Pronchery if (pkt->had_max_data_frame)
205*e7be843bSPierre Pronchery fifd->regen_frame(OSSL_QUIC_FRAME_TYPE_MAX_DATA,
206*e7be843bSPierre Pronchery UINT64_MAX, pkt,
207*e7be843bSPierre Pronchery fifd->regen_frame_arg);
208*e7be843bSPierre Pronchery
209*e7be843bSPierre Pronchery if (pkt->had_max_streams_bidi_frame)
210*e7be843bSPierre Pronchery fifd->regen_frame(OSSL_QUIC_FRAME_TYPE_MAX_STREAMS_BIDI,
211*e7be843bSPierre Pronchery UINT64_MAX, pkt,
212*e7be843bSPierre Pronchery fifd->regen_frame_arg);
213*e7be843bSPierre Pronchery
214*e7be843bSPierre Pronchery if (pkt->had_max_streams_uni_frame)
215*e7be843bSPierre Pronchery fifd->regen_frame(OSSL_QUIC_FRAME_TYPE_MAX_STREAMS_UNI,
216*e7be843bSPierre Pronchery UINT64_MAX, pkt,
217*e7be843bSPierre Pronchery fifd->regen_frame_arg);
218*e7be843bSPierre Pronchery
219*e7be843bSPierre Pronchery if (pkt->had_ack_frame)
220*e7be843bSPierre Pronchery /*
221*e7be843bSPierre Pronchery * We always use the ACK_WITH_ECN frame type to represent the ACK frame
222*e7be843bSPierre Pronchery * type in our callback; we assume it is the caller's job to decide
223*e7be843bSPierre Pronchery * whether it wants to send ECN data or not.
224*e7be843bSPierre Pronchery */
225*e7be843bSPierre Pronchery fifd->regen_frame(OSSL_QUIC_FRAME_TYPE_ACK_WITH_ECN,
226*e7be843bSPierre Pronchery UINT64_MAX, pkt,
227*e7be843bSPierre Pronchery fifd->regen_frame_arg);
228*e7be843bSPierre Pronchery
229*e7be843bSPierre Pronchery ossl_quic_txpim_pkt_release(fifd->txpim, pkt);
230*e7be843bSPierre Pronchery }
231*e7be843bSPierre Pronchery
on_discarded(void * arg)232*e7be843bSPierre Pronchery static void on_discarded(void *arg)
233*e7be843bSPierre Pronchery {
234*e7be843bSPierre Pronchery QUIC_TXPIM_PKT *pkt = arg;
235*e7be843bSPierre Pronchery QUIC_FIFD *fifd = pkt->fifd;
236*e7be843bSPierre Pronchery QUIC_CFQ_ITEM *cfq_item, *cfq_item_next;
237*e7be843bSPierre Pronchery
238*e7be843bSPierre Pronchery /*
239*e7be843bSPierre Pronchery * Don't need to do anything to SSTREAMs for STREAM and CRYPTO streams, as
240*e7be843bSPierre Pronchery * we assume caller will clean them up.
241*e7be843bSPierre Pronchery */
242*e7be843bSPierre Pronchery
243*e7be843bSPierre Pronchery /* GCR */
244*e7be843bSPierre Pronchery for (cfq_item = pkt->retx_head; cfq_item != NULL; cfq_item = cfq_item_next) {
245*e7be843bSPierre Pronchery cfq_item_next = cfq_item->pkt_next;
246*e7be843bSPierre Pronchery ossl_quic_cfq_release(fifd->cfq, cfq_item);
247*e7be843bSPierre Pronchery }
248*e7be843bSPierre Pronchery
249*e7be843bSPierre Pronchery ossl_quic_txpim_pkt_release(fifd->txpim, pkt);
250*e7be843bSPierre Pronchery }
251*e7be843bSPierre Pronchery
ossl_quic_fifd_pkt_commit(QUIC_FIFD * fifd,QUIC_TXPIM_PKT * pkt)252*e7be843bSPierre Pronchery int ossl_quic_fifd_pkt_commit(QUIC_FIFD *fifd, QUIC_TXPIM_PKT *pkt)
253*e7be843bSPierre Pronchery {
254*e7be843bSPierre Pronchery QUIC_CFQ_ITEM *cfq_item;
255*e7be843bSPierre Pronchery const QUIC_TXPIM_CHUNK *chunks;
256*e7be843bSPierre Pronchery size_t i, num_chunks;
257*e7be843bSPierre Pronchery QUIC_SSTREAM *sstream;
258*e7be843bSPierre Pronchery
259*e7be843bSPierre Pronchery pkt->fifd = fifd;
260*e7be843bSPierre Pronchery
261*e7be843bSPierre Pronchery pkt->ackm_pkt.on_lost = on_lost;
262*e7be843bSPierre Pronchery pkt->ackm_pkt.on_acked = on_acked;
263*e7be843bSPierre Pronchery pkt->ackm_pkt.on_discarded = on_discarded;
264*e7be843bSPierre Pronchery pkt->ackm_pkt.cb_arg = pkt;
265*e7be843bSPierre Pronchery
266*e7be843bSPierre Pronchery ossl_list_tx_history_init_elem(&pkt->ackm_pkt);
267*e7be843bSPierre Pronchery pkt->ackm_pkt.anext = pkt->ackm_pkt.lnext = NULL;
268*e7be843bSPierre Pronchery
269*e7be843bSPierre Pronchery /*
270*e7be843bSPierre Pronchery * Mark the CFQ items which have been added to this packet as having been
271*e7be843bSPierre Pronchery * transmitted.
272*e7be843bSPierre Pronchery */
273*e7be843bSPierre Pronchery for (cfq_item = pkt->retx_head;
274*e7be843bSPierre Pronchery cfq_item != NULL;
275*e7be843bSPierre Pronchery cfq_item = cfq_item->pkt_next)
276*e7be843bSPierre Pronchery ossl_quic_cfq_mark_tx(fifd->cfq, cfq_item);
277*e7be843bSPierre Pronchery
278*e7be843bSPierre Pronchery /*
279*e7be843bSPierre Pronchery * Mark the send stream chunks which have been added to the packet as having
280*e7be843bSPierre Pronchery * been transmitted.
281*e7be843bSPierre Pronchery */
282*e7be843bSPierre Pronchery chunks = ossl_quic_txpim_pkt_get_chunks(pkt);
283*e7be843bSPierre Pronchery num_chunks = ossl_quic_txpim_pkt_get_num_chunks(pkt);
284*e7be843bSPierre Pronchery for (i = 0; i < num_chunks; ++i) {
285*e7be843bSPierre Pronchery sstream = fifd->get_sstream_by_id(chunks[i].stream_id,
286*e7be843bSPierre Pronchery pkt->ackm_pkt.pkt_space,
287*e7be843bSPierre Pronchery fifd->get_sstream_by_id_arg);
288*e7be843bSPierre Pronchery if (sstream == NULL)
289*e7be843bSPierre Pronchery continue;
290*e7be843bSPierre Pronchery
291*e7be843bSPierre Pronchery if (chunks[i].end >= chunks[i].start
292*e7be843bSPierre Pronchery && !ossl_quic_sstream_mark_transmitted(sstream,
293*e7be843bSPierre Pronchery chunks[i].start,
294*e7be843bSPierre Pronchery chunks[i].end))
295*e7be843bSPierre Pronchery return 0;
296*e7be843bSPierre Pronchery
297*e7be843bSPierre Pronchery if (chunks[i].has_fin
298*e7be843bSPierre Pronchery && !ossl_quic_sstream_mark_transmitted_fin(sstream,
299*e7be843bSPierre Pronchery chunks[i].end + 1))
300*e7be843bSPierre Pronchery return 0;
301*e7be843bSPierre Pronchery }
302*e7be843bSPierre Pronchery
303*e7be843bSPierre Pronchery /* Inform the ACKM. */
304*e7be843bSPierre Pronchery return ossl_ackm_on_tx_packet(fifd->ackm, &pkt->ackm_pkt);
305*e7be843bSPierre Pronchery }
306*e7be843bSPierre Pronchery
ossl_quic_fifd_set_qlog_cb(QUIC_FIFD * fifd,QLOG * (* get_qlog_cb)(void * arg),void * get_qlog_cb_arg)307*e7be843bSPierre Pronchery void ossl_quic_fifd_set_qlog_cb(QUIC_FIFD *fifd, QLOG *(*get_qlog_cb)(void *arg),
308*e7be843bSPierre Pronchery void *get_qlog_cb_arg)
309*e7be843bSPierre Pronchery {
310*e7be843bSPierre Pronchery fifd->get_qlog_cb = get_qlog_cb;
311*e7be843bSPierre Pronchery fifd->get_qlog_cb_arg = get_qlog_cb_arg;
312*e7be843bSPierre Pronchery }
313