blob: 6c931fadd10632d5e5757f9f361767b579c7936d [file] [log] [blame]
Miroslav Zagorac70230c62020-12-09 16:54:31 +01001/***
2 * Copyright 2020 HAProxy Technologies
3 *
4 * This file is part of the HAProxy OpenTracing filter.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
20#include "include.h"
21
22
23/*
24 * OpenTracing filter id, used to identify OpenTracing filters.
25 * The name of this variable is consistent with the other filter names
26 * declared in include/haproxy/filters.h .
27 */
28const char *ot_flt_id = "the OpenTracing filter";
29
30
31/***
32 * NAME
33 * flt_ot_is_disabled -
34 *
35 * ARGUMENTS
36 * f -
37 * event -
38 *
39 * DESCRIPTION
40 * -
41 *
42 * RETURN VALUE
43 * -
44 */
45bool flt_ot_is_disabled(const struct filter *f FLT_OT_DBG_ARGS(, int event))
46{
47#ifdef DEBUG_OT
48 const struct flt_ot_conf *conf = FLT_OT_CONF(f);
49 const char *msg;
50#endif
51 bool retval;
52
53 retval = FLT_OT_RT_CTX(f->ctx)->flag_disabled ? 1 : 0;
54
55#ifdef DEBUG_OT
56 msg = retval ? " (disabled)" : "";
57
58 if (FLT_OT_IN_RANGE(event, 0, FLT_OT_EVENT_MAX - 1))
59 FLT_OT_DBG(2, "filter '%s', type: %s, event: '%s' %d%s", conf->id, flt_ot_type(f), flt_ot_event_data[event].name, event, msg);
60 else
61 FLT_OT_DBG(2, "filter '%s', type: %s%s", conf->id, flt_ot_type(f), msg);
62#endif
63
64 return retval;
65}
66
67
68/***
69 * NAME
70 * flt_ot_return_int -
71 *
72 * ARGUMENTS
73 * f -
74 * err -
75 * retval -
76 *
77 * DESCRIPTION
78 * -
79 *
80 * RETURN VALUE
81 * -
82 */
83static int flt_ot_return_int(const struct filter *f, char **err, int retval)
84{
85 struct flt_ot_runtime_context *rt_ctx = f->ctx;
86
87 if ((retval == FLT_OT_RET_ERROR) || ((err != NULL) && (*err != NULL))) {
88 if (rt_ctx->flag_harderr) {
89 FLT_OT_DBG(1, "WARNING: filter hard-error (disabled)");
90
91 rt_ctx->flag_disabled = 1;
92
93 _HA_ATOMIC_ADD(FLT_OT_CONF(f)->cnt.disabled + 1, 1);
94 } else {
95 FLT_OT_DBG(1, "WARNING: filter soft-error");
96 }
97
98 retval = FLT_OT_RET_OK;
99 }
100
101 FLT_OT_ERR_FREE(*err);
102
103 return retval;
104}
105
106
107/***
108 * NAME
109 * flt_ot_return_void -
110 *
111 * ARGUMENTS
112 * f -
113 * err -
114 *
115 * DESCRIPTION
116 * -
117 *
118 * RETURN VALUE
119 * This function does not return a value.
120 */
121static void flt_ot_return_void(const struct filter *f, char **err)
122{
123 struct flt_ot_runtime_context *rt_ctx = f->ctx;
124
125 if ((err != NULL) && (*err != NULL)) {
126 if (rt_ctx->flag_harderr) {
127 FLT_OT_DBG(1, "WARNING: filter hard-error (disabled)");
128
129 rt_ctx->flag_disabled = 1;
130
131 _HA_ATOMIC_ADD(FLT_OT_CONF(f)->cnt.disabled + 1, 1);
132 } else {
133 FLT_OT_DBG(1, "WARNING: filter soft-error");
134 }
135 }
136
137 FLT_OT_ERR_FREE(*err);
138}
139
140
141/***
142 * NAME
143 * flt_ot_init - Initialize the filter.
144 *
145 * ARGUMENTS
146 * p -
147 * fconf -
148 *
149 * DESCRIPTION
150 * It initializes the filter for a proxy. You may define this callback
151 * if you need to complete your filter configuration.
152 *
153 * RETURN VALUE
154 * Returns a negative value if an error occurs, any other value otherwise.
155 */
156static int flt_ot_init(struct proxy *p, struct flt_conf *fconf)
157{
158 struct flt_ot_conf *conf = FLT_OT_DEREF(fconf, conf, NULL);
Miroslav Zagorac66f09a42021-06-10 01:19:13 +0200159 char *err = NULL;
160 int retval = FLT_OT_RET_ERROR;
Miroslav Zagorac70230c62020-12-09 16:54:31 +0100161
162 FLT_OT_FUNC("%p, %p", p, fconf);
163
164 if (conf == NULL)
Miroslav Zagorac5b5b0622022-03-04 09:56:00 +0100165 FLT_OT_RETURN_INT(retval);
Miroslav Zagorac70230c62020-12-09 16:54:31 +0100166
167 flt_ot_cli_init();
168
Miroslav Zagorac66f09a42021-06-10 01:19:13 +0200169 /*
170 * Initialize the OpenTracing library.
Miroslav Zagorac66f09a42021-06-10 01:19:13 +0200171 */
Miroslav Zagoracfcf4e3d2021-06-10 01:23:15 +0200172 retval = ot_init(&(conf->tracer->tracer), conf->tracer->plugin, &err);
Miroslav Zagorac66f09a42021-06-10 01:19:13 +0200173 if (retval != FLT_OT_RET_ERROR)
Miroslav Zagoracfcf4e3d2021-06-10 01:23:15 +0200174 /* Do nothing. */;
Miroslav Zagorac66f09a42021-06-10 01:19:13 +0200175 else if (err != NULL) {
176 FLT_OT_ALERT("%s", err);
177
178 FLT_OT_ERR_FREE(err);
179 }
180
Miroslav Zagorac5b5b0622022-03-04 09:56:00 +0100181 FLT_OT_RETURN_INT(retval);
Miroslav Zagorac70230c62020-12-09 16:54:31 +0100182}
183
184
185/***
186 * NAME
187 * flt_ot_deinit - Free resources allocated by the filter.
188 *
189 * ARGUMENTS
190 * p -
191 * fconf -
192 *
193 * DESCRIPTION
194 * It cleans up what the parsing function and the init callback have done.
195 * This callback is useful to release memory allocated for the filter
196 * configuration.
197 *
198 * RETURN VALUE
199 * This function does not return a value.
200 */
201static void flt_ot_deinit(struct proxy *p, struct flt_conf *fconf)
202{
203 struct flt_ot_conf **conf = (fconf == NULL) ? NULL : (typeof(conf))&(fconf->conf);
204#ifdef DEBUG_OT
205 int i;
206#endif
207
208 FLT_OT_FUNC("%p, %p", p, fconf);
209
210 if (conf == NULL)
211 FLT_OT_RETURN();
212
213 ot_debug();
214 ot_close(&((*conf)->tracer->tracer));
215
216#ifdef DEBUG_OT
217 FLT_OT_DBG(0, "--- used events ----------");
218 for (i = 0; i < FLT_OT_TABLESIZE((*conf)->cnt.event); i++)
219 if ((*conf)->cnt.event[i].flag_used)
220 FLT_OT_DBG(0, " %02d: %" PRIu64 " / %" PRIu64, i, (*conf)->cnt.event[i].htx[0], (*conf)->cnt.event[i].htx[1]);
221#endif
222
223 flt_ot_conf_free(conf);
224
225 FLT_OT_MEMINFO();
226
227 FLT_OT_RETURN();
228}
229
230
231/***
232 * NAME
233 * flt_ot_check - Check configuration of the filter for the specified proxy.
234 *
235 * ARGUMENTS
236 * p -
237 * fconf -
238 *
239 * DESCRIPTION
240 * Optionally, by implementing the flt_ot_check() callback, you add a
241 * step to check the internal configuration of your filter after the
242 * parsing phase, when the HAProxy configuration is fully defined.
243 *
244 * RETURN VALUE
245 * Returns the number of encountered errors.
246 */
247static int flt_ot_check(struct proxy *p, struct flt_conf *fconf)
248{
249 struct proxy *px;
250 struct flt_ot_conf *conf = FLT_OT_DEREF(fconf, conf, NULL);
251 struct flt_ot_conf_group *conf_group;
252 struct flt_ot_conf_scope *conf_scope;
253 struct flt_ot_conf_ph *ph_group, *ph_scope;
254 int retval = 0, scope_unused_cnt = 0, span_root_cnt = 0;
255
256 FLT_OT_FUNC("%p, %p", p, fconf);
257
258 if (conf == NULL)
Miroslav Zagorac5b5b0622022-03-04 09:56:00 +0100259 FLT_OT_RETURN_INT(++retval);
Miroslav Zagorac70230c62020-12-09 16:54:31 +0100260
261 /*
262 * If only the proxy specified with the <p> parameter is checked, then
263 * no duplicate filters can be found that are not defined in the same
264 * configuration sections.
265 */
266 for (px = proxies_list; px != NULL; px = px->next) {
267 struct flt_conf *fconf_tmp;
268
269 FLT_OT_DBG(2, "proxy '%s'", px->id);
270
271 /*
272 * The names of all OT filters (filter ID) should be checked,
273 * they must be unique.
274 */
275 list_for_each_entry(fconf_tmp, &(px->filter_configs), list)
276 if ((fconf_tmp != fconf) && (fconf_tmp->id == ot_flt_id)) {
277 struct flt_ot_conf *conf_tmp = fconf_tmp->conf;
278
279 FLT_OT_DBG(2, " OT filter '%s'", conf_tmp->id);
280
281 if (strcmp(conf_tmp->id, conf->id) == 0) {
282 FLT_OT_ALERT("''%s' : duplicated filter ID'", conf_tmp->id);
283
284 retval++;
285 }
286 }
287 }
288
289 if (FLT_OT_DEREF(conf->tracer, id, NULL) == NULL) {
290 FLT_OT_ALERT("''%s' : no tracer found'", conf->id);
291
292 retval++;
293 }
294
295 /*
296 * Checking that all defined 'ot-group' sections have correctly declared
297 * 'ot-scope' sections (ie whether the declared 'ot-scope' sections have
298 * corresponding definitions).
299 */
300 list_for_each_entry(conf_group, &(conf->groups), list)
301 list_for_each_entry(ph_scope, &(conf_group->ph_scopes), list) {
302 bool flag_found = 0;
303
304 list_for_each_entry(conf_scope, &(conf->scopes), list)
305 if (strcmp(ph_scope->id, conf_scope->id) == 0) {
306 ph_scope->ptr = conf_scope;
307 conf_scope->flag_used = 1;
308 flag_found = 1;
309
310 break;
311 }
312
313 if (!flag_found) {
314 FLT_OT_ALERT("'" FLT_OT_PARSE_SECTION_GROUP_ID " '%s' : try to use undefined " FLT_OT_PARSE_SECTION_SCOPE_ID " '%s''", conf_group->id, ph_scope->id);
315
316 retval++;
317 }
318 }
319
320 if (conf->tracer != NULL) {
321 /*
322 * Checking that all declared 'groups' keywords have correctly
323 * defined 'ot-group' sections.
324 */
325 list_for_each_entry(ph_group, &(conf->tracer->ph_groups), list) {
326 bool flag_found = 0;
327
328 list_for_each_entry(conf_group, &(conf->groups), list)
329 if (strcmp(ph_group->id, conf_group->id) == 0) {
330 ph_group->ptr = conf_group;
331 conf_group->flag_used = 1;
332 flag_found = 1;
333
334 break;
335 }
336
337 if (!flag_found) {
338 FLT_OT_ALERT("'" FLT_OT_PARSE_SECTION_TRACER_ID " '%s' : try to use undefined " FLT_OT_PARSE_SECTION_GROUP_ID " '%s''", conf->tracer->id, ph_group->id);
339
340 retval++;
341 }
342 }
343
344 /*
345 * Checking that all declared 'scopes' keywords have correctly
346 * defined 'ot-scope' sections.
347 */
348 list_for_each_entry(ph_scope, &(conf->tracer->ph_scopes), list) {
349 bool flag_found = 0;
350
351 list_for_each_entry(conf_scope, &(conf->scopes), list)
352 if (strcmp(ph_scope->id, conf_scope->id) == 0) {
353 ph_scope->ptr = conf_scope;
354 conf_scope->flag_used = 1;
355 flag_found = 1;
356
357 break;
358 }
359
360 if (!flag_found) {
361 FLT_OT_ALERT("'" FLT_OT_PARSE_SECTION_TRACER_ID " '%s' : try to use undefined " FLT_OT_PARSE_SECTION_SCOPE_ID " '%s''", conf->tracer->id, ph_scope->id);
362
363 retval++;
364 }
365 }
366 }
367
368 FLT_OT_DBG(3, "--- filter '%s' configuration ----------", conf->id);
369 FLT_OT_DBG(3, "- defined spans ----------");
370
371 list_for_each_entry(conf_scope, &(conf->scopes), list) {
372 if (conf_scope->flag_used) {
373 struct flt_ot_conf_span *conf_span;
374
375 /*
376 * In principle, only one span should be labeled
377 * as a root span.
378 */
379 list_for_each_entry(conf_span, &(conf_scope->spans), list) {
380 FLT_OT_DBG_CONF_SPAN(" ", conf_span);
381
382 span_root_cnt += conf_span->flag_root ? 1 : 0;
383 }
384
385#ifdef DEBUG_OT
386 conf->cnt.event[conf_scope->event].flag_used = 1;
387#endif
388
389 /* Set the flags of the analyzers used. */
390 conf->tracer->analyzers |= flt_ot_event_data[conf_scope->event].an_bit;
391 } else {
392 FLT_OT_ALERT("''%s' : unused " FLT_OT_PARSE_SECTION_SCOPE_ID " '%s''", conf->id, conf_scope->id);
393
394 scope_unused_cnt++;
395 }
396 }
397
398 /*
399 * Unused scopes or a number of root spans other than one do not
400 * necessarily have to be errors, but it is good to print it when
401 * starting HAProxy.
402 */
403 if (scope_unused_cnt > 0)
404 FLT_OT_ALERT("''%s' : %d scope(s) not in use'", conf->id, scope_unused_cnt);
405
406 if (LIST_ISEMPTY(&(conf->scopes)))
407 /* Do nothing. */;
408 else if (span_root_cnt == 0)
409 FLT_OT_ALERT("''%s' : no span is marked as the root span'", conf->id);
410 else if (span_root_cnt > 1)
411 FLT_OT_ALERT("''%s' : multiple spans are marked as the root span'", conf->id);
412
413 FLT_OT_DBG_LIST(conf, group, "", "defined", _group,
414 FLT_OT_DBG_CONF_GROUP(" ", _group);
415 FLT_OT_DBG_LIST(_group, ph_scope, " ", "used", _scope, FLT_OT_DBG_CONF_PH(" ", _scope)));
416 FLT_OT_DBG_LIST(conf, scope, "", "defined", _scope, FLT_OT_DBG_CONF_SCOPE(" ", _scope));
417
418 if (conf->tracer != NULL) {
419 FLT_OT_DBG(3, " --- tracer '%s' configuration ----------", conf->tracer->id);
420 FLT_OT_DBG_LIST(conf->tracer, ph_group, " ", "used", _group, FLT_OT_DBG_CONF_PH(" ", _group));
421 FLT_OT_DBG_LIST(conf->tracer, ph_scope, " ", "used", _scope, FLT_OT_DBG_CONF_PH(" ", _scope));
422 }
423
Miroslav Zagorac5b5b0622022-03-04 09:56:00 +0100424 FLT_OT_RETURN_INT(retval);
Miroslav Zagorac70230c62020-12-09 16:54:31 +0100425}
426
427
Miroslav Zagorac70230c62020-12-09 16:54:31 +0100428/***
429 * NAME
430 * flt_ot_init_per_thread -
431 *
432 * ARGUMENTS
433 * p -
434 * fconf -
435 *
436 * DESCRIPTION
437 * It initializes the filter for each thread. It works the same way than
438 * flt_ot_init() but in the context of a thread. This callback is called
439 * after the thread creation.
440 *
441 * RETURN VALUE
442 * Returns a negative value if an error occurs, any other value otherwise.
443 */
444static int flt_ot_init_per_thread(struct proxy *p, struct flt_conf *fconf)
445{
Miroslav Zagoracfcf4e3d2021-06-10 01:23:15 +0200446 struct flt_ot_conf *conf = FLT_OT_DEREF(fconf, conf, NULL);
447 char *err = NULL;
448 int retval = FLT_OT_RET_ERROR;
Miroslav Zagorac70230c62020-12-09 16:54:31 +0100449
450 FLT_OT_FUNC("%p, %p", p, fconf);
451
Miroslav Zagoracfcf4e3d2021-06-10 01:23:15 +0200452 if (conf == NULL)
Miroslav Zagorac5b5b0622022-03-04 09:56:00 +0100453 FLT_OT_RETURN_INT(retval);
Miroslav Zagoracfcf4e3d2021-06-10 01:23:15 +0200454
455 /*
456 * Start the OpenTracing library tracer thread.
457 * Enable HTX streams filtering.
458 */
459 if (!(fconf->flags & FLT_CFG_FL_HTX)) {
460 retval = ot_start(conf->tracer->tracer, conf->tracer->cfgbuf, &err);
461 if (retval != FLT_OT_RET_ERROR)
462 fconf->flags |= FLT_CFG_FL_HTX;
463 else if (err != NULL) {
464 FLT_OT_ALERT("%s", err);
465
466 FLT_OT_ERR_FREE(err);
467 }
468 } else {
469 retval = FLT_OT_RET_OK;
470 }
471
Miroslav Zagorac5b5b0622022-03-04 09:56:00 +0100472 FLT_OT_RETURN_INT(retval);
Miroslav Zagorac70230c62020-12-09 16:54:31 +0100473}
474
475
Miroslav Zagoracfcf4e3d2021-06-10 01:23:15 +0200476#ifdef DEBUG_OT
477
Miroslav Zagorac70230c62020-12-09 16:54:31 +0100478/***
479 * NAME
480 * flt_ot_deinit_per_thread -
481 *
482 * ARGUMENTS
483 * p -
484 * fconf -
485 *
486 * DESCRIPTION
487 * It cleans up what the init_per_thread callback have done. It is called
488 * in the context of a thread, before exiting it.
489 *
490 * RETURN VALUE
491 * This function does not return a value.
492 */
493static void flt_ot_deinit_per_thread(struct proxy *p, struct flt_conf *fconf)
494{
495 FLT_OT_FUNC("%p, %p", p, fconf);
496
497 FLT_OT_RETURN();
498}
499
500#endif /* DEBUG_OT */
501
502
503/***
504 * NAME
505 * flt_ot_attach - Called when a filter instance is created and attach to a stream.
506 *
507 * ARGUMENTS
508 * s -
509 * f -
510 *
511 * DESCRIPTION
512 * It is called after a filter instance creation, when it is attached to a
513 * stream. This happens when the stream is started for filters defined on
514 * the stream's frontend and when the backend is set for filters declared
515 * on the stream's backend. It is possible to ignore the filter, if needed,
516 * by returning 0. This could be useful to have conditional filtering.
517 *
518 * RETURN VALUE
519 * Returns a negative value if an error occurs, 0 to ignore the filter,
520 * any other value otherwise.
521 */
522static int flt_ot_attach(struct stream *s, struct filter *f)
523{
524 const struct flt_ot_conf *conf = FLT_OT_CONF(f);
525 char *err = NULL;
526
527 FLT_OT_FUNC("%p, %p", s, f);
528
529 if (conf->tracer->flag_disabled) {
530 FLT_OT_DBG(2, "filter '%s', type: %s (disabled)", conf->id, flt_ot_type(f));
531
Miroslav Zagorac5b5b0622022-03-04 09:56:00 +0100532 FLT_OT_RETURN_INT(FLT_OT_RET_IGNORE);
Miroslav Zagorac70230c62020-12-09 16:54:31 +0100533 }
534 else if (conf->tracer->rate_limit < FLT_OT_FLOAT_U32(FLT_OT_RATE_LIMIT_MAX, FLT_OT_RATE_LIMIT_MAX)) {
535 uint32_t rnd = ha_random32();
536
537 if (conf->tracer->rate_limit <= rnd) {
538 FLT_OT_DBG(2, "filter '%s', type: %s (ignored: %u <= %u)", conf->id, flt_ot_type(f), conf->tracer->rate_limit, rnd);
539
Miroslav Zagorac5b5b0622022-03-04 09:56:00 +0100540 FLT_OT_RETURN_INT(FLT_OT_RET_IGNORE);
Miroslav Zagorac70230c62020-12-09 16:54:31 +0100541 }
542 }
543
544 FLT_OT_DBG(2, "filter '%s', type: %s (run)", conf->id, flt_ot_type(f));
545
546 f->ctx = flt_ot_runtime_context_init(s, f, &err);
547 FLT_OT_ERR_FREE(err);
548 if (f->ctx == NULL) {
549 FLT_OT_LOG(LOG_EMERG, "failed to create context");
550
Miroslav Zagorac5b5b0622022-03-04 09:56:00 +0100551 FLT_OT_RETURN_INT(FLT_OT_RET_IGNORE);
Miroslav Zagorac70230c62020-12-09 16:54:31 +0100552 }
553
554 /*
555 * AN_REQ_WAIT_HTTP and AN_RES_WAIT_HTTP analyzers can only be used
556 * in the .channel_post_analyze callback function.
557 */
558 f->pre_analyzers |= conf->tracer->analyzers & ((AN_REQ_ALL & ~AN_REQ_WAIT_HTTP & ~AN_REQ_HTTP_TARPIT) | (AN_RES_ALL & ~AN_RES_WAIT_HTTP));
559 f->post_analyzers |= conf->tracer->analyzers & (AN_REQ_WAIT_HTTP | AN_RES_WAIT_HTTP);
560
561 FLT_OT_LOG(LOG_INFO, "%08x %08x", f->pre_analyzers, f->post_analyzers);
562
563 flt_ot_vars_dump(s);
564 flt_ot_http_headers_dump(&(s->req));
565
Miroslav Zagorac5b5b0622022-03-04 09:56:00 +0100566 FLT_OT_RETURN_INT(FLT_OT_RET_OK);
Miroslav Zagorac70230c62020-12-09 16:54:31 +0100567}
568
569
570#ifdef DEBUG_OT
571
572/***
573 * NAME
574 * flt_ot_stream_start - Called when a stream is created.
575 *
576 * ARGUMENTS
577 * s -
578 * f -
579 *
580 * DESCRIPTION
581 * It is called when a stream is started. This callback can fail by
582 * returning a negative value. It will be considered as a critical error
583 * by HAProxy which disabled the listener for a short time.
584 *
585 * RETURN VALUE
586 * Returns a negative value if an error occurs, any other value otherwise.
587 */
588static int flt_ot_stream_start(struct stream *s, struct filter *f)
589{
590 char *err = NULL;
591 int retval = FLT_OT_RET_OK;
592
593 FLT_OT_FUNC("%p, %p", s, f);
594
595 if (flt_ot_is_disabled(f FLT_OT_DBG_ARGS(, -1)))
Miroslav Zagorac5b5b0622022-03-04 09:56:00 +0100596 FLT_OT_RETURN_INT(retval);
Miroslav Zagorac70230c62020-12-09 16:54:31 +0100597
Miroslav Zagorac5b5b0622022-03-04 09:56:00 +0100598 FLT_OT_RETURN_INT(flt_ot_return_int(f, &err, retval));
Miroslav Zagorac70230c62020-12-09 16:54:31 +0100599}
600
601
602/***
603 * NAME
604 * flt_ot_stream_set_backend - Called when a backend is set for a stream.
605 *
606 * ARGUMENTS
607 * s -
608 * f -
609 * be -
610 *
611 * DESCRIPTION
612 * It is called when a backend is set for a stream. This callbacks will be
613 * called for all filters attached to a stream (frontend and backend). Note
614 * this callback is not called if the frontend and the backend are the same.
615 *
616 * RETURN VALUE
617 * Returns a negative value if an error occurs, any other value otherwise.
618 */
619static int flt_ot_stream_set_backend(struct stream *s, struct filter *f, struct proxy *be)
620{
621 char *err = NULL;
622 int retval = FLT_OT_RET_OK;
623
624 FLT_OT_FUNC("%p, %p, %p", s, f, be);
625
626 if (flt_ot_is_disabled(f FLT_OT_DBG_ARGS(, -1)))
Miroslav Zagorac5b5b0622022-03-04 09:56:00 +0100627 FLT_OT_RETURN_INT(retval);
Miroslav Zagorac70230c62020-12-09 16:54:31 +0100628
629 FLT_OT_DBG(3, "backend: %s", be->id);
630
Miroslav Zagorac5b5b0622022-03-04 09:56:00 +0100631 FLT_OT_RETURN_INT(flt_ot_return_int(f, &err, retval));
Miroslav Zagorac70230c62020-12-09 16:54:31 +0100632}
633
634
635/***
636 * NAME
637 * flt_ot_stream_stop - Called when a stream is destroyed.
638 *
639 * ARGUMENTS
640 * s -
641 * f -
642 *
643 * DESCRIPTION
644 * It is called when a stream is stopped. This callback always succeed.
645 * Anyway, it is too late to return an error.
646 *
647 * RETURN VALUE
648 * This function does not return a value.
649 */
650static void flt_ot_stream_stop(struct stream *s, struct filter *f)
651{
652 char *err = NULL;
653
654 FLT_OT_FUNC("%p, %p", s, f);
655
656 if (flt_ot_is_disabled(f FLT_OT_DBG_ARGS(, -1)))
657 FLT_OT_RETURN();
658
659 flt_ot_return_void(f, &err);
660
661 FLT_OT_RETURN();
662}
663
664#endif /* DEBUG_OT */
665
666
667/***
668 * NAME
669 * flt_ot_detach - Called when a filter instance is detach from a stream, just before its destruction.
670 *
671 * ARGUMENTS
672 * s -
673 * f -
674 *
675 * DESCRIPTION
676 * It is called when a filter instance is detached from a stream, before its
677 * destruction. This happens when the stream is stopped for filters defined
678 * on the stream's frontend and when the analyze ends for filters defined on
679 * the stream's backend.
680 *
681 * RETURN VALUE
682 * This function does not return a value.
683 */
684static void flt_ot_detach(struct stream *s, struct filter *f)
685{
686 FLT_OT_FUNC("%p, %p", s, f);
687
688 FLT_OT_DBG(2, "filter '%s', type: %s", FLT_OT_CONF(f)->id, flt_ot_type(f));
689
690 flt_ot_runtime_context_free(f);
691
692 FLT_OT_RETURN();
693}
694
695
696/***
697 * NAME
698 * flt_ot_check_timeouts - Called when a stream is woken up because of an expired timer.
699 *
700 * ARGUMENTS
701 * s -
702 * f -
703 *
704 * DESCRIPTION
705 * -
706 *
707 * RETURN VALUE
708 * This function does not return a value.
709 */
710static void flt_ot_check_timeouts(struct stream *s, struct filter *f)
711{
712 char *err = NULL;
713
714 FLT_OT_FUNC("%p, %p", s, f);
715
716 if (flt_ot_is_disabled(f FLT_OT_DBG_ARGS(, -1)))
717 FLT_OT_RETURN();
718
719 s->pending_events |= TASK_WOKEN_MSG;
720
721 flt_ot_return_void(f, &err);
722
723 FLT_OT_RETURN();
724}
725
726
727/***
728 * NAME
729 * flt_ot_channel_start_analyze - Called when analyze starts for a given channel.
730 *
731 * ARGUMENTS
732 * s -
733 * f -
734 * chn -
735 *
736 * DESCRIPTION
737 * -
738 *
739 * RETURN VALUE
740 * Returns a negative value if an error occurs, 0 if it needs to wait,
741 * any other value otherwise.
742 */
743static int flt_ot_channel_start_analyze(struct stream *s, struct filter *f, struct channel *chn)
744{
745 char *err = NULL;
746 int retval;
747
748 FLT_OT_FUNC("%p, %p, %p", s, f, chn);
749
750 if (flt_ot_is_disabled(f FLT_OT_DBG_ARGS(, (chn->flags & CF_ISRESP) ? FLT_OT_EVENT_RES_SERVER_SESS_START : FLT_OT_EVENT_REQ_CLIENT_SESS_START)))
Miroslav Zagorac5b5b0622022-03-04 09:56:00 +0100751 FLT_OT_RETURN_INT(FLT_OT_RET_OK);
Miroslav Zagorac70230c62020-12-09 16:54:31 +0100752
753 FLT_OT_DBG(3, "channel: %s, mode: %s (%s)", flt_ot_chn_label(chn), flt_ot_pr_mode(s), flt_ot_stream_pos(s));
754
755 if (chn->flags & CF_ISRESP) {
756 /* The response channel. */
757 chn->analysers |= f->pre_analyzers & AN_RES_ALL;
758
759 /* The event 'on-server-session-start'. */
760 retval = flt_ot_event_run(s, f, chn, FLT_OT_EVENT_RES_SERVER_SESS_START, &err);
761 if (retval == FLT_OT_RET_WAIT) {
762 channel_dont_read(chn);
763 channel_dont_close(chn);
764 }
765 } else {
766 /* The request channel. */
767 chn->analysers |= f->pre_analyzers & AN_REQ_ALL;
768
769 /* The event 'on-client-session-start'. */
770 retval = flt_ot_event_run(s, f, chn, FLT_OT_EVENT_REQ_CLIENT_SESS_START, &err);
771 }
772
773// register_data_filter(s, chn, f);
774
Miroslav Zagorac5b5b0622022-03-04 09:56:00 +0100775 FLT_OT_RETURN_INT(flt_ot_return_int(f, &err, retval));
Miroslav Zagorac70230c62020-12-09 16:54:31 +0100776}
777
778
779/***
780 * NAME
781 * flt_ot_channel_pre_analyze - Called before a processing happens on a given channel.
782 *
783 * ARGUMENTS
784 * s -
785 * f -
786 * chn - the channel on which the analyzing is done
787 * an_bit - the analyzer id
788 *
789 * DESCRIPTION
790 * -
791 *
792 * RETURN VALUE
793 * Returns a negative value if an error occurs, 0 if it needs to wait,
794 * any other value otherwise.
795 */
796static int flt_ot_channel_pre_analyze(struct stream *s, struct filter *f, struct channel *chn, uint an_bit)
797{
798 char *err = NULL;
799 int i, event = -1, retval;
800
801 FLT_OT_FUNC("%p, %p, %p, 0x%08x", s, f, chn, an_bit);
802
803 for (i = 0; i < FLT_OT_TABLESIZE(flt_ot_event_data); i++)
804 if (flt_ot_event_data[i].an_bit == an_bit) {
805 event = i;
806
807 break;
808 }
809
810 if (flt_ot_is_disabled(f FLT_OT_DBG_ARGS(, event)))
Miroslav Zagorac5b5b0622022-03-04 09:56:00 +0100811 FLT_OT_RETURN_INT(FLT_OT_RET_OK);
Miroslav Zagorac70230c62020-12-09 16:54:31 +0100812
813 FLT_OT_DBG(3, "channel: %s, mode: %s (%s), analyzer: %s", flt_ot_chn_label(chn), flt_ot_pr_mode(s), flt_ot_stream_pos(s), flt_ot_analyzer(an_bit));
814
815 retval = flt_ot_event_run(s, f, chn, event, &err);
816
817 if ((retval == FLT_OT_RET_WAIT) && (chn->flags & CF_ISRESP)) {
818 channel_dont_read(chn);
819 channel_dont_close(chn);
820 }
821
Miroslav Zagorac5b5b0622022-03-04 09:56:00 +0100822 FLT_OT_RETURN_INT(flt_ot_return_int(f, &err, retval));
Miroslav Zagorac70230c62020-12-09 16:54:31 +0100823}
824
825
826/***
827 * NAME
828 * flt_ot_channel_post_analyze - Called after a processing happens on a given channel.
829 *
830 * ARGUMENTS
831 * s -
832 * f -
833 * chn -
834 * an_bit -
835 *
836 * DESCRIPTION
837 * This function, for its part, is not resumable. It is called when a
838 * filterable analyzer finishes its processing. So it called once for
839 * the same analyzer.
840 *
841 * RETURN VALUE
842 * Returns a negative value if an error occurs, 0 if it needs to wait,
843 * any other value otherwise.
844 */
845static int flt_ot_channel_post_analyze(struct stream *s, struct filter *f, struct channel *chn, uint an_bit)
846{
847 char *err = NULL;
848 int i, event = -1, retval;
849
850 FLT_OT_FUNC("%p, %p, %p, 0x%08x", s, f, chn, an_bit);
851
852 for (i = 0; i < FLT_OT_TABLESIZE(flt_ot_event_data); i++)
853 if (flt_ot_event_data[i].an_bit == an_bit) {
854 event = i;
855
856 break;
857 }
858
859 if (flt_ot_is_disabled(f FLT_OT_DBG_ARGS(, event)))
Miroslav Zagorac5b5b0622022-03-04 09:56:00 +0100860 FLT_OT_RETURN_INT(FLT_OT_RET_OK);
Miroslav Zagorac70230c62020-12-09 16:54:31 +0100861
862 FLT_OT_DBG(3, "channel: %s, mode: %s (%s), analyzer: %s", flt_ot_chn_label(chn), flt_ot_pr_mode(s), flt_ot_stream_pos(s), flt_ot_analyzer(an_bit));
863
864 retval = flt_ot_event_run(s, f, chn, event, &err);
865
Miroslav Zagorac5b5b0622022-03-04 09:56:00 +0100866 FLT_OT_RETURN_INT(flt_ot_return_int(f, &err, retval));
Miroslav Zagorac70230c62020-12-09 16:54:31 +0100867}
868
869
870/***
871 * NAME
872 * flt_ot_channel_end_analyze - Called when analyze ends for a given channel.
873 *
874 * ARGUMENTS
875 * s -
876 * f -
877 * chn -
878 *
879 * DESCRIPTION
880 * -
881 *
882 * RETURN VALUE
883 * Returns a negative value if an error occurs, 0 if it needs to wait,
884 * any other value otherwise.
885 */
886static int flt_ot_channel_end_analyze(struct stream *s, struct filter *f, struct channel *chn)
887{
888 char *err = NULL;
889 int rc, retval;
890
891 FLT_OT_FUNC("%p, %p, %p", s, f, chn);
892
893 if (flt_ot_is_disabled(f FLT_OT_DBG_ARGS(, (chn->flags & CF_ISRESP) ? FLT_OT_EVENT_RES_SERVER_SESS_END : FLT_OT_EVENT_REQ_CLIENT_SESS_END)))
Miroslav Zagorac5b5b0622022-03-04 09:56:00 +0100894 FLT_OT_RETURN_INT(FLT_OT_RET_OK);
Miroslav Zagorac70230c62020-12-09 16:54:31 +0100895
896 FLT_OT_DBG(3, "channel: %s, mode: %s (%s)", flt_ot_chn_label(chn), flt_ot_pr_mode(s), flt_ot_stream_pos(s));
897
898 if (chn->flags & CF_ISRESP) {
899 /* The response channel, event 'on-server-session-end'. */
900 retval = flt_ot_event_run(s, f, chn, FLT_OT_EVENT_RES_SERVER_SESS_END, &err);
901 } else {
902 /* The request channel, event 'on-client-session-end'. */
903 retval = flt_ot_event_run(s, f, chn, FLT_OT_EVENT_REQ_CLIENT_SESS_END, &err);
904
905 /*
906 * In case an event using server response is defined and not
907 * executed, event 'on-server-unavailable' is called here.
908 */
909 if ((FLT_OT_CONF(f)->tracer->analyzers & AN_RES_ALL) && !(FLT_OT_RT_CTX(f->ctx)->analyzers & AN_RES_ALL)) {
910 rc = flt_ot_event_run(s, f, chn, FLT_OT_EVENT_REQ_SERVER_UNAVAILABLE, &err);
911 if ((retval == FLT_OT_RET_OK) && (rc != FLT_OT_RET_OK))
912 retval = rc;
913 }
914 }
915
Miroslav Zagorac5b5b0622022-03-04 09:56:00 +0100916 FLT_OT_RETURN_INT(flt_ot_return_int(f, &err, retval));
Miroslav Zagorac70230c62020-12-09 16:54:31 +0100917}
918
919
920#ifdef DEBUG_OT
921
922/***
923 * NAME
924 * flt_ot_http_headers -
925 *
926 * ARGUMENTS
927 * s -
928 * f -
929 * msg -
930 *
931 * DESCRIPTION
932 * -
933 *
934 * RETURN VALUE
935 * Returns a negative value if an error occurs, 0 if it needs to wait,
936 * any other value otherwise.
937 */
938static int flt_ot_http_headers(struct stream *s, struct filter *f, struct http_msg *msg)
939{
940 char *err = NULL;
941 struct htx *htx = htxbuf(&(msg->chn->buf));
942 struct htx_sl *sl = http_get_stline(htx);
943 int retval = FLT_OT_RET_OK;
944
945 FLT_OT_FUNC("%p, %p, %p", s, f, msg);
946
947 if (flt_ot_is_disabled(f FLT_OT_DBG_ARGS(, -1)))
Miroslav Zagorac5b5b0622022-03-04 09:56:00 +0100948 FLT_OT_RETURN_INT(retval);
Miroslav Zagorac70230c62020-12-09 16:54:31 +0100949
950 FLT_OT_DBG(3, "channel: %s, mode: %s (%s), %.*s %.*s %.*s", flt_ot_chn_label(msg->chn), flt_ot_pr_mode(s), flt_ot_stream_pos(s), HTX_SL_P1_LEN(sl), HTX_SL_P1_PTR(sl), HTX_SL_P2_LEN(sl), HTX_SL_P2_PTR(sl), HTX_SL_P3_LEN(sl), HTX_SL_P3_PTR(sl));
951
Miroslav Zagorac5b5b0622022-03-04 09:56:00 +0100952 FLT_OT_RETURN_INT(flt_ot_return_int(f, &err, retval));
Miroslav Zagorac70230c62020-12-09 16:54:31 +0100953}
954
955
956/***
957 * NAME
958 * flt_ot_http_payload -
959 *
960 * ARGUMENTS
961 * s -
962 * f -
963 * msg -
964 * offset -
965 * len -
966 *
967 * DESCRIPTION
968 * -
969 *
970 * RETURN VALUE
971 * Returns a negative value if an error occurs, any other value otherwise.
972 */
973static int flt_ot_http_payload(struct stream *s, struct filter *f, struct http_msg *msg, uint offset, uint len)
974{
975 char *err = NULL;
976 int retval = len;
977
978 FLT_OT_FUNC("%p, %p, %p, %u, %u", s, f, msg, offset, len);
979
980 if (flt_ot_is_disabled(f FLT_OT_DBG_ARGS(, -1)))
Miroslav Zagorac5b5b0622022-03-04 09:56:00 +0100981 FLT_OT_RETURN_INT(len);
Miroslav Zagorac70230c62020-12-09 16:54:31 +0100982
983 FLT_OT_DBG(3, "channel: %s, mode: %s (%s), offset: %u, len: %u, forward: %d", flt_ot_chn_label(msg->chn), flt_ot_pr_mode(s), flt_ot_stream_pos(s), offset, len, retval);
984
985 if (retval != len)
986 task_wakeup(s->task, TASK_WOKEN_MSG);
987
Miroslav Zagorac5b5b0622022-03-04 09:56:00 +0100988 FLT_OT_RETURN_INT(flt_ot_return_int(f, &err, retval));
Miroslav Zagorac70230c62020-12-09 16:54:31 +0100989}
990
991
992/***
993 * NAME
994 * flt_ot_http_end -
995 *
996 * ARGUMENTS
997 * s -
998 * f -
999 * msg -
1000 *
1001 * DESCRIPTION
1002 * -
1003 *
1004 * RETURN VALUE
1005 * Returns a negative value if an error occurs, 0 if it needs to wait,
1006 * any other value otherwise.
1007 */
1008static int flt_ot_http_end(struct stream *s, struct filter *f, struct http_msg *msg)
1009{
1010 char *err = NULL;
1011 int retval = FLT_OT_RET_OK;
1012
1013 FLT_OT_FUNC("%p, %p, %p", s, f, msg);
1014
1015 if (flt_ot_is_disabled(f FLT_OT_DBG_ARGS(, -1)))
Miroslav Zagorac5b5b0622022-03-04 09:56:00 +01001016 FLT_OT_RETURN_INT(retval);
Miroslav Zagorac70230c62020-12-09 16:54:31 +01001017
1018 FLT_OT_DBG(3, "channel: %s, mode: %s (%s)", flt_ot_chn_label(msg->chn), flt_ot_pr_mode(s), flt_ot_stream_pos(s));
1019
Miroslav Zagorac5b5b0622022-03-04 09:56:00 +01001020 FLT_OT_RETURN_INT(flt_ot_return_int(f, &err, retval));
Miroslav Zagorac70230c62020-12-09 16:54:31 +01001021}
1022
1023
1024/***
1025 * NAME
1026 * flt_ot_http_reset -
1027 *
1028 * ARGUMENTS
1029 * s -
1030 * f -
1031 * msg -
1032 *
1033 * DESCRIPTION
1034 * -
1035 *
1036 * RETURN VALUE
1037 * This function does not return a value.
1038 */
1039static void flt_ot_http_reset(struct stream *s, struct filter *f, struct http_msg *msg)
1040{
1041 char *err = NULL;
1042
1043 FLT_OT_FUNC("%p, %p, %p", s, f, msg);
1044
1045 if (flt_ot_is_disabled(f FLT_OT_DBG_ARGS(, -1)))
1046 FLT_OT_RETURN();
1047
1048 FLT_OT_DBG(3, "channel: %s, mode: %s (%s)", flt_ot_chn_label(msg->chn), flt_ot_pr_mode(s), flt_ot_stream_pos(s));
1049
1050 flt_ot_return_void(f, &err);
1051
1052 FLT_OT_RETURN();
1053}
1054
1055
1056/***
1057 * NAME
1058 * flt_ot_http_reply -
1059 *
1060 * ARGUMENTS
1061 * s -
1062 * f -
1063 * status -
1064 * msg -
1065 *
1066 * DESCRIPTION
1067 * -
1068 *
1069 * RETURN VALUE
1070 * This function does not return a value.
1071 */
1072static void flt_ot_http_reply(struct stream *s, struct filter *f, short status, const struct buffer *msg)
1073{
1074 char *err = NULL;
1075
1076 FLT_OT_FUNC("%p, %p, %hd, %p", s, f, status, msg);
1077
1078 if (flt_ot_is_disabled(f FLT_OT_DBG_ARGS(, -1)))
1079 FLT_OT_RETURN();
1080
1081 FLT_OT_DBG(3, "channel: -, mode: %s (%s)", flt_ot_pr_mode(s), flt_ot_stream_pos(s));
1082
1083 flt_ot_return_void(f, &err);
1084
1085 FLT_OT_RETURN();
1086}
1087
1088
1089/***
1090 * NAME
1091 * flt_ot_tcp_payload -
1092 *
1093 * ARGUMENTS
1094 * s -
1095 * f -
1096 * chn -
1097 * offset -
1098 * len -
1099 *
1100 * DESCRIPTION
1101 * -
1102 *
1103 * RETURN VALUE
1104 * Returns a negative value if an error occurs, any other value otherwise.
1105 */
1106static int flt_ot_tcp_payload(struct stream *s, struct filter *f, struct channel *chn, uint offset, uint len)
1107{
1108 char *err = NULL;
1109 int retval = len;
1110
1111 FLT_OT_FUNC("%p, %p, %p, %u, %u", s, f, chn, offset, len);
1112
1113 if (flt_ot_is_disabled(f FLT_OT_DBG_ARGS(, -1)))
Miroslav Zagorac5b5b0622022-03-04 09:56:00 +01001114 FLT_OT_RETURN_INT(len);
Miroslav Zagorac70230c62020-12-09 16:54:31 +01001115
1116 FLT_OT_DBG(3, "channel: %s, mode: %s (%s), offset: %u, len: %u, forward: %d", flt_ot_chn_label(chn), flt_ot_pr_mode(s), flt_ot_stream_pos(s), offset, len, retval);
1117
1118 if (s->flags & SF_HTX) {
1119 } else {
1120 }
1121
1122 if (retval != len)
1123 task_wakeup(s->task, TASK_WOKEN_MSG);
1124
Miroslav Zagorac5b5b0622022-03-04 09:56:00 +01001125 FLT_OT_RETURN_INT(flt_ot_return_int(f, &err, retval));
Miroslav Zagorac70230c62020-12-09 16:54:31 +01001126}
1127
1128#endif /* DEBUG_OT */
1129
1130
1131struct flt_ops flt_ot_ops = {
1132 /* Callbacks to manage the filter lifecycle. */
1133 .init = flt_ot_init,
1134 .deinit = flt_ot_deinit,
1135 .check = flt_ot_check,
Miroslav Zagoracfcf4e3d2021-06-10 01:23:15 +02001136 .init_per_thread = flt_ot_init_per_thread,
Miroslav Zagorac70230c62020-12-09 16:54:31 +01001137 .deinit_per_thread = FLT_OT_DBG_IFDEF(flt_ot_deinit_per_thread, NULL),
1138
1139 /* Stream callbacks. */
1140 .attach = flt_ot_attach,
1141 .stream_start = FLT_OT_DBG_IFDEF(flt_ot_stream_start, NULL),
1142 .stream_set_backend = FLT_OT_DBG_IFDEF(flt_ot_stream_set_backend, NULL),
1143 .stream_stop = FLT_OT_DBG_IFDEF(flt_ot_stream_stop, NULL),
1144 .detach = flt_ot_detach,
1145 .check_timeouts = flt_ot_check_timeouts,
1146
1147 /* Channel callbacks. */
1148 .channel_start_analyze = flt_ot_channel_start_analyze,
1149 .channel_pre_analyze = flt_ot_channel_pre_analyze,
1150 .channel_post_analyze = flt_ot_channel_post_analyze,
1151 .channel_end_analyze = flt_ot_channel_end_analyze,
1152
1153 /* HTTP callbacks. */
1154 .http_headers = FLT_OT_DBG_IFDEF(flt_ot_http_headers, NULL),
1155 .http_payload = FLT_OT_DBG_IFDEF(flt_ot_http_payload, NULL),
1156 .http_end = FLT_OT_DBG_IFDEF(flt_ot_http_end, NULL),
1157 .http_reset = FLT_OT_DBG_IFDEF(flt_ot_http_reset, NULL),
1158 .http_reply = FLT_OT_DBG_IFDEF(flt_ot_http_reply, NULL),
1159
1160 /* TCP callbacks. */
1161 .tcp_payload = FLT_OT_DBG_IFDEF(flt_ot_tcp_payload, NULL)
1162};
1163
1164
1165REGISTER_BUILD_OPTS("Built with OpenTracing support.");
1166
1167/*
1168 * Local variables:
1169 * c-indent-level: 8
1170 * c-basic-offset: 8
1171 * End:
1172 *
1173 * vi: noexpandtab shiftwidth=8 tabstop=8
1174 */