#define QUIC_FL_CONN_NEED_POST_HANDSHAKE_FRMS (1U << 2) /* HANDSHAKE_DONE must be sent */
/* gap here */
#define QUIC_FL_CONN_ACCEPT_REGISTERED (1U << 4)
-/* gap here */
+#define QUIC_FL_CONN_UDP_GSO_EIO (1U << 5) /* GSO disabled due to a EIO occured on same listener */
#define QUIC_FL_CONN_IDLE_TIMER_RESTARTED_AFTER_READ (1U << 6)
#define QUIC_FL_CONN_RETRANS_NEEDED (1U << 7)
#define QUIC_FL_CONN_RETRANS_OLD_DATA (1U << 8) /* retransmission in progress for probing with already sent data */
_(QUIC_FL_CONN_SPIN_BIT,
_(QUIC_FL_CONN_NEED_POST_HANDSHAKE_FRMS,
_(QUIC_FL_CONN_ACCEPT_REGISTERED,
+ _(QUIC_FL_CONN_UDP_GSO_EIO,
_(QUIC_FL_CONN_IDLE_TIMER_RESTARTED_AFTER_READ,
_(QUIC_FL_CONN_RETRANS_NEEDED,
_(QUIC_FL_CONN_RETRANS_OLD_DATA,
_(QUIC_FL_CONN_EXP_TIMER,
_(QUIC_FL_CONN_CLOSING,
_(QUIC_FL_CONN_DRAINING,
- _(QUIC_FL_CONN_IMMEDIATE_CLOSE)))))))))))))))))))))));
+ _(QUIC_FL_CONN_IMMEDIATE_CLOSE))))))))))))))))))))))));
/* epilogue */
_(~0U);
return buf;
cc_algo = l->bind_conf->quic_cc_algo;
qc->flags = 0;
+
+ /* Duplicate GSO status on listener to connection */
+ if (HA_ATOMIC_LOAD(&l->flags) & LI_F_UDP_GSO_NOTSUPP)
+ qc->flags |= QUIC_FL_CONN_UDP_GSO_EIO;
+
/* Mark this connection as having not received any token when 0-RTT is enabled. */
if (l->bind_conf->ssl_conf.early_data && !token)
qc->flags |= QUIC_FL_CONN_NO_TOKEN_RCVD;
/* At this point no connection was accounted for yet on this
* listener so it's OK to just swap the pointer.
*/
- if (new_li && new_li != __objt_listener(qc->target))
+ if (new_li && new_li != __objt_listener(qc->target)) {
qc->target = &new_li->obj_type;
+ /* Update GSO conn support based on new listener status. */
+ if (HA_ATOMIC_LOAD(&new_li->flags) & LI_F_UDP_GSO_NOTSUPP)
+ qc->flags |= QUIC_FL_CONN_UDP_GSO_EIO;
+ else
+ qc->flags &= ~QUIC_FL_CONN_UDP_GSO_EIO;
+ }
+
/* Rebind the connection FD. */
if (qc_test_fd(qc)) {
/* Reading is reactivated by the new thread. */
/* If datagram bigger than MTU, several ones were encoded for GSO usage. */
if (dglen > qc->path->mtu) {
- /* TODO: note that at this time for connection to backends this
- * part is not run because no more than an MTU has been prepared for
- * such connections (dglen <= qc->path->mtu). So, here l is not NULL.
- */
- if (likely(!(HA_ATOMIC_LOAD(&l->flags) & LI_F_UDP_GSO_NOTSUPP))) {
+ if (likely(!(qc->flags & QUIC_FL_CONN_UDP_GSO_EIO))) {
TRACE_PROTO("send multiple datagrams with GSO", QUIC_EV_CONN_SPPKTS, qc);
gso = qc->path->mtu;
}
int ret = qc_snd_buf(qc, &tmpbuf, tmpbuf.data, 0, gso);
if (ret < 0) {
if (gso && ret == -EIO) {
+ /* GSO must not be used if already disabled. */
+ BUG_ON(qc->flags & QUIC_FL_CONN_UDP_GSO_EIO);
+
/* TODO: note that at this time for connection to backends this
* part is not run because no more than an MTU has been
* prepared for such connections (l is not NULL).
*/
TRACE_ERROR("mark listener UDP GSO as unsupported", QUIC_EV_CONN_SPPKTS, qc, first_pkt);
HA_ATOMIC_OR(&l->flags, LI_F_UDP_GSO_NOTSUPP);
+ qc->flags |= QUIC_FL_CONN_UDP_GSO_EIO;
continue;
}
prv_pkt = cur_pkt;
}
else if (!(quic_tune.options & QUIC_TUNE_NO_UDP_GSO) &&
+ !(qc->flags & QUIC_FL_CONN_UDP_GSO_EIO) &&
dglen == qc->path->mtu &&
(char *)end < b_wrap(buf) &&
- ++gso_dgram_cnt < QUIC_MAX_GSO_DGRAMS &&
- l && !(HA_ATOMIC_LOAD(&l->flags) & LI_F_UDP_GSO_NOTSUPP)) {
+ ++gso_dgram_cnt < QUIC_MAX_GSO_DGRAMS) {
/* TODO: note that for backends GSO is not used. No more than
* an MTU is prepared.
*/