You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
412 lines
16 KiB
412 lines
16 KiB
5 months ago
|
/*
|
||
|
* include/haproxy/spoe-t.h
|
||
|
* Macros, variables and structures for the SPOE filter.
|
||
|
*
|
||
|
* Copyright (C) 2017 HAProxy Technologies, Christopher Faulet <cfaulet@haproxy.com>
|
||
|
*
|
||
|
* This library is free software; you can redistribute it and/or
|
||
|
* modify it under the terms of the GNU Lesser General Public
|
||
|
* License as published by the Free Software Foundation, version 2.1
|
||
|
* exclusively.
|
||
|
*
|
||
|
* This library is distributed in the hope that it will be useful,
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
|
* Lesser General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU Lesser General Public
|
||
|
* License along with this library; if not, write to the Free Software
|
||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||
|
*/
|
||
|
|
||
|
#ifndef _HAPROXY_SPOE_T_H
|
||
|
#define _HAPROXY_SPOE_T_H
|
||
|
|
||
|
#include <sys/time.h>
|
||
|
|
||
|
#include <haproxy/buf-t.h>
|
||
|
#include <haproxy/dynbuf-t.h>
|
||
|
#include <haproxy/filters-t.h>
|
||
|
#include <haproxy/freq_ctr-t.h>
|
||
|
#include <haproxy/proxy-t.h>
|
||
|
#include <haproxy/sample-t.h>
|
||
|
#include <haproxy/stream-t.h>
|
||
|
#include <haproxy/task-t.h>
|
||
|
#include <haproxy/thread-t.h>
|
||
|
|
||
|
/* Type of list of messages */
|
||
|
#define SPOE_MSGS_BY_EVENT 0x01
|
||
|
#define SPOE_MSGS_BY_GROUP 0x02
|
||
|
|
||
|
/* Flags set on the SPOE agent */
|
||
|
#define SPOE_FL_CONT_ON_ERR 0x00000001 /* Do not stop events processing when an error occurred */
|
||
|
#define SPOE_FL_PIPELINING 0x00000002 /* Set when SPOE agent supports pipelining (set by default) */
|
||
|
#define SPOE_FL_ASYNC 0x00000004 /* Set when SPOE agent supports async (set by default) */
|
||
|
#define SPOE_FL_SND_FRAGMENTATION 0x00000008 /* Set when SPOE agent supports sending fragmented payload */
|
||
|
#define SPOE_FL_RCV_FRAGMENTATION 0x00000010 /* Set when SPOE agent supports receiving fragmented payload */
|
||
|
#define SPOE_FL_FORCE_SET_VAR 0x00000020 /* Set when SPOE agent will set all variables from agent (and not only known variables) */
|
||
|
|
||
|
/* Flags set on the SPOE context */
|
||
|
#define SPOE_CTX_FL_CLI_CONNECTED 0x00000001 /* Set after that on-client-session event was processed */
|
||
|
#define SPOE_CTX_FL_SRV_CONNECTED 0x00000002 /* Set after that on-server-session event was processed */
|
||
|
#define SPOE_CTX_FL_REQ_PROCESS 0x00000004 /* Set when SPOE is processing the request */
|
||
|
#define SPOE_CTX_FL_RSP_PROCESS 0x00000008 /* Set when SPOE is processing the response */
|
||
|
#define SPOE_CTX_FL_FRAGMENTED 0x00000010 /* Set when a fragmented frame is processing */
|
||
|
|
||
|
#define SPOE_CTX_FL_PROCESS (SPOE_CTX_FL_REQ_PROCESS|SPOE_CTX_FL_RSP_PROCESS)
|
||
|
|
||
|
/* Flags set on the SPOE applet */
|
||
|
#define SPOE_APPCTX_FL_PIPELINING 0x00000001 /* Set if pipelining is supported */
|
||
|
#define SPOE_APPCTX_FL_ASYNC 0x00000002 /* Set if asynchronus frames is supported */
|
||
|
#define SPOE_APPCTX_FL_FRAGMENTATION 0x00000004 /* Set if fragmentation is supported */
|
||
|
|
||
|
#define SPOE_APPCTX_ERR_NONE 0x00000000 /* no error yet, leave it to zero */
|
||
|
#define SPOE_APPCTX_ERR_TOUT 0x00000001 /* SPOE applet timeout */
|
||
|
|
||
|
/* Flags set on the SPOE frame */
|
||
|
#define SPOE_FRM_FL_FIN 0x00000001
|
||
|
#define SPOE_FRM_FL_ABRT 0x00000002
|
||
|
|
||
|
/* Masks to get data type or flags value */
|
||
|
#define SPOE_DATA_T_MASK 0x0F
|
||
|
#define SPOE_DATA_FL_MASK 0xF0
|
||
|
|
||
|
/* Flags to set Boolean values */
|
||
|
#define SPOE_DATA_FL_FALSE 0x00
|
||
|
#define SPOE_DATA_FL_TRUE 0x10
|
||
|
|
||
|
/* All possible states for a SPOE context */
|
||
|
enum spoe_ctx_state {
|
||
|
SPOE_CTX_ST_NONE = 0,
|
||
|
SPOE_CTX_ST_READY,
|
||
|
SPOE_CTX_ST_ENCODING_MSGS,
|
||
|
SPOE_CTX_ST_SENDING_MSGS,
|
||
|
SPOE_CTX_ST_WAITING_ACK,
|
||
|
SPOE_CTX_ST_DONE,
|
||
|
SPOE_CTX_ST_ERROR,
|
||
|
};
|
||
|
|
||
|
/* All possible states for a SPOE applet */
|
||
|
enum spoe_appctx_state {
|
||
|
SPOE_APPCTX_ST_CONNECT = 0,
|
||
|
SPOE_APPCTX_ST_CONNECTING,
|
||
|
SPOE_APPCTX_ST_IDLE,
|
||
|
SPOE_APPCTX_ST_PROCESSING,
|
||
|
SPOE_APPCTX_ST_SENDING_FRAG_NOTIFY,
|
||
|
SPOE_APPCTX_ST_WAITING_SYNC_ACK,
|
||
|
SPOE_APPCTX_ST_DISCONNECT,
|
||
|
SPOE_APPCTX_ST_DISCONNECTING,
|
||
|
SPOE_APPCTX_ST_EXIT,
|
||
|
SPOE_APPCTX_ST_END,
|
||
|
};
|
||
|
|
||
|
/* All supported SPOE actions */
|
||
|
enum spoe_action_type {
|
||
|
SPOE_ACT_T_SET_VAR = 1,
|
||
|
SPOE_ACT_T_UNSET_VAR,
|
||
|
SPOE_ACT_TYPES,
|
||
|
};
|
||
|
|
||
|
/* All supported SPOE events */
|
||
|
enum spoe_event {
|
||
|
SPOE_EV_NONE = 0,
|
||
|
|
||
|
/* Request events */
|
||
|
SPOE_EV_ON_CLIENT_SESS = 1,
|
||
|
SPOE_EV_ON_TCP_REQ_FE,
|
||
|
SPOE_EV_ON_TCP_REQ_BE,
|
||
|
SPOE_EV_ON_HTTP_REQ_FE,
|
||
|
SPOE_EV_ON_HTTP_REQ_BE,
|
||
|
|
||
|
/* Response events */
|
||
|
SPOE_EV_ON_SERVER_SESS,
|
||
|
SPOE_EV_ON_TCP_RSP,
|
||
|
SPOE_EV_ON_HTTP_RSP,
|
||
|
|
||
|
SPOE_EV_EVENTS
|
||
|
};
|
||
|
|
||
|
/* Errors triggered by streams */
|
||
|
enum spoe_context_error {
|
||
|
SPOE_CTX_ERR_NONE = 0,
|
||
|
SPOE_CTX_ERR_TOUT,
|
||
|
SPOE_CTX_ERR_RES,
|
||
|
SPOE_CTX_ERR_TOO_BIG,
|
||
|
SPOE_CTX_ERR_FRAG_FRAME_ABRT,
|
||
|
SPOE_CTX_ERR_INTERRUPT,
|
||
|
SPOE_CTX_ERR_UNKNOWN = 255,
|
||
|
SPOE_CTX_ERRS,
|
||
|
};
|
||
|
|
||
|
/* Errors triggered by SPOE applet */
|
||
|
enum spoe_frame_error {
|
||
|
SPOE_FRM_ERR_NONE = 0,
|
||
|
SPOE_FRM_ERR_IO,
|
||
|
SPOE_FRM_ERR_TOUT,
|
||
|
SPOE_FRM_ERR_TOO_BIG,
|
||
|
SPOE_FRM_ERR_INVALID,
|
||
|
SPOE_FRM_ERR_NO_VSN,
|
||
|
SPOE_FRM_ERR_NO_FRAME_SIZE,
|
||
|
SPOE_FRM_ERR_NO_CAP,
|
||
|
SPOE_FRM_ERR_BAD_VSN,
|
||
|
SPOE_FRM_ERR_BAD_FRAME_SIZE,
|
||
|
SPOE_FRM_ERR_FRAG_NOT_SUPPORTED,
|
||
|
SPOE_FRM_ERR_INTERLACED_FRAMES,
|
||
|
SPOE_FRM_ERR_FRAMEID_NOTFOUND,
|
||
|
SPOE_FRM_ERR_RES,
|
||
|
SPOE_FRM_ERR_UNKNOWN = 99,
|
||
|
SPOE_FRM_ERRS,
|
||
|
};
|
||
|
|
||
|
/* Scopes used for variables set by agents. It is a way to be agnotic to vars
|
||
|
* scope. */
|
||
|
enum spoe_vars_scope {
|
||
|
SPOE_SCOPE_PROC = 0, /* <=> SCOPE_PROC */
|
||
|
SPOE_SCOPE_SESS, /* <=> SCOPE_SESS */
|
||
|
SPOE_SCOPE_TXN, /* <=> SCOPE_TXN */
|
||
|
SPOE_SCOPE_REQ, /* <=> SCOPE_REQ */
|
||
|
SPOE_SCOPE_RES, /* <=> SCOPE_RES */
|
||
|
};
|
||
|
|
||
|
/* Frame Types sent by HAProxy and by agents */
|
||
|
enum spoe_frame_type {
|
||
|
SPOE_FRM_T_UNSET = 0,
|
||
|
|
||
|
/* Frames sent by HAProxy */
|
||
|
SPOE_FRM_T_HAPROXY_HELLO = 1,
|
||
|
SPOE_FRM_T_HAPROXY_DISCON,
|
||
|
SPOE_FRM_T_HAPROXY_NOTIFY,
|
||
|
|
||
|
/* Frames sent by the agents */
|
||
|
SPOE_FRM_T_AGENT_HELLO = 101,
|
||
|
SPOE_FRM_T_AGENT_DISCON,
|
||
|
SPOE_FRM_T_AGENT_ACK
|
||
|
};
|
||
|
|
||
|
/* All supported data types */
|
||
|
enum spoe_data_type {
|
||
|
SPOE_DATA_T_NULL = 0,
|
||
|
SPOE_DATA_T_BOOL,
|
||
|
SPOE_DATA_T_INT32,
|
||
|
SPOE_DATA_T_UINT32,
|
||
|
SPOE_DATA_T_INT64,
|
||
|
SPOE_DATA_T_UINT64,
|
||
|
SPOE_DATA_T_IPV4,
|
||
|
SPOE_DATA_T_IPV6,
|
||
|
SPOE_DATA_T_STR,
|
||
|
SPOE_DATA_T_BIN,
|
||
|
SPOE_DATA_TYPES
|
||
|
};
|
||
|
|
||
|
|
||
|
/* Describe an argument that will be linked to a message. It is a sample fetch,
|
||
|
* with an optional name. */
|
||
|
struct spoe_arg {
|
||
|
char *name; /* Name of the argument, may be NULL */
|
||
|
unsigned int name_len; /* The name length, 0 if NULL */
|
||
|
struct sample_expr *expr; /* Sample expression */
|
||
|
struct list list; /* Used to chain SPOE args */
|
||
|
};
|
||
|
|
||
|
/* Used during the config parsing only because, when a SPOE agent section is
|
||
|
* parsed, messages/groups can be undefined. */
|
||
|
struct spoe_placeholder {
|
||
|
char *id; /* SPOE placeholder id */
|
||
|
struct list list; /* Use to chain SPOE placeholders */
|
||
|
};
|
||
|
|
||
|
/* Used during the config parsing, when SPOE agent section is parsed, to
|
||
|
* register some variable names. */
|
||
|
struct spoe_var_placeholder {
|
||
|
char *name; /* The variable name */
|
||
|
struct list list; /* Use to chain SPOE var placeholders */
|
||
|
};
|
||
|
|
||
|
/* Describe a message that will be sent in a NOTIFY frame. A message has a name,
|
||
|
* an argument list (see above) and it is linked to a specific event. */
|
||
|
struct spoe_message {
|
||
|
char *id; /* SPOE message id */
|
||
|
unsigned int id_len; /* The message id length */
|
||
|
struct spoe_agent *agent; /* SPOE agent owning this SPOE message */
|
||
|
struct spoe_group *group; /* SPOE group owning this SPOE message (can be NULL) */
|
||
|
struct {
|
||
|
char *file; /* file where the SPOE message appears */
|
||
|
int line; /* line where the SPOE message appears */
|
||
|
} conf; /* config information */
|
||
|
unsigned int nargs; /* # of arguments */
|
||
|
struct list args; /* Arguments added when the SPOE messages is sent */
|
||
|
struct list list; /* Used to chain SPOE messages */
|
||
|
struct list by_evt; /* By event list */
|
||
|
struct list by_grp; /* By group list */
|
||
|
|
||
|
struct list acls; /* ACL declared on this message */
|
||
|
struct acl_cond *cond; /* acl condition to meet */
|
||
|
enum spoe_event event; /* SPOE_EV_* */
|
||
|
};
|
||
|
|
||
|
/* Describe a group of messages that will be sent in a NOTIFY frame. A group has
|
||
|
* a name and a list of messages. It can be used by HAProxy, outside events
|
||
|
* processing, mainly in (tcp|http) rules. */
|
||
|
struct spoe_group {
|
||
|
char *id; /* SPOE group id */
|
||
|
struct spoe_agent *agent; /* SPOE agent owning this SPOE group */
|
||
|
struct {
|
||
|
char *file; /* file where the SPOE group appears */
|
||
|
int line; /* line where the SPOE group appears */
|
||
|
} conf; /* config information */
|
||
|
|
||
|
struct list phs; /* List of placeholders used during conf parsing */
|
||
|
struct list messages; /* List of SPOE messages that will be sent by this
|
||
|
* group */
|
||
|
|
||
|
struct list list; /* Used to chain SPOE groups */
|
||
|
};
|
||
|
|
||
|
/* Describe a SPOE agent. */
|
||
|
struct spoe_agent {
|
||
|
char *id; /* SPOE agent id (name) */
|
||
|
struct {
|
||
|
char *file; /* file where the SPOE agent appears */
|
||
|
int line; /* line where the SPOE agent appears */
|
||
|
} conf; /* config information */
|
||
|
union {
|
||
|
struct proxy *be; /* Backend used by this agent */
|
||
|
char *name; /* Backend name used during conf parsing */
|
||
|
} b;
|
||
|
struct {
|
||
|
unsigned int hello; /* Max time to receive AGENT-HELLO frame (in SPOE applet) */
|
||
|
unsigned int idle; /* Max Idle timeout (in SPOE applet) */
|
||
|
unsigned int processing; /* Max time to process an event (in the main stream) */
|
||
|
} timeout;
|
||
|
|
||
|
/* Config info */
|
||
|
char *var_pfx; /* Prefix used for vars set by the agent */
|
||
|
char *var_on_error; /* Variable to set when an error occurred, in the TXN scope */
|
||
|
char *var_t_process; /* Variable to set to report the processing time of the last event/group, in the TXN scope */
|
||
|
char *var_t_total; /* Variable to set to report the cumulative processing time, in the TXN scope */
|
||
|
unsigned int flags; /* SPOE_FL_* */
|
||
|
unsigned int cps_max; /* Maximum # of connections per second */
|
||
|
unsigned int eps_max; /* Maximum # of errors per second */
|
||
|
unsigned int max_frame_size; /* Maximum frame size for this agent, before any negotiation */
|
||
|
unsigned int max_fpa; /* Maximum # of frames handled per applet at once */
|
||
|
|
||
|
struct list events[SPOE_EV_EVENTS]; /* List of SPOE messages that will be sent
|
||
|
* for each supported events */
|
||
|
|
||
|
struct list groups; /* List of available SPOE groups */
|
||
|
|
||
|
struct list messages; /* list of all messages attached to this SPOE agent */
|
||
|
|
||
|
/* running info */
|
||
|
struct {
|
||
|
char *engine_id; /* engine-id string */
|
||
|
unsigned int frame_size; /* current maximum frame size, only used to encode messages */
|
||
|
unsigned int processing;
|
||
|
struct freq_ctr processing_per_sec;
|
||
|
|
||
|
struct freq_ctr conn_per_sec; /* connections per second */
|
||
|
struct freq_ctr err_per_sec; /* connection errors per second */
|
||
|
|
||
|
struct eb_root idle_applets; /* idle SPOE applets available to process data */
|
||
|
struct list applets; /* all SPOE applets for this agent */
|
||
|
struct list sending_queue; /* Queue of streams waiting to send data */
|
||
|
struct list waiting_queue; /* Queue of streams waiting for a ack, in async mode */
|
||
|
__decl_thread(HA_SPINLOCK_T lock);
|
||
|
} *rt;
|
||
|
|
||
|
struct {
|
||
|
unsigned int applets; /* # of SPOE applets */
|
||
|
unsigned int idles; /* # of idle applets */
|
||
|
unsigned int nb_sending; /* # of streams waiting to send data */
|
||
|
unsigned int nb_waiting; /* # of streams waiting for a ack */
|
||
|
unsigned long long nb_processed; /* # of frames processed by the SPOE */
|
||
|
unsigned long long nb_errors; /* # of errors during the processing */
|
||
|
} counters;
|
||
|
};
|
||
|
|
||
|
/* SPOE filter configuration */
|
||
|
struct spoe_config {
|
||
|
char *id; /* The SPOE engine name. If undefined in HAProxy config,
|
||
|
* it will be set with the SPOE agent name */
|
||
|
struct proxy *proxy; /* Proxy owning the filter */
|
||
|
struct spoe_agent *agent; /* Agent used by this filter */
|
||
|
struct proxy agent_fe; /* Agent frontend */
|
||
|
};
|
||
|
|
||
|
/* SPOE context attached to a stream. It is the main structure that handles the
|
||
|
* processing offload */
|
||
|
struct spoe_context {
|
||
|
struct filter *filter; /* The SPOE filter */
|
||
|
struct stream *strm; /* The stream that should be offloaded */
|
||
|
|
||
|
struct list *events; /* List of messages that will be sent during the stream processing */
|
||
|
struct list *groups; /* List of available SPOE group */
|
||
|
|
||
|
struct buffer buffer; /* Buffer used to store a encoded messages */
|
||
|
struct buffer_wait buffer_wait; /* position in the list of resources waiting for a buffer */
|
||
|
struct list list;
|
||
|
|
||
|
enum spoe_ctx_state state; /* SPOE_CTX_ST_* */
|
||
|
unsigned int flags; /* SPOE_CTX_FL_* */
|
||
|
unsigned int status_code; /* SPOE_CTX_ERR_* */
|
||
|
|
||
|
unsigned int stream_id; /* stream_id and frame_id are used */
|
||
|
unsigned int frame_id; /* to map NOTIFY and ACK frames */
|
||
|
unsigned int process_exp; /* expiration date to process an event */
|
||
|
|
||
|
struct spoe_appctx *spoe_appctx; /* SPOE appctx sending the current frame */
|
||
|
struct {
|
||
|
struct spoe_message *curmsg; /* SPOE message from which to resume encoding */
|
||
|
struct spoe_arg *curarg; /* SPOE arg in <curmsg> from which to resume encoding */
|
||
|
unsigned int curoff; /* offset in <curarg> from which to resume encoding */
|
||
|
unsigned int curlen; /* length of <curarg> need to be encode, for SMP_F_MAY_CHANGE data */
|
||
|
unsigned int flags; /* SPOE_FRM_FL_* */
|
||
|
} frag_ctx; /* Info about fragmented frames, valid on if SPOE_CTX_FL_FRAGMENTED is set */
|
||
|
|
||
|
struct {
|
||
|
struct timeval tv_start; /* start date of the current event/group */
|
||
|
struct timeval tv_request; /* date the frame processing starts (reset for each frag) */
|
||
|
struct timeval tv_queue; /* date the frame is queued (reset for each frag) */
|
||
|
struct timeval tv_wait; /* date the stream starts waiting for a response */
|
||
|
struct timeval tv_response; /* date the response processing starts */
|
||
|
long t_request; /* delay to encode and push the frame in queue (cumulative for frags) */
|
||
|
long t_queue; /* delay before the frame gets out the sending queue (cumulative for frags) */
|
||
|
long t_waiting; /* delay before the response is reveived */
|
||
|
long t_response; /* delay to process the response (from the stream pov) */
|
||
|
long t_process; /* processing time of the last event/group */
|
||
|
unsigned long t_total; /* cumulative processing time */
|
||
|
} stats; /* Stats for this stream */
|
||
|
};
|
||
|
|
||
|
/* SPOE context inside a appctx */
|
||
|
struct spoe_appctx {
|
||
|
struct appctx *owner; /* the owner */
|
||
|
struct task *task; /* task to handle applet timeouts */
|
||
|
struct spoe_agent *agent; /* agent on which the applet is attached */
|
||
|
|
||
|
unsigned int version; /* the negotiated version */
|
||
|
unsigned int max_frame_size; /* the negotiated max-frame-size value */
|
||
|
unsigned int flags; /* SPOE_APPCTX_FL_* */
|
||
|
|
||
|
unsigned int status_code; /* SPOE_FRM_ERR_* */
|
||
|
#if defined(DEBUG_SPOE) || defined(DEBUG_FULL)
|
||
|
char *reason; /* Error message, used for debugging only */
|
||
|
int rlen; /* reason length */
|
||
|
#endif
|
||
|
|
||
|
struct buffer buffer; /* Buffer used to store a encoded messages */
|
||
|
struct buffer_wait buffer_wait; /* position in the list of resources waiting for a buffer */
|
||
|
struct list waiting_queue; /* list of streams waiting for a ACK frame, in sync and pipelining mode */
|
||
|
struct list list; /* next spoe appctx for the same agent */
|
||
|
struct eb32_node node; /* node used for applets tree */
|
||
|
unsigned int cur_fpa;
|
||
|
|
||
|
struct {
|
||
|
struct spoe_context *ctx; /* SPOE context owning the fragmented frame */
|
||
|
unsigned int cursid; /* stream-id of the fragmented frame. used if the processing is aborted */
|
||
|
unsigned int curfid; /* frame-id of the fragmented frame. used if the processing is aborted */
|
||
|
} frag_ctx; /* Info about fragmented frames, unused for unfragmented frames */
|
||
|
};
|
||
|
|
||
|
#endif /* _HAPROXY_SPOE_T_H */
|