MINOR: quic: detect connection migration

Detect connection migration attempted by the client. This is done by
comparing addresses stored in quic-conn with src/dest addresses of the
UDP datagram.

A new function qc_handle_conn_migration() has been added. For the
moment, no operation is conducted and the function will be completed
during connection migration implementation. The only notable things is
the increment of a new counter "quic_conn_migration_done".

This should be backported up to 2.7.
This commit is contained in:
Amaury Denoyelle 2022-12-02 09:57:32 +01:00
parent 21e611dc89
commit eec0b3c1bd
3 changed files with 51 additions and 0 deletions

View File

@ -24,6 +24,8 @@ enum {
QUIC_ST_HALF_OPEN_CONN,
QUIC_ST_HDSHK_FAIL,
QUIC_ST_STATELESS_RESET_SENT,
/* Special events of interest */
QUIC_ST_CONN_MIGRATION_DONE,
/* Transport errors */
QUIC_ST_TRANSP_ERR_NO_ERROR,
QUIC_ST_TRANSP_ERR_INTERNAL_ERROR,
@ -68,6 +70,8 @@ struct quic_counters {
long long half_open_conn; /* total number of half open connections */
long long hdshk_fail; /* total number of handshake failures */
long long stateless_reset_sent; /* total number of handshake failures */
/* Special events of interest */
long long conn_migration_done; /* total number of connection migration handled */
/* Transport errors */
long long quic_transp_err_no_error; /* total number of NO_ERROR connection errors */
long long quic_transp_err_internal_error; /* total number of INTERNAL_ERROR connection errors */

View File

@ -6312,6 +6312,37 @@ static int qc_rx_check_closing(struct quic_conn *qc,
return 1;
}
/* React to a connection migration initiated on <qc> by a client with the new
* path addresses <peer_addr>/<local_addr>.
*
* Returns 0 on success else non-zero.
*/
static int qc_handle_conn_migration(struct quic_conn *qc,
const struct sockaddr_storage *peer_addr,
const struct sockaddr_storage *local_addr)
{
TRACE_ENTER(QUIC_EV_CONN_LPKT, qc);
/* RFC 9000 9. Connection Migration
*
* TODO
* An endpoint MUST
* perform path validation (Section 8.2) if it detects any change to a
* peer's address, unless it has previously validated that address.
*/
qc->local_addr = *local_addr;
qc->peer_addr = *peer_addr;
HA_ATOMIC_INC(&qc->prx_counters->conn_migration_done);
TRACE_LEAVE(QUIC_EV_CONN_LPKT, qc);
return 0;
err:
TRACE_LEAVE(QUIC_EV_CONN_LPKT, qc);
return 1;
}
/* Handle a parsed packet <pkt> by the connection <qc>. Data will be copied
* into <qc> receive buffer after header protection removal procedure.
*
@ -7315,6 +7346,17 @@ int quic_dgram_parse(struct quic_dgram *dgram, struct quic_conn *from_qc,
goto next;
}
/* Detect QUIC connection migration. */
if (ipcmp(&qc->peer_addr, &dgram->saddr, 1) ||
ipcmp(&qc->local_addr, &dgram->daddr, 1)) {
if (qc_handle_conn_migration(qc, &dgram->saddr, &dgram->daddr)) {
/* Skip the entire datagram. */
TRACE_ERROR("error during connection migration, datagram dropped", QUIC_EV_CONN_LPKT, qc);
pkt->len = end - pos;
goto next;
}
}
qc_rx_pkt_handle(qc, pkt, dgram, pos, &tasklist_head);
next:

View File

@ -33,6 +33,9 @@ static struct name_desc quic_stats[] = {
.desc = "Total number of handshake failures" },
[QUIC_ST_STATELESS_RESET_SENT] = { .name = "quic_stless_rst_sent",
.desc = "Total number of stateless reset packet sent" },
/* Special events of interest */
[QUIC_ST_CONN_MIGRATION_DONE] = { .name = "quic_conn_migration_done",
.desc = "Total number of connection migration proceeded" },
/* Transport errors */
[QUIC_ST_TRANSP_ERR_NO_ERROR] = { .name = "quic_transp_err_no_error",
.desc = "Total number of NO_ERROR errors received" },
@ -104,6 +107,8 @@ static void quic_fill_stats(void *data, struct field *stats)
stats[QUIC_ST_HALF_OPEN_CONN] = mkf_u64(FN_GAUGE, counters->half_open_conn);
stats[QUIC_ST_HDSHK_FAIL] = mkf_u64(FN_COUNTER, counters->hdshk_fail);
stats[QUIC_ST_STATELESS_RESET_SENT] = mkf_u64(FN_COUNTER, counters->stateless_reset_sent);
/* Special events of interest */
stats[QUIC_ST_CONN_MIGRATION_DONE] = mkf_u64(FN_COUNTER, counters->conn_migration_done);
/* Transport errors */
stats[QUIC_ST_TRANSP_ERR_NO_ERROR] = mkf_u64(FN_COUNTER, counters->quic_transp_err_no_error);
stats[QUIC_ST_TRANSP_ERR_INTERNAL_ERROR] = mkf_u64(FN_COUNTER, counters->quic_transp_err_internal_error);