From: Christopher Faulet Date: Thu, 31 Oct 2024 10:30:46 +0000 (+0100) Subject: MINOR: stream: Save the last filter evaluated interrupting the processing X-Git-Tag: v3.1-dev11~6 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=53de6da1c097549615df59966ec984b6a50b15d0;p=thirdparty%2Fhaproxy.git MINOR: stream: Save the last filter evaluated interrupting the processing It is very similar to the last evaluated rule. When a filter returns an error that interrupts the processing, it is saved in the stream, in the last_entity field, with the type 2. The pointer on filter config is saved. This pointer never changes during runtime and is part of the proxy's structure. It is an element of the filter_configs list in the proxy structure. "last_entity" sample fetch was update accordingly. The filter identifier is returned, if defined. Otherwise the save pointer. --- diff --git a/include/haproxy/stream-t.h b/include/haproxy/stream-t.h index 9589c30484..0cd9baba53 100644 --- a/include/haproxy/stream-t.h +++ b/include/haproxy/stream-t.h @@ -292,7 +292,7 @@ struct stream { struct { void *ptr; /* Pointer on the entity (def: NULL) */ - int type; /* entity type (0: undef, 1: rule) */ + int type; /* entity type (0: undef, 1: rule, 2: filter) */ } last_entity; /* last evaluated entity that interrupted processing */ unsigned int stream_epoch; /* copy of stream_epoch when the stream was created */ diff --git a/src/filters.c b/src/filters.c index e650a08996..45bfa12a67 100644 --- a/src/filters.c +++ b/src/filters.c @@ -72,7 +72,11 @@ static int handle_analyzer_result(struct stream *s, struct channel *chn, unsigne #define BREAK_EXECUTION(strm, chn, label) \ do { \ - strm_flt(strm)->current[CHN_IDX(chn)] = filter; \ + if (ret < 0) { \ + (strm)->last_entity.type = 2; \ + (strm)->last_entity.ptr = filter; \ + } \ + strm_flt(strm)->current[CHN_IDX(chn)] = filter; \ goto label; \ } while (0) @@ -556,8 +560,11 @@ flt_set_stream_backend(struct stream *s, struct proxy *be) list_for_each_entry(filter, &strm_flt(s)->filters, list) { if (FLT_OPS(filter)->stream_set_backend) { filter->calls++; - if (FLT_OPS(filter)->stream_set_backend(s, filter, be) < 0) + if (FLT_OPS(filter)->stream_set_backend(s, filter, be) < 0) { + s->last_entity.type = 2; + s->last_entity.ptr = filter; return -1; + } } } if (be->be_req_ana & AN_REQ_FLT_START_BE) { @@ -693,8 +700,11 @@ flt_http_payload(struct stream *s, struct http_msg *msg, unsigned int len) DBG_TRACE_DEVEL(FLT_ID(filter), STRM_EV_HTTP_ANA|STRM_EV_FLT_ANA, s); filter->calls++; ret = FLT_OPS(filter)->http_payload(s, filter, msg, out + offset, data - offset); - if (ret < 0) + if (ret < 0) { + s->last_entity.type = 2; + s->last_entity.ptr = filter; goto end; + } data = ret + *flt_off - *strm_off; *flt_off += ret; } @@ -832,8 +842,11 @@ flt_post_analyze(struct stream *s, struct channel *chn, unsigned int an_bit) DBG_TRACE_DEVEL(FLT_ID(filter), STRM_EV_FLT_ANA, s); filter->calls++; ret = FLT_OPS(filter)->channel_post_analyze(s, filter, chn, an_bit); - if (ret < 0) + if (ret < 0) { + s->last_entity.type = 2; + s->last_entity.ptr = filter; break; + } filter->post_analyzers &= ~an_bit; } } @@ -986,8 +999,11 @@ flt_tcp_payload(struct stream *s, struct channel *chn, unsigned int len) DBG_TRACE_DEVEL(FLT_ID(filter), STRM_EV_TCP_ANA|STRM_EV_FLT_ANA, s); filter->calls++; ret = FLT_OPS(filter)->tcp_payload(s, filter, chn, out + offset, data - offset); - if (ret < 0) + if (ret < 0) { + s->last_entity.type = 2; + s->last_entity.ptr = filter; goto end; + } data = ret + *flt_off - *strm_off; *flt_off += ret; } diff --git a/src/stream.c b/src/stream.c index 618f350f73..e015b97bf9 100644 --- a/src/stream.c +++ b/src/stream.c @@ -4137,6 +4137,21 @@ static int smp_fetch_last_entity(const struct arg *args, struct sample *smp, con trash->data = snprintf(trash->area, trash->size, "%s:%d", rule->conf.file, rule->conf.line); smp->data.u.str = *trash; } + else if (smp->strm->last_entity.type == 2) { + struct filter *filter = smp->strm->last_entity.ptr; + + if (FLT_ID(filter)) { + smp->flags |= SMP_F_CONST; + smp->data.u.str.area = (char *)FLT_ID(filter); + smp->data.u.str.data = strlen(FLT_ID(filter)); + } + else { + struct buffer *trash = get_trash_chunk(); + + trash->data = snprintf(trash->area, trash->size, "%p", filter->config); + smp->data.u.str = *trash; + } + } else return 0;