MINOR: tevt/mux-spop: Report termination events for the SPOP connect/stream

Termination events are now reported for the SPOP connections and the SPOP
streams. In addition, all available termination events logs are reported in
the "show-fd" callback function. The .ctl and .sctl callback functions were
also update to support, respectively, MUX_CTL_TEVTS and MUX_SCTL_TEVTS
commands.
This commit is contained in:
Christopher Faulet 2025-02-04 11:03:31 +01:00
parent 514a912a4d
commit 4f8ae5b1f6

View File

@ -49,6 +49,8 @@ struct spop_conn {
unsigned int nb_reserved; /* number of reserved streams */ unsigned int nb_reserved; /* number of reserved streams */
unsigned int stream_cnt; /* total number of streams seen */ unsigned int stream_cnt; /* total number of streams seen */
uint32_t term_evts_log; /* Termination events log: first 4 events reported */
struct proxy *proxy; /* the proxy this connection was created for */ struct proxy *proxy; /* the proxy this connection was created for */
struct spoe_agent *agent; /* SPOE agent used by this mux */ struct spoe_agent *agent; /* SPOE agent used by this mux */
struct task *task; /* timeout management task */ struct task *task; /* timeout management task */
@ -551,6 +553,13 @@ static inline int spop_recv_allowed(const struct spop_conn *spop_conn)
return 0; return 0;
} }
static inline void spop_conn_report_term_evt(struct spop_conn *spop_conn, enum muxc_term_event_type type)
{
enum term_event_loc loc = tevt_loc_muxc + 8; /* Always on backend side for now */
spop_conn->term_evts_log = tevt_report_event(spop_conn->term_evts_log, loc, type);
}
/* Restarts reading on the connection if it was not enabled */ /* Restarts reading on the connection if it was not enabled */
static inline void spop_conn_restart_reading(const struct spop_conn *spop_conn, int consider_buffer) static inline void spop_conn_restart_reading(const struct spop_conn *spop_conn, int consider_buffer)
{ {
@ -671,6 +680,7 @@ static int spop_init(struct connection *conn, struct proxy *px, struct session *
spop_conn->nb_sc = 0; spop_conn->nb_sc = 0;
spop_conn->nb_reserved = 0; spop_conn->nb_reserved = 0;
spop_conn->stream_cnt = 0; spop_conn->stream_cnt = 0;
spop_conn->term_evts_log = 0;
spop_conn->dbuf = *input; spop_conn->dbuf = *input;
spop_conn->dsi = -1; spop_conn->dsi = -1;
@ -741,9 +751,12 @@ static void spop_release(struct spop_conn *spop_conn)
spop_conn->task = NULL; spop_conn->task = NULL;
} }
tasklet_free(spop_conn->wait_event.tasklet); tasklet_free(spop_conn->wait_event.tasklet);
if (conn && spop_conn->wait_event.events != 0) if (conn) {
if (spop_conn->wait_event.events != 0)
conn->xprt->unsubscribe(conn, conn->xprt_ctx, spop_conn->wait_event.events, conn->xprt->unsubscribe(conn, conn->xprt_ctx, spop_conn->wait_event.events,
&spop_conn->wait_event); &spop_conn->wait_event);
spop_conn_report_term_evt(spop_conn, muxc_tevt_type_shutw);
}
pool_free(pool_head_spop_conn, spop_conn); pool_free(pool_head_spop_conn, spop_conn);
@ -1119,8 +1132,12 @@ static inline void spop_strm_propagate_term_flags(struct spop_conn *spop_conn, s
} }
if (spop_conn_read0_pending(spop_conn) || spop_strm->state == SPOP_SS_CLOSED) { if (spop_conn_read0_pending(spop_conn) || spop_strm->state == SPOP_SS_CLOSED) {
se_fl_set(spop_strm->sd, SE_FL_EOS); se_fl_set(spop_strm->sd, SE_FL_EOS);
if (!se_fl_test(spop_strm->sd, SE_FL_EOI)) if (!se_fl_test(spop_strm->sd, SE_FL_EOI)) {
se_fl_set(spop_strm->sd, SE_FL_ERROR); se_fl_set(spop_strm->sd, SE_FL_ERROR);
se_report_term_evt(spop_strm->sd, (spop_conn->flags & SPOP_CF_ERROR ? se_tevt_type_truncated_rcv_err : se_tevt_type_truncated_eos));
}
else
se_report_term_evt(spop_strm->sd, (spop_conn->flags & SPOP_CF_ERROR ? se_tevt_type_rcv_err : se_tevt_type_eos));
} }
if (se_fl_test(spop_strm->sd, SE_FL_ERR_PENDING)) if (se_fl_test(spop_strm->sd, SE_FL_ERR_PENDING))
se_fl_set(spop_strm->sd, SE_FL_ERROR); se_fl_set(spop_strm->sd, SE_FL_ERROR);
@ -1535,6 +1552,43 @@ static int spop_conn_send_disconnect(struct spop_conn *spop_conn)
spop_conn->flags |= SPOP_CF_DISCO_SENT; spop_conn->flags |= SPOP_CF_DISCO_SENT;
ret = 1; ret = 1;
switch (spop_conn->errcode) {
case SPOP_ERR_NONE:
spop_conn_report_term_evt(spop_conn, muxc_tevt_type_graceful_shut);
break;
case SPOP_ERR_IO:
spop_conn_report_term_evt(spop_conn, muxc_tevt_type_other_err);
break;
case SPOP_ERR_TOUT:
spop_conn_report_term_evt(spop_conn, muxc_tevt_type_tout);
break;
case SPOP_ERR_TOO_BIG:
case SPOP_ERR_INVALID:
case SPOP_ERR_NO_VSN:
case SPOP_ERR_NO_FRAME_SIZE:
case SPOP_ERR_NO_CAP:
case SPOP_ERR_BAD_VSN:
case SPOP_ERR_BAD_FRAME_SIZE:
case SPOP_ERR_FRAG_NOT_SUPPORTED:
case SPOP_ERR_INTERLACED_FRAMES:
case SPOP_ERR_FRAMEID_NOTFOUND:
spop_conn_report_term_evt(spop_conn, muxc_tevt_type_proto_err);
break;
case SPOP_ERR_RES:
case SPOP_ERR_UNKNOWN:
spop_conn_report_term_evt(spop_conn, muxc_tevt_type_internal_err);
break;
default:
spop_conn_report_term_evt(spop_conn, muxc_tevt_type_tout);
break;
}
end: end:
TRACE_LEAVE(SPOP_EV_TX_FRAME|SPOP_EV_TX_DISCO, spop_conn->conn); TRACE_LEAVE(SPOP_EV_TX_FRAME|SPOP_EV_TX_DISCO, spop_conn->conn);
return ret; return ret;
@ -1834,6 +1888,7 @@ static int spop_conn_handle_disconnect(struct spop_conn *spop_conn)
spop_conn_error(spop_conn, status_code); spop_conn_error(spop_conn, status_code);
spop_conn->state = SPOP_CS_CLOSED; spop_conn->state = SPOP_CS_CLOSED;
spop_wake_some_streams(spop_conn, 0/*last*/); spop_wake_some_streams(spop_conn, 0/*last*/);
spop_conn_report_term_evt(spop_conn, muxc_tevt_type_goaway_rcvd);
TRACE_LEAVE(SPOP_EV_RX_FRAME|SPOP_EV_RX_DISCO, spop_conn->conn); TRACE_LEAVE(SPOP_EV_RX_FRAME|SPOP_EV_RX_DISCO, spop_conn->conn);
return 1; return 1;
fail: fail:
@ -2203,6 +2258,15 @@ static void spop_process_demux(struct spop_conn *spop_conn)
spop_conn->flags |= SPOP_CF_END_REACHED; spop_conn->flags |= SPOP_CF_END_REACHED;
} }
if (spop_conn->flags & SPOP_CF_ERROR)
spop_conn_report_term_evt(spop_conn, ((eb_is_empty(&spop_conn->streams_by_id) && (spop_conn->state == SPOP_CS_FRAME_H))
? muxc_tevt_type_rcv_err
: muxc_tevt_type_truncated_rcv_err));
else if (spop_conn->flags & SPOP_CF_END_REACHED)
spop_conn_report_term_evt(spop_conn, ((eb_is_empty(&spop_conn->streams_by_id) && (spop_conn->state == SPOP_CS_FRAME_H))
? muxc_tevt_type_shutr
: muxc_tevt_type_truncated_shutr));
if (spop_strm && spop_strm_sc(spop_strm) && if (spop_strm && spop_strm_sc(spop_strm) &&
(b_data(&spop_strm->rxbuf) || (b_data(&spop_strm->rxbuf) ||
spop_conn_read0_pending(spop_conn) || spop_conn_read0_pending(spop_conn) ||
@ -2411,6 +2475,7 @@ static int spop_send(struct spop_conn *spop_conn)
if (conn->flags & CO_FL_ERROR) { if (conn->flags & CO_FL_ERROR) {
spop_conn->flags |= SPOP_CF_ERR_PENDING; spop_conn->flags |= SPOP_CF_ERR_PENDING;
spop_conn_report_term_evt(spop_conn, muxc_tevt_type_snd_err);
if (spop_conn->flags & SPOP_CF_END_REACHED) if (spop_conn->flags & SPOP_CF_END_REACHED)
spop_conn->flags |= SPOP_CF_ERROR; spop_conn->flags |= SPOP_CF_ERROR;
b_reset(br_tail(spop_conn->mbuf)); b_reset(br_tail(spop_conn->mbuf));
@ -2604,6 +2669,8 @@ static int spop_ctl(struct connection *conn, enum mux_ctl_type mux_ctl, void *ou
return spop_conn->nb_streams; return spop_conn->nb_streams;
case MUX_CTL_GET_MAXSTRM: case MUX_CTL_GET_MAXSTRM:
return spop_conn->streams_limit; return spop_conn->streams_limit;
case MUX_CTL_TEVTS:
return spop_conn->term_evts_log;
default: default:
return -1; return -1;
} }
@ -2619,7 +2686,8 @@ static int spop_sctl(struct stconn *sc, enum mux_sctl_type mux_sctl, void *outpu
if (output) if (output)
*((int64_t *)output) = spop_strm->id; *((int64_t *)output) = spop_strm->id;
return ret; return ret;
case MUX_SCTL_TEVTS:
return spop_strm->sd->term_evts_log;
default: default:
return -1; return -1;
} }
@ -2663,6 +2731,8 @@ static struct task *spop_timeout_task(struct task *t, void *context, unsigned in
conn_delete_from_tree(spop_conn->conn); conn_delete_from_tree(spop_conn->conn);
HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock); HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
spop_conn_report_term_evt(spop_conn, muxc_tevt_type_tout);
} }
do_leave: do_leave:
@ -3234,6 +3304,7 @@ static size_t spop_snd_buf(struct stconn *sc, struct buffer *buf, size_t count,
if (spop_conn->state >= SPOP_CS_ERROR) { if (spop_conn->state >= SPOP_CS_ERROR) {
se_fl_set(spop_strm->sd, SE_FL_ERROR); se_fl_set(spop_strm->sd, SE_FL_ERROR);
se_report_term_evt(spop_strm->sd, se_tevt_type_snd_err);
TRACE_DEVEL("connection is in error, leaving in error", SPOP_EV_STRM_SEND|SPOP_EV_SPOP_STRM_ERR|SPOP_EV_STRM_ERR, TRACE_DEVEL("connection is in error, leaving in error", SPOP_EV_STRM_SEND|SPOP_EV_SPOP_STRM_ERR|SPOP_EV_STRM_ERR,
spop_conn->conn, spop_strm); spop_conn->conn, spop_strm);
return 0; return 0;
@ -3339,7 +3410,7 @@ static int spop_show_fd(struct buffer *msg, struct connection *conn)
tmbuf = br_tail(spop_conn->mbuf); tmbuf = br_tail(spop_conn->mbuf);
chunk_appendf(msg, " spop_conn.st0=%d .maxid=%d .flg=0x%04x .nbst=%u" chunk_appendf(msg, " spop_conn.st0=%d .maxid=%d .flg=0x%04x .nbst=%u"
" .nbcs=%u .send_cnt=%d .tree_cnt=%d .orph_cnt=%d .sub=%d " " .nbcs=%u .send_cnt=%d .tree_cnt=%d .orph_cnt=%d .sub=%d "
".dsi=%d .dbuf=%u@%p+%u/%u .mbuf=[%u..%u|%u],h=[%u@%p+%u/%u],t=[%u@%p+%u/%u]", ".dsi=%d .dbuf=%u@%p+%u/%u .mbuf=[%u..%u|%u],h=[%u@%p+%u/%u],t=[%u@%p+%u/%u] .evts=%s",
spop_conn->state, spop_conn->max_id, spop_conn->flags, spop_conn->state, spop_conn->max_id, spop_conn->flags,
spop_conn->nb_streams, spop_conn->nb_sc, send_cnt, tree_cnt, orph_cnt, spop_conn->nb_streams, spop_conn->nb_sc, send_cnt, tree_cnt, orph_cnt,
spop_conn->wait_event.events, spop_conn->dsi, spop_conn->wait_event.events, spop_conn->dsi,
@ -3349,7 +3420,8 @@ static int spop_show_fd(struct buffer *msg, struct connection *conn)
(unsigned int)b_data(hmbuf), b_orig(hmbuf), (unsigned int)b_data(hmbuf), b_orig(hmbuf),
(unsigned int)b_head_ofs(hmbuf), (unsigned int)b_size(hmbuf), (unsigned int)b_head_ofs(hmbuf), (unsigned int)b_size(hmbuf),
(unsigned int)b_data(tmbuf), b_orig(tmbuf), (unsigned int)b_data(tmbuf), b_orig(tmbuf),
(unsigned int)b_head_ofs(tmbuf), (unsigned int)b_size(tmbuf)); (unsigned int)b_head_ofs(tmbuf), (unsigned int)b_size(tmbuf),
tevt_evts2str(spop_conn->term_evts_log));
if (spop_strm) { if (spop_strm) {
chunk_appendf(msg, " last_spop_strm=%p .id=%d .flg=0x%04x .rxbuf=%u@%p+%u/%u .sc=%p", chunk_appendf(msg, " last_spop_strm=%p .id=%d .flg=0x%04x .rxbuf=%u@%p+%u/%u .sc=%p",
@ -3358,10 +3430,10 @@ static int spop_show_fd(struct buffer *msg, struct connection *conn)
(unsigned int)b_head_ofs(&spop_strm->rxbuf), (unsigned int)b_size(&spop_strm->rxbuf), (unsigned int)b_head_ofs(&spop_strm->rxbuf), (unsigned int)b_size(&spop_strm->rxbuf),
spop_strm_sc(spop_strm)); spop_strm_sc(spop_strm));
chunk_appendf(msg, " .sd.flg=0x%08x", se_fl_get(spop_strm->sd)); chunk_appendf(msg, " .sd.flg=0x%08x .sd.evts=%s", se_fl_get(spop_strm->sd), tevt_evts2str(spop_strm->sd->term_evts_log));
if (!se_fl_test(spop_strm->sd, SE_FL_ORPHAN)) if (!se_fl_test(spop_strm->sd, SE_FL_ORPHAN))
chunk_appendf(msg, " .sc.flg=0x%08x .sc.app=%p", chunk_appendf(msg, " .sc.flg=0x%08x .sc.app=%p .sc.evts=%s",
spop_strm_sc(spop_strm)->flags, spop_strm_sc(spop_strm)->app); spop_strm_sc(spop_strm)->flags, spop_strm_sc(spop_strm)->app, tevt_evts2str(spop_strm_sc(spop_strm)->term_evts_log));
chunk_appendf(msg, " .subs=%p", spop_strm->subs); chunk_appendf(msg, " .subs=%p", spop_strm->subs);
if (spop_strm->subs) { if (spop_strm->subs) {