blob: 2dbf6e565715806f1b0a50b898773a137a52a0a0 [file] [log] [blame]
Christopher Faulet1f40b912017-02-17 09:32:19 +01001/*
2 * include/types/spoe.h
3 * Macros, variables and structures for the SPOE filter.
4 *
5 * Copyright (C) 2017 HAProxy Technologies, Christopher Faulet <cfaulet@haproxy.com>
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation, version 2.1
10 * exclusively.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#ifndef _TYPES_SPOE_H
23#define _TYPES_SPOE_H
24
Christopher Fauletb2dd1e02018-03-22 09:07:41 +010025#include <sys/time.h>
26
Christopher Faulet1f40b912017-02-17 09:32:19 +010027#include <common/buffer.h>
28#include <common/mini-clist.h>
Christopher Faulet24289f22017-09-25 14:48:02 +020029#include <common/hathreads.h>
Christopher Faulet1f40b912017-02-17 09:32:19 +010030
31#include <types/filters.h>
32#include <types/freq_ctr.h>
Christopher Faulet7250b8f2018-03-26 17:19:01 +020033#include <types/log.h>
Christopher Faulet1f40b912017-02-17 09:32:19 +010034#include <types/proxy.h>
35#include <types/sample.h>
36#include <types/stream.h>
37#include <types/task.h>
38
Christopher Fauletc718b822017-09-21 16:50:56 +020039/* Type of list of messages */
40#define SPOE_MSGS_BY_EVENT 0x01
41#define SPOE_MSGS_BY_GROUP 0x02
42
Christopher Faulet1f40b912017-02-17 09:32:19 +010043/* Flags set on the SPOE agent */
44#define SPOE_FL_CONT_ON_ERR 0x00000001 /* Do not stop events processing when an error occurred */
Christopher Faulet305c6072017-02-23 16:17:53 +010045#define SPOE_FL_PIPELINING 0x00000002 /* Set when SPOE agent supports pipelining (set by default) */
46#define SPOE_FL_ASYNC 0x00000004 /* Set when SPOE agent supports async (set by default) */
Christopher Fauletcecd8522017-02-24 22:11:21 +010047#define SPOE_FL_SND_FRAGMENTATION 0x00000008 /* Set when SPOE agent supports sending fragmented payload */
48#define SPOE_FL_RCV_FRAGMENTATION 0x00000010 /* Set when SPOE agent supports receiving fragmented payload */
Etienne Carriereaec89892017-12-14 09:36:40 +000049#define SPOE_FL_FORCE_SET_VAR 0x00000020 /* Set when SPOE agent will set all variables from agent (and not only known variables) */
Christopher Faulet1f40b912017-02-17 09:32:19 +010050
51/* Flags set on the SPOE context */
52#define SPOE_CTX_FL_CLI_CONNECTED 0x00000001 /* Set after that on-client-session event was processed */
53#define SPOE_CTX_FL_SRV_CONNECTED 0x00000002 /* Set after that on-server-session event was processed */
54#define SPOE_CTX_FL_REQ_PROCESS 0x00000004 /* Set when SPOE is processing the request */
55#define SPOE_CTX_FL_RSP_PROCESS 0x00000008 /* Set when SPOE is processing the response */
56#define SPOE_CTX_FL_FRAGMENTED 0x00000010 /* Set when a fragmented frame is processing */
57
58#define SPOE_CTX_FL_PROCESS (SPOE_CTX_FL_REQ_PROCESS|SPOE_CTX_FL_RSP_PROCESS)
59
60/* Flags set on the SPOE applet */
61#define SPOE_APPCTX_FL_PIPELINING 0x00000001 /* Set if pipelining is supported */
62#define SPOE_APPCTX_FL_ASYNC 0x00000002 /* Set if asynchronus frames is supported */
63#define SPOE_APPCTX_FL_FRAGMENTATION 0x00000004 /* Set if fragmentation is supported */
Christopher Faulet1f40b912017-02-17 09:32:19 +010064
65#define SPOE_APPCTX_ERR_NONE 0x00000000 /* no error yet, leave it to zero */
66#define SPOE_APPCTX_ERR_TOUT 0x00000001 /* SPOE applet timeout */
67
68/* Flags set on the SPOE frame */
69#define SPOE_FRM_FL_FIN 0x00000001
70#define SPOE_FRM_FL_ABRT 0x00000002
71
72/* All possible states for a SPOE context */
73enum spoe_ctx_state {
74 SPOE_CTX_ST_NONE = 0,
75 SPOE_CTX_ST_READY,
76 SPOE_CTX_ST_ENCODING_MSGS,
77 SPOE_CTX_ST_SENDING_MSGS,
78 SPOE_CTX_ST_WAITING_ACK,
79 SPOE_CTX_ST_DONE,
80 SPOE_CTX_ST_ERROR,
81};
82
83/* All possible states for a SPOE applet */
84enum spoe_appctx_state {
85 SPOE_APPCTX_ST_CONNECT = 0,
86 SPOE_APPCTX_ST_CONNECTING,
87 SPOE_APPCTX_ST_IDLE,
88 SPOE_APPCTX_ST_PROCESSING,
89 SPOE_APPCTX_ST_SENDING_FRAG_NOTIFY,
90 SPOE_APPCTX_ST_WAITING_SYNC_ACK,
91 SPOE_APPCTX_ST_DISCONNECT,
92 SPOE_APPCTX_ST_DISCONNECTING,
93 SPOE_APPCTX_ST_EXIT,
94 SPOE_APPCTX_ST_END,
95};
96
97/* All supported SPOE actions */
98enum spoe_action_type {
99 SPOE_ACT_T_SET_VAR = 1,
100 SPOE_ACT_T_UNSET_VAR,
101 SPOE_ACT_TYPES,
102};
103
104/* All supported SPOE events */
105enum spoe_event {
106 SPOE_EV_NONE = 0,
107
108 /* Request events */
109 SPOE_EV_ON_CLIENT_SESS = 1,
110 SPOE_EV_ON_TCP_REQ_FE,
111 SPOE_EV_ON_TCP_REQ_BE,
112 SPOE_EV_ON_HTTP_REQ_FE,
113 SPOE_EV_ON_HTTP_REQ_BE,
114
115 /* Response events */
116 SPOE_EV_ON_SERVER_SESS,
117 SPOE_EV_ON_TCP_RSP,
118 SPOE_EV_ON_HTTP_RSP,
119
120 SPOE_EV_EVENTS
121};
122
123/* Errors triggered by streams */
124enum spoe_context_error {
125 SPOE_CTX_ERR_NONE = 0,
126 SPOE_CTX_ERR_TOUT,
127 SPOE_CTX_ERR_RES,
128 SPOE_CTX_ERR_TOO_BIG,
129 SPOE_CTX_ERR_FRAG_FRAME_ABRT,
Christopher Faulet344c4ab2017-09-22 10:20:13 +0200130 SPOE_CTX_ERR_INTERRUPT,
Christopher Faulet1f40b912017-02-17 09:32:19 +0100131 SPOE_CTX_ERR_UNKNOWN = 255,
132 SPOE_CTX_ERRS,
133};
134
135/* Errors triggerd by SPOE applet */
136enum spoe_frame_error {
137 SPOE_FRM_ERR_NONE = 0,
138 SPOE_FRM_ERR_IO,
139 SPOE_FRM_ERR_TOUT,
140 SPOE_FRM_ERR_TOO_BIG,
141 SPOE_FRM_ERR_INVALID,
142 SPOE_FRM_ERR_NO_VSN,
143 SPOE_FRM_ERR_NO_FRAME_SIZE,
144 SPOE_FRM_ERR_NO_CAP,
145 SPOE_FRM_ERR_BAD_VSN,
146 SPOE_FRM_ERR_BAD_FRAME_SIZE,
147 SPOE_FRM_ERR_FRAG_NOT_SUPPORTED,
148 SPOE_FRM_ERR_INTERLACED_FRAMES,
149 SPOE_FRM_ERR_FRAMEID_NOTFOUND,
150 SPOE_FRM_ERR_RES,
151 SPOE_FRM_ERR_UNKNOWN = 99,
152 SPOE_FRM_ERRS,
153};
154
155/* Scopes used for variables set by agents. It is a way to be agnotic to vars
156 * scope. */
157enum spoe_vars_scope {
158 SPOE_SCOPE_PROC = 0, /* <=> SCOPE_PROC */
159 SPOE_SCOPE_SESS, /* <=> SCOPE_SESS */
160 SPOE_SCOPE_TXN, /* <=> SCOPE_TXN */
161 SPOE_SCOPE_REQ, /* <=> SCOPE_REQ */
162 SPOE_SCOPE_RES, /* <=> SCOPE_RES */
163};
164
165
166/* Describe an argument that will be linked to a message. It is a sample fetch,
167 * with an optional name. */
168struct spoe_arg {
169 char *name; /* Name of the argument, may be NULL */
170 unsigned int name_len; /* The name length, 0 if NULL */
171 struct sample_expr *expr; /* Sample expression */
172 struct list list; /* Used to chain SPOE args */
173};
174
175/* Used during the config parsing only because, when a SPOE agent section is
Christopher Faulet11610f32017-09-21 10:23:10 +0200176 * parsed, messages/groups can be undefined. */
177struct spoe_placeholder {
178 char *id; /* SPOE placeholder id */
179 struct list list; /* Use to chain SPOE placeholders */
Christopher Faulet1f40b912017-02-17 09:32:19 +0100180};
181
Christopher Faulet336d3ef2017-12-22 10:00:55 +0100182/* Used during the config parsing, when SPOE agent section is parsed, to
183 * register some variable names. */
184struct spoe_var_placeholder {
185 char *name; /* The variable name */
186 struct list list; /* Use to chain SPOE var placeholders */
187};
188
Christopher Faulet1f40b912017-02-17 09:32:19 +0100189/* Describe a message that will be sent in a NOTIFY frame. A message has a name,
190 * an argument list (see above) and it is linked to a specific event. */
191struct spoe_message {
Christopher Faulet11610f32017-09-21 10:23:10 +0200192 char *id; /* SPOE message id */
193 unsigned int id_len; /* The message id length */
194 struct spoe_agent *agent; /* SPOE agent owning this SPOE message */
195 struct spoe_group *group; /* SPOE group owning this SPOE message (can be NULL) */
Christopher Faulet1f40b912017-02-17 09:32:19 +0100196 struct {
Christopher Faulet11610f32017-09-21 10:23:10 +0200197 char *file; /* file where the SPOE message appears */
198 int line; /* line where the SPOE message appears */
Christopher Faulet1f40b912017-02-17 09:32:19 +0100199 } conf; /* config information */
Christopher Faulet11610f32017-09-21 10:23:10 +0200200 unsigned int nargs; /* # of arguments */
201 struct list args; /* Arguments added when the SPOE messages is sent */
202 struct list list; /* Used to chain SPOE messages */
203 struct list by_evt; /* By event list */
204 struct list by_grp; /* By group list */
Christopher Faulet1f40b912017-02-17 09:32:19 +0100205
Christopher Faulet11610f32017-09-21 10:23:10 +0200206 struct list acls; /* ACL declared on this message */
207 struct acl_cond *cond; /* acl condition to meet */
208 enum spoe_event event; /* SPOE_EV_* */
Christopher Faulet1f40b912017-02-17 09:32:19 +0100209};
210
Christopher Faulet11610f32017-09-21 10:23:10 +0200211/* Describe a group of messages that will be sent in a NOTIFY frame. A group has
212 * a name and a list of messages. It can be used by HAProxy, outside events
213 * processing, mainly in (tcp|http) rules. */
214struct spoe_group {
215 char *id; /* SPOE group id */
216 struct spoe_agent *agent; /* SPOE agent owning this SPOE group */
217 struct {
218 char *file; /* file where the SPOE group appears */
219 int line; /* line where the SPOE group appears */
220 } conf; /* config information */
221
222 struct list phs; /* List of placeholders used during conf parsing */
223 struct list messages; /* List of SPOE messages that will be sent by this
224 * group */
225
226 struct list list; /* Used to chain SPOE groups */
227};
228
Christopher Faulet1f40b912017-02-17 09:32:19 +0100229/* Describe a SPOE agent. */
230struct spoe_agent {
231 char *id; /* SPOE agent id (name) */
232 struct {
233 char *file; /* file where the SPOE agent appears */
234 int line; /* line where the SPOE agent appears */
235 } conf; /* config information */
236 union {
237 struct proxy *be; /* Backend used by this agent */
238 char *name; /* Backend name used during conf parsing */
239 } b;
240 struct {
241 unsigned int hello; /* Max time to receive AGENT-HELLO frame (in SPOE applet) */
242 unsigned int idle; /* Max Idle timeout (in SPOE applet) */
243 unsigned int processing; /* Max time to process an event (in the main stream) */
244 } timeout;
245
246 /* Config info */
Christopher Faulet1f40b912017-02-17 09:32:19 +0100247 char *var_pfx; /* Prefix used for vars set by the agent */
248 char *var_on_error; /* Variable to set when an error occurred, in the TXN scope */
Christopher Faulet36bda1c2018-03-22 09:08:20 +0100249 char *var_t_process; /* Variable to set to report the processing time of the last event/group, in the TXN scope */
250 char *var_t_total; /* Variable to set to report the cumulative processing time, in the TXN scope */
Christopher Faulet1f40b912017-02-17 09:32:19 +0100251 unsigned int flags; /* SPOE_FL_* */
252 unsigned int cps_max; /* Maximum # of connections per second */
253 unsigned int eps_max; /* Maximum # of errors per second */
254 unsigned int max_frame_size; /* Maximum frame size for this agent, before any negotiation */
Christopher Faulet1f40b912017-02-17 09:32:19 +0100255 unsigned int max_fpa; /* Maximum # of frames handled per applet at once */
256
Christopher Faulet11610f32017-09-21 10:23:10 +0200257 struct list events[SPOE_EV_EVENTS]; /* List of SPOE messages that will be sent
Christopher Faulet1f40b912017-02-17 09:32:19 +0100258 * for each supported events */
259
Christopher Faulet11610f32017-09-21 10:23:10 +0200260 struct list groups; /* List of available SPOE groups */
261
262 struct list messages; /* list of all messages attached to this SPOE agent */
263
Christopher Faulet1f40b912017-02-17 09:32:19 +0100264 /* running info */
Christopher Faulet24289f22017-09-25 14:48:02 +0200265 struct {
Christopher Fauletb1bb1af2019-09-17 11:55:52 +0200266 char *engine_id; /* engine-id string */
Christopher Faulet24289f22017-09-25 14:48:02 +0200267 unsigned int frame_size; /* current maximum frame size, only used to encode messages */
Christopher Faulet6f9ea4f2018-01-24 16:13:48 +0100268 unsigned int processing;
269 struct freq_ctr processing_per_sec;
Christopher Faulet24289f22017-09-25 14:48:02 +0200270
271 struct freq_ctr conn_per_sec; /* connections per second */
272 struct freq_ctr err_per_sec; /* connetion errors per second */
Christopher Faulet1f40b912017-02-17 09:32:19 +0100273
Christopher Fauletb077cdc2018-01-24 16:37:57 +0100274 struct eb_root idle_applets; /* idle SPOE applets available to process data */
275 struct list applets; /* all SPOE applets for this agent */
Christopher Faulet24289f22017-09-25 14:48:02 +0200276 struct list sending_queue; /* Queue of streams waiting to send data */
277 struct list waiting_queue; /* Queue of streams waiting for a ack, in async mode */
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100278 __decl_hathreads(HA_SPINLOCK_T lock);
Christopher Faulet24289f22017-09-25 14:48:02 +0200279 } *rt;
Christopher Faulet1f40b912017-02-17 09:32:19 +0100280
Christopher Fauletcaf2fec2018-04-04 10:25:50 +0200281 struct {
282 unsigned int applets; /* # of SPOE applets */
283 unsigned int idles; /* # of idle applets */
284 unsigned int nb_sending; /* # of streams waiting to send data */
285 unsigned int nb_waiting; /* # of streams waiting for a ack */
286 unsigned long long nb_processed; /* # of frames processed by the SPOE */
287 unsigned long long nb_errors; /* # of errors during the processing */
288 } counters;
Christopher Faulet1f40b912017-02-17 09:32:19 +0100289};
290
291/* SPOE filter configuration */
292struct spoe_config {
Christopher Faulet7ee86672017-09-19 11:08:28 +0200293 char *id; /* The SPOE engine name. If undefined in HAProxy config,
294 * it will be set with the SPOE agent name */
Christopher Faulet1f40b912017-02-17 09:32:19 +0100295 struct proxy *proxy; /* Proxy owning the filter */
296 struct spoe_agent *agent; /* Agent used by this filter */
297 struct proxy agent_fe; /* Agent frontend */
298};
299
300/* SPOE context attached to a stream. It is the main structure that handles the
301 * processing offload */
302struct spoe_context {
303 struct filter *filter; /* The SPOE filter */
304 struct stream *strm; /* The stream that should be offloaded */
305
Christopher Faulet11610f32017-09-21 10:23:10 +0200306 struct list *events; /* List of messages that will be sent during the stream processing */
Christopher Faulet76c09ef2017-09-21 11:03:52 +0200307 struct list *groups; /* List of available SPOE group */
Christopher Faulet11610f32017-09-21 10:23:10 +0200308
Willy Tarreauc9fa0482018-07-10 17:43:27 +0200309 struct buffer buffer; /* Buffer used to store a encoded messages */
Christopher Faulet1f40b912017-02-17 09:32:19 +0100310 struct buffer_wait buffer_wait; /* position in the list of ressources waiting for a buffer */
311 struct list list;
312
313 enum spoe_ctx_state state; /* SPOE_CTX_ST_* */
314 unsigned int flags; /* SPOE_CTX_FL_* */
315 unsigned int status_code; /* SPOE_CTX_ERR_* */
316
317 unsigned int stream_id; /* stream_id and frame_id are used */
318 unsigned int frame_id; /* to map NOTIFY and ACK frames */
319 unsigned int process_exp; /* expiration date to process an event */
320
Christopher Fauletfce747b2018-01-24 15:59:32 +0100321 struct spoe_appctx *spoe_appctx; /* SPOE appctx sending the current frame */
Christopher Faulet1f40b912017-02-17 09:32:19 +0100322 struct {
Christopher Faulet1f40b912017-02-17 09:32:19 +0100323 struct spoe_message *curmsg; /* SPOE message from which to resume encoding */
324 struct spoe_arg *curarg; /* SPOE arg in <curmsg> from which to resume encoding */
325 unsigned int curoff; /* offset in <curarg> from which to resume encoding */
Kevin Zhuf7f54282019-04-26 14:00:01 +0800326 unsigned int curlen; /* length of <curarg> need to be encode, for SMP_F_MAY_CHANGE data */
Christopher Faulet1f40b912017-02-17 09:32:19 +0100327 unsigned int flags; /* SPOE_FRM_FL_* */
328 } frag_ctx; /* Info about fragmented frames, valid on if SPOE_CTX_FL_FRAGMENTED is set */
Christopher Fauletb2dd1e02018-03-22 09:07:41 +0100329
330 struct {
331 struct timeval tv_start; /* start date of the current event/group */
332 struct timeval tv_request; /* date the frame processing starts (reset for each frag) */
333 struct timeval tv_queue; /* date the frame is queued (reset for each frag) */
334 struct timeval tv_wait; /* date the stream starts waiting for a response */
335 struct timeval tv_response; /* date the response processing starts */
336 long t_request; /* delay to encode and push the frame in queue (cumulative for frags) */
337 long t_queue; /* delay before the frame gets out the sending queue (cumulative for frags) */
338 long t_waiting; /* delay before the response is reveived */
339 long t_response; /* delay to process the response (from the stream pov) */
340 long t_process; /* processing time of the last event/group */
341 unsigned long t_total; /* cumulative processing time */
342 } stats; /* Stats for this stream */
Christopher Faulet1f40b912017-02-17 09:32:19 +0100343};
344
345/* SPOE context inside a appctx */
346struct spoe_appctx {
347 struct appctx *owner; /* the owner */
348 struct task *task; /* task to handle applet timeouts */
349 struct spoe_agent *agent; /* agent on which the applet is attached */
350
351 unsigned int version; /* the negotiated version */
352 unsigned int max_frame_size; /* the negotiated max-frame-size value */
353 unsigned int flags; /* SPOE_APPCTX_FL_* */
354
355 unsigned int status_code; /* SPOE_FRM_ERR_* */
356#if defined(DEBUG_SPOE) || defined(DEBUG_FULL)
357 char *reason; /* Error message, used for debugging only */
358 int rlen; /* reason length */
359#endif
360
Willy Tarreauc9fa0482018-07-10 17:43:27 +0200361 struct buffer buffer; /* Buffer used to store a encoded messages */
Christopher Faulet1f40b912017-02-17 09:32:19 +0100362 struct buffer_wait buffer_wait; /* position in the list of ressources waiting for a buffer */
363 struct list waiting_queue; /* list of streams waiting for a ACK frame, in sync and pipelining mode */
364 struct list list; /* next spoe appctx for the same agent */
Christopher Fauletb077cdc2018-01-24 16:37:57 +0100365 struct eb32_node node; /* node used for applets tree */
Christopher Faulet8f82b202018-01-24 16:23:03 +0100366 unsigned int cur_fpa;
Christopher Faulet1f40b912017-02-17 09:32:19 +0100367
368 struct {
369 struct spoe_context *ctx; /* SPOE context owning the fragmented frame */
370 unsigned int cursid; /* stream-id of the fragmented frame. used if the processing is aborted */
371 unsigned int curfid; /* frame-id of the fragmented frame. used if the processing is aborted */
372 } frag_ctx; /* Info about fragmented frames, unused for unfragmented frames */
373};
374
375/* Frame Types sent by HAProxy and by agents */
376enum spoe_frame_type {
Christopher Fauletf032c3e2017-02-17 15:18:35 +0100377 SPOE_FRM_T_UNSET = 0,
378
Christopher Faulet1f40b912017-02-17 09:32:19 +0100379 /* Frames sent by HAProxy */
380 SPOE_FRM_T_HAPROXY_HELLO = 1,
381 SPOE_FRM_T_HAPROXY_DISCON,
382 SPOE_FRM_T_HAPROXY_NOTIFY,
383
384 /* Frames sent by the agents */
385 SPOE_FRM_T_AGENT_HELLO = 101,
386 SPOE_FRM_T_AGENT_DISCON,
387 SPOE_FRM_T_AGENT_ACK
388};
389
390/* All supported data types */
391enum spoe_data_type {
392 SPOE_DATA_T_NULL = 0,
393 SPOE_DATA_T_BOOL,
394 SPOE_DATA_T_INT32,
395 SPOE_DATA_T_UINT32,
396 SPOE_DATA_T_INT64,
397 SPOE_DATA_T_UINT64,
398 SPOE_DATA_T_IPV4,
399 SPOE_DATA_T_IPV6,
400 SPOE_DATA_T_STR,
401 SPOE_DATA_T_BIN,
402 SPOE_DATA_TYPES
403};
404
405/* Masks to get data type or flags value */
406#define SPOE_DATA_T_MASK 0x0F
407#define SPOE_DATA_FL_MASK 0xF0
408
409/* Flags to set Boolean values */
410#define SPOE_DATA_FL_FALSE 0x00
411#define SPOE_DATA_FL_TRUE 0x10
412
413
414#endif /* _TYPES_SPOE_H */