#define QUIC_FL_RX_PACKET_ACK_ELICITING (1UL << 0)
/* Packet is the first one in the containing datagram. */
#define QUIC_FL_RX_PACKET_DGRAM_FIRST (1UL << 1)
+/* Spin bit set */
+#define QUIC_FL_RX_PACKET_SPIN_BIT (1UL << 2)
struct quic_rx_packet {
struct list list;
/* Flags at connection level */
#define QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED (1U << 0)
+#define QUIC_FL_CONN_SPIN_BIT (1U << 1) /* Spin bit set by remote peer */
#define QUIC_FL_CONN_POST_HANDSHAKE_FRAMES_BUILT (1U << 2)
#define QUIC_FL_CONN_LISTENER (1U << 3)
#define QUIC_FL_CONN_ACCEPT_REGISTERED (1U << 4)
TRACE_LEAVE(QUIC_EV_CONN_RXPKT, qc);
return ret;
}
+
+/* Detect the value of the spin bit to be used. */
+static inline void qc_handle_spin_bit(struct quic_conn *qc, struct quic_rx_packet *pkt,
+ struct quic_enc_level *qel)
+{
+ uint64_t largest_pn = qel->pktns->rx.largest_pn;
+
+ if (qel != &qc->els[QUIC_TLS_ENC_LEVEL_APP] || largest_pn == -1 ||
+ pkt->pn <= largest_pn)
+ return;
+
+ if (qc_is_listener(qc)) {
+ if (pkt->flags & QUIC_FL_RX_PACKET_SPIN_BIT)
+ qc->flags |= QUIC_FL_CONN_SPIN_BIT;
+ else
+ qc->flags &= ~QUIC_FL_CONN_SPIN_BIT;
+ }
+ else {
+ if (pkt->flags & QUIC_FL_RX_PACKET_SPIN_BIT)
+ qc->flags &= ~QUIC_FL_CONN_SPIN_BIT;
+ else
+ qc->flags |= QUIC_FL_CONN_SPIN_BIT;
+ }
+}
+
/* Remove the header protection of packets at <el> encryption level.
* Always succeeds.
*/
TRACE_ERROR("hp removing error", QUIC_EV_CONN_ELRMHP, qc);
}
else {
+ qc_handle_spin_bit(qc, pqpkt, el);
/* The AAD includes the packet number field */
pqpkt->aad_len = pqpkt->pn_offset + pqpkt->pnl;
/* Store the packet into the tree of packets to decrypt. */
goto out;
}
+ qc_handle_spin_bit(qc, pkt, qel);
/* The AAD includes the packet number field. */
pkt->aad_len = pkt->pn_offset + pkt->pnl;
if (pkt->len - pkt->aad_len < QUIC_TLS_TAG_LEN) {
}
}
else {
+ if (byte0 & QUIC_PACKET_SPIN_BIT)
+ pkt->flags |= QUIC_FL_RX_PACKET_SPIN_BIT;
pkt->type = QUIC_PACKET_TYPE_SHORT;
*long_header = 0;
}
unsigned char tls_flags)
{
int ret = 0;
+ unsigned char spin_bit =
+ (qc->flags & QUIC_FL_CONN_SPIN_BIT) ? QUIC_PACKET_SPIN_BIT : 0;
TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
}
/* #0 byte flags */
- *(*buf)++ = QUIC_PACKET_FIXED_BIT |
+ *(*buf)++ = QUIC_PACKET_FIXED_BIT | spin_bit |
((tls_flags & QUIC_FL_TLS_KP_BIT_SET) ? QUIC_PACKET_KEY_PHASE_BIT : 0) | (pn_len - 1);
/* Destination connection ID */
if (qc->dcid.len) {