1 /* 2 * include/haproxy/spoe-t.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 _HAPROXY_SPOE_T_H 23 #define _HAPROXY_SPOE_T_H 24 25 #include <sys/time.h> 26 27 #include <haproxy/buf-t.h> 28 #include <haproxy/dynbuf-t.h> 29 #include <haproxy/filters-t.h> 30 #include <haproxy/freq_ctr-t.h> 31 #include <haproxy/proxy-t.h> 32 #include <haproxy/sample-t.h> 33 #include <haproxy/stream-t.h> 34 #include <haproxy/task-t.h> 35 #include <haproxy/thread-t.h> 36 37 /* Type of list of messages */ 38 #define SPOE_MSGS_BY_EVENT 0x01 39 #define SPOE_MSGS_BY_GROUP 0x02 40 41 /* Flags set on the SPOE agent */ 42 #define SPOE_FL_CONT_ON_ERR 0x00000001 /* Do not stop events processing when an error occurred */ 43 #define SPOE_FL_PIPELINING 0x00000002 /* Set when SPOE agent supports pipelining (set by default) */ 44 #define SPOE_FL_ASYNC 0x00000004 /* Set when SPOE agent supports async (set by default) */ 45 #define SPOE_FL_SND_FRAGMENTATION 0x00000008 /* Set when SPOE agent supports sending fragmented payload */ 46 #define SPOE_FL_RCV_FRAGMENTATION 0x00000010 /* Set when SPOE agent supports receiving fragmented payload */ 47 #define SPOE_FL_FORCE_SET_VAR 0x00000020 /* Set when SPOE agent will set all variables from agent (and not only known variables) */ 48 49 /* Flags set on the SPOE context */ 50 #define SPOE_CTX_FL_CLI_CONNECTED 0x00000001 /* Set after that on-client-session event was processed */ 51 #define SPOE_CTX_FL_SRV_CONNECTED 0x00000002 /* Set after that on-server-session event was processed */ 52 #define SPOE_CTX_FL_REQ_PROCESS 0x00000004 /* Set when SPOE is processing the request */ 53 #define SPOE_CTX_FL_RSP_PROCESS 0x00000008 /* Set when SPOE is processing the response */ 54 #define SPOE_CTX_FL_FRAGMENTED 0x00000010 /* Set when a fragmented frame is processing */ 55 56 #define SPOE_CTX_FL_PROCESS (SPOE_CTX_FL_REQ_PROCESS|SPOE_CTX_FL_RSP_PROCESS) 57 58 /* Flags set on the SPOE applet */ 59 #define SPOE_APPCTX_FL_PIPELINING 0x00000001 /* Set if pipelining is supported */ 60 #define SPOE_APPCTX_FL_ASYNC 0x00000002 /* Set if asynchronus frames is supported */ 61 #define SPOE_APPCTX_FL_FRAGMENTATION 0x00000004 /* Set if fragmentation is supported */ 62 63 #define SPOE_APPCTX_ERR_NONE 0x00000000 /* no error yet, leave it to zero */ 64 #define SPOE_APPCTX_ERR_TOUT 0x00000001 /* SPOE applet timeout */ 65 66 /* Flags set on the SPOE frame */ 67 #define SPOE_FRM_FL_FIN 0x00000001 68 #define SPOE_FRM_FL_ABRT 0x00000002 69 70 /* Masks to get data type or flags value */ 71 #define SPOE_DATA_T_MASK 0x0F 72 #define SPOE_DATA_FL_MASK 0xF0 73 74 /* Flags to set Boolean values */ 75 #define SPOE_DATA_FL_FALSE 0x00 76 #define SPOE_DATA_FL_TRUE 0x10 77 78 /* All possible states for a SPOE context */ 79 enum spoe_ctx_state { 80 SPOE_CTX_ST_NONE = 0, 81 SPOE_CTX_ST_READY, 82 SPOE_CTX_ST_ENCODING_MSGS, 83 SPOE_CTX_ST_SENDING_MSGS, 84 SPOE_CTX_ST_WAITING_ACK, 85 SPOE_CTX_ST_DONE, 86 SPOE_CTX_ST_ERROR, 87 }; 88 89 /* All possible states for a SPOE applet */ 90 enum spoe_appctx_state { 91 SPOE_APPCTX_ST_CONNECT = 0, 92 SPOE_APPCTX_ST_CONNECTING, 93 SPOE_APPCTX_ST_IDLE, 94 SPOE_APPCTX_ST_PROCESSING, 95 SPOE_APPCTX_ST_SENDING_FRAG_NOTIFY, 96 SPOE_APPCTX_ST_WAITING_SYNC_ACK, 97 SPOE_APPCTX_ST_DISCONNECT, 98 SPOE_APPCTX_ST_DISCONNECTING, 99 SPOE_APPCTX_ST_EXIT, 100 SPOE_APPCTX_ST_END, 101 }; 102 103 /* All supported SPOE actions */ 104 enum spoe_action_type { 105 SPOE_ACT_T_SET_VAR = 1, 106 SPOE_ACT_T_UNSET_VAR, 107 SPOE_ACT_TYPES, 108 }; 109 110 /* All supported SPOE events */ 111 enum spoe_event { 112 SPOE_EV_NONE = 0, 113 114 /* Request events */ 115 SPOE_EV_ON_CLIENT_SESS = 1, 116 SPOE_EV_ON_TCP_REQ_FE, 117 SPOE_EV_ON_TCP_REQ_BE, 118 SPOE_EV_ON_HTTP_REQ_FE, 119 SPOE_EV_ON_HTTP_REQ_BE, 120 121 /* Response events */ 122 SPOE_EV_ON_SERVER_SESS, 123 SPOE_EV_ON_TCP_RSP, 124 SPOE_EV_ON_HTTP_RSP, 125 126 SPOE_EV_EVENTS 127 }; 128 129 /* Errors triggered by streams */ 130 enum spoe_context_error { 131 SPOE_CTX_ERR_NONE = 0, 132 SPOE_CTX_ERR_TOUT, 133 SPOE_CTX_ERR_RES, 134 SPOE_CTX_ERR_TOO_BIG, 135 SPOE_CTX_ERR_FRAG_FRAME_ABRT, 136 SPOE_CTX_ERR_INTERRUPT, 137 SPOE_CTX_ERR_UNKNOWN = 255, 138 SPOE_CTX_ERRS, 139 }; 140 141 /* Errors triggered by SPOE applet */ 142 enum spoe_frame_error { 143 SPOE_FRM_ERR_NONE = 0, 144 SPOE_FRM_ERR_IO, 145 SPOE_FRM_ERR_TOUT, 146 SPOE_FRM_ERR_TOO_BIG, 147 SPOE_FRM_ERR_INVALID, 148 SPOE_FRM_ERR_NO_VSN, 149 SPOE_FRM_ERR_NO_FRAME_SIZE, 150 SPOE_FRM_ERR_NO_CAP, 151 SPOE_FRM_ERR_BAD_VSN, 152 SPOE_FRM_ERR_BAD_FRAME_SIZE, 153 SPOE_FRM_ERR_FRAG_NOT_SUPPORTED, 154 SPOE_FRM_ERR_INTERLACED_FRAMES, 155 SPOE_FRM_ERR_FRAMEID_NOTFOUND, 156 SPOE_FRM_ERR_RES, 157 SPOE_FRM_ERR_UNKNOWN = 99, 158 SPOE_FRM_ERRS, 159 }; 160 161 /* Scopes used for variables set by agents. It is a way to be agnotic to vars 162 * scope. */ 163 enum spoe_vars_scope { 164 SPOE_SCOPE_PROC = 0, /* <=> SCOPE_PROC */ 165 SPOE_SCOPE_SESS, /* <=> SCOPE_SESS */ 166 SPOE_SCOPE_TXN, /* <=> SCOPE_TXN */ 167 SPOE_SCOPE_REQ, /* <=> SCOPE_REQ */ 168 SPOE_SCOPE_RES, /* <=> SCOPE_RES */ 169 }; 170 171 /* Frame Types sent by HAProxy and by agents */ 172 enum spoe_frame_type { 173 SPOE_FRM_T_UNSET = 0, 174 175 /* Frames sent by HAProxy */ 176 SPOE_FRM_T_HAPROXY_HELLO = 1, 177 SPOE_FRM_T_HAPROXY_DISCON, 178 SPOE_FRM_T_HAPROXY_NOTIFY, 179 180 /* Frames sent by the agents */ 181 SPOE_FRM_T_AGENT_HELLO = 101, 182 SPOE_FRM_T_AGENT_DISCON, 183 SPOE_FRM_T_AGENT_ACK 184 }; 185 186 /* All supported data types */ 187 enum spoe_data_type { 188 SPOE_DATA_T_NULL = 0, 189 SPOE_DATA_T_BOOL, 190 SPOE_DATA_T_INT32, 191 SPOE_DATA_T_UINT32, 192 SPOE_DATA_T_INT64, 193 SPOE_DATA_T_UINT64, 194 SPOE_DATA_T_IPV4, 195 SPOE_DATA_T_IPV6, 196 SPOE_DATA_T_STR, 197 SPOE_DATA_T_BIN, 198 SPOE_DATA_TYPES 199 }; 200 201 202 /* Describe an argument that will be linked to a message. It is a sample fetch, 203 * with an optional name. */ 204 struct spoe_arg { 205 char *name; /* Name of the argument, may be NULL */ 206 unsigned int name_len; /* The name length, 0 if NULL */ 207 struct sample_expr *expr; /* Sample expression */ 208 struct list list; /* Used to chain SPOE args */ 209 }; 210 211 /* Used during the config parsing only because, when a SPOE agent section is 212 * parsed, messages/groups can be undefined. */ 213 struct spoe_placeholder { 214 char *id; /* SPOE placeholder id */ 215 struct list list; /* Use to chain SPOE placeholders */ 216 }; 217 218 /* Used during the config parsing, when SPOE agent section is parsed, to 219 * register some variable names. */ 220 struct spoe_var_placeholder { 221 char *name; /* The variable name */ 222 struct list list; /* Use to chain SPOE var placeholders */ 223 }; 224 225 /* Describe a message that will be sent in a NOTIFY frame. A message has a name, 226 * an argument list (see above) and it is linked to a specific event. */ 227 struct spoe_message { 228 char *id; /* SPOE message id */ 229 unsigned int id_len; /* The message id length */ 230 struct spoe_agent *agent; /* SPOE agent owning this SPOE message */ 231 struct spoe_group *group; /* SPOE group owning this SPOE message (can be NULL) */ 232 struct { 233 char *file; /* file where the SPOE message appears */ 234 int line; /* line where the SPOE message appears */ 235 } conf; /* config information */ 236 unsigned int nargs; /* # of arguments */ 237 struct list args; /* Arguments added when the SPOE messages is sent */ 238 struct list list; /* Used to chain SPOE messages */ 239 struct list by_evt; /* By event list */ 240 struct list by_grp; /* By group list */ 241 242 struct list acls; /* ACL declared on this message */ 243 struct acl_cond *cond; /* acl condition to meet */ 244 enum spoe_event event; /* SPOE_EV_* */ 245 }; 246 247 /* Describe a group of messages that will be sent in a NOTIFY frame. A group has 248 * a name and a list of messages. It can be used by HAProxy, outside events 249 * processing, mainly in (tcp|http) rules. */ 250 struct spoe_group { 251 char *id; /* SPOE group id */ 252 struct spoe_agent *agent; /* SPOE agent owning this SPOE group */ 253 struct { 254 char *file; /* file where the SPOE group appears */ 255 int line; /* line where the SPOE group appears */ 256 } conf; /* config information */ 257 258 struct list phs; /* List of placeholders used during conf parsing */ 259 struct list messages; /* List of SPOE messages that will be sent by this 260 * group */ 261 262 struct list list; /* Used to chain SPOE groups */ 263 }; 264 265 /* Describe a SPOE agent. */ 266 struct spoe_agent { 267 char *id; /* SPOE agent id (name) */ 268 struct { 269 char *file; /* file where the SPOE agent appears */ 270 int line; /* line where the SPOE agent appears */ 271 } conf; /* config information */ 272 union { 273 struct proxy *be; /* Backend used by this agent */ 274 char *name; /* Backend name used during conf parsing */ 275 } b; 276 struct { 277 unsigned int hello; /* Max time to receive AGENT-HELLO frame (in SPOE applet) */ 278 unsigned int idle; /* Max Idle timeout (in SPOE applet) */ 279 unsigned int processing; /* Max time to process an event (in the main stream) */ 280 } timeout; 281 282 /* Config info */ 283 struct spoe_config *spoe_conf; /* SPOE filter config */ 284 char *var_pfx; /* Prefix used for vars set by the agent */ 285 char *var_on_error; /* Variable to set when an error occurred, in the TXN scope */ 286 char *var_t_process; /* Variable to set to report the processing time of the last event/group, in the TXN scope */ 287 char *var_t_total; /* Variable to set to report the cumulative processing time, in the TXN scope */ 288 unsigned int flags; /* SPOE_FL_* */ 289 unsigned int cps_max; /* Maximum # of connections per second */ 290 unsigned int eps_max; /* Maximum # of errors per second */ 291 unsigned int max_frame_size; /* Maximum frame size for this agent, before any negotiation */ 292 unsigned int max_fpa; /* Maximum # of frames handled per applet at once */ 293 294 struct list events[SPOE_EV_EVENTS]; /* List of SPOE messages that will be sent 295 * for each supported events */ 296 297 struct list groups; /* List of available SPOE groups */ 298 299 struct list messages; /* list of all messages attached to this SPOE agent */ 300 301 /* running info */ 302 struct { 303 char *engine_id; /* engine-id string */ 304 unsigned int frame_size; /* current maximum frame size, only used to encode messages */ 305 unsigned int processing; 306 struct freq_ctr processing_per_sec; 307 308 struct freq_ctr conn_per_sec; /* connections per second */ 309 struct freq_ctr err_per_sec; /* connection errors per second */ 310 311 struct eb_root idle_applets; /* idle SPOE applets available to process data */ 312 struct list applets; /* all SPOE applets for this agent */ 313 struct list sending_queue; /* Queue of streams waiting to send data */ 314 struct list waiting_queue; /* Queue of streams waiting for a ack, in async mode */ 315 __decl_thread(HA_SPINLOCK_T lock); 316 } *rt; 317 318 struct { 319 unsigned int applets; /* # of SPOE applets */ 320 unsigned int idles; /* # of idle applets */ 321 unsigned int nb_sending; /* # of streams waiting to send data */ 322 unsigned int nb_waiting; /* # of streams waiting for a ack */ 323 unsigned long long nb_processed; /* # of frames processed by the SPOE */ 324 unsigned long long nb_errors; /* # of errors during the processing */ 325 } counters; 326 }; 327 328 /* SPOE filter configuration */ 329 struct spoe_config { 330 char *id; /* The SPOE engine name. If undefined in HAProxy config, 331 * it will be set with the SPOE agent name */ 332 struct proxy *proxy; /* Proxy owning the filter */ 333 struct spoe_agent *agent; /* Agent used by this filter */ 334 struct proxy agent_fe; /* Agent frontend */ 335 }; 336 337 /* SPOE context attached to a stream. It is the main structure that handles the 338 * processing offload */ 339 struct spoe_context { 340 struct filter *filter; /* The SPOE filter */ 341 struct stream *strm; /* The stream that should be offloaded */ 342 343 struct list *events; /* List of messages that will be sent during the stream processing */ 344 struct list *groups; /* List of available SPOE group */ 345 346 struct buffer buffer; /* Buffer used to store a encoded messages */ 347 struct buffer_wait buffer_wait; /* position in the list of resources waiting for a buffer */ 348 struct list list; 349 350 enum spoe_ctx_state state; /* SPOE_CTX_ST_* */ 351 unsigned int flags; /* SPOE_CTX_FL_* */ 352 unsigned int status_code; /* SPOE_CTX_ERR_* */ 353 354 unsigned int stream_id; /* stream_id and frame_id are used */ 355 unsigned int frame_id; /* to map NOTIFY and ACK frames */ 356 unsigned int process_exp; /* expiration date to process an event */ 357 358 struct spoe_appctx *spoe_appctx; /* SPOE appctx sending the current frame */ 359 struct { 360 struct spoe_message *curmsg; /* SPOE message from which to resume encoding */ 361 struct spoe_arg *curarg; /* SPOE arg in <curmsg> from which to resume encoding */ 362 unsigned int curoff; /* offset in <curarg> from which to resume encoding */ 363 unsigned int curlen; /* length of <curarg> need to be encode, for SMP_F_MAY_CHANGE data */ 364 unsigned int flags; /* SPOE_FRM_FL_* */ 365 } frag_ctx; /* Info about fragmented frames, valid on if SPOE_CTX_FL_FRAGMENTED is set */ 366 367 struct { 368 struct timeval tv_start; /* start date of the current event/group */ 369 struct timeval tv_request; /* date the frame processing starts (reset for each frag) */ 370 struct timeval tv_queue; /* date the frame is queued (reset for each frag) */ 371 struct timeval tv_wait; /* date the stream starts waiting for a response */ 372 struct timeval tv_response; /* date the response processing starts */ 373 long t_request; /* delay to encode and push the frame in queue (cumulative for frags) */ 374 long t_queue; /* delay before the frame gets out the sending queue (cumulative for frags) */ 375 long t_waiting; /* delay before the response is reveived */ 376 long t_response; /* delay to process the response (from the stream pov) */ 377 long t_process; /* processing time of the last event/group */ 378 unsigned long t_total; /* cumulative processing time */ 379 } stats; /* Stats for this stream */ 380 }; 381 382 /* SPOE context inside a appctx */ 383 struct spoe_appctx { 384 struct appctx *owner; /* the owner */ 385 struct task *task; /* task to handle applet timeouts */ 386 struct spoe_agent *agent; /* agent on which the applet is attached */ 387 388 unsigned int version; /* the negotiated version */ 389 unsigned int max_frame_size; /* the negotiated max-frame-size value */ 390 unsigned int flags; /* SPOE_APPCTX_FL_* */ 391 392 unsigned int status_code; /* SPOE_FRM_ERR_* */ 393 #if defined(DEBUG_SPOE) || defined(DEBUG_FULL) 394 char *reason; /* Error message, used for debugging only */ 395 int rlen; /* reason length */ 396 #endif 397 398 struct buffer buffer; /* Buffer used to store a encoded messages */ 399 struct buffer_wait buffer_wait; /* position in the list of resources waiting for a buffer */ 400 struct list waiting_queue; /* list of streams waiting for a ACK frame, in sync and pipelining mode */ 401 struct list list; /* next spoe appctx for the same agent */ 402 struct eb32_node node; /* node used for applets tree */ 403 unsigned int cur_fpa; 404 405 struct { 406 struct spoe_context *ctx; /* SPOE context owning the fragmented frame */ 407 unsigned int cursid; /* stream-id of the fragmented frame. used if the processing is aborted */ 408 unsigned int curfid; /* frame-id of the fragmented frame. used if the processing is aborted */ 409 } frag_ctx; /* Info about fragmented frames, unused for unfragmented frames */ 410 }; 411 412 #endif /* _HAPROXY_SPOE_T_H */ 413