diff --git a/src/liblsquic/lsquic_conn_public.h b/src/liblsquic/lsquic_conn_public.h index 47dfeb0..f78d0eb 100644 --- a/src/liblsquic/lsquic_conn_public.h +++ b/src/liblsquic/lsquic_conn_public.h @@ -57,6 +57,11 @@ struct lsquic_conn_public { #if LSQUIC_EXTRA_CHECKS unsigned long stream_frame_bytes; #endif + /* "unsigned" is wide enough: these values are only used for amplification + * limit before initial path is validated. + */ + unsigned bytes_in; /* successfully processed */ + unsigned bytes_out; }; #endif diff --git a/src/liblsquic/lsquic_full_conn_ietf.c b/src/liblsquic/lsquic_full_conn_ietf.c index 61a4c3a..1a886c6 100644 --- a/src/liblsquic/lsquic_full_conn_ietf.c +++ b/src/liblsquic/lsquic_full_conn_ietf.c @@ -137,6 +137,12 @@ enum ifull_conn_flags }; +enum more_flags +{ + MF_VALIDATE_PATH = 1 << 0, +}; + + #define N_PATHS 2 enum send @@ -314,6 +320,7 @@ struct ietf_full_conn unsigned ifc_max_streams_in[N_SDS]; uint64_t ifc_max_stream_data_uni; enum ifull_conn_flags ifc_flags; + enum more_flags ifc_mflags; enum send_flags ifc_send_flags; enum send_flags ifc_delayed_send; struct { @@ -1306,6 +1313,12 @@ lsquic_ietf_full_conn_server_new (struct lsquic_engine_public *enpub, conn->ifc_paths[0].cop_path = imc->imc_path; conn->ifc_paths[0].cop_flags = COP_VALIDATED; conn->ifc_used_paths = 1 << 0; + if (imc->imc_flags & IMC_ADDR_VALIDATED) + lsquic_send_ctl_path_validated(&conn->ifc_send_ctl); + else + conn->ifc_mflags |= MF_VALIDATE_PATH; + conn->ifc_pub.bytes_out = imc->imc_bytes_out; + conn->ifc_pub.bytes_in = imc->imc_bytes_in; if (imc->imc_flags & IMC_PATH_CHANGED) { LSQ_DEBUG("path changed during mini conn: schedule PATH_CHALLENGE"); @@ -6369,6 +6382,14 @@ process_regular_packet (struct ietf_full_conn *conn, else conn->ifc_spin_bit = !lsquic_packet_in_spin_bit(packet_in); } + conn->ifc_pub.bytes_in += packet_in->pi_data_sz; + if ((conn->ifc_mflags & MF_VALIDATE_PATH) && + (packet_in->pi_header_type == HETY_NOT_SET + || packet_in->pi_header_type == HETY_HANDSHAKE)) + { + conn->ifc_mflags &= ~MF_VALIDATE_PATH; + lsquic_send_ctl_path_validated(&conn->ifc_send_ctl); + } return 0; case REC_ST_DUP: LSQ_INFO("packet %"PRIu64" is a duplicate", packet_in->pi_packno); @@ -6567,6 +6588,8 @@ ietf_full_conn_ci_packet_sent (struct lsquic_conn *lconn, lsquic_alarmset_set(&conn->ifc_alset, AL_BLOCKED_KA, packet_out->po_sent + (1 + (7 & lsquic_crand_get_nybble( conn->ifc_enpub->enp_crand))) * 1000000); + conn->ifc_pub.bytes_out += lsquic_packet_out_sent_sz(&conn->ifc_conn, + packet_out); } diff --git a/src/liblsquic/lsquic_packet_out.h b/src/liblsquic/lsquic_packet_out.h index 74467d7..867e3fe 100644 --- a/src/liblsquic/lsquic_packet_out.h +++ b/src/liblsquic/lsquic_packet_out.h @@ -214,7 +214,7 @@ typedef struct lsquic_packet_out lconn->cn_pf->pf_packout_max_header_size(lconn, po_flags, dcid_len)) #define lsquic_packet_out_total_sz(lconn, p) (\ - lconn->cn_pf->pf_packout_size(lconn, p)) + (lconn)->cn_pf->pf_packout_size(lconn, p)) #if __GNUC__ #if LSQUIC_EXTRA_CHECKS diff --git a/src/liblsquic/lsquic_send_ctl.c b/src/liblsquic/lsquic_send_ctl.c index 7ac100e..4994af1 100644 --- a/src/liblsquic/lsquic_send_ctl.c +++ b/src/liblsquic/lsquic_send_ctl.c @@ -119,6 +119,12 @@ send_ctl_all_bytes_out (const struct lsquic_send_ctl *ctl); static void send_ctl_reschedule_poison (struct lsquic_send_ctl *ctl); +static int +send_ctl_can_send_pre_hsk (struct lsquic_send_ctl *ctl); + +static int +send_ctl_can_send (struct lsquic_send_ctl *ctl); + #ifdef NDEBUG static #elif __GNUC__ @@ -363,6 +369,11 @@ lsquic_send_ctl_init (lsquic_send_ctl_t *ctl, struct lsquic_alarmset *alset, ctl->sc_flags |= SC_SANITY_CHECK; #endif ctl->sc_gap = UINT64_MAX - 1 /* Can't have +1 == 0 */; + if ((ctl->sc_conn_pub->lconn->cn_flags & (LSCONN_IETF|LSCONN_SERVER)) + == (LSCONN_IETF|LSCONN_SERVER)) + ctl->sc_can_send = send_ctl_can_send_pre_hsk; + else + ctl->sc_can_send = send_ctl_can_send; } @@ -1367,13 +1378,8 @@ lsquic_send_ctl_pacer_blocked (struct lsquic_send_ctl *ctl) } -#ifndef NDEBUG -#if __GNUC__ -__attribute__((weak)) -#endif -#endif -int -lsquic_send_ctl_can_send (lsquic_send_ctl_t *ctl) +static int +send_ctl_can_send (struct lsquic_send_ctl *ctl) { const unsigned n_out = send_ctl_all_bytes_out(ctl); LSQ_DEBUG("%s: n_out: %u (unacked_all: %u); cwnd: %"PRIu64, __func__, @@ -1400,6 +1406,37 @@ lsquic_send_ctl_can_send (lsquic_send_ctl_t *ctl) } +static int +send_ctl_can_send_pre_hsk (struct lsquic_send_ctl *ctl) +{ + unsigned bytes_in, bytes_out; + + bytes_in = ctl->sc_conn_pub->bytes_in; + bytes_out = ctl->sc_conn_pub->bytes_out + ctl->sc_bytes_scheduled; + if (bytes_out >= bytes_in * 2 + bytes_in / 2 /* This should work out + to around 3 on average */) + { + LSQ_DEBUG("%s: amplification block: %u bytes in, %u bytes out", + __func__, bytes_in, bytes_out); + return 0; + } + else + return send_ctl_can_send(ctl); +} + + +#ifndef NDEBUG +#if __GNUC__ +__attribute__((weak)) +#endif +#endif +int +lsquic_send_ctl_can_send (struct lsquic_send_ctl *ctl) +{ + return ctl->sc_can_send(ctl); +} + + /* Like lsquic_send_ctl_can_send(), but no mods */ static int send_ctl_could_send (const struct lsquic_send_ctl *ctl) @@ -2982,3 +3019,11 @@ lsquic_send_ctl_begin_optack_detection (struct lsquic_send_ctl *ctl) rand = lsquic_crand_get_byte(ctl->sc_enpub->enp_crand); ctl->sc_gap = ctl->sc_cur_packno + 1 + rand; } + + +void +lsquic_send_ctl_path_validated (struct lsquic_send_ctl *ctl) +{ + LSQ_DEBUG("path validated: switch to regular can_send"); + ctl->sc_can_send = send_ctl_can_send; +} diff --git a/src/liblsquic/lsquic_send_ctl.h b/src/liblsquic/lsquic_send_ctl.h index c4d7685..908f381 100644 --- a/src/liblsquic/lsquic_send_ctl.h +++ b/src/liblsquic/lsquic_send_ctl.h @@ -64,6 +64,7 @@ typedef struct lsquic_send_ctl { lsquic_time_t sc_largest_acked_sent_time; lsquic_time_t sc_last_sent_time; lsquic_time_t sc_last_rto_time; + int (*sc_can_send)(struct lsquic_send_ctl *); unsigned sc_bytes_unacked_retx; unsigned sc_bytes_scheduled; union { @@ -383,4 +384,7 @@ lsquic_send_ctl_begin_optack_detection (struct lsquic_send_ctl *); #define lsquic_send_ctl_n_unacked(ctl_) ((ctl_)->sc_n_in_flight_retx) +void +lsquic_send_ctl_path_validated (struct lsquic_send_ctl *); + #endif