Hi Willy,

Here are quite old pending patches I had to submit.

Thanks,
-- 
Christopher
>From a20ac171da06f16cb0bc1fb49cbf1939156cb2af Mon Sep 17 00:00:00 2001
From: Christopher Faulet <christopher.fau...@capflam.org>
Date: Tue, 21 Jun 2016 11:42:37 +0200
Subject: [PATCH 1/3] MEDIUM: filters: Add attch/detach and stream_set_backend
 callbacks

New callbacks have been added to handle creation and destruction of filter
instances:

* 'attach' callback is called after a filter instance creation, when it is
  attached to a stream. This happens when the stream is started for filters
  defined on the stream's frontend and when the backend is set for filters
  declared on the stream's backend. It is possible to ignore the filter, if
  needed, by returning 0. This could be useful to have conditional filtering.

* 'detach' callback is called when a filter instance is detached from a stream,
  before its destruction. This happens when the stream is stopped for filters
  defined on the stream's frontend and when the analyze ends for filters defined
  on the stream's backend.

In addition, the callback 'stream_set_backend' has been added to know when a
backend is set for a stream. It is only called when the frontend and the backend
are not the same. And it is called for all filters attached to a stream
(frontend and backend).

Finally, the TRACE filter has been updated.
---
 include/types/filters.h | 34 +++++++++++++++++++++++++++-------
 src/filters.c           | 27 ++++++++++++++++++++++++---
 src/flt_trace.c         | 48 ++++++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 97 insertions(+), 12 deletions(-)

diff --git a/include/types/filters.h b/include/types/filters.h
index 62fcfb1..62b457d 100644
--- a/include/types/filters.h
+++ b/include/types/filters.h
@@ -64,14 +64,32 @@ struct flt_kw_list {
  *                          number of errors encountered.
  *
  *
+ *  - attach              : Called after a filter instance creation, when it is
+ *                          attached to a stream. This happens when the stream
+ *                          is started for filters defined on the stream's
+ *                          frontend and when the backend is set for filters
+ *                          declared on the stream's backend.
+ *                          Returns a negative value if an error occurs, 0 if
+ *                          the filter must be ignored for the stream, any other
+ *                          value otherwise.
  *  - stream_start        : Called when a stream is started. This callback will
- *                          only be called for filters defined on a proxy with
- *                          the frontend capability.
+ *                          only be called for filters defined on the stream's
+ *                          frontend.
+ *                          Returns a negative value if an error occurs, any
+ *                          other value otherwise.
+ *  - stream_set_backend  : Called when a backend is set for a stream. This
+ *                          callbacks will be called for all filters attached
+ *                          to a stream (frontend and backend).
  *                          Returns a negative value if an error occurs, any
  *                          other value otherwise.
  *  - stream_stop         : Called when a stream is stopped. This callback will
- *                          only be called for filters defined on a proxy with
- *                          the frontend capability.
+ *                          only be called for filters defined on the stream's
+ *                          frontend.
+ *  - detach              : Called when a filter instance is detached from a
+ *                          stream, before its destruction. This happens when
+ *                          the stream is stopped for filters defined on the
+ *                          stream's frontend and when the analyze ends for
+ *                          filters defined on the stream's backend.
  *
  *
  *  - channel_start_analyze: Called when a filter starts to analyze a channel.
@@ -133,12 +151,14 @@ struct flt_ops {
 	int  (*init)  (struct proxy *p, struct flt_conf *fconf);
 	void (*deinit)(struct proxy *p, struct flt_conf *fconf);
 	int  (*check) (struct proxy *p, struct flt_conf *fconf);
-
 	/*
 	 * Stream callbacks
 	 */
-	int  (*stream_start)     (struct stream *s, struct filter *f);
-	void (*stream_stop)      (struct stream *s, struct filter *f);
+	int  (*attach)            (struct stream *s, struct filter *f);
+	int  (*stream_start)      (struct stream *s, struct filter *f);
+	int  (*stream_set_backend)(struct stream *s, struct filter *f, struct proxy *be);
+	void (*stream_stop)       (struct stream *s, struct filter *f);
+	void (*detach)            (struct stream *s, struct filter *f);
 
 	/*
 	 * Channel callbacks
diff --git a/src/filters.c b/src/filters.c
index 7f8fae4..a1b36ba 100644
--- a/src/filters.c
+++ b/src/filters.c
@@ -304,11 +304,21 @@ static int
 flt_stream_add_filter(struct stream *s, struct flt_conf *fconf, unsigned int flags)
 {
 	struct filter *f = pool_alloc2(pool2_filter);
+
 	if (!f) /* not enough memory */
 		return -1;
 	memset(f, 0, sizeof(*f));
 	f->config = fconf;
 	f->flags |= flags;
+
+	if (FLT_OPS(f)->attach) {
+		int ret = FLT_OPS(f)->attach(s, f);
+		if (ret <= 0) {
+			pool_free2(pool2_filter, f);
+			return ret;
+		}
+	}
+
 	LIST_ADDQ(&strm_flt(s)->filters, &f->list);
 	strm_flt(s)->flags |= STRM_FLT_FL_HAS_FILTERS;
 	return 0;
@@ -345,6 +355,8 @@ flt_stream_release(struct stream *s, int only_backend)
 
 	list_for_each_entry_safe(filter, back, &strm_flt(s)->filters, list) {
 		if (!only_backend || (filter->flags & FLT_FL_IS_BACKEND_FILTER)) {
+			if (FLT_OPS(filter)->detach)
+				FLT_OPS(filter)->detach(s, filter);
 			LIST_DEL(&filter->list);
 			pool_free2(pool2_filter, filter);
 		}
@@ -387,21 +399,30 @@ flt_stream_stop(struct stream *s)
 
 /*
  * Called when a backend is set for a stream. If the frontend and the backend
- * are the same, this function does nothing. Else it attaches all backend
- * filters to the stream. Returns -1 if an error occurs, 0 otherwise.
+ * are not the same, this function attaches all backend filters to the
+ * stream. Returns -1 if an error occurs, 0 otherwise.
  */
 int
 flt_set_stream_backend(struct stream *s, struct proxy *be)
 {
 	struct flt_conf *fconf;
+	struct filter   *filter;
 
 	if (strm_fe(s) == be)
-		return 0;
+		goto end;
 
 	list_for_each_entry(fconf, &be->filter_configs, list) {
 		if (flt_stream_add_filter(s, fconf, FLT_FL_IS_BACKEND_FILTER) < 0)
 			return -1;
 	}
+
+  end:
+	list_for_each_entry(filter, &strm_flt(s)->filters, list) {
+		if (FLT_OPS(filter)->stream_set_backend &&
+		    FLT_OPS(filter)->stream_set_backend(s, filter, be) < 0)
+			return -1;
+	}
+
 	return 0;
 }
 
diff --git a/src/flt_trace.c b/src/flt_trace.c
index a052ab5..ce3bf5c 100644
--- a/src/flt_trace.c
+++ b/src/flt_trace.c
@@ -66,6 +66,12 @@ stream_pos(const struct stream *s)
 	return (s->flags & SF_BE_ASSIGNED) ? "backend" : "frontend";
 }
 
+static const char *
+filter_type(const struct filter *f)
+{
+	return (f->flags & FLT_FL_IS_BACKEND_FILTER) ? "backend" : "frontend";
+}
+
 /***************************************************************************
  * Hooks that manage the filter lifecycle (init/check/deinit)
  **************************************************************************/
@@ -111,6 +117,28 @@ trace_check(struct proxy *px, struct flt_conf *fconf)
 /**************************************************************************
  * Hooks to handle start/stop of streams
  *************************************************************************/
+/* Called when a filter instance is created and attach to a stream */
+static int
+trace_attach(struct stream *s, struct filter *filter)
+{
+	struct trace_config *conf = FLT_CONF(filter);
+
+	STRM_TRACE(conf, s, "%-25s: filter-type=%s",
+		   __FUNCTION__, filter_type(filter));
+	return 1;
+}
+
+/* Called when a filter instance is detach from a stream, just before its
+ * destruction */
+static void
+trace_detach(struct stream *s, struct filter *filter)
+{
+	struct trace_config *conf = FLT_CONF(filter);
+
+	STRM_TRACE(conf, s, "%-25s: filter-type=%s",
+		   __FUNCTION__, filter_type(filter));
+}
+
 /* Called when a stream is created */
 static int
 trace_stream_start(struct stream *s, struct filter *filter)
@@ -122,6 +150,19 @@ trace_stream_start(struct stream *s, struct filter *filter)
 	return 0;
 }
 
+
+/* Called when a backend is set for a stream */
+static int
+trace_stream_set_backend(struct stream *s, struct filter *filter,
+			 struct proxy *be)
+{
+	struct trace_config *conf = FLT_CONF(filter);
+
+	STRM_TRACE(conf, s, "%-25s: backend=%s",
+		   __FUNCTION__, be->id);
+	return 0;
+}
+
 /* Called when a stream is destroyed */
 static void
 trace_stream_stop(struct stream *s, struct filter *filter)
@@ -410,8 +451,11 @@ struct flt_ops trace_ops = {
 	.check  = trace_check,
 
 	/* Handle start/stop of streams */
-	.stream_start = trace_stream_start,
-	.stream_stop  = trace_stream_stop,
+	.attach             = trace_attach,
+	.detach             = trace_detach,
+	.stream_start       = trace_stream_start,
+	.stream_set_backend = trace_stream_set_backend,
+	.stream_stop        = trace_stream_stop,
 
 	/* Handle channels activity */
 	.channel_start_analyze = trace_chn_start_analyze,
-- 
2.7.4

>From ae5fbb2797e6e1abe085cf3d2172558e9fdee335 Mon Sep 17 00:00:00 2001
From: Christopher Faulet <christopher.fau...@capflam.org>
Date: Tue, 21 Jun 2016 11:50:49 +0200
Subject: [PATCH 2/3] MINOR: filters: Update filters documentation accordingly
 to recent changes

---
 doc/internals/filters.txt | 200 ++++++++++++++++++++++++++++++++--------------
 1 file changed, 140 insertions(+), 60 deletions(-)

diff --git a/doc/internals/filters.txt b/doc/internals/filters.txt
index a89abb4..7e949a9 100644
--- a/doc/internals/filters.txt
+++ b/doc/internals/filters.txt
@@ -1,6 +1,6 @@
                    -----------------------------------------
                           Filters Guide - version 1.7
-                          ( Last update: 2016-05-11 )
+                          ( Last update: 2016-06-21 )
                    ------------------------------------------
                           Author : Christopher Faulet
               Contact : christopher dot faulet at capflam dot org
@@ -33,7 +33,7 @@ SUMMARY
   3.1.      API Overview
   3.2.      Defining the filter name and its configuration
   3.3.      Managing the filter lifecycle
-  3.4.      Handling the streams creation and desctruction
+  3.4.      Handling the streams activity
   3.5.      Analyzing the channels activity
   3.6.      Filtering the data exchanged
   4.    FAQ
@@ -186,8 +186,11 @@ existing callbacks. Available callbacks are listed in the following structure:
         /*
          * Stream callbacks
          */
-        int  (*stream_start)     (struct stream *s, struct filter *f);
-        void (*stream_stop)      (struct stream *s, struct filter *f);
+        int  (*attach)            (struct stream *s, struct filter *f);
+        int  (*stream_start)      (struct stream *s, struct filter *f);
+        int  (*stream_set_backend)(struct stream *s, struct filter *f, struct proxy *be);
+        void (*stream_stop)       (struct stream *s, struct filter *f);
+        void (*detach)            (struct stream *s, struct filter *f);
 
         /*
          * Channel callbacks
@@ -510,17 +513,23 @@ TODO: Add callbacks to handle creation/destruction of filter instances. And
       document it.
 
 
-3.4. HANDLING THE STREAMS CREATION AND DESCTRUCTION
----------------------------------------------------
+3.4. HANDLING THE STREAMS ACTIVITY
+-----------------------------------
 
-You may be interessted to handle stream creation and destruction. If so, you
-must define followings callbacks:
+You may be interessted to handle streams activity. For now, there is three
+callbacks that you should define to do so:
 
   * 'flt_ops.stream_start': It is called when a stream is started. This callback
                             can fail by returning a negative value. It will be
                             considered as a critical error by HAProxy which
                             disabled the listener for a short time.
 
+  * 'flt_ops.stream_set_backend': It is called when a backend is set for a
+                                  stream. This callbacks will be called for all
+                                  filters attached to a stream (frontend and
+                                  backend). Note this callback is not called if
+                                  the frontend and the backend are the same.
+
   * 'flt_ops.stream_stop': It is called when a stream is stopped. This callback
                            always succeed. Anyway, it is too late to return an
                            error.
@@ -538,6 +547,18 @@ For example:
          return 0;
     }
 
+    /* Called when a backend is set for a stream */
+    static int
+    my_filter_stream_set_backend(struct stream *s, struct filter *filter,
+                                 struct proxy *be)
+    {
+         struct my_filter_config *my_conf = FLT_CONF(filter);
+
+        /* ... */
+
+        return 0;
+    }
+
     /* Called when a stream is destroyed */
     static void
     my_filter_stream_stop(struct stream *s, struct filter *filter)
@@ -551,6 +572,45 @@ For example:
 WARNING: Handling the streams creation and destuction is only possible for
          filters defined on proxies with the frontend capability.
 
+In addition, it is possible to handle creation and destruction of filter
+instances using following callbacks:
+
+  * 'flt_ops.attach': It is called after a filter instance creation, when it is
+                      attached to a stream. This happens when the stream is
+                      started for filters defined on the stream's frontend and
+                      when the backend is set for filters declared on the
+                      stream's backend. It is possible to ignore the filter, if
+                      needed, by returning 0. This could be useful to have
+                      conditional filtering.
+
+  * 'flt_ops.detach': It is called when a filter instance is detached from a
+                      stream, before its destruction. This happens when the
+                      stream is stopped for filters defined on the stream's
+                      frontend and when the analyze ends for filters defined on
+                      the stream's backend.
+
+For example:
+
+    /* Called when a filter instance is created and attach to a stream */
+    static int
+    my_filter_attach(struct stream *s, struct filter *filter)
+    {
+        struct my_filter_config *my_conf = FLT_CONF(filter);
+
+        if (/* ... */)
+            return 0; /* Ignore the filter here */
+        return 1;
+    }
+
+    /* Called when a filter instance is detach from a stream, just before its
+     * destruction */
+    static void
+    my_filter_detach(struct stream *s, struct filter *filter)
+    {
+        struct my_filter_config *my_conf = FLT_CONF(filter);
+
+        /* ... */
+    }
 
 3.5. ANALYZING THE CHANNELS ACTIVITY
 ------------------------------------
@@ -727,58 +787,78 @@ example:
 
 Workflow on channels can be summarized as following:
 
-                |
-     +----------+-----------+
-     | flt_ops.stream_start |
-     +----------+-----------+
-                |
-               ...
-                |
-                +-<-- [1]                 +------->---------+
-                |                 --+     |                 |                 --+
-                +------<----------+ |     |                 +--------<--------+ |
-                |                 | |     |                 |                 | |
-                V                 | |     |                 V                 | |
-+-------------------------------+ | |     | +-------------------------------+ | |
-|      flt_start_analyze        +-+ |     | |      flt_start_analyze        +-+ |
-|(flt_ops.channel_start_analyze)|   | F   | |(flt_ops.channel_start_analyze)|   |
-+---------------+---------------+   | R   | +---------------+---------------+   |
-                |                   | O   |                 |                   |
-                +------<---------+  | N   ^                 +--------<-------+  | B
-                |                |  | T   |                 |                |  | A
-+---------------+------------+   |  | E   | +---------------+------------+   |  | C
-|+--------------V-------------+  |  | N   | |+--------------V-------------+  |  | K
-||+----------------------------+ |  | D   | ||+----------------------------+ |  | E
-|||flt_ops.channel_pre_analyze | |  |     | |||flt_ops.channel_pre_analyze | |  | N
-|||             V              | |  |     | |||             V              | |  | D
-|||          analyzer          +-+  |     | |||          analyzer          +-+  |
-+||             V              |    |     | +||             V              |    |
- +|flt_ops.channel_post_analyze|    |     |  +|flt_ops.channel_post_analyze|    |
-  +-------------+--------------+    |     |   +-------------+--------------+    |
-                |                 --+     |                 |                   |
-                +------------>------------+                ...                  |
-                                                            |                   |
-                                                [ data filtering (see below) ]  |
-                                                            |                   |
-                                                           ...                  |
-                                                            |                   |
-                                                            +--------<--------+ |
-                                                            |                 | |
-                                                            V                 | |
-                                            +-------------------------------+ | |
-                                            |       flt_end_analyze         +-+ |
-                                            | (flt_ops.channel_end_analyze) |   |
-                                            +---------------+---------------+   |
-                                                            |                 --+
-                        If HTTP stream, go back to [1] --<--+
-                                                            |
-                                                           ...
-                                                            |
-                                                 +----------+-----------+
-                                                 | flt_ops.stream_stop  |
-                                                 +----------+-----------+
-                                                            |
-                                                            V
+   FE: Called for filters defined on the stream's frontend
+   BE: Called for filters defined on the stream's backend
+
+                                          +------->---------+
+                |                         |                 |
+    +----------------------+              |      +----------------------+
+    |  flt_ops.attach (FE) |              |      |  flt_ops.attach (BE) |
+    +----------------------+              |      +----------------------+
+                |                         |                  |
+                V                         |                  V
+  +--------------------------+            | +------------------------------------+
+  | flt_ops.stream_start (FE)|            | | flt_ops.stream_set_backend (FE+BE) |
+  +--------------------------+            | +------------------------------------+
+                |                         |                  |
+               ...                        |                 ...
+                |                         |                  |
+                +-<-- [1]                 ^                  |
+                |                 --+     |                  |                 --+
+                +------<----------+ |     |                  +--------<--------+ |
+                |                 | |     |                  |                 | |
+                V                 | |     |                  V                 | |
++-------------------------------+ | |     |  +-------------------------------+ | |
+|      flt_start_analyze (FE)   +-+ |     |  |      flt_start_analyze (BE)   +-+ |
+|(flt_ops.channel_start_analyze)|   | F   |  |(flt_ops.channel_start_analyze)|   |
++---------------+---------------+   | R   |  +-------------------------------+   |
+                |                   | O   |                  |                   |
+                +------<---------+  | N   ^                  +--------<-------+  | B
+                |                |  | T   |                  |                |  | A
++---------------|------------+   |  | E   |  +---------------|------------+   |  | C
+|+--------------V-------------+  |  | N   |  |+--------------V-------------+  |  | K
+||+----------------------------+ |  | D   |  ||+----------------------------+ |  | E
+|||flt_ops.channel_pre_analyze | |  |     |  |||flt_ops.channel_pre_analyze | |  | N
+|||             V              | |  |     |  |||             V              | |  | D
+|||        analyzer (FE)       +-+  |     |  |||     analyzer (FE+BE)       +-+  |
++||             V              |    |     |  +||             V              |    |
+ +|flt_ops.channel_post_analyze|    |     |   +|flt_ops.channel_post_analyze|    |
+  +----------------------------+    |     |    +----------------------------+    |
+                |                 --+     |                  |                   |
+                +------------>------------+                 ...                  |
+                                                             |                   |
+                                                 [ data filtering (see below) ]  |
+                                                             |                   |
+                                                            ...                  |
+                                                             |                   |
+                                                             +--------<--------+ |
+                                                             |                 | |
+                                                             V                 | |
+                                             +-------------------------------+ | |
+                                             |    flt_end_analyze (FE+BE)    +-+ |
+                                             | (flt_ops.channel_end_analyze) |   |
+                                             +---------------+---------------+   |
+                                                             |                 --+
+                                                             V
+                                                  +----------------------+
+                                                  |  flt_ops.detach (BE) |
+                                                  +----------------------+
+                                                             |
+                         If HTTP stream, go back to [1] --<--+
+                                                             |
+                                                            ...
+                                                             |
+                                                             V
+                                                 +--------------------------+
+                                                 | flt_ops.stream_stop (FE) |
+                                                 +--------------------------+
+                                                              |
+                                                              V
+                                                   +----------------------+
+                                                   |  flt_ops.detach (FE) |
+                                                   +----------------------+
+                                                              |
+                                                              V
 
 By zooming on an analyzer box we have:
 
-- 
2.7.4

>From acd3cbe98778d10cd4a753631163ade700148334 Mon Sep 17 00:00:00 2001
From: Christopher Faulet <christopher.fau...@capflam.org>
Date: Tue, 21 Jun 2016 11:54:52 +0200
Subject: [PATCH 3/3] MINOR: filters: Call stream_set_backend callbacks before
 updating backend stats

So if an internal error is returned, the number of cumulated connections on the
backend is not incremented.
---
 src/proxy.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/src/proxy.c b/src/proxy.c
index b90773f..33ffc4c 100644
--- a/src/proxy.c
+++ b/src/proxy.c
@@ -1132,15 +1132,16 @@ int stream_set_backend(struct stream *s, struct proxy *be)
 {
 	if (s->flags & SF_BE_ASSIGNED)
 		return 1;
+
+	if (flt_set_stream_backend(s, be) < 0)
+		return 0;
+
 	s->be = be;
 	be->beconn++;
 	if (be->beconn > be->be_counters.conn_max)
 		be->be_counters.conn_max = be->beconn;
 	proxy_inc_be_ctr(be);
 
-	if (flt_set_stream_backend(s, be) < 0)
-		return 0;
-
 	/* assign new parameters to the stream from the new backend */
 	s->si[1].flags &= ~SI_FL_INDEP_STR;
 	if (be->options2 & PR_O2_INDEPSTR)
-- 
2.7.4

Reply via email to