#define QUIC_FL_PKTNS_ACK_REQUIRED (1UL << 1)
/* Flag the packet number space as needing probing */
#define QUIC_FL_PKTNS_PROBE_NEEDED (1UL << 2)
+/* Flag the packet number space as having received a packet with a new largest
+ * packet number, to be acknowledege
+ */
+#define QUIC_FL_PKTNS_NEW_LARGEST_PN (1UL << 3)
/* The maximum number of dgrams which may be sent upon PTO expirations. */
#define QUIC_MAX_NB_PTO_DGRAMS 2
unsigned int pto_probe;
/* In flight bytes for this packet number space. */
size_t in_flight;
+ /* The acknowledgement delay of the packet with the largest packet number */
+ uint64_t ack_delay;
} tx;
struct {
/* Largest packet number */
int64_t largest_acked_pn;
struct quic_arngs arngs;
unsigned int nb_aepkts_since_last_ack;
+ /* The time the packet with the largest packet number was received */
+ uint64_t largest_time_received;
} rx;
unsigned int flags;
};
/* Source address of this packet. */
struct sockaddr_storage saddr;
unsigned int flags;
+ unsigned int time_received;
};
/* QUIC datagram handler */
return (ack_frm->ack_delay << conn->tx.params.ack_delay_exponent) / 1000;
}
+/* Returns the <ack_delay> field value in microsecond to be set in an ACK frame
+ * depending on the time the packet with a new largest packet number was received.
+ */
+static inline uint64_t quic_compute_ack_delay_us(unsigned int time_received,
+ struct quic_conn *conn)
+{
+ return ((now_ms - time_received) * 1000) >> conn->tx.params.ack_delay_exponent;
+}
+
/* Initialize <dst> transport parameters with default values (when absent)
* from <quic_dflt_trasports_params>.
* Never fails.
pktns->tx.time_of_last_eliciting = 0;
pktns->tx.loss_time = TICK_ETERNITY;
pktns->tx.in_flight = 0;
+ pktns->tx.ack_delay = 0;
pktns->rx.largest_pn = -1;
pktns->rx.largest_acked_pn = -1;
pktns->rx.arngs.sz = 0;
pktns->rx.arngs.enc_sz = 0;
pktns->rx.nb_aepkts_since_last_ack = 0;
+ pktns->rx.largest_time_received = 0;
pktns->flags = 0;
}
{
struct eb64_node *node;
int64_t largest_pn = -1;
+ unsigned int largest_pn_time_received = 0;
struct quic_conn *qc = ctx->qc;
struct quic_enc_level *qel = cur_el;
qel->pktns->rx.nb_aepkts_since_last_ack++;
qc_idle_timer_rearm(qc, 1);
}
- if (pkt->pn > largest_pn)
+ if (pkt->pn > largest_pn) {
largest_pn = pkt->pn;
+ largest_pn_time_received = pkt->time_received;
+ }
/* Update the list of ranges to acknowledge. */
if (!quic_update_ack_ranges_list(&qel->pktns->rx.arngs, &ar))
TRACE_DEVEL("Could not update ack range list",
}
HA_RWLOCK_WRUNLOCK(QUIC_LOCK, &qel->rx.pkts_rwlock);
- /* Update the largest packet number. */
- if (largest_pn != -1 && largest_pn > qel->pktns->rx.largest_pn)
+ if (largest_pn != -1 && largest_pn > qel->pktns->rx.largest_pn) {
+ /* Update the largest packet number. */
qel->pktns->rx.largest_pn = largest_pn;
+ /* Update the largest acknowledged packet timestamps */
+ qel->pktns->rx.largest_time_received = largest_pn_time_received;
+ qel->pktns->flags |= QUIC_FL_PKTNS_NEW_LARGEST_PN;
+ }
+
if (!qc_treat_rx_crypto_frms(qel, ctx))
goto err;
/* Build an ACK frame if required. */
ack_frm_len = 0;
if ((qel->pktns->flags & QUIC_FL_PKTNS_ACK_REQUIRED) && !qel->pktns->tx.pto_probe) {
+ struct quic_arngs *arngs = &qel->pktns->rx.arngs;
BUG_ON(eb_is_empty(&qel->pktns->rx.arngs.root));
- ack_frm.tx_ack.ack_delay = 0;
- ack_frm.tx_ack.arngs = &qel->pktns->rx.arngs;
+ ack_frm.tx_ack.arngs = arngs;
+ if (qel->pktns->flags & QUIC_FL_PKTNS_NEW_LARGEST_PN) {
+ qel->pktns->tx.ack_delay =
+ quic_compute_ack_delay_us(qel->pktns->rx.largest_time_received, qc);
+ qel->pktns->flags &= ~QUIC_FL_PKTNS_NEW_LARGEST_PN;
+ }
+ ack_frm.tx_ack.ack_delay = qel->pktns->tx.ack_delay;
/* XXX BE CAREFUL XXX : here we reserved at least one byte for the
* smallest frame (PING) and <*pn_len> more for the packet number. Note
* that from here, we do not know if we will have to send a PING frame.
if (!pkt)
goto err;
+ pkt->time_received = now_ms;
quic_rx_packet_refinc(pkt);
qc_lstnr_pkt_rcv(pos, end, pkt, first_pkt, dgram);
first_pkt = 0;