]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: stream: Save the last filter evaluated interrupting the processing
authorChristopher Faulet <cfaulet@haproxy.com>
Thu, 31 Oct 2024 10:30:46 +0000 (11:30 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Thu, 31 Oct 2024 15:39:04 +0000 (16:39 +0100)
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.

include/haproxy/stream-t.h
src/filters.c
src/stream.c

index 9589c304842b738f277aabee5e7fb13fa0e5645b..0cd9baba53f856f71de063a390da399c3a1b121e 100644 (file)
@@ -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 */
index e650a08996806da626584d5e1f30077baee6e7d6..45bfa12a67c4e82495588dc4b8c163bf54e12d70 100644 (file)
@@ -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;
                }
index 618f350f73b365d59406e25725dab5d094e3a9f4..e015b97bf9ab463e5484a9a33a6afc7e81e54dd5 100644 (file)
@@ -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;